Updated React Graph Calendar to SPFx 1.10 + adding Personal Tab support (#1111)
Updated React Graph Calendar to SPFx 1.10 + adding Personal Tab support (#1111)
This commit is contained in:
parent
e636d68221
commit
11da7ad89d
|
@ -1,7 +1,7 @@
|
|||
# React Graph Calendar Web Part
|
||||
|
||||
## Summary
|
||||
This is a sample web part developed using React Framework to gather events from the underlying group calendar of a Team site. This sample also demonstrates the utilization of web parts as Teams tabs and offering a visualization context to change behaviors based on the platform used (Getting the proper information from the team vs. SharePoint site, understanding the context of the theme on Teams, etc.).
|
||||
This is a sample web part developed using React Framework to gather events from the underlying group calendar of a Team site. This sample also demonstrates the utilization of web parts as Teams tabs and Personal tab and offering a visualization context to change behaviors based on the platform used (Getting the proper information from the team vs. SharePoint site, understanding the context of the theme on Teams, etc.).
|
||||
|
||||
### Web Part in SharePoint Online
|
||||
![The web part in action](./assets/react-graph-calendar-spo.gif)
|
||||
|
@ -9,14 +9,14 @@ This is a sample web part developed using React Framework to gather events from
|
|||
### Web Part in Microsoft Teams
|
||||
![The web part in action](./assets/react-graph-calendar-teams.gif)
|
||||
|
||||
Webpart is developed using below technologies
|
||||
Web part is developed using below technologies
|
||||
* React Framework
|
||||
* Full Calendar (fullcalendar.io)
|
||||
* Microsoft Teams API
|
||||
* Office UI Fabric
|
||||
|
||||
## Used SharePoint Framework Version
|
||||
![drop](https://img.shields.io/badge/version-1.9.1-green.svg)
|
||||
![drop](https://img.shields.io/badge/version-1.10-green.svg)
|
||||
|
||||
## Applies to
|
||||
|
||||
|
@ -38,6 +38,7 @@ react-graph-calendar | [Sébastien Levert](https://www.linkedin.com/in/sebastien
|
|||
Version|Date|Comments
|
||||
-------|----|--------
|
||||
1.0 |December 29, 2019 | Initial Release
|
||||
1.1 |January 08, 2020 | Bumped to SPFx 1.10 and added the Personal Tab support
|
||||
|
||||
## Disclaimer
|
||||
**THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.**
|
||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 9.1 MiB After Width: | Height: | Size: 5.2 MiB |
Binary file not shown.
Before Width: | Height: | Size: 9.3 MiB After Width: | Height: | Size: 8.7 MiB |
|
@ -11,6 +11,10 @@
|
|||
{
|
||||
"resource": "Microsoft Graph",
|
||||
"scope": "Group.Read.All"
|
||||
},
|
||||
{
|
||||
"resource": "Microsoft Graph",
|
||||
"scope": "Calendars.Read"
|
||||
}
|
||||
]
|
||||
},
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -17,10 +17,10 @@
|
|||
"@fullcalendar/moment": "^4.3.0",
|
||||
"@fullcalendar/moment-timezone": "^4.3.0",
|
||||
"@fullcalendar/react": "^4.3.0",
|
||||
"@microsoft/sp-core-library": "1.9.1",
|
||||
"@microsoft/sp-lodash-subset": "1.9.1",
|
||||
"@microsoft/sp-office-ui-fabric-core": "1.9.1",
|
||||
"@microsoft/sp-webpart-base": "1.9.1",
|
||||
"@microsoft/sp-core-library": "1.10.0",
|
||||
"@microsoft/sp-lodash-subset": "1.10.0",
|
||||
"@microsoft/sp-office-ui-fabric-core": "1.10.0",
|
||||
"@microsoft/sp-webpart-base": "1.10.0",
|
||||
"@types/es6-promise": "0.0.33",
|
||||
"@types/react": "16.8.8",
|
||||
"@types/react-dom": "16.8.3",
|
||||
|
@ -35,10 +35,10 @@
|
|||
"@types/react": "16.8.8"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@microsoft/sp-build-web": "1.9.1",
|
||||
"@microsoft/sp-tslint-rules": "1.9.1",
|
||||
"@microsoft/sp-module-interfaces": "1.9.1",
|
||||
"@microsoft/sp-webpart-workbench": "1.9.1",
|
||||
"@microsoft/sp-build-web": "1.10.0",
|
||||
"@microsoft/sp-tslint-rules": "1.10.0",
|
||||
"@microsoft/sp-module-interfaces": "1.10.0",
|
||||
"@microsoft/sp-webpart-workbench": "1.10.0",
|
||||
"@microsoft/rush-stack-compiler-2.9": "0.7.16",
|
||||
"gulp": "~3.9.1",
|
||||
"@types/chai": "3.4.34",
|
||||
|
|
|
@ -12,15 +12,15 @@
|
|||
// Components that allow authors to embed arbitrary script code should set this to true.
|
||||
// https://support.office.com/en-us/article/Turn-scripting-capabilities-on-or-off-1f2c515f-5d7e-448a-9fd7-835da935584f
|
||||
"requiresCustomScript": false,
|
||||
"supportedHosts": ["SharePointWebPart", "TeamsTab"],
|
||||
"supportedHosts": ["SharePointWebPart", "TeamsTab", "TeamsPersonalApp"],
|
||||
"preconfiguredEntries": [{
|
||||
"groupId": "5c03119e-3074-46fd-976b-c60198311f70", // Other
|
||||
"group": { "default": "Other" },
|
||||
"title": { "default": "GraphCalendar" },
|
||||
"description": { "default": "GraphCalendar description" },
|
||||
"officeFabricIconFontName": "Page",
|
||||
"title": { "default": "Graph Calendar" },
|
||||
"description": { "default": "Graph Calendar" },
|
||||
"officeFabricIconFontName": "Calendar",
|
||||
"properties": {
|
||||
"description": "GraphCalendar"
|
||||
"description": "Graph Calendar"
|
||||
}
|
||||
}]
|
||||
}
|
||||
|
|
|
@ -44,15 +44,14 @@ export default class GraphCalendarWebPart extends BaseClientSideWebPart<IGraphCa
|
|||
}
|
||||
|
||||
// Sets the Teams context if in Teams
|
||||
if (this.context.microsoftTeams) {
|
||||
this.context.microsoftTeams.getContext(context => {
|
||||
this._teamsContext = context;
|
||||
// resolve the promise
|
||||
resolve(undefined);
|
||||
});
|
||||
if (this.context.sdks.microsoftTeams) {
|
||||
this._teamsContext = this.context.sdks.microsoftTeams.context;
|
||||
|
||||
// Initialize the OUIF icons if in Teams
|
||||
initializeIcons();
|
||||
|
||||
// resolve the promise
|
||||
resolve(undefined);
|
||||
} else {
|
||||
// resolve the promise
|
||||
resolve(undefined);
|
||||
|
|
|
@ -17,6 +17,12 @@ interface IGraphCalendarState {
|
|||
isEventDetailsOpen: boolean;
|
||||
currentSelectedEvent: EventInput;
|
||||
groupId: string;
|
||||
tabType: TabType;
|
||||
}
|
||||
|
||||
enum TabType {
|
||||
TeamsTab,
|
||||
PersonalTab
|
||||
}
|
||||
|
||||
export default class GraphCalendar extends React.Component<IGraphCalendarProps, IGraphCalendarState> {
|
||||
|
@ -45,7 +51,8 @@ export default class GraphCalendar extends React.Component<IGraphCalendarProps,
|
|||
currentActiveEndDate: null,
|
||||
isEventDetailsOpen: false,
|
||||
currentSelectedEvent: null,
|
||||
groupId: this._isRunningInTeams() ? this.props.teamsContext.groupId : this.props.context.pageContext.site.group ? this.props.context.pageContext.site.group.id : ""
|
||||
groupId: this._isRunningInTeams() ? this.props.teamsContext.groupId : this.props.context.pageContext.site.group ? this.props.context.pageContext.site.group.id : "",
|
||||
tabType: this._isRunningInTeams() ? (this._isPersonalTab() ? TabType.PersonalTab : TabType.TeamsTab) : TabType.TeamsTab
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -73,7 +80,7 @@ export default class GraphCalendar extends React.Component<IGraphCalendarProps,
|
|||
plugins={[ dayGridPlugin ]}
|
||||
windowResize={this._handleResize.bind(this)}
|
||||
datesRender={this._datesRender.bind(this)}
|
||||
eventClick={this._handleEventClick.bind(this)}
|
||||
eventClick={this._openEventPanel.bind(this)}
|
||||
height={this.state.height}
|
||||
events={this.state.events} />
|
||||
{this.state.currentSelectedEvent &&
|
||||
|
@ -81,6 +88,8 @@ export default class GraphCalendar extends React.Component<IGraphCalendarProps,
|
|||
isOpen={this.state.isEventDetailsOpen}
|
||||
type={ PanelType.smallFixedFar }
|
||||
headerText={this.state.currentSelectedEvent ? this.state.currentSelectedEvent.title : ""}
|
||||
onDismiss={this._closeEventPanel.bind(this)}
|
||||
isLightDismiss={true}
|
||||
closeButtonAriaLabel='Close'>
|
||||
<h3>Start Time</h3>
|
||||
<span>{moment(this.state.currentSelectedEvent.start).format('MMMM Do YYYY [at] h:mm:ss a')}</span>
|
||||
|
@ -123,17 +132,40 @@ export default class GraphCalendar extends React.Component<IGraphCalendarProps,
|
|||
return this.props.teamsContext;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates if the current web part is running in a Personal Tab
|
||||
*/
|
||||
private _isPersonalTab() {
|
||||
let _isPersonalTab: Boolean = false;
|
||||
|
||||
if(this._isRunningInTeams() && !this.props.teamsContext.teamId) {
|
||||
_isPersonalTab = true;
|
||||
}
|
||||
|
||||
return _isPersonalTab;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles the click event and opens the OUIF Panel
|
||||
* @param eventClickInfo The information about the selected event
|
||||
*/
|
||||
private _handleEventClick(eventClickInfo: any) {
|
||||
private _openEventPanel(eventClickInfo: any) {
|
||||
this.setState({
|
||||
isEventDetailsOpen: true,
|
||||
currentSelectedEvent: eventClickInfo.event
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles the click event on the dismiss from the Panel and closes the OUIF Panel
|
||||
*/
|
||||
private _closeEventPanel() {
|
||||
this.setState({
|
||||
isEventDetailsOpen: true,
|
||||
currentSelectedEvent: null
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* If the view changed, reload the events based on the active view
|
||||
* @param info Information about the current active view
|
||||
|
@ -166,15 +198,20 @@ export default class GraphCalendar extends React.Component<IGraphCalendarProps,
|
|||
*/
|
||||
private _loadEvents(startDate: Date, endDate: Date): void {
|
||||
|
||||
// If a Group was found, execute the query. If not, do nothing.
|
||||
if(this.state.groupId) {
|
||||
// If a Group was found or running in the context of a Personal tab, execute the query. If not, do nothing.
|
||||
if(this.state.groupId || this.state.tabType == TabType.PersonalTab) {
|
||||
|
||||
this.props.context.msGraphClientFactory
|
||||
.getClient()
|
||||
.then((client: MSGraphClient): void => {
|
||||
|
||||
let apiUrl: string = `/groups/${this.state.groupId}/events`;
|
||||
if(this._isPersonalTab()) {
|
||||
apiUrl = '/me/events';
|
||||
}
|
||||
|
||||
client
|
||||
.api(`/groups/${this.state.groupId}/events`)
|
||||
.api(apiUrl)
|
||||
.version("v1.0")
|
||||
.select('subject,start,end,location,bodyPreview,isAllDay')
|
||||
.filter(`start/dateTime ge '${startDate.toISOString()}' and end/dateTime le '${endDate.toISOString()}'`)
|
||||
|
|
Loading…
Reference in New Issue