Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update sp service to pull current year birthdays #5374

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions samples/react-birthdays/.nvmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
v18.18.2
2 changes: 2 additions & 0 deletions samples/react-birthdays/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ email | Text | true
* [João Mendes](https://github.com/joaojmendes)
* [Sajal Maity](https://github.com/smaity)
* [Valeras Narbutas](https://github.com/ValerasNarbutas)
* [Gretchun Kim](https://github.com/gretchunkim)

## Version history

Expand All @@ -72,6 +73,7 @@ Version|Date|Comments
3.0.0|April 7, 2022 | Upgraded to SPFx 1.14.0
4.0.0|March 6, 2023 | Upgraded to SPFx 1.16.1
5.0.0|October 2, 2024 | Upgraded to SPFx 1.20.0
5.1.0|January 13,2025 | Edited SPService to ensure current year is used to pull upcoming birthdays

## Minimal Path to Awesome

Expand Down
7 changes: 6 additions & 1 deletion samples/react-birthdays/assets/sample.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
"The Web Part Birthdays shows the upcoming birthdays in the company, the web part reads birthdays from a list located on the tenant\u0027s root site with title \u0022Birthdays.\u0022"
],
"creationDateTime": "2019-07-23",
"updateDateTime": "2024-10-02",
"updateDateTime": "2025-01-13",
"products": [
"SharePoint"
],
Expand Down Expand Up @@ -239,6 +239,11 @@
"company": "JP Morgan Chase",
"pictureUrl": "https://github.com/smaity.png",
"name": "Sajal Maity"
},
{
"gitHubAccount": "gretchunkim",
"pictureUrl": "https://github.com/gretchunkim.png",
"name": "Azores"
}
],
"references": [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ export class HappyBirthdayCard extends React.Component<IHappyBirthdayCardProps,
<div className={styles.documentCard}>
<Image
imageFit={ImageFit.cover}
// @ts-ignore: Object is possibly 'null'.
// @ts-expect-error: Object is possibly 'null'.
src={imageTemplate[this.props.imageTemplate]?.imageUrl}
width={IMG_WIDTH}
height={IMG_HEIGTH}
Expand All @@ -108,6 +108,7 @@ export class HappyBirthdayCard extends React.Component<IHappyBirthdayCardProps,
actions={[
{
iconProps: { iconName: 'Mail' },
// eslint-disable-next-line @typescript-eslint/no-explicit-any
onClick: (ev: any) => {
ev.preventDefault();
ev.stopPropagation();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
export interface IHappyBirthdayCardProps {
userName?:string | undefined;
jobDescription?: string;
userName: string;
jobDescription: string;
birthday: string;
anniversary: boolean;
userEmail:string;
anniversary?: boolean;
congratulationsMsg?: string;
imageTemplate:string;
}
userEmail: string;
imageTemplate: number; // Change this to a number to represent the index of the imageTemplate array
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,23 +12,21 @@ export class HappyBirthday extends React.Component<IHappyBirthdayProps, IHappbir
return (
<div className={styles.happyBirthday}>
{
this.props.users.map((user: IUser) => {
return (
<div className={styles.container}>
<HappyBirthdayCard userName={user.userName}
jobDescription={user.jobDescription}
birthday={moment(user.birthday, ["MM-DD-YYYY", "YYYY-MM-DD", "DD/MM/YYYY", "MM/DD/YYYY"]).format('Do MMMM')}
anniversary={user.anniversary}
congratulationsMsg={user.message}
userEmail={user.userEmail}
imageTemplate={this.props.imageTemplate}
/>
</div>
);
})
this.props.users.map((user: IUser, index: number) => (
<div className={styles.container} key={user.key || index}>
<HappyBirthdayCard
userName={user.userName}
jobDescription={user.jobDescription || "No Job Description"}
birthday={moment(user.birthday).format('Do MMMM')}
anniversary={!!user.anniversary}
congratulationsMsg={user.message}
userEmail={user.userEmail}
imageTemplate={Number(this.props.imageTemplate)} // Ensure this is a number
/>
</div>
))
}
</div>
);
}
}
export default HappyBirthday;
14 changes: 7 additions & 7 deletions samples/react-birthdays/src/controls/happybirthday/IUser.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
export interface IUser {
key: string;
userName:string;
jobDescription?: string;
birthday: string;
userEmail: string;
message: string;
anniversary: boolean;
key: string; // Unique key
userName: string; // Name of the user
message: string; // Birthday message
anniversary: boolean; // Anniversary flag
userEmail: string; // User's email address
jobDescription: string; // Job title
birthday: string; // ISO string of the birthday date
}
8 changes: 4 additions & 4 deletions samples/react-birthdays/src/services/IUser.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
export interface IUser {
key: string;
userName:string;
jobDescription?: string;
birthday: string;
userEmail: string;
userName: string;
message: string;
anniversary: boolean;
userEmail: string;
jobDescription: string;
birthday: string; // ISO string of the birthday
}
80 changes: 36 additions & 44 deletions samples/react-birthdays/src/services/SPService.ts
Original file line number Diff line number Diff line change
@@ -1,64 +1,56 @@
import { WebPartContext } from "@microsoft/sp-webpart-base";
import { MSGraphClientV3 } from "@microsoft/sp-http";
import { MSGraphClientV3 } from "@microsoft/sp-http";
import * as moment from 'moment';

export class SPService {
// private graphClient: MSGraphClientV3 = null;
private graphClient: MSGraphClientV3;
private birthdayListTitle: string = "Birthdays";
constructor(private _context: WebPartContext) {
// private birthdayListTitle: string = "Birthdays";

}
// Get Profiles
public async getPBirthdays(upcommingDays: number): Promise<any[]> {
let _results, _today: string, _month: number, _day: number;
let _filter: string, _countdays: number, _f:number, _nextYearStart: string;
let _FinalDate: string;
constructor(private _context: WebPartContext) {}

// Get Birthdays ignoring the year
// eslint-disable-next-line @typescript-eslint/no-explicit-any
public async getPBirthdays(upcomingDays: number): Promise<any[]> {
try {
_results = null;
_today = '2000-' + moment().format('MM-DD');
_month = parseInt(moment().format('MM'));
_day = parseInt(moment().format('DD'));
_filter = "fields/Birthday ge '" + _today + "'";
// If we are in December we have to look if there are birthdays in January
// we have to build a condition to select birthday in January based on number of upcommingDays
// we can not use the year for test, the year is always 2000.
console.log(_month);
_countdays = _day + upcommingDays;
_f = 0;
if (_month === 12 && _countdays > 31) {
_nextYearStart = '2000-01-01';
_FinalDate = '2000-01-';
_f = _countdays - 31;
_FinalDate = _FinalDate + _f;
_filter = "fields/Birthday ge '" + _today + "' or (fields/Birthday ge '" + _nextYearStart + "' and fields/Birthday le '" + _FinalDate + "')";
}
else{
_FinalDate = '2000-';
if ((_countdays) > 31) {
_f = _countdays - 31;
_month = _month + 1;
_FinalDate = _FinalDate +_month + '-' + _f;
}else{
_FinalDate = _FinalDate +_month + '-' + _countdays;
}
_filter = "fields/Birthday ge '" + _today + "' and fields/Birthday le '" + _FinalDate + "'";
}
const today = moment();
const todayMMDD = today.format('MM-DD'); // Get today's date as MM-DD
const futureMMDD = today.add(upcomingDays, 'days').format('MM-DD'); // Calculate future date

this.graphClient = await this._context.msGraphClientFactory.getClient('3');
_results = await this.graphClient.api(`sites/root/lists('${this.birthdayListTitle}')/items?orderby=Fields/Birthday`)

// Fetch all birthdays without filtering
const response = await this.graphClient
.api(`sites/root/lists('Birthdays')/items?orderby=fields/Birthday`)
.version('v1.0')
.expand('fields')
//.top(upcommingDays)
.filter(_filter)
.get();

return _results.value;
// Filter results locally
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const filteredItems = response.value.filter((item: any) => {
const birthday = item.fields.Birthday;
if (!birthday) return false; // Skip if Birthday is missing

const birthdayMMDD = moment(birthday).format('MM-DD'); // Extract MM-DD
if (todayMMDD > futureMMDD) {
// Handle year transition (December to January)
return (
birthdayMMDD >= todayMMDD || // Later in the current year
birthdayMMDD <= futureMMDD // Earlier in the next year
);
} else {
// Normal case (same year)
return birthdayMMDD >= todayMMDD && birthdayMMDD <= futureMMDD;
}
});

return filteredItems;
} catch (error) {
console.dir(error);
console.error("Error fetching birthdays:", error);
return Promise.reject(error);
}
}

}

export default SPService;
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import { IBirthdaysProps } from './components/IBirthdaysProps';
export interface IBirthdaysWebPartProps {
title: string;
numberUpcomingDays: number;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
template: any;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import * as moment from 'moment';
import { IBirthdayState } from './IBirthdaysState';
import SPService from '../../../services/SPService';
import { WebPartTitle } from "@pnp/spfx-controls-react/lib/WebPartTitle";
// eslint-disable-next-line @typescript-eslint/no-var-requires
const imgBackgroundBallons: string = require('../../../assets/ballonsBackgroud.png');
import { Image, ImageFit } from 'office-ui-fabric-react/lib/Image';
import { Label } from 'office-ui-fabric-react/lib/Label';
Expand All @@ -23,16 +24,16 @@ export default class Birthdays extends React.Component<IBirthdaysProps, IBirthda
};
}

public componentDidMount(): void {
this.GetUsers();
public async componentDidMount(): Promise<void> {
await this.GetUsers();
}

public componentDidUpdate(prevProps: IBirthdaysProps, prevState: IBirthdayState): void {

}
// Render
public render(): React.ReactElement<IBirthdaysProps> {
let _center: any = !this.state.showBirthdays ? "center" : "";
const _center: React.CSSProperties['textAlign'] = !this.state.showBirthdays ? "center" : undefined;
return (
<div className={styles.happyBirthday}
style={{ textAlign: _center }} >
Expand Down Expand Up @@ -60,7 +61,7 @@ export default class Birthdays extends React.Component<IBirthdaysProps, IBirthda
}

// Sort Array of Birthdays
private SortBirthdays(users: IUser[]) {
private SortBirthdays(users: IUser[]): IUser[] {
return users.sort( (a, b) => {
if (a.birthday > b.birthday) {
return 1;
Expand All @@ -72,7 +73,7 @@ export default class Birthdays extends React.Component<IBirthdaysProps, IBirthda
});
}
// Load List Of Users
private async GetUsers() {
private async GetUsers(): Promise<void> {
let _otherMonthsBirthdays: IUser[], _dezemberBirthdays: IUser[];
const listItems = await this._spServices.getPBirthdays(this.props.numberUpcomingDays);
if (listItems && listItems.length > 0) {
Expand All @@ -86,14 +87,14 @@ export default class Birthdays extends React.Component<IBirthdaysProps, IBirthda
// first select all bithdays of Dezember to sort this must be the first to show
if (moment().format('MM') === '12') {
_dezemberBirthdays = this._users.filter( (v) => {
var _currentMonth = moment(v.birthday, ["MM-DD-YYYY", "YYYY-MM-DD", "DD/MM/YYYY", "MM/DD/YYYY"]).format('MM');
const _currentMonth = moment(v.birthday, ["MM-DD-YYYY", "YYYY-MM-DD", "DD/MM/YYYY", "MM/DD/YYYY"]).format('MM');
return (_currentMonth === '12');
});
// Sort by birthday date in Dezember month
_dezemberBirthdays = this.SortBirthdays(_dezemberBirthdays);
// select birthdays != of month 12
_otherMonthsBirthdays = this._users.filter((v) => {
var _currentMonth = moment(v.birthday, ["MM-DD-YYYY", "YYYY-MM-DD", "DD/MM/YYYY", "MM/DD/YYYY"]).format('MM');
const _currentMonth = moment(v.birthday, ["MM-DD-YYYY", "YYYY-MM-DD", "DD/MM/YYYY", "MM/DD/YYYY"]).format('MM');
return (_currentMonth !== '12');
});
// sort by birthday date
Expand Down
Loading