diff --git a/samples/react-modern-organization-chart/src/components/OrganizationChart/IOrganizationChartProps.ts b/samples/react-modern-organization-chart/src/components/OrganizationChart/IOrganizationChartProps.ts index 1c830c30d..7c9d7b76a 100644 --- a/samples/react-modern-organization-chart/src/components/OrganizationChart/IOrganizationChartProps.ts +++ b/samples/react-modern-organization-chart/src/components/OrganizationChart/IOrganizationChartProps.ts @@ -9,4 +9,5 @@ export interface IOrganizationChartProps { themeVariant: IReadonlyTheme | undefined; displayMode: DisplayMode; updateProperty: (value: string) => void; + refreshInterval: number; } diff --git a/samples/react-modern-organization-chart/src/components/OrganizationChart/OrganizationChart.tsx b/samples/react-modern-organization-chart/src/components/OrganizationChart/OrganizationChart.tsx index e4177153a..91b719a73 100644 --- a/samples/react-modern-organization-chart/src/components/OrganizationChart/OrganizationChart.tsx +++ b/samples/react-modern-organization-chart/src/components/OrganizationChart/OrganizationChart.tsx @@ -56,6 +56,10 @@ presenceStatus["PresenceUnknown"] = PersonaPresence.none; export const OrganizationChart: React.FunctionComponent = ( props: IOrganizationChartProps ) => { + + // Timer Id used by setInterval + let _timerId:number = 0; + // Application Context (React.Context) const applicationContext: IAppContext = { currentUser: props.currentUser, context: props.context, @@ -255,10 +259,12 @@ export const OrganizationChart: React.FunctionComponent _managersList, _currentUserProfile, _reportsList, + getPresenceStatus, } = await useGetUserProperties( applicationContext.currentUser.loginName, applicationContext.context ); + setState({ ...state, isloading: false, @@ -266,6 +272,33 @@ export const OrganizationChart: React.FunctionComponent reportsList: _reportsList, userProfile: _currentUserProfile, }); + + // Pooling status each x min ( value define as property in webpart) + // test if there are an Timer running if exist clear + if (_timerId) { + clearInterval(_timerId); + } + const _interval = props.refreshInterval * 60000; + _timerId = setInterval(async () => { + const newPresenceStatus = await getPresenceStatus( + _managersList, + _reportsList, + _currentUserProfile + ); + const { + managersList, + currentUserProfile, + reportsList, + } = newPresenceStatus; + setState({ + ...state, + isloading: false, + managerList: managersList, + reportsList: reportsList, + userProfile: currentUserProfile, + }); + }, _interval); + // } catch (error) { setState({ diff --git a/samples/react-modern-organization-chart/src/hooks/useGetUserProperties.ts b/samples/react-modern-organization-chart/src/hooks/useGetUserProperties.ts index 651c91cc4..7f31df771 100644 --- a/samples/react-modern-organization-chart/src/hooks/useGetUserProperties.ts +++ b/samples/react-modern-organization-chart/src/hooks/useGetUserProperties.ts @@ -121,8 +121,13 @@ export const useGetUserProperties = async ( const _managersPresences: IUserPresence[] = await getUserPresence( _managersObjIds ); - // Update Array of managers with presence - if (_managersPresences.length > 0) { + await updateManagersPresence(_managersPresences); + }; +//************************************************************************************// +// function Update List os Managers with presence status +//************************************************************************************// + const updateManagersPresence = async (_managersPresences: IUserPresence[]):Promise => { + if (_managersPresences.length > 0) { for (const _presence of _managersPresences) { const i = _.findIndex(_managersList, (v) => { return v.id == _presence.id; @@ -136,8 +141,10 @@ export const useGetUserProperties = async ( }; } } + return _managersList; }; + //************************************************************************************// // Get Direct Reports //*************************************************************************************// @@ -172,8 +179,16 @@ export const useGetUserProperties = async ( _userReportObjIds ); // Update Array of direct reports with presence - if (_directReportsPresences.length > 0) { - for (const _presence of _directReportsPresences) { + await updateDirectReportsPresence(_directReportsPresences); + }; + + //*************************************************************************************// + // Funcion Update List os Direct Reports with presence status + //*************************************************************************************// +const updateDirectReportsPresence = async (directReportsPresences: IUserPresence[]):Promise => { + // Update Array of direct reports with presence + if (directReportsPresences.length > 0) { + for (const _presence of directReportsPresences) { const i = _.findIndex(_reportsList, (v) => { return v.id == _presence.id; }); @@ -186,14 +201,51 @@ export const useGetUserProperties = async ( }; } } - }; + return _reportsList; +}; + +//*************************************************************************************// + // Get news status of managers and direct Reports + //*************************************************************************************// + + const getPresenceStatus = async ( managersList: IUserInfo[],reportsList:IUserInfo[], currentUserProfile: any):Promise => { + const _managersObjIds:string[] = []; + const _userReportObjIds:string[] = []; + + // get managersObjIds + for (const _manager of managersList){ + _managersObjIds.push(_manager.id); + } + // get new status of Managers and update list os managers + const _managersPresences: IUserPresence[] = await getUserPresence(_managersObjIds); + managersList = await updateManagersPresence(_managersPresences); + + // Get objsId of DirectReports + for (const _userReport of reportsList){ + _userReportObjIds.push(_userReport.id); + } + // get new status of Direct Reports and update list of direct Reports + const _directReportsPresences: IUserPresence[] = await getUserPresence( + _userReportObjIds + ); + + reportsList = await updateDirectReportsPresence(_directReportsPresences); + + // Get update status for current user + + const _currentUserPresenceUpd: IUserPresence[] = await getUserPresence([currentUserProfile.id]); + currentUserProfile.presence = { activity: _currentUserPresenceUpd[0].activity, availability: _currentUserPresenceUpd[0].availability}; + + return { managersList, currentUserProfile, reportsList }; + + }; //*************************************************************************************// // End Functions //*************************************************************************************// //*************************************************************************************// - // Get Current User Profile + // MAIN - Get Current User Profile //*************************************************************************************// const _currentUserProfile: any = await sp.profiles .usingCaching() @@ -204,6 +256,7 @@ export const useGetUserProperties = async ( const _directReports: string[] = _currentUserProfile.DirectReports; // Get userObjId const _currentUserObjId: string = await getUserId( _currentUserProfile.UserProfileProperties); + _currentUserProfile.id = _currentUserObjId; // Get Current user Picture and User Presence _currentUserProfile.PictureUrl = await getImageBase64( `/_layouts/15/userphoto.aspx?size=M&accountname=${_currentUserProfile.Email}`, _currentUserObjId); @@ -219,5 +272,5 @@ export const useGetUserProperties = async ( // Return objects // _managersList , _currentUserProfile , DirectReports //*************************************************************************************// - return { _managersList, _currentUserProfile, _reportsList }; + return { _managersList, _currentUserProfile, _reportsList, getPresenceStatus }; }; diff --git a/samples/react-modern-organization-chart/src/webparts/organizationChart/OrganizationChartWebPart.manifest.json b/samples/react-modern-organization-chart/src/webparts/organizationChart/OrganizationChartWebPart.manifest.json index 3e419da23..f96101017 100644 --- a/samples/react-modern-organization-chart/src/webparts/organizationChart/OrganizationChartWebPart.manifest.json +++ b/samples/react-modern-organization-chart/src/webparts/organizationChart/OrganizationChartWebPart.manifest.json @@ -21,7 +21,8 @@ "description": { "default": "Organization Chart" }, "officeFabricIconFontName": "Org", "properties": { - "title": "Organization Chart" + "title": "Organization Chart", + "refreshInterval": "5" } }] } diff --git a/samples/react-modern-organization-chart/src/webparts/organizationChart/OrganizationChartWebPart.ts b/samples/react-modern-organization-chart/src/webparts/organizationChart/OrganizationChartWebPart.ts index 9967e6074..990373d08 100644 --- a/samples/react-modern-organization-chart/src/webparts/organizationChart/OrganizationChartWebPart.ts +++ b/samples/react-modern-organization-chart/src/webparts/organizationChart/OrganizationChartWebPart.ts @@ -1,45 +1,56 @@ -import * as React from 'react'; -import * as ReactDom from 'react-dom'; -import { Version } from '@microsoft/sp-core-library'; +import * as React from "react"; +import * as ReactDom from "react-dom"; +import { Version } from "@microsoft/sp-core-library"; import { IPropertyPaneConfiguration, - PropertyPaneTextField -} from '@microsoft/sp-property-pane'; -import { BaseClientSideWebPart } from '@microsoft/sp-webpart-base'; -import { ThemeProvider, ThemeChangedEventArgs, IReadonlyTheme } from '@microsoft/sp-component-base'; -import * as strings from 'OrganizationChartWebPartStrings'; -import {OrganizationChart} from '../../components/OrganizationChart/OrganizationChart'; -import { IOrganizationChartProps } from '../../components/OrganizationChart/IOrganizationChartProps'; + PropertyPaneTextField, + PropertyPaneSlider, + PropertyPaneLabel, +} from "@microsoft/sp-property-pane"; +import { BaseClientSideWebPart } from "@microsoft/sp-webpart-base"; +import { + ThemeProvider, + ThemeChangedEventArgs, + IReadonlyTheme, +} from "@microsoft/sp-component-base"; +import * as strings from "OrganizationChartWebPartStrings"; +import { OrganizationChart } from "../../components/OrganizationChart/OrganizationChart"; +import { IOrganizationChartProps } from "../../components/OrganizationChart/IOrganizationChartProps"; import { loadTheme } from "office-ui-fabric-react"; -import { DisplayMode } from '@microsoft/sp-core-library'; +import { DisplayMode } from "@microsoft/sp-core-library"; import { sp } from "@pnp/sp"; const teamsDefaultTheme = require("../../common/TeamsDefaultTheme.json"); const teamsDarkTheme = require("../../common/TeamsDarkTheme.json"); const teamsContrastTheme = require("../../common/TeamsContrastTheme.json"); - - export interface IOrganizationChartWebPartProps { title: string; displayMode: DisplayMode; updateProperty: (value: string) => void; + refreshInterval: number; } -export default class OrganizationChartWebPart extends BaseClientSideWebPart { +export default class OrganizationChartWebPart extends BaseClientSideWebPart< + IOrganizationChartWebPartProps +> { private _themeProvider: ThemeProvider; private _themeVariant: IReadonlyTheme | undefined; protected async onInit(): Promise { - sp.setup({ - spfxContext: this.context + spfxContext: this.context, }); - this._themeProvider = this.context.serviceScope.consume(ThemeProvider.serviceKey); + this._themeProvider = this.context.serviceScope.consume( + ThemeProvider.serviceKey + ); // If it exists, get the theme variant this._themeVariant = this._themeProvider.tryGetTheme(); // Register a handler to be notified if the theme variant changes - this._themeProvider.themeChangedEvent.add(this, this._handleThemeChangedEvent); + this._themeProvider.themeChangedEvent.add( + this, + this._handleThemeChangedEvent + ); if (this.context.sdks.microsoftTeams) { // in teams ? @@ -62,31 +73,30 @@ export default class OrganizationChartWebPart extends BaseClientSideWebPart { this.context.domElement.setAttribute("data-theme", theme); document.body.setAttribute("data-theme", theme); if (theme == "dark") { loadTheme({ - palette: teamsDarkTheme + palette: teamsDarkTheme, }); } - if (theme == "default") { + if (theme == "default") { loadTheme({ - palette: teamsDefaultTheme + palette: teamsDefaultTheme, }); } if (theme == "contrast") { loadTheme({ - palette: teamsContrastTheme + palette: teamsContrastTheme, }); } } - public render(): void { const element: React.ReactElement = React.createElement( OrganizationChart, @@ -96,9 +106,10 @@ export default class OrganizationChartWebPart extends BaseClientSideWebPart { - this.properties.title = value; - } + updateProperty: (value: string) => { + this.properties.title = value; + }, + refreshInterval: this.properties.refreshInterval, } ); @@ -110,7 +121,7 @@ export default class OrganizationChartWebPart extends BaseClientSideWebPart