commit
d32bfd5521
|
@ -0,0 +1,25 @@
|
||||||
|
# EditorConfig helps developers define and maintain consistent
|
||||||
|
# coding styles between different editors and IDEs
|
||||||
|
# editorconfig.org
|
||||||
|
|
||||||
|
root = true
|
||||||
|
|
||||||
|
|
||||||
|
[*]
|
||||||
|
|
||||||
|
# change these settings to your own preference
|
||||||
|
indent_style = space
|
||||||
|
indent_size = 2
|
||||||
|
|
||||||
|
# we recommend you to keep these unchanged
|
||||||
|
end_of_line = lf
|
||||||
|
charset = utf-8
|
||||||
|
trim_trailing_whitespace = true
|
||||||
|
insert_final_newline = true
|
||||||
|
|
||||||
|
[*.md]
|
||||||
|
trim_trailing_whitespace = false
|
||||||
|
|
||||||
|
[{package,bower}.json]
|
||||||
|
indent_style = space
|
||||||
|
indent_size = 2
|
|
@ -0,0 +1,32 @@
|
||||||
|
# Logs
|
||||||
|
logs
|
||||||
|
*.log
|
||||||
|
npm-debug.log*
|
||||||
|
|
||||||
|
# Dependency directories
|
||||||
|
node_modules
|
||||||
|
|
||||||
|
# Build generated files
|
||||||
|
dist
|
||||||
|
lib
|
||||||
|
solution
|
||||||
|
temp
|
||||||
|
*.sppkg
|
||||||
|
|
||||||
|
# Coverage directory used by tools like istanbul
|
||||||
|
coverage
|
||||||
|
|
||||||
|
# OSX
|
||||||
|
.DS_Store
|
||||||
|
|
||||||
|
# Visual Studio files
|
||||||
|
.ntvs_analysis.dat
|
||||||
|
.vs
|
||||||
|
bin
|
||||||
|
obj
|
||||||
|
|
||||||
|
# Resx Generated Code
|
||||||
|
*.resx.ts
|
||||||
|
|
||||||
|
# Styles Generated Code
|
||||||
|
*.scss.ts
|
|
@ -0,0 +1,12 @@
|
||||||
|
{
|
||||||
|
"@microsoft/generator-sharepoint": {
|
||||||
|
"isCreatingSolution": false,
|
||||||
|
"environment": "spo",
|
||||||
|
"version": "1.8.0",
|
||||||
|
"libraryName": "react-graph-reports",
|
||||||
|
"libraryId": "94cfede6-79e3-4298-8946-0347885a12d5",
|
||||||
|
"packageManager": "npm",
|
||||||
|
"isDomainIsolated": false,
|
||||||
|
"componentType": "webpart"
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,61 @@
|
||||||
|
## react-graph-reports
|
||||||
|
|
||||||
|
## Summary
|
||||||
|
This sample describe a SPFX application which reterive an office 365 usage reports using Microsoft Graph API. This application also use chartjs library to generate graph.
|
||||||
|
|
||||||
|
|
||||||
|
![Office 365 Usage Reports using Microsoft Graph API](./assets/react-graph-reports.gif)
|
||||||
|
|
||||||
|
## Used SharePoint Framework Version
|
||||||
|
![drop](https://img.shields.io/badge/version-GA-green.svg)
|
||||||
|
|
||||||
|
## Applies to
|
||||||
|
|
||||||
|
* [SharePoint Framework](https:/dev.office.com/sharepoint)
|
||||||
|
* [Office 365 tenant](https://dev.office.com/sharepoint/docs/spfx/set-up-your-development-environment)
|
||||||
|
|
||||||
|
## Prerequisites
|
||||||
|
|
||||||
|
> You need following set of permissions in order to retrieve office 365 usage reports. Find out more about consuming the [Microsoft Graph API in the SharePoint Framework](https://docs.microsoft.com/en-us/sharepoint/dev/spfx/use-aad-tutorial)<br><br>![Microsoft Graph API Permissions](./assets/graph-api-permissions-usage-reports.png)
|
||||||
|
|
||||||
|
|
||||||
|
## Solution
|
||||||
|
|
||||||
|
Solution|Author(s)
|
||||||
|
--------|---------
|
||||||
|
react-graph-reports | Ejaz Hussain
|
||||||
|
|
||||||
|
## Version history
|
||||||
|
|
||||||
|
Version|Date|Comments
|
||||||
|
-------|----|--------
|
||||||
|
1.0|April 09, 2019|Initial release
|
||||||
|
|
||||||
|
## 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.**
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Minimal Path to Awesome
|
||||||
|
|
||||||
|
- Clone this repository
|
||||||
|
- in the command line run:
|
||||||
|
- `npm install`
|
||||||
|
- `gulp serve`
|
||||||
|
|
||||||
|
If you have not previously granted the required Microsoft Graph permissions, you need to:
|
||||||
|
|
||||||
|
- Run `gulp bundle --ship`
|
||||||
|
- Run `gulp package-solution --ship`
|
||||||
|
- Install the .sppkg file (under .\sharepoint\solution) to the SP app catalog
|
||||||
|
- Approve the API permissions in the new SP admin center
|
||||||
|
|
||||||
|
## Features
|
||||||
|
Here are main features for this application
|
||||||
|
|
||||||
|
- Material UI Components (Tab)
|
||||||
|
- Microsoft Graph API to reterive Office 365 Usage reports
|
||||||
|
- ChartJS integrations
|
||||||
|
- Dependency Injection in SPFX using Service Scope
|
||||||
|
|
||||||
|
<img src="https://telemetry.sharepointpnp.com/sp-dev-fx-webparts/samples/react-graph-reports" />
|
Binary file not shown.
After Width: | Height: | Size: 6.2 KiB |
Binary file not shown.
After Width: | Height: | Size: 3.3 MiB |
|
@ -0,0 +1,19 @@
|
||||||
|
{
|
||||||
|
"$schema": "https://developer.microsoft.com/json-schemas/spfx-build/config.2.0.schema.json",
|
||||||
|
"version": "2.0",
|
||||||
|
"bundles": {
|
||||||
|
"graph-reports-web-part": {
|
||||||
|
"components": [
|
||||||
|
{
|
||||||
|
"entrypoint": "./lib/webparts/graphReports/GraphReportsWebPart.js",
|
||||||
|
"manifest": "./src/webparts/graphReports/GraphReportsWebPart.manifest.json"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"externals": {},
|
||||||
|
"localizedResources": {
|
||||||
|
"GraphReportsWebPartStrings": "lib/webparts/graphReports/loc/{locale}.js",
|
||||||
|
"ControlStrings": "node_modules/@pnp/spfx-controls-react/lib/loc/{locale}.js"
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,4 @@
|
||||||
|
{
|
||||||
|
"$schema": "https://developer.microsoft.com/json-schemas/spfx-build/copy-assets.schema.json",
|
||||||
|
"deployCdnPath": "temp/deploy"
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
{
|
||||||
|
"$schema": "https://developer.microsoft.com/json-schemas/spfx-build/deploy-azure-storage.schema.json",
|
||||||
|
"workingDir": "./temp/deploy/",
|
||||||
|
"account": "<!-- STORAGE ACCOUNT NAME -->",
|
||||||
|
"container": "react-graph-reports",
|
||||||
|
"accessKey": "<!-- ACCESS KEY -->"
|
||||||
|
}
|
|
@ -0,0 +1,24 @@
|
||||||
|
{
|
||||||
|
"$schema": "https://developer.microsoft.com/json-schemas/spfx-build/package-solution.schema.json",
|
||||||
|
"solution": {
|
||||||
|
"name": "react-graph-reports-client-side-solution",
|
||||||
|
"id": "94cfede6-79e3-4298-8946-0347885a12d5",
|
||||||
|
"version": "1.0.0.0",
|
||||||
|
"includeClientSideAssets": true,
|
||||||
|
"skipFeatureDeployment": true,
|
||||||
|
"isDomainIsolated": false,
|
||||||
|
"webApiPermissionRequests": [
|
||||||
|
{
|
||||||
|
"resource": "Microsoft Graph",
|
||||||
|
"scope": "User.ReadBasic.All"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"resource": "Microsoft Graph",
|
||||||
|
"scope": "Reports.Read.All"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"paths": {
|
||||||
|
"zippedPackage": "solution/react-graph-reports.sppkg"
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,10 @@
|
||||||
|
{
|
||||||
|
"$schema": "https://developer.microsoft.com/json-schemas/core-build/serve.schema.json",
|
||||||
|
"port": 4321,
|
||||||
|
"https": true,
|
||||||
|
"initialPage": "https://localhost:5432/workbench",
|
||||||
|
"api": {
|
||||||
|
"port": 5432,
|
||||||
|
"entryPath": "node_modules/@microsoft/sp-webpart-workbench/lib/api/"
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,4 @@
|
||||||
|
{
|
||||||
|
"$schema": "https://developer.microsoft.com/json-schemas/spfx-build/write-manifests.schema.json",
|
||||||
|
"cdnBasePath": "<!-- PATH TO CDN -->"
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
const gulp = require('gulp');
|
||||||
|
const build = require('@microsoft/sp-build-web');
|
||||||
|
build.addSuppression(`Warning - [sass] The local CSS class 'ms-Grid' is not camelCase and will not be type-safe.`);
|
||||||
|
|
||||||
|
build.initialize(gulp);
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,53 @@
|
||||||
|
{
|
||||||
|
"name": "react-graph-reports",
|
||||||
|
"version": "0.0.1",
|
||||||
|
"private": true,
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.10.0"
|
||||||
|
},
|
||||||
|
"scripts": {
|
||||||
|
"build": "gulp bundle",
|
||||||
|
"clean": "gulp clean",
|
||||||
|
"test": "gulp test"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@material-ui/core": "^3.9.2",
|
||||||
|
"@material-ui/icons": "^3.0.2",
|
||||||
|
"@microsoft/sp-core-library": "1.8.0",
|
||||||
|
"@microsoft/sp-lodash-subset": "1.8.0",
|
||||||
|
"@microsoft/sp-office-ui-fabric-core": "1.8.0",
|
||||||
|
"@microsoft/sp-property-pane": "1.8.0",
|
||||||
|
"@microsoft/sp-webpart-base": "1.8.0",
|
||||||
|
"@pnp/common": "^1.3.1",
|
||||||
|
"@pnp/graph": "^1.3.1",
|
||||||
|
"@pnp/logging": "^1.3.1",
|
||||||
|
"@pnp/odata": "^1.3.1",
|
||||||
|
"@pnp/sp": "^1.3.1",
|
||||||
|
"@pnp/spfx-controls-react": "^1.13.0-beta.892b624",
|
||||||
|
"@types/es6-promise": "0.0.33",
|
||||||
|
"@types/react": "16.4.2",
|
||||||
|
"@types/react-dom": "16.0.5",
|
||||||
|
"@types/webpack-env": "1.13.1",
|
||||||
|
"chart.js": "^2.8.0",
|
||||||
|
"react": "16.7.0",
|
||||||
|
"react-chartjs-2": "^2.7.6",
|
||||||
|
"react-dom": "16.7.0",
|
||||||
|
"typeface-roboto": "0.0.54"
|
||||||
|
},
|
||||||
|
"resolutions": {
|
||||||
|
"@types/react": "16.4.2"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@microsoft/microsoft-graph-types": "^1.7.0",
|
||||||
|
"@microsoft/rush-stack-compiler-3.3": "^0.1.6",
|
||||||
|
"@microsoft/sp-build-web": "1.8.0",
|
||||||
|
"@microsoft/sp-module-interfaces": "1.8.0",
|
||||||
|
"@microsoft/sp-tslint-rules": "1.8.0",
|
||||||
|
"@microsoft/sp-webpart-workbench": "1.8.0",
|
||||||
|
"@types/chai": "3.4.34",
|
||||||
|
"@types/mocha": "2.2.38",
|
||||||
|
"ajv": "~5.2.2",
|
||||||
|
"gulp": "~3.9.1",
|
||||||
|
"typescript": "^3.3.4000"
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1 @@
|
||||||
|
// A file is required to be in the root of the /src directory by the TypeScript compiler
|
|
@ -0,0 +1,99 @@
|
||||||
|
import { ServiceKey, ServiceScope } from '@microsoft/sp-core-library';
|
||||||
|
import { MSGraphClientFactory, MSGraphClient } from '@microsoft/sp-http';
|
||||||
|
|
||||||
|
export interface ICustomGraphService {
|
||||||
|
getMyDetails(): Promise<JSON>;
|
||||||
|
getSharePointSiteUsagePages(period: number): Promise<JSON>;
|
||||||
|
getSharePointSiteUsageSiteCounts(period: number): Promise<JSON>;
|
||||||
|
getSharePointActivityFileCounts(period: number): Promise<JSON>;
|
||||||
|
getOneDriveUsageFileCounts(period: number): Promise<JSON>;
|
||||||
|
getEmailActivityUserDetail(period: number): Promise<JSON>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class CustomGraphService implements ICustomGraphService {
|
||||||
|
|
||||||
|
public static readonly serviceKey: ServiceKey<ICustomGraphService> =
|
||||||
|
ServiceKey.create<ICustomGraphService>('my-custom-app:ICustomGraphService', CustomGraphService);
|
||||||
|
|
||||||
|
private _msGraphClientFactory: MSGraphClientFactory;
|
||||||
|
|
||||||
|
constructor(serviceScope: ServiceScope) {
|
||||||
|
serviceScope.whenFinished(() => {
|
||||||
|
this._msGraphClientFactory = serviceScope.consume(MSGraphClientFactory.serviceKey);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public getMyDetails(): Promise<JSON> {
|
||||||
|
return new Promise<JSON>((resolve, reject) => {
|
||||||
|
this._msGraphClientFactory.getClient().then((_msGraphClient: MSGraphClient) => {
|
||||||
|
_msGraphClient.api('/me').get((error, user: JSON, rawResponse?: any) => {
|
||||||
|
resolve(user);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//#region SharePoint
|
||||||
|
|
||||||
|
public getSharePointSiteUsagePages(period: number): Promise<JSON> {
|
||||||
|
return new Promise<JSON>((resolve, reject) => {
|
||||||
|
this._msGraphClientFactory.getClient().then((_msGraphClient: MSGraphClient) => {
|
||||||
|
_msGraphClient.api("https://graph.microsoft.com/beta/reports/getSharePointSiteUsagePages(period='D" + period + "')?$format=application/json").get((error, report: any, rawResponse?: any) => {
|
||||||
|
resolve(report);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
public getSharePointSiteUsageSiteCounts(period: number): Promise<JSON> {
|
||||||
|
return new Promise<JSON>((resolve, reject) => {
|
||||||
|
this._msGraphClientFactory.getClient().then((_msGraphClient: MSGraphClient) => {
|
||||||
|
_msGraphClient.api("https://graph.microsoft.com/beta/reports/getSharePointSiteUsageSiteCounts(period='D" + period + "')?$format=application/json").get((error, report: any, rawResponse?: any) => {
|
||||||
|
resolve(report);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
public getSharePointActivityFileCounts(period: number): Promise<JSON> {
|
||||||
|
return new Promise<JSON>((resolve, reject) => {
|
||||||
|
this._msGraphClientFactory.getClient().then((_msGraphClient: MSGraphClient) => {
|
||||||
|
_msGraphClient.api("https://graph.microsoft.com/beta/reports/getSharePointActivityFileCounts(period='D" + period + "')?$format=application/json").get((error, report: any, rawResponse?: any) => {
|
||||||
|
resolve(report);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
//#endregion SharePoint
|
||||||
|
|
||||||
|
|
||||||
|
//#region OneDrive
|
||||||
|
public getOneDriveUsageFileCounts(period: number): Promise<JSON> {
|
||||||
|
return new Promise<JSON>((resolve, reject) => {
|
||||||
|
this._msGraphClientFactory.getClient().then((_msGraphClient: MSGraphClient) => {
|
||||||
|
_msGraphClient.api("https://graph.microsoft.com/beta/reports/getOneDriveUsageFileCounts(period='D" + period + "')?$format=application/json").get((error, report: any, rawResponse?: any) => {
|
||||||
|
resolve(report);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
//#endregion OneDrive
|
||||||
|
|
||||||
|
//#region OutLook
|
||||||
|
public getEmailActivityUserDetail(period: number): Promise<JSON> {
|
||||||
|
return new Promise<JSON>((resolve, reject) => {
|
||||||
|
this._msGraphClientFactory.getClient().then((_msGraphClient: MSGraphClient) => {
|
||||||
|
_msGraphClient.api("https://graph.microsoft.com/beta/reports/getEmailActivityUserDetail(period='D" + period + "')?$format=application/json").get((error, report: any, rawResponse?: any) => {
|
||||||
|
resolve(report);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//#endregion Outlook
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1 @@
|
||||||
|
export { CustomGraphService, ICustomGraphService } from './CustomGraphService';
|
|
@ -0,0 +1,27 @@
|
||||||
|
{
|
||||||
|
"$schema": "https://developer.microsoft.com/json-schemas/spfx/client-side-web-part-manifest.schema.json",
|
||||||
|
"id": "23c794f0-6a72-4dd6-b324-cb813fdae517",
|
||||||
|
"alias": "GraphReportsWebPart",
|
||||||
|
"componentType": "WebPart",
|
||||||
|
|
||||||
|
// The "*" signifies that the version should be taken from the package.json
|
||||||
|
"version": "*",
|
||||||
|
"manifestVersion": 2,
|
||||||
|
|
||||||
|
// If true, the component can only be installed on sites where Custom Script is allowed.
|
||||||
|
// 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"],
|
||||||
|
|
||||||
|
"preconfiguredEntries": [{
|
||||||
|
"groupId": "5c03119e-3074-46fd-976b-c60198311f70", // Other
|
||||||
|
"group": { "default": "Other" },
|
||||||
|
"title": { "default": "Office 365 Usage Reports" },
|
||||||
|
"description": { "default": "This web part will fetch different reports using Graph API and display them in graphical interface, i.e Charts " },
|
||||||
|
"officeFabricIconFontName": "AnalyticsReport",
|
||||||
|
"properties": {
|
||||||
|
"description": "graphReports"
|
||||||
|
}
|
||||||
|
}]
|
||||||
|
}
|
|
@ -0,0 +1,63 @@
|
||||||
|
import * as React from 'react';
|
||||||
|
import * as ReactDom from 'react-dom';
|
||||||
|
import { Version } from '@microsoft/sp-core-library';
|
||||||
|
import { BaseClientSideWebPart } from '@microsoft/sp-webpart-base';
|
||||||
|
import {
|
||||||
|
IPropertyPaneConfiguration,
|
||||||
|
PropertyPaneTextField
|
||||||
|
} from '@microsoft/sp-property-pane';
|
||||||
|
|
||||||
|
import * as strings from 'GraphReportsWebPartStrings';
|
||||||
|
import GraphReports from './components/GraphReports';
|
||||||
|
import { IGraphReportsProps } from './components/IGraphReportsProps';
|
||||||
|
|
||||||
|
export interface IGraphReportsWebPartProps {
|
||||||
|
description: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
export default class GraphReportsWebPart extends BaseClientSideWebPart<IGraphReportsWebPartProps> {
|
||||||
|
|
||||||
|
|
||||||
|
public render(): void {
|
||||||
|
const element: React.ReactElement<IGraphReportsProps > = React.createElement(
|
||||||
|
GraphReports,
|
||||||
|
{
|
||||||
|
customServiceScope: this.context.serviceScope
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
ReactDom.render(element, this.domElement);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected onDispose(): void {
|
||||||
|
ReactDom.unmountComponentAtNode(this.domElement);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected get dataVersion(): Version {
|
||||||
|
return Version.parse('1.0');
|
||||||
|
}
|
||||||
|
|
||||||
|
protected getPropertyPaneConfiguration(): IPropertyPaneConfiguration {
|
||||||
|
return {
|
||||||
|
pages: [
|
||||||
|
{
|
||||||
|
header: {
|
||||||
|
description: strings.PropertyPaneDescription
|
||||||
|
},
|
||||||
|
groups: [
|
||||||
|
{
|
||||||
|
groupName: strings.BasicGroupName,
|
||||||
|
groupFields: [
|
||||||
|
PropertyPaneTextField('description', {
|
||||||
|
label: strings.DescriptionFieldLabel
|
||||||
|
})
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,40 @@
|
||||||
|
@import '~@microsoft/sp-office-ui-fabric-core/dist/sass/SPFabricCore.scss';
|
||||||
|
|
||||||
|
// @import 'typeface-roboto';
|
||||||
|
.graphReports {
|
||||||
|
flex-grow: 1;
|
||||||
|
|
||||||
|
.topHeader{
|
||||||
|
font-size: 25px;
|
||||||
|
}
|
||||||
|
.tabBackground{
|
||||||
|
background-color: #0078d4;
|
||||||
|
}
|
||||||
|
|
||||||
|
.paper {
|
||||||
|
padding: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sharepointDashboard {
|
||||||
|
padding: 0 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.divider {
|
||||||
|
display: block;
|
||||||
|
border: 0;
|
||||||
|
margin: 4em 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.oneDriveDashboard {
|
||||||
|
padding: 0 6px;
|
||||||
|
|
||||||
|
.header {
|
||||||
|
margin: 10px 0px;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.formControl {
|
||||||
|
margin: 0px;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,71 @@
|
||||||
|
import * as React from 'react';
|
||||||
|
import styles from './GraphReports.module.scss';
|
||||||
|
import { IGraphReportsProps } from './IGraphReportsProps';
|
||||||
|
import { withStyles } from '@material-ui/core/styles';
|
||||||
|
import { escape } from '@microsoft/sp-lodash-subset';
|
||||||
|
import Paper from '@material-ui/core/Paper';
|
||||||
|
import Typography from '@material-ui/core/Typography';
|
||||||
|
import Grid from '@material-ui/core/Grid';
|
||||||
|
import AppBar from '@material-ui/core/AppBar';
|
||||||
|
import Tabs from '@material-ui/core/Tabs';
|
||||||
|
import Tab from '@material-ui/core/Tab';
|
||||||
|
import { IGraphReportsState } from './IGraphReportsState';
|
||||||
|
import SharePointReports from './SharePointReports/SharePointReports';
|
||||||
|
import OneDriveReports from './OneDriveReports/OneDriveReports';
|
||||||
|
import OutlookReports from './OutlookReports/OutlookReports';
|
||||||
|
|
||||||
|
export default class GraphReports extends React.Component<IGraphReportsProps, IGraphReportsState> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
constructor(props: IGraphReportsProps, state: IGraphReportsState) {
|
||||||
|
super(props);
|
||||||
|
this.state = {
|
||||||
|
value: 0
|
||||||
|
};
|
||||||
|
this.handleChange = this.handleChange.bind(this);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public handleChange(event: React.ChangeEvent<{}>, value: any): void {
|
||||||
|
|
||||||
|
this.setState({
|
||||||
|
value: value
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public render(): React.ReactElement<IGraphReportsProps> {
|
||||||
|
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={styles.graphReports}>
|
||||||
|
<Grid container spacing={24}>
|
||||||
|
<Grid item xs={12}>
|
||||||
|
<h1 className={styles.topHeader}>Office 365 usage reports</h1>
|
||||||
|
<Paper className={styles.paper}>
|
||||||
|
<AppBar position="static">
|
||||||
|
<Tabs className={styles.tabBackground} value={this.state.value} onChange={this.handleChange}>
|
||||||
|
<Tab label="SharePoint" />
|
||||||
|
<Tab label="OneDrive" />
|
||||||
|
<Tab label="Outlook" />
|
||||||
|
</Tabs>
|
||||||
|
</AppBar>
|
||||||
|
{this.state.value === 0 && <SharePointReports customServiceScope={this.props.customServiceScope} />}
|
||||||
|
{this.state.value === 1 && <OneDriveReports customServiceScope={this.props.customServiceScope} />}
|
||||||
|
{this.state.value === 2 && <OutlookReports customServiceScope={this.props.customServiceScope} />}
|
||||||
|
</Paper>
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
import { ServiceScope } from "@microsoft/sp-core-library";
|
||||||
|
|
||||||
|
export interface IGraphReportsProps {
|
||||||
|
customServiceScope: ServiceScope;
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,3 @@
|
||||||
|
export interface IGraphReportsState {
|
||||||
|
value: number;
|
||||||
|
}
|
|
@ -0,0 +1,186 @@
|
||||||
|
import * as React from 'react';
|
||||||
|
import Grid from '@material-ui/core/Grid';
|
||||||
|
import { CustomGraphService } from '../../../../../services';
|
||||||
|
import { ServiceScope } from '@microsoft/sp-core-library';
|
||||||
|
import { ChartPoint } from 'chart.js';
|
||||||
|
import styles from '../../GraphReports.module.scss';
|
||||||
|
import { ChoiceGroup } from 'office-ui-fabric-react/lib/ChoiceGroup';
|
||||||
|
import { Line } from 'react-chartjs-2';
|
||||||
|
|
||||||
|
|
||||||
|
export interface IGetOneDriveUsageFileCountsProps {
|
||||||
|
customServiceScope: ServiceScope;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IGetOneDriveUsageFileCountsState {
|
||||||
|
data: [];
|
||||||
|
period: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default class GetOneDriveUsageFileCounts extends React.Component<IGetOneDriveUsageFileCountsProps, IGetOneDriveUsageFileCountsState> {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
private _customGraphServiceInstance;
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
constructor(props: IGetOneDriveUsageFileCountsProps) {
|
||||||
|
super(props);
|
||||||
|
|
||||||
|
this.state = {
|
||||||
|
data: [],
|
||||||
|
period: 7
|
||||||
|
};
|
||||||
|
|
||||||
|
this._onChange = this._onChange.bind(this);
|
||||||
|
//MSGraphClient
|
||||||
|
this._customGraphServiceInstance = this.props.customServiceScope.consume(CustomGraphService.serviceKey);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public componentDidMount() {
|
||||||
|
this._customGraphServiceInstance.getOneDriveUsageFileCounts(this.state.period).then((reportData: any) => {
|
||||||
|
this.setState({
|
||||||
|
data: reportData.value
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
private _onChange = (ev: React.FormEvent<HTMLInputElement>, option: any): void => {
|
||||||
|
|
||||||
|
let period: number = Number(option.key);
|
||||||
|
if (period) {
|
||||||
|
this._customGraphServiceInstance.getOneDriveUsageFileCounts(period).then((reportData: any) => {
|
||||||
|
this.setState({
|
||||||
|
data: reportData.value,
|
||||||
|
period: period
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public render(): React.ReactElement<IGetOneDriveUsageFileCountsProps> {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
let labels: any[] = [];
|
||||||
|
let totalFiles: ChartPoint[] = [];
|
||||||
|
let activeFiles: ChartPoint[] = [];
|
||||||
|
if (this.state.data.length > 0) {
|
||||||
|
labels = this.state.data.map((item: any) => {
|
||||||
|
return (
|
||||||
|
item.reportDate
|
||||||
|
);
|
||||||
|
});
|
||||||
|
labels = labels.reverse();
|
||||||
|
totalFiles = this.state.data.map((item: any) => {
|
||||||
|
return (
|
||||||
|
item.total
|
||||||
|
);
|
||||||
|
});
|
||||||
|
totalFiles = totalFiles.reverse();
|
||||||
|
activeFiles = this.state.data.map((item: any) => {
|
||||||
|
return (
|
||||||
|
item.active
|
||||||
|
);
|
||||||
|
});
|
||||||
|
activeFiles = activeFiles.reverse();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// // set the data
|
||||||
|
const data: Chart.ChartData = {
|
||||||
|
labels:
|
||||||
|
[
|
||||||
|
...labels
|
||||||
|
],
|
||||||
|
datasets: [
|
||||||
|
{
|
||||||
|
label: 'Total Files',
|
||||||
|
fill: false,
|
||||||
|
// lineTension: 0,
|
||||||
|
data: totalFiles,
|
||||||
|
backgroundColor: "rgba(0, 120, 212, 0.2)",
|
||||||
|
borderColor: "#0078d4",
|
||||||
|
borderWidth: 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Active Files',
|
||||||
|
fill: false,
|
||||||
|
// lineTension: 0,
|
||||||
|
data: activeFiles,
|
||||||
|
backgroundColor: 'rgba(232, 17, 35, 0.2)',
|
||||||
|
borderColor: '#e81123',
|
||||||
|
borderWidth: 1
|
||||||
|
}
|
||||||
|
|
||||||
|
]
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
const options: Chart.ChartOptions = {
|
||||||
|
responsive: true,
|
||||||
|
hover: {
|
||||||
|
mode: "index"
|
||||||
|
},
|
||||||
|
legend: {
|
||||||
|
display: true,
|
||||||
|
},
|
||||||
|
title: {
|
||||||
|
display: true,
|
||||||
|
text: "Number of total and active files"
|
||||||
|
},
|
||||||
|
scales: {
|
||||||
|
yAxes: [{
|
||||||
|
stacked: false
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
|
||||||
|
<Grid item xs={12}>
|
||||||
|
<ChoiceGroup
|
||||||
|
label="Pick report period"
|
||||||
|
defaultSelectedKey='7'
|
||||||
|
onChange={this._onChange}
|
||||||
|
options={[
|
||||||
|
{
|
||||||
|
key: '7',
|
||||||
|
iconProps: { iconName: 'CalendarDay' },
|
||||||
|
text: '7 days'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: '30',
|
||||||
|
iconProps: { iconName: 'CalendarDay' },
|
||||||
|
text: '30 days'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: '90',
|
||||||
|
iconProps: { iconName: 'CalendarDay' },
|
||||||
|
text: '90 days'
|
||||||
|
}
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
|
||||||
|
</Grid>
|
||||||
|
<Grid className={styles.divider} item xs={12}>
|
||||||
|
{this.state.data.length > 0 ? <Line data={data} options={options} redraw /> : ""}
|
||||||
|
</Grid>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,51 @@
|
||||||
|
import * as React from 'react';
|
||||||
|
import styles from '../GraphReports.module.scss';
|
||||||
|
import { withStyles } from '@material-ui/core/styles';
|
||||||
|
import { escape } from '@microsoft/sp-lodash-subset';
|
||||||
|
import Paper from '@material-ui/core/Paper';
|
||||||
|
import Typography from '@material-ui/core/Typography';
|
||||||
|
import Grid from '@material-ui/core/Grid';
|
||||||
|
import AppBar from '@material-ui/core/AppBar';
|
||||||
|
import TextField from '@material-ui/core/TextField';
|
||||||
|
|
||||||
|
import { MenuItem } from '@material-ui/core';
|
||||||
|
import { ServiceScope } from '@microsoft/sp-core-library';
|
||||||
|
import { css } from '@uifabric/utilities';
|
||||||
|
import GetOneDriveUsageFileCounts from './GetOneDriveUsageFileCounts/GetOneDriveUsageFileCounts';
|
||||||
|
|
||||||
|
|
||||||
|
export interface IOneDriveReportsProps {
|
||||||
|
customServiceScope: ServiceScope;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IOneDriveReportsState {
|
||||||
|
data: [];
|
||||||
|
}
|
||||||
|
|
||||||
|
export default class OneDriveReports extends React.Component<IOneDriveReportsProps, IOneDriveReportsState> {
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
constructor(props: IOneDriveReportsProps, state: IOneDriveReportsState) {
|
||||||
|
super(props);
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public render(): React.ReactElement<IOneDriveReportsProps> {
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={styles.oneDriveDashboard}>
|
||||||
|
<Grid item xs={12} className={styles.header}>
|
||||||
|
<GetOneDriveUsageFileCounts customServiceScope={this.props.customServiceScope} />
|
||||||
|
</Grid>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,175 @@
|
||||||
|
import * as React from 'react';
|
||||||
|
import Grid from '@material-ui/core/Grid';
|
||||||
|
import { CustomGraphService } from '../../../../../services';
|
||||||
|
import { ServiceScope } from '@microsoft/sp-core-library';
|
||||||
|
import { ChartPoint } from 'chart.js';
|
||||||
|
import styles from '../../GraphReports.module.scss';
|
||||||
|
import { ChoiceGroup } from 'office-ui-fabric-react/lib/ChoiceGroup';
|
||||||
|
import { Line, Pie } from 'react-chartjs-2';
|
||||||
|
|
||||||
|
|
||||||
|
export interface IGetEmailActivityUserDetailProps {
|
||||||
|
customServiceScope: ServiceScope;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IGetEmailActivityUserDetailState {
|
||||||
|
data: [];
|
||||||
|
period: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default class GetEmailActivityUserDetail extends React.Component<IGetEmailActivityUserDetailProps, IGetEmailActivityUserDetailState> {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
private _customGraphServiceInstance;
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
constructor(props: IGetEmailActivityUserDetailProps) {
|
||||||
|
super(props);
|
||||||
|
|
||||||
|
this.state = {
|
||||||
|
data: [],
|
||||||
|
period: 7
|
||||||
|
};
|
||||||
|
|
||||||
|
this._onChange = this._onChange.bind(this);
|
||||||
|
//MSGraphClient
|
||||||
|
this._customGraphServiceInstance = this.props.customServiceScope.consume(CustomGraphService.serviceKey);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public componentDidMount() {
|
||||||
|
this._customGraphServiceInstance.getEmailActivityUserDetail(this.state.period).then((reportData: any) => {
|
||||||
|
this.setState({
|
||||||
|
data: reportData.value
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
private _onChange = (ev: React.FormEvent<HTMLInputElement>, option: any): void => {
|
||||||
|
|
||||||
|
let period: number = Number(option.key);
|
||||||
|
if (period) {
|
||||||
|
this._customGraphServiceInstance.getEmailActivityUserDetail(period).then((reportData: any) => {
|
||||||
|
this.setState({
|
||||||
|
data: reportData.value,
|
||||||
|
period: period
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public render(): React.ReactElement<IGetEmailActivityUserDetailProps> {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
let chartData: any[] = [];
|
||||||
|
|
||||||
|
|
||||||
|
let assignedProducts: ChartPoint[] = [];
|
||||||
|
|
||||||
|
if (this.state.data.length > 0) {
|
||||||
|
|
||||||
|
this.state.data.map((item: any) => {
|
||||||
|
chartData.push(item.sendCount);
|
||||||
|
chartData.push(item.receiveCount);
|
||||||
|
chartData.push(item.readCount);
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// // set the data
|
||||||
|
const data: Chart.ChartData = {
|
||||||
|
labels:
|
||||||
|
[
|
||||||
|
'Sent',
|
||||||
|
'received',
|
||||||
|
'Read'
|
||||||
|
],
|
||||||
|
datasets: [
|
||||||
|
{
|
||||||
|
data: chartData,
|
||||||
|
backgroundColor: [
|
||||||
|
'#FF6384',
|
||||||
|
'#36A2EB',
|
||||||
|
'#FFCE56'
|
||||||
|
],
|
||||||
|
hoverBackgroundColor: [
|
||||||
|
'#FF6384',
|
||||||
|
'#36A2EB',
|
||||||
|
'#FFCE56'
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
]
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
const options: Chart.ChartOptions = {
|
||||||
|
responsive: true,
|
||||||
|
hover: {
|
||||||
|
mode: "index"
|
||||||
|
},
|
||||||
|
legend: {
|
||||||
|
display: true,
|
||||||
|
},
|
||||||
|
title: {
|
||||||
|
display: true,
|
||||||
|
text: "Email Activity User Detail"
|
||||||
|
},
|
||||||
|
scales: {
|
||||||
|
yAxes: [{
|
||||||
|
stacked: true
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
|
||||||
|
<Grid item xs={12}>
|
||||||
|
<ChoiceGroup
|
||||||
|
label="Pick report period"
|
||||||
|
defaultSelectedKey='7'
|
||||||
|
onChange={this._onChange}
|
||||||
|
options={[
|
||||||
|
{
|
||||||
|
key: '7',
|
||||||
|
iconProps: { iconName: 'CalendarDay' },
|
||||||
|
text: '7 days'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: '30',
|
||||||
|
iconProps: { iconName: 'CalendarDay' },
|
||||||
|
text: '30 days'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: '90',
|
||||||
|
iconProps: { iconName: 'CalendarDay' },
|
||||||
|
text: '90 days'
|
||||||
|
}
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
|
||||||
|
</Grid>
|
||||||
|
<Grid className={styles.divider} item xs={12}>
|
||||||
|
{this.state.data.length > 0 ? <Pie data={data} options={options} redraw/> : ""}
|
||||||
|
</Grid>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,52 @@
|
||||||
|
import * as React from 'react';
|
||||||
|
import styles from '../GraphReports.module.scss';
|
||||||
|
import Grid from '@material-ui/core/Grid';
|
||||||
|
import { ServiceScope } from '@microsoft/sp-core-library';
|
||||||
|
import GetEmailActivityUserDetail from './GetEmailActivityUserDetail/GetEmailActivityUserDetail';
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
export interface IOutlookReportsProps {
|
||||||
|
customServiceScope: ServiceScope;
|
||||||
|
}
|
||||||
|
export interface IOutlookReportsState {
|
||||||
|
data: any[];
|
||||||
|
period: number;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export default class OutlookReports extends React.Component<IOutlookReportsProps, IOutlookReportsState> {
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
constructor(props: IOutlookReportsProps) {
|
||||||
|
super(props);
|
||||||
|
|
||||||
|
this.handleChange = this.handleChange.bind(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public handleChange(): void {
|
||||||
|
|
||||||
|
// this.setState({
|
||||||
|
// selectedReport: event.target.value
|
||||||
|
// });
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public render(): React.ReactElement<IOutlookReportsProps> {
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={styles.sharepointDashboard}>
|
||||||
|
|
||||||
|
<Grid item xs={12} className={styles.header}>
|
||||||
|
<GetEmailActivityUserDetail customServiceScope={this.props.customServiceScope} />
|
||||||
|
</Grid>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,165 @@
|
||||||
|
import * as React from 'react';
|
||||||
|
import Grid from '@material-ui/core/Grid';
|
||||||
|
import { CustomGraphService } from '../../../../../services';
|
||||||
|
import { ServiceScope } from '@microsoft/sp-core-library';
|
||||||
|
import { ChartControl, ChartType } from '@pnp/spfx-controls-react/lib/ChartControl';
|
||||||
|
import { ChartPoint } from 'chart.js';
|
||||||
|
import { ChoiceGroup } from 'office-ui-fabric-react/lib/ChoiceGroup';
|
||||||
|
import { Line } from 'react-chartjs-2';
|
||||||
|
|
||||||
|
|
||||||
|
export interface IGetSharePointActivityFileCountsProps {
|
||||||
|
customServiceScope: ServiceScope;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IGetSharePointActivityFileCountsState {
|
||||||
|
data: [];
|
||||||
|
period: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default class GetSharePointActivityFileCounts extends React.Component<IGetSharePointActivityFileCountsProps, IGetSharePointActivityFileCountsState> {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
private _customGraphServiceInstance;
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
constructor(props: IGetSharePointActivityFileCountsProps) {
|
||||||
|
super(props);
|
||||||
|
|
||||||
|
this.state = {
|
||||||
|
data: [],
|
||||||
|
period: 7
|
||||||
|
};
|
||||||
|
|
||||||
|
this._onChange = this._onChange.bind(this);
|
||||||
|
//MSGraphClient
|
||||||
|
this._customGraphServiceInstance = this.props.customServiceScope.consume(CustomGraphService.serviceKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
public componentDidMount() {
|
||||||
|
this._customGraphServiceInstance.getSharePointActivityFileCounts(this.state.period).then((reportData: any) => {
|
||||||
|
|
||||||
|
this.setState({
|
||||||
|
data: reportData.value
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private _onChange = (ev: React.FormEvent<HTMLInputElement>, option: any): void => {
|
||||||
|
|
||||||
|
let period: number = Number(option.key);
|
||||||
|
if (period) {
|
||||||
|
this._customGraphServiceInstance.getSharePointActivityFileCounts(period).then((reportData: any) => {
|
||||||
|
this.setState({
|
||||||
|
data: reportData.value,
|
||||||
|
period: period
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public render(): React.ReactElement<IGetSharePointActivityFileCountsProps> {
|
||||||
|
|
||||||
|
let labels: any[] = [];
|
||||||
|
let chartData: ChartPoint[] = [];
|
||||||
|
let sharedInternally: ChartPoint[] = [];
|
||||||
|
|
||||||
|
if (this.state.data.length > 0) {
|
||||||
|
labels = this.state.data.map((item: any) => {
|
||||||
|
return (
|
||||||
|
item.reportDate
|
||||||
|
);
|
||||||
|
});
|
||||||
|
// labels = labels.reverse();
|
||||||
|
chartData = this.state.data.map((item: any) => {
|
||||||
|
return (
|
||||||
|
item.viewedOrEdited
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
//chartData = chartData.reverse();
|
||||||
|
|
||||||
|
sharedInternally = this.state.data.map((item: any) => {
|
||||||
|
return (
|
||||||
|
item.sharedInternally
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// set the data
|
||||||
|
const data: Chart.ChartData = {
|
||||||
|
labels:
|
||||||
|
[
|
||||||
|
...labels
|
||||||
|
],
|
||||||
|
datasets: [
|
||||||
|
{
|
||||||
|
label: 'View or Edit Files',
|
||||||
|
fill: 'start',
|
||||||
|
lineTension: 0,
|
||||||
|
data: chartData,
|
||||||
|
backgroundColor: "rgb(0, 188, 242, 0.2)",
|
||||||
|
borderColor: "rgb(0, 188, 242)",
|
||||||
|
borderWidth: 1,
|
||||||
|
showLine: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Shared Internally',
|
||||||
|
fill: false,
|
||||||
|
lineTension: 0,
|
||||||
|
data: sharedInternally,
|
||||||
|
backgroundColor: "rgb(16, 124, 16, 0.2)",
|
||||||
|
borderColor: "rgb(16, 124, 16)",
|
||||||
|
borderWidth: 1,
|
||||||
|
showLine: true
|
||||||
|
},
|
||||||
|
]
|
||||||
|
};
|
||||||
|
|
||||||
|
// set the options
|
||||||
|
const options: Chart.ChartOptions = {
|
||||||
|
legend: {
|
||||||
|
display: true,
|
||||||
|
},
|
||||||
|
title: {
|
||||||
|
display: true,
|
||||||
|
text: "Number of files by activity type"
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<Grid item xs={12}>
|
||||||
|
<ChoiceGroup
|
||||||
|
label="Pick report period"
|
||||||
|
defaultSelectedKey='7'
|
||||||
|
onChange={this._onChange}
|
||||||
|
options={[
|
||||||
|
{
|
||||||
|
key: '7',
|
||||||
|
iconProps: { iconName: 'CalendarDay' },
|
||||||
|
text: '7 days'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: '30',
|
||||||
|
iconProps: { iconName: 'CalendarDay' },
|
||||||
|
text: '30 days'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: '90',
|
||||||
|
iconProps: { iconName: 'CalendarDay' },
|
||||||
|
text: '90 days'
|
||||||
|
}
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
|
||||||
|
</Grid>
|
||||||
|
<Grid item xs={12}>
|
||||||
|
{this.state.data.length > 0 ? <Line data={data} options={options} redraw /> : ""}
|
||||||
|
</Grid>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,146 @@
|
||||||
|
import * as React from 'react';
|
||||||
|
import Grid from '@material-ui/core/Grid';
|
||||||
|
import { CustomGraphService } from '../../../../../services';
|
||||||
|
import { ServiceScope } from '@microsoft/sp-core-library';
|
||||||
|
import { ChartControl, ChartType } from '@pnp/spfx-controls-react/lib/ChartControl';
|
||||||
|
import { ChartPoint } from 'chart.js';
|
||||||
|
import { ChoiceGroup } from 'office-ui-fabric-react/lib/ChoiceGroup';
|
||||||
|
import { Bar } from 'react-chartjs-2';
|
||||||
|
|
||||||
|
|
||||||
|
export interface IGetSharePointSiteUsagePagesProps {
|
||||||
|
customServiceScope: ServiceScope;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IGetSharePointSiteUsagePagesState {
|
||||||
|
data: [];
|
||||||
|
period: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default class GetSharePointSiteUsagePages extends React.Component<IGetSharePointSiteUsagePagesProps, IGetSharePointSiteUsagePagesState> {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
private _customGraphServiceInstance;
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
constructor(props: IGetSharePointSiteUsagePagesProps) {
|
||||||
|
super(props);
|
||||||
|
|
||||||
|
this.state = {
|
||||||
|
data: [],
|
||||||
|
period: 7
|
||||||
|
};
|
||||||
|
|
||||||
|
this._onChange = this._onChange.bind(this);
|
||||||
|
//MSGraphClient
|
||||||
|
this._customGraphServiceInstance = this.props.customServiceScope.consume(CustomGraphService.serviceKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
public componentDidMount() {
|
||||||
|
this._customGraphServiceInstance.getSharePointSiteUsagePages(this.state.period).then((reportData: any) => {
|
||||||
|
|
||||||
|
this.setState({
|
||||||
|
data: reportData.value
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
}
|
||||||
|
private _onChange = (ev: React.FormEvent<HTMLInputElement>, option: any): void => {
|
||||||
|
|
||||||
|
let period: number = Number(option.key);
|
||||||
|
if (period) {
|
||||||
|
this._customGraphServiceInstance.getSharePointSiteUsagePages(period).then((reportData: any) => {
|
||||||
|
this.setState({
|
||||||
|
data: reportData.value,
|
||||||
|
period: period
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public render(): React.ReactElement<IGetSharePointSiteUsagePagesProps> {
|
||||||
|
|
||||||
|
let labels: any[] = [];
|
||||||
|
let chartData: ChartPoint[] = [];
|
||||||
|
|
||||||
|
if (this.state.data.length > 0) {
|
||||||
|
labels = this.state.data.map((item: any) => {
|
||||||
|
return (
|
||||||
|
item.reportDate
|
||||||
|
);
|
||||||
|
});
|
||||||
|
chartData = this.state.data.map((item: any) => {
|
||||||
|
return (
|
||||||
|
item.pageViewCount
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// set the data
|
||||||
|
const data: Chart.ChartData = {
|
||||||
|
|
||||||
|
labels:
|
||||||
|
[
|
||||||
|
...labels
|
||||||
|
],
|
||||||
|
datasets: [
|
||||||
|
{
|
||||||
|
label: 'Page View Count',
|
||||||
|
fill: true,
|
||||||
|
lineTension: 0,
|
||||||
|
data: chartData,
|
||||||
|
backgroundColor: 'rgba(255,99,132,0.2)',
|
||||||
|
borderColor: 'rgba(255,99,132,1)',
|
||||||
|
borderWidth: 1,
|
||||||
|
hoverBackgroundColor: 'rgba(255,99,132,0.4)',
|
||||||
|
hoverBorderColor: 'rgba(255,99,132,1)',
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
|
||||||
|
// set the options
|
||||||
|
const options: Chart.ChartOptions = {
|
||||||
|
responsive: true,
|
||||||
|
legend: {
|
||||||
|
display: false,
|
||||||
|
},
|
||||||
|
title: {
|
||||||
|
display: true,
|
||||||
|
text: "Number of pages viewed across all sites."
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<Grid item xs={12}>
|
||||||
|
<ChoiceGroup
|
||||||
|
label="Pick report period"
|
||||||
|
defaultSelectedKey='7'
|
||||||
|
onChange={this._onChange}
|
||||||
|
options={[
|
||||||
|
{
|
||||||
|
key: '7',
|
||||||
|
iconProps: { iconName: 'CalendarDay' },
|
||||||
|
text: '7 days'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: '30',
|
||||||
|
iconProps: { iconName: 'CalendarDay' },
|
||||||
|
text: '30 days'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: '90',
|
||||||
|
iconProps: { iconName: 'CalendarDay' },
|
||||||
|
text: '90 days'
|
||||||
|
}
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
|
||||||
|
</Grid>
|
||||||
|
<Grid item xs={12}>
|
||||||
|
{this.state.data.length > 0 ? <Bar data={data} options={options} redraw /> : ""}
|
||||||
|
</Grid>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,174 @@
|
||||||
|
import * as React from 'react';
|
||||||
|
import Grid from '@material-ui/core/Grid';
|
||||||
|
import { CustomGraphService } from '../../../../../services';
|
||||||
|
import { ServiceScope } from '@microsoft/sp-core-library';
|
||||||
|
import { ChartControl, ChartType } from '@pnp/spfx-controls-react/lib/ChartControl';
|
||||||
|
import { ChartPoint, ChartHoverOptions } from 'chart.js';
|
||||||
|
import styles from '../../GraphReports.module.scss';
|
||||||
|
import Divider from '@material-ui/core/Divider/Divider';
|
||||||
|
import { ChoiceGroup } from 'office-ui-fabric-react/lib/ChoiceGroup';
|
||||||
|
import { Line } from 'react-chartjs-2';
|
||||||
|
|
||||||
|
|
||||||
|
export interface IGetSharePointSiteUsageSiteCountsProps {
|
||||||
|
customServiceScope: ServiceScope;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IGetSharePointSiteUsageSiteCountsState {
|
||||||
|
data: [];
|
||||||
|
period: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default class GetSharePointSiteUsageSiteCounts extends React.Component<IGetSharePointSiteUsageSiteCountsProps, IGetSharePointSiteUsageSiteCountsState> {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
private _customGraphServiceInstance;
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
constructor(props: IGetSharePointSiteUsageSiteCountsProps) {
|
||||||
|
super(props);
|
||||||
|
|
||||||
|
this.state = {
|
||||||
|
data: [],
|
||||||
|
period: 7
|
||||||
|
};
|
||||||
|
|
||||||
|
//MSGraphClient
|
||||||
|
this._customGraphServiceInstance = this.props.customServiceScope.consume(CustomGraphService.serviceKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
public componentDidMount() {
|
||||||
|
this._customGraphServiceInstance.getSharePointSiteUsageSiteCounts(this.state.period).then((reportData: any) => {
|
||||||
|
|
||||||
|
this.setState({
|
||||||
|
data: reportData.value
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private _onChange = (ev: React.FormEvent<HTMLInputElement>, option: any): void => {
|
||||||
|
|
||||||
|
let period: number = Number(option.key);
|
||||||
|
if (period) {
|
||||||
|
this._customGraphServiceInstance.getSharePointSiteUsageSiteCounts(period).then((reportData: any) => {
|
||||||
|
this.setState({
|
||||||
|
data: reportData.value,
|
||||||
|
period: period
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public render(): React.ReactElement<IGetSharePointSiteUsageSiteCountsProps> {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
let labels: any[] = [];
|
||||||
|
let totalSites: ChartPoint[] = [];
|
||||||
|
let activeSites: ChartPoint[] = [];
|
||||||
|
if (this.state.data.length > 0) {
|
||||||
|
labels = this.state.data.map((item: any) => {
|
||||||
|
return (
|
||||||
|
item.reportDate
|
||||||
|
);
|
||||||
|
});
|
||||||
|
labels = labels.reverse();
|
||||||
|
totalSites = this.state.data.map((item: any) => {
|
||||||
|
return (
|
||||||
|
item.total
|
||||||
|
);
|
||||||
|
});
|
||||||
|
totalSites = totalSites.reverse();
|
||||||
|
activeSites = this.state.data.map((item: any) => {
|
||||||
|
return (
|
||||||
|
item.active
|
||||||
|
);
|
||||||
|
});
|
||||||
|
activeSites = activeSites.reverse();
|
||||||
|
}
|
||||||
|
|
||||||
|
// set the data
|
||||||
|
const data: Chart.ChartData = {
|
||||||
|
labels:
|
||||||
|
[
|
||||||
|
...labels
|
||||||
|
],
|
||||||
|
datasets: [
|
||||||
|
{
|
||||||
|
label: 'Total Sites',
|
||||||
|
fill: false,
|
||||||
|
// lineTension: 0,
|
||||||
|
data: totalSites,
|
||||||
|
backgroundColor: "rgba(0, 120, 212, 0.2)",
|
||||||
|
borderColor: "#0078d4",
|
||||||
|
borderWidth: 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Active Sites',
|
||||||
|
fill: false,
|
||||||
|
// lineTension: 0,
|
||||||
|
data: activeSites,
|
||||||
|
backgroundColor: 'rgba(232, 17, 35, 0.2)',
|
||||||
|
borderColor: '#e81123',
|
||||||
|
borderWidth: 1
|
||||||
|
}
|
||||||
|
|
||||||
|
]
|
||||||
|
};
|
||||||
|
|
||||||
|
const options: Chart.ChartOptions = {
|
||||||
|
responsive: true,
|
||||||
|
hover: {
|
||||||
|
mode: "index"
|
||||||
|
},
|
||||||
|
legend: {
|
||||||
|
display: true,
|
||||||
|
},
|
||||||
|
title: {
|
||||||
|
display: true,
|
||||||
|
text: "Number of total and active sites"
|
||||||
|
},
|
||||||
|
scales: {
|
||||||
|
yAxes: [{
|
||||||
|
stacked: false
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
|
||||||
|
<Grid item xs={12}>
|
||||||
|
<ChoiceGroup
|
||||||
|
label="Pick report period"
|
||||||
|
defaultSelectedKey='7'
|
||||||
|
onChange={this._onChange}
|
||||||
|
options={[
|
||||||
|
{
|
||||||
|
key: '7',
|
||||||
|
iconProps: { iconName: 'CalendarDay' },
|
||||||
|
text: '7 days'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: '30',
|
||||||
|
iconProps: { iconName: 'CalendarDay' },
|
||||||
|
text: '30 days'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: '90',
|
||||||
|
iconProps: { iconName: 'CalendarDay' },
|
||||||
|
text: '90 days'
|
||||||
|
}
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
</Grid>
|
||||||
|
|
||||||
|
<Grid className={styles.divider} item xs={12}>
|
||||||
|
{this.state.data.length > 0 ? <Line data={data} options={options} redraw /> : ""}
|
||||||
|
</Grid>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,5 @@
|
||||||
|
import { ServiceScope } from "@microsoft/sp-core-library";
|
||||||
|
|
||||||
|
export interface ISharePointReportsProps {
|
||||||
|
customServiceScope: ServiceScope;
|
||||||
|
}
|
|
@ -0,0 +1,3 @@
|
||||||
|
export interface ISharePointReportsState {
|
||||||
|
selectedReport: string;
|
||||||
|
}
|
|
@ -0,0 +1,107 @@
|
||||||
|
import * as React from 'react';
|
||||||
|
import styles from '../GraphReports.module.scss';
|
||||||
|
import { ISharePointReportsProps } from './ISharePointReportsProps';
|
||||||
|
import Grid from '@material-ui/core/Grid';
|
||||||
|
import TextField from '@material-ui/core/TextField';
|
||||||
|
import { ISharePointReportsState } from './ISharePointReportsState';
|
||||||
|
import { MenuItem } from '@material-ui/core';
|
||||||
|
import GetSharePointSiteUsagePages from './GetSharePointSiteUsagePages/GetSharePointSiteUsagePages';
|
||||||
|
import GetSharePointSiteUsageSiteCounts from './GetSharePointSiteUsageSiteCounts/GetSharePointSiteUsageSiteCounts';
|
||||||
|
import GetSharePointActivityFileCounts from './GetSharePointActivityFileCounts/GetSharePointActivityFileCounts';
|
||||||
|
|
||||||
|
export default class SharePointReports extends React.Component<ISharePointReportsProps, ISharePointReportsState> {
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
constructor(props: ISharePointReportsProps) {
|
||||||
|
super(props);
|
||||||
|
|
||||||
|
this.state = {
|
||||||
|
selectedReport: "sharePoint-site-usage"
|
||||||
|
};
|
||||||
|
this.handleChange = this.handleChange.bind(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public handleChange(event: any): void {
|
||||||
|
|
||||||
|
this.setState({
|
||||||
|
selectedReport: event.target.value
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private _renderSelectedReports(param) {
|
||||||
|
switch (param) {
|
||||||
|
case 'sharePoint-site-usage':
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<GetSharePointSiteUsagePages customServiceScope={this.props.customServiceScope} />
|
||||||
|
<GetSharePointSiteUsageSiteCounts customServiceScope={this.props.customServiceScope} />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
case 'sharepoint-activity':
|
||||||
|
return <GetSharePointActivityFileCounts customServiceScope={this.props.customServiceScope} />;
|
||||||
|
default:
|
||||||
|
return 'sharePoint-site-usage';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public render(): React.ReactElement<ISharePointReportsProps> {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
const reports = [
|
||||||
|
{
|
||||||
|
value: 'sharePoint-site-usage',
|
||||||
|
label: 'SharePoint Site Usage'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 'sharepoint-activity',
|
||||||
|
label: 'SharePoint Activity'
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={styles.sharepointDashboard}>
|
||||||
|
|
||||||
|
<Grid item xs={6}>
|
||||||
|
<TextField
|
||||||
|
id="outlined-select-currency"
|
||||||
|
select
|
||||||
|
label="Analytics Reports"
|
||||||
|
// className={classes.textField}
|
||||||
|
value={this.state.selectedReport}
|
||||||
|
onChange={(e) => this.handleChange(e)}
|
||||||
|
// SelectProps={{
|
||||||
|
// MenuProps: {
|
||||||
|
// className: classes.menu,
|
||||||
|
// },
|
||||||
|
// }}
|
||||||
|
// helperText="Please select report"
|
||||||
|
margin="normal"
|
||||||
|
variant="outlined"
|
||||||
|
>
|
||||||
|
{reports.map(option => (
|
||||||
|
<MenuItem key={option.value} value={option.value}>
|
||||||
|
{option.label}
|
||||||
|
</MenuItem>
|
||||||
|
))}
|
||||||
|
</TextField>
|
||||||
|
</Grid>
|
||||||
|
|
||||||
|
{this._renderSelectedReports(this.state.selectedReport)}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
define([], function() {
|
||||||
|
return {
|
||||||
|
"PropertyPaneDescription": "Description",
|
||||||
|
"BasicGroupName": "Group Name",
|
||||||
|
"DescriptionFieldLabel": "Description Field"
|
||||||
|
}
|
||||||
|
});
|
|
@ -0,0 +1,10 @@
|
||||||
|
declare interface IGraphReportsWebPartStrings {
|
||||||
|
PropertyPaneDescription: string;
|
||||||
|
BasicGroupName: string;
|
||||||
|
DescriptionFieldLabel: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
declare module 'GraphReportsWebPartStrings' {
|
||||||
|
const strings: IGraphReportsWebPartStrings;
|
||||||
|
export = strings;
|
||||||
|
}
|
Binary file not shown.
After Width: | Height: | Size: 3.0 KiB |
Binary file not shown.
After Width: | Height: | Size: 1.4 KiB |
Binary file not shown.
After Width: | Height: | Size: 3.0 KiB |
Binary file not shown.
After Width: | Height: | Size: 1.4 KiB |
|
@ -0,0 +1,38 @@
|
||||||
|
{
|
||||||
|
"extends": "./node_modules/@microsoft/rush-stack-compiler-3.3/includes/tsconfig-web.json",
|
||||||
|
"compilerOptions": {
|
||||||
|
"target": "es5",
|
||||||
|
"forceConsistentCasingInFileNames": true,
|
||||||
|
"module": "esnext",
|
||||||
|
"moduleResolution": "node",
|
||||||
|
"jsx": "react",
|
||||||
|
"declaration": true,
|
||||||
|
"sourceMap": true,
|
||||||
|
"experimentalDecorators": true,
|
||||||
|
"skipLibCheck": true,
|
||||||
|
"outDir": "lib",
|
||||||
|
"inlineSources": false,
|
||||||
|
"strictNullChecks": false,
|
||||||
|
"noUnusedLocals": false,
|
||||||
|
"typeRoots": [
|
||||||
|
"./node_modules/@types",
|
||||||
|
"./node_modules/@microsoft"
|
||||||
|
],
|
||||||
|
"types": [
|
||||||
|
"es6-promise",
|
||||||
|
"webpack-env"
|
||||||
|
],
|
||||||
|
"lib": [
|
||||||
|
"es5",
|
||||||
|
"dom",
|
||||||
|
"es2015.collection"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"include": [
|
||||||
|
"src/**/*.ts"
|
||||||
|
],
|
||||||
|
"exclude": [
|
||||||
|
"node_modules",
|
||||||
|
"lib"
|
||||||
|
]
|
||||||
|
}
|
|
@ -0,0 +1,30 @@
|
||||||
|
{
|
||||||
|
"extends": "@microsoft/sp-tslint-rules/base-tslint.json",
|
||||||
|
"rules": {
|
||||||
|
"class-name": false,
|
||||||
|
"export-name": false,
|
||||||
|
"forin": false,
|
||||||
|
"label-position": false,
|
||||||
|
"member-access": true,
|
||||||
|
"no-arg": false,
|
||||||
|
"no-console": false,
|
||||||
|
"no-construct": false,
|
||||||
|
"no-duplicate-variable": true,
|
||||||
|
"no-eval": false,
|
||||||
|
"no-function-expression": true,
|
||||||
|
"no-internal-module": true,
|
||||||
|
"no-shadowed-variable": true,
|
||||||
|
"no-switch-case-fall-through": true,
|
||||||
|
"no-unnecessary-semicolons": true,
|
||||||
|
"no-unused-expression": true,
|
||||||
|
"no-use-before-declare": true,
|
||||||
|
"no-with-statement": true,
|
||||||
|
"semicolon": true,
|
||||||
|
"trailing-comma": false,
|
||||||
|
"typedef": false,
|
||||||
|
"typedef-whitespace": false,
|
||||||
|
"use-named-parameter": true,
|
||||||
|
"variable-name": false,
|
||||||
|
"whitespace": false
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue