Merge pull request #1038 from ejazhussain/react-msgraph-extension
React msgraph extension
This commit is contained in:
commit
62980c4d6d
|
@ -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": {
|
||||
"version": "1.9.1",
|
||||
"libraryName": "react-msgraph-extension",
|
||||
"libraryId": "7ecf1b13-cb5b-451d-bfda-b11fa316d6c1",
|
||||
"environment": "spo",
|
||||
"packageManager": "npm",
|
||||
"isCreatingSolution": true,
|
||||
"isDomainIsolated": true,
|
||||
"componentType": "webpart"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,68 @@
|
|||
## react-msgraph-extension
|
||||
|
||||
## Summary
|
||||
This sample shows how to managed Microsoft Graph Open Extension in SPFX. This application uses **User** Resource to create Open Extension.
|
||||
|
||||
## ScreenShots
|
||||
|
||||
### Create a new Microsoft Graph Open Extension
|
||||
![Create a new Microsoft Graph Open Extension](./assets/create-graph-extension.png)
|
||||
|
||||
### Get an existing Microsoft Graph Open Extension
|
||||
![Get existing Microsoft Graph Open Extension](./assets/get-graph-extension.png)
|
||||
|
||||
|
||||
## Used SharePoint Framework Version
|
||||
![drop](https://img.shields.io/badge/version-1.9.1-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 manage Microsoft Open Graph Extension.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-extension-user-permissions.png)
|
||||
|
||||
|
||||
## Solution
|
||||
|
||||
Solution|Author(s)
|
||||
--------|---------
|
||||
react-msgraph-extension | Ejaz Hussain
|
||||
|
||||
## Version history
|
||||
|
||||
Version|Date|Comments
|
||||
-------|----|--------
|
||||
1.0|October 20, 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
|
||||
|
||||
- Create a new Open Graph Extension
|
||||
- Get an existing Graph Open Extension
|
||||
- Update an existing Open Graph Extension
|
||||
- Remove an existing Open Graph Extension
|
||||
|
||||
|
||||
<img src="https://telemetry.sharepointpnp.com/sp-dev-fx-webparts/samples/react-msgraph-extension" />
|
Binary file not shown.
After Width: | Height: | Size: 22 KiB |
Binary file not shown.
After Width: | Height: | Size: 24 KiB |
Binary file not shown.
After Width: | Height: | Size: 14 KiB |
|
@ -0,0 +1,18 @@
|
|||
{
|
||||
"$schema": "https://developer.microsoft.com/json-schemas/spfx-build/config.2.0.schema.json",
|
||||
"version": "2.0",
|
||||
"bundles": {
|
||||
"graphextension-web-part": {
|
||||
"components": [
|
||||
{
|
||||
"entrypoint": "./lib/webparts/graphextension/GraphextensionWebPart.js",
|
||||
"manifest": "./src/webparts/graphextension/GraphextensionWebPart.manifest.json"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"externals": {},
|
||||
"localizedResources": {
|
||||
"GraphextensionWebPartStrings": "lib/webparts/graphextension/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-msgraph-extension",
|
||||
"accessKey": "<!-- ACCESS KEY -->"
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
{
|
||||
"$schema": "https://developer.microsoft.com/json-schemas/spfx-build/package-solution.schema.json",
|
||||
"solution": {
|
||||
"name": "react-msgraph-extension-client-side-solution",
|
||||
"id": "7ecf1b13-cb5b-451d-bfda-b11fa316d6c1",
|
||||
"version": "1.0.0.0",
|
||||
"includeClientSideAssets": true,
|
||||
"skipFeatureDeployment": true,
|
||||
"isDomainIsolated": false,
|
||||
"webApiPermissionRequests": [
|
||||
{
|
||||
"resource": "Microsoft Graph",
|
||||
"scope": "User.ReadBasic.All"
|
||||
},
|
||||
{
|
||||
"resource": "Microsoft Graph",
|
||||
"scope": "User.ReadWrite.All"
|
||||
}
|
||||
]
|
||||
},
|
||||
"paths": {
|
||||
"zippedPackage": "solution/react-msgraph-extension.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,44 @@
|
|||
{
|
||||
"name": "react-msgraph-extension",
|
||||
"version": "0.0.1",
|
||||
"private": true,
|
||||
"main": "lib/index.js",
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "gulp bundle",
|
||||
"clean": "gulp clean",
|
||||
"test": "gulp test"
|
||||
},
|
||||
"dependencies": {
|
||||
"@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",
|
||||
"@pnp/common": "^1.3.6",
|
||||
"@types/es6-promise": "0.0.33",
|
||||
"@types/react": "16.8.8",
|
||||
"@types/react-dom": "16.8.3",
|
||||
"@types/webpack-env": "1.13.1",
|
||||
"office-ui-fabric-react": "6.189.2",
|
||||
"react": "16.8.5",
|
||||
"react-dom": "16.8.5",
|
||||
"react-toastify": "^5.4.0",
|
||||
"semantic-ui-react": "^0.88.1"
|
||||
},
|
||||
"resolutions": {
|
||||
"@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/rush-stack-compiler-2.9": "0.7.16",
|
||||
"gulp": "~3.9.1",
|
||||
"@types/chai": "3.4.34",
|
||||
"@types/mocha": "2.2.38",
|
||||
"ajv": "~5.2.2"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
export default class Constants {
|
||||
public static readonly ExtensionName = "com.ejazhussain.settings";
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1 @@
|
|||
// A file is required to be in the root of the /src directory by the TypeScript compiler
|
|
@ -0,0 +1,4 @@
|
|||
export interface IFormSchema {
|
||||
Theme?: string;
|
||||
Tags?: string;
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
export default class IPersona {
|
||||
public name: string;
|
||||
public email: string;
|
||||
public phone: string;
|
||||
public photo: string;
|
||||
|
||||
constructor(name: string, email: string, phone: string, photo: string) {
|
||||
this.name = name;
|
||||
this.email = email;
|
||||
this.phone = phone;
|
||||
this.photo = photo;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,164 @@
|
|||
import { MSGraphClient } from "@microsoft/sp-http";
|
||||
import IPersona from "./../models/IPersona";
|
||||
import Constants from '../common/constants';
|
||||
|
||||
export class MsGraphService {
|
||||
|
||||
private context = null;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
constructor(context: any) {
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
public async PatchExtension(userSettings: any): Promise<any> {
|
||||
|
||||
try {
|
||||
|
||||
let result = await this.PATCH(`/me/extensions/${Constants.ExtensionName}`, JSON.stringify(userSettings));
|
||||
|
||||
return result;
|
||||
|
||||
}
|
||||
catch (error) {
|
||||
console.log("Error in PatchExtension:", error);
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public async CreateExtension(userSettings: any): Promise<any> {
|
||||
|
||||
try {
|
||||
|
||||
let result = await this.POST(`/me/extensions`, JSON.stringify(userSettings));
|
||||
|
||||
return result;
|
||||
|
||||
}
|
||||
catch (error) {
|
||||
console.log("Error in CreateExtension:", error);
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public async GetExtension(): Promise<any> {
|
||||
|
||||
try {
|
||||
|
||||
let result = await this.GET(`/me/extensions/${Constants.ExtensionName}`);
|
||||
|
||||
return result;
|
||||
|
||||
}
|
||||
catch (error) {
|
||||
console.log("Error in GetExtension:", error);
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
public async DeleteExtension(): Promise<any> {
|
||||
|
||||
try {
|
||||
|
||||
let result = await this.DELETE(`/me/extensions/${Constants.ExtensionName}`);
|
||||
return result;
|
||||
|
||||
}
|
||||
catch (error) {
|
||||
console.log("Error in DeleteExtension:", error);
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public async GetUserProfile(): Promise<any> {
|
||||
|
||||
try {
|
||||
|
||||
let userResponse: any = await this.GET("/me");
|
||||
let photoResponse: any = await this.GET("/me/photo/$value", "blob");
|
||||
|
||||
let user = {
|
||||
name: userResponse.displayName,
|
||||
email: userResponse.mail,
|
||||
phone: userResponse.businessPhones[0],
|
||||
photo: window.URL.createObjectURL(photoResponse)
|
||||
} as IPersona;
|
||||
|
||||
return user;
|
||||
|
||||
}
|
||||
catch (error) {
|
||||
console.log("Error in GetUserProfile:", error);
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
private GET(query: string, responseType?: string): Promise<any> {
|
||||
return new Promise<any>((resolve, reject) => {
|
||||
this.context.msGraphClientFactory.getClient().then((client: MSGraphClient): void => {
|
||||
client.api(query).responseType(responseType)
|
||||
.get((error, response) => {
|
||||
if (error) {
|
||||
reject(error);
|
||||
return;
|
||||
}
|
||||
resolve(response);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
private POST(query: string, content: string) {
|
||||
return new Promise<any>((resolve, reject) => {
|
||||
this.context.msGraphClientFactory.getClient().then((client: MSGraphClient): void => {
|
||||
client.api(query)
|
||||
.post(content, (error, response) => {
|
||||
if (error) {
|
||||
reject(error);
|
||||
}
|
||||
resolve(response);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
private PATCH(query: string, content: string) {
|
||||
return new Promise<any>((resolve, reject) => {
|
||||
this.context.msGraphClientFactory.getClient().then((client: MSGraphClient): void => {
|
||||
client.api(query)
|
||||
.patch(content, (error, response, rawResponse) => {
|
||||
if (error) {
|
||||
reject(error);
|
||||
}
|
||||
resolve(rawResponse);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
private DELETE(query: string) {
|
||||
return new Promise<any>((resolve, reject) => {
|
||||
this.context.msGraphClientFactory.getClient().then((client: MSGraphClient): void => {
|
||||
client.api(query)
|
||||
.delete((error, response, rawResponse) => {
|
||||
if (error) {
|
||||
reject(error);
|
||||
}
|
||||
resolve(rawResponse);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
{
|
||||
"$schema": "https://developer.microsoft.com/json-schemas/spfx/client-side-web-part-manifest.schema.json",
|
||||
"id": "8cc62b32-de8c-4600-bdee-325dc55f587f",
|
||||
"alias": "GraphextensionWebPart",
|
||||
"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": "SpfxSolutions" },
|
||||
"title": { "default": "Graph Extension" },
|
||||
"description": { "default": "This solution provide working demo to create, get and update microsoft graph extensions" },
|
||||
"officeFabricIconFontName": "Emoji2",
|
||||
"properties": {
|
||||
"description": "graphextension"
|
||||
}
|
||||
}]
|
||||
}
|
|
@ -0,0 +1,69 @@
|
|||
import * as React from 'react';
|
||||
import * as ReactDom from 'react-dom';
|
||||
import { Version } from '@microsoft/sp-core-library';
|
||||
import {
|
||||
BaseClientSideWebPart,
|
||||
IPropertyPaneConfiguration,
|
||||
PropertyPaneTextField
|
||||
} from '@microsoft/sp-webpart-base';
|
||||
|
||||
import * as strings from 'GraphextensionWebPartStrings';
|
||||
import Graphextension from './components/Graphextension';
|
||||
import { IGraphextensionProps } from './components/IGraphextensionProps';
|
||||
import { SPComponentLoader } from '@microsoft/sp-loader';
|
||||
import { ToastContainer, toast } from 'react-toastify';
|
||||
|
||||
export interface IGraphextensionWebPartProps {
|
||||
description: string;
|
||||
}
|
||||
|
||||
export default class GraphextensionWebPart extends BaseClientSideWebPart<IGraphextensionWebPartProps> {
|
||||
|
||||
protected onInit(): Promise<void> {
|
||||
|
||||
//toast.configure()
|
||||
SPComponentLoader.loadCss("https://cdn.jsdelivr.net/npm/semantic-ui@2.4.2/dist/semantic.min.css");
|
||||
return super.onInit();
|
||||
}
|
||||
|
||||
public render(): void {
|
||||
const element: React.ReactElement<IGraphextensionProps > = React.createElement(
|
||||
Graphextension,
|
||||
{
|
||||
webpartContext: this.context
|
||||
}
|
||||
);
|
||||
|
||||
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,96 @@
|
|||
@import '~office-ui-fabric-react/dist/sass/References.scss';
|
||||
|
||||
.graphextension {
|
||||
.container {
|
||||
width: 100%;
|
||||
margin: 0px auto;
|
||||
box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.2), 0 25px 50px 0 rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.row {
|
||||
@include ms-Grid-row;
|
||||
@include ms-fontColor-neutralDark;
|
||||
//background-color: $ms-color-themeDark;
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
|
||||
.column12 {
|
||||
@include ms-Grid-col;
|
||||
@include ms-lg12;
|
||||
// @include ms-xl8;
|
||||
// @include ms-xlPush2;
|
||||
// @include ms-lgPush1;
|
||||
}
|
||||
.column10 {
|
||||
@include ms-Grid-col;
|
||||
@include ms-lg10;
|
||||
}
|
||||
.column8 {
|
||||
@include ms-Grid-col;
|
||||
@include ms-lg8;
|
||||
}
|
||||
.column6 {
|
||||
@include ms-Grid-col;
|
||||
@include ms-lg6;
|
||||
}
|
||||
.column4 {
|
||||
@include ms-Grid-col;
|
||||
@include ms-lg4;
|
||||
}
|
||||
.column2 {
|
||||
@include ms-Grid-col;
|
||||
@include ms-lg2;
|
||||
}
|
||||
|
||||
|
||||
.title {
|
||||
@include ms-font-xl;
|
||||
@include ms-fontColor-white;
|
||||
}
|
||||
|
||||
.subTitle {
|
||||
@include ms-font-l;
|
||||
@include ms-fontColor-white;
|
||||
}
|
||||
|
||||
.description {
|
||||
@include ms-font-l;
|
||||
@include ms-fontColor-white;
|
||||
}
|
||||
|
||||
.button {
|
||||
|
||||
// Our button
|
||||
text-decoration: none;
|
||||
height: 32px;
|
||||
margin:20px 0;
|
||||
min-width: 80px;
|
||||
//background-color: $ms-color-themePrimary;
|
||||
//border-color: $ms-color-themePrimary;
|
||||
//color: $ms-color-white;
|
||||
|
||||
// Basic Button
|
||||
// outline: transparent;
|
||||
// position: relative;
|
||||
// font-family: "Segoe UI WestEuropean","Segoe UI",-apple-system,BlinkMacSystemFont,Roboto,"Helvetica Neue",sans-serif;
|
||||
// -webkit-font-smoothing: antialiased;
|
||||
// font-size: $ms-font-size-m;
|
||||
// font-weight: $ms-font-weight-regular;
|
||||
// border-width: 0;
|
||||
// text-align: center;
|
||||
// cursor: pointer;
|
||||
// display: inline-block;
|
||||
// padding: 0 16px;
|
||||
|
||||
.label {
|
||||
font-weight: $ms-font-weight-semibold;
|
||||
font-size: $ms-font-size-m;
|
||||
height: 32px;
|
||||
line-height: 32px;
|
||||
margin: 0 4px;
|
||||
vertical-align: top;
|
||||
display: inline-block;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,279 @@
|
|||
import * as React from 'react';
|
||||
import styles from './Graphextension.module.scss';
|
||||
import { IGraphextensionProps } from './IGraphextensionProps';
|
||||
import { escape, isEmpty } from '@microsoft/sp-lodash-subset';
|
||||
import { MsGraphService } from '../../../services/MSGraphService';
|
||||
import { Tab, Header } from 'semantic-ui-react';
|
||||
import { TextField, MaskedTextField } from 'office-ui-fabric-react/lib/TextField';
|
||||
import { Stack, IStackProps } from 'office-ui-fabric-react/lib/Stack';
|
||||
import { IFormSchema } from '../../../models/IFormSchema';
|
||||
import { DefaultButton, PrimaryButton } from 'office-ui-fabric-react';
|
||||
import Constants from './../../../common/constants';
|
||||
import { ToastContainer, toast } from 'react-toastify';
|
||||
import { string } from 'prop-types';
|
||||
require('./ReactToastify.css');
|
||||
import { stringIsNullOrEmpty } from "@pnp/common";
|
||||
|
||||
|
||||
export interface IGraphextensionState {
|
||||
schemaForm?: IFormSchema;
|
||||
onSuccess?: Boolean;
|
||||
onFail?: Boolean;
|
||||
response?: any;
|
||||
}
|
||||
|
||||
|
||||
export default class Graphextension extends React.Component<IGraphextensionProps, IGraphextensionState> {
|
||||
|
||||
|
||||
|
||||
//MS Graph service
|
||||
private graphService: MsGraphService;
|
||||
|
||||
constructor(props: IGraphextensionProps, state: IGraphextensionState) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
schemaForm: {} as IFormSchema
|
||||
};
|
||||
this.onChangeValue = this.onChangeValue.bind(this);
|
||||
this.onCreateExtension = this.onCreateExtension.bind(this);
|
||||
this.onGetExtension = this.onGetExtension.bind(this);
|
||||
this.onPatchExtension = this.onPatchExtension.bind(this);
|
||||
this.onDeleteExtension = this.onDeleteExtension.bind(this);
|
||||
this.onTabChange = this.onTabChange.bind(this);
|
||||
this.graphService = new MsGraphService(this.props.webpartContext);
|
||||
}
|
||||
|
||||
public componentDidMount() {
|
||||
|
||||
}
|
||||
|
||||
private onChangeValue(event: any, newValue?: string) {
|
||||
this.setState({
|
||||
schemaForm: {
|
||||
...this.state.schemaForm,
|
||||
[event.target.name]: newValue
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private async onPatchExtension() {
|
||||
|
||||
|
||||
if (this.state.schemaForm != null && !isEmpty(this.state.schemaForm)) {
|
||||
|
||||
|
||||
let result = await this.graphService.GetExtension();
|
||||
|
||||
let userSettings = {
|
||||
"@odata.type": "microsoft.graph.openTypeExtension",
|
||||
"extensionName": Constants.ExtensionName,
|
||||
"Theme": !stringIsNullOrEmpty(this.state.schemaForm.Theme) ? this.state.schemaForm.Theme : result.Theme,
|
||||
"Tags": !stringIsNullOrEmpty(this.state.schemaForm.Tags) ? this.state.schemaForm.Tags : result.Tags
|
||||
};
|
||||
|
||||
//Patch Extesion
|
||||
let response = await this.graphService.PatchExtension(userSettings);
|
||||
if (response != null && response.ok) {
|
||||
toast.success("Graph Extension Successfully Updated!", {
|
||||
position: toast.POSITION.BOTTOM_CENTER
|
||||
});
|
||||
}
|
||||
else {
|
||||
toast.error("Error in patching graph extension !", {
|
||||
position: toast.POSITION.BOTTOM_CENTER
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private async onCreateExtension() {
|
||||
|
||||
|
||||
if (this.state.schemaForm != null && !isEmpty(this.state.schemaForm)) {
|
||||
|
||||
|
||||
let userSettings = {
|
||||
"@odata.type": "microsoft.graph.openTypeExtension",
|
||||
"extensionName": Constants.ExtensionName,
|
||||
"Theme": this.state.schemaForm.Theme,
|
||||
"Tags": this.state.schemaForm.Tags
|
||||
};
|
||||
|
||||
//Create Extesion
|
||||
let response = await this.graphService.CreateExtension(userSettings);
|
||||
if (response != null) {
|
||||
toast.success("Graph Extension created !", {
|
||||
position: toast.POSITION.BOTTOM_CENTER
|
||||
});
|
||||
}
|
||||
else {
|
||||
toast.error("Error in creating graph extension !", {
|
||||
position: toast.POSITION.BOTTOM_CENTER
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private async onDeleteExtension() {
|
||||
|
||||
//Delete Extesion
|
||||
let response = await this.graphService.DeleteExtension();
|
||||
if (response != null && response.ok) {
|
||||
|
||||
toast.success("Graph extension removed !", {
|
||||
position: toast.POSITION.BOTTOM_CENTER
|
||||
});
|
||||
}
|
||||
else {
|
||||
|
||||
toast.error("Error in removing graph extension !", {
|
||||
position: toast.POSITION.BOTTOM_CENTER
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private async onGetExtension() {
|
||||
|
||||
//Get Extesion
|
||||
let response = await this.graphService.GetExtension();
|
||||
if (response != null) {
|
||||
|
||||
this.setState({
|
||||
response
|
||||
});
|
||||
toast.success("Graph Extension retrieved !", {
|
||||
position: toast.POSITION.BOTTOM_CENTER
|
||||
});
|
||||
}
|
||||
else {
|
||||
this.setState({
|
||||
response: null
|
||||
});
|
||||
toast.error("Error in retrieving graph extension !", {
|
||||
position: toast.POSITION.BOTTOM_CENTER
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private onTabChange(e: any, data: any): void {
|
||||
console.log(data);
|
||||
this.setState({
|
||||
response: null,
|
||||
schemaForm: null
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
public render(): React.ReactElement<IGraphextensionProps> {
|
||||
|
||||
|
||||
const columnProps: Partial<IStackProps> = {
|
||||
tokens: { childrenGap: 15 },
|
||||
styles: { root: { width: 300 } }
|
||||
};
|
||||
const panes = [
|
||||
{
|
||||
menuItem: 'POST', render: () =>
|
||||
<Tab.Pane>
|
||||
<Header as='h3'>Create open extension</Header>
|
||||
<Stack horizontal tokens={{ childrenGap: 50 }} styles={{ root: { width: 650 } }}>
|
||||
<Stack {...columnProps}>
|
||||
<TextField
|
||||
name="Theme"
|
||||
label="Theme"
|
||||
value={this.state.schemaForm ? this.state.schemaForm.Theme : ""}
|
||||
onChange={this.onChangeValue} />
|
||||
<TextField
|
||||
name="Tags"
|
||||
label="Tags"
|
||||
value={this.state.schemaForm ? this.state.schemaForm.Tags : ""}
|
||||
onChange={this.onChangeValue} />
|
||||
</Stack>
|
||||
<Stack {...columnProps}>
|
||||
{this.state.schemaForm != null ?
|
||||
<pre>{JSON.stringify(this.state.schemaForm, null, 2)}</pre>
|
||||
: ""}
|
||||
</Stack>
|
||||
</Stack>
|
||||
<PrimaryButton className={styles.button} text="Create Extension" onClick={this.onCreateExtension} allowDisabledFocus />
|
||||
|
||||
</Tab.Pane>
|
||||
},
|
||||
{
|
||||
menuItem: 'GET', render: () =>
|
||||
|
||||
<Tab.Pane>
|
||||
<Header as='h3'>Get open extension</Header>
|
||||
<PrimaryButton className={styles.button} text="Get Extension" onClick={this.onGetExtension} allowDisabledFocus />
|
||||
|
||||
<Stack horizontal tokens={{ childrenGap: 50 }} styles={{ root: { width: 650 } }}>
|
||||
<Stack {...columnProps}>
|
||||
{this.state.response != null ? <pre>{JSON.stringify(this.state.response, null, 2)}</pre> : ""}
|
||||
</Stack>
|
||||
</Stack>
|
||||
</Tab.Pane>
|
||||
},
|
||||
{
|
||||
menuItem: 'PATCH', render: () =>
|
||||
|
||||
<Tab.Pane>
|
||||
<Header as='h3'>Patch Extension</Header>
|
||||
<Stack horizontal tokens={{ childrenGap: 50 }} styles={{ root: { width: 650 } }}>
|
||||
<Stack {...columnProps}>
|
||||
<TextField
|
||||
name="Theme"
|
||||
label="Theme"
|
||||
value={this.state.schemaForm ? this.state.schemaForm.Theme : ""}
|
||||
onChange={this.onChangeValue} />
|
||||
<TextField
|
||||
name="Tags"
|
||||
label="Tags"
|
||||
value={this.state.schemaForm ? this.state.schemaForm.Tags : ""}
|
||||
onChange={this.onChangeValue} />
|
||||
</Stack>
|
||||
<Stack {...columnProps}>
|
||||
{this.state.schemaForm != null ?
|
||||
<pre>{JSON.stringify(this.state.schemaForm, null, 2)}</pre>
|
||||
: ""}
|
||||
</Stack>
|
||||
</Stack>
|
||||
<PrimaryButton className={styles.button} text="Patch Extension" onClick={this.onPatchExtension} allowDisabledFocus />
|
||||
|
||||
|
||||
|
||||
</Tab.Pane>
|
||||
},
|
||||
{
|
||||
menuItem: 'DELETE', render: () => <Tab.Pane>
|
||||
<Header as='h3'>Delete Extension</Header>
|
||||
<PrimaryButton className={styles.button} text="Delete Extension" onClick={this.onDeleteExtension} allowDisabledFocus />
|
||||
|
||||
<Stack horizontal tokens={{ childrenGap: 50 }} styles={{ root: { width: 650 } }}>
|
||||
<Stack {...columnProps}>
|
||||
</Stack>
|
||||
</Stack>
|
||||
</Tab.Pane>
|
||||
}
|
||||
];
|
||||
return (
|
||||
<div className={styles.graphextension}>
|
||||
<div className={styles.container}>
|
||||
<div className={styles.row}>
|
||||
<div className={styles.column12}>
|
||||
<Header as='h1'>Graph Open Extension Demo</Header>
|
||||
</div>
|
||||
</div>
|
||||
<div className={styles.row}>
|
||||
<div className={styles.column12}>
|
||||
<Tab panes={panes} onTabChange={this.onTabChange}></Tab>
|
||||
<ToastContainer></ToastContainer>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
import { WebPartContext } from "@microsoft/sp-webpart-base";
|
||||
|
||||
export interface IGraphextensionProps {
|
||||
webpartContext:WebPartContext;
|
||||
}
|
|
@ -0,0 +1,624 @@
|
|||
.Toastify__toast-container {
|
||||
z-index: 9999;
|
||||
-webkit-transform: translate3d(0, 0, 9999px);
|
||||
position: fixed;
|
||||
padding: 4px;
|
||||
width: 320px;
|
||||
box-sizing: border-box;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.Toastify__toast-container--top-left {
|
||||
top: 1em;
|
||||
left: 1em;
|
||||
}
|
||||
|
||||
.Toastify__toast-container--top-center {
|
||||
top: 1em;
|
||||
left: 50%;
|
||||
margin-left: -160px;
|
||||
}
|
||||
|
||||
.Toastify__toast-container--top-right {
|
||||
top: 1em;
|
||||
right: 1em;
|
||||
}
|
||||
|
||||
.Toastify__toast-container--bottom-left {
|
||||
bottom: 1em;
|
||||
left: 1em;
|
||||
}
|
||||
|
||||
.Toastify__toast-container--bottom-center {
|
||||
bottom: 1em;
|
||||
left: 50%;
|
||||
margin-left: -160px;
|
||||
}
|
||||
|
||||
.Toastify__toast-container--bottom-right {
|
||||
bottom: 1em;
|
||||
right: 1em;
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 480px) {
|
||||
.Toastify__toast-container {
|
||||
width: 100vw;
|
||||
padding: 0;
|
||||
left: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.Toastify__toast-container--top-left,
|
||||
.Toastify__toast-container--top-center,
|
||||
.Toastify__toast-container--top-right {
|
||||
top: 0;
|
||||
}
|
||||
|
||||
.Toastify__toast-container--bottom-left,
|
||||
.Toastify__toast-container--bottom-center,
|
||||
.Toastify__toast-container--bottom-right {
|
||||
bottom: 0;
|
||||
}
|
||||
|
||||
.Toastify__toast-container--rtl {
|
||||
right: 0;
|
||||
left: initial;
|
||||
}
|
||||
}
|
||||
|
||||
.Toastify__toast {
|
||||
position: relative;
|
||||
min-height: 64px;
|
||||
box-sizing: border-box;
|
||||
margin-bottom: 1rem;
|
||||
padding: 8px;
|
||||
border-radius: 1px;
|
||||
box-shadow: 0 1px 10px 0 rgba(0, 0, 0, 0.1), 0 2px 15px 0 rgba(0, 0, 0, 0.05);
|
||||
display: -ms-flexbox;
|
||||
display: flex;
|
||||
-ms-flex-pack: justify;
|
||||
justify-content: space-between;
|
||||
max-height: 800px;
|
||||
overflow: hidden;
|
||||
font-family: sans-serif;
|
||||
cursor: pointer;
|
||||
direction: ltr;
|
||||
}
|
||||
|
||||
.Toastify__toast--rtl {
|
||||
direction: rtl;
|
||||
}
|
||||
|
||||
.Toastify__toast--default {
|
||||
background: #fff;
|
||||
color: #aaa;
|
||||
}
|
||||
|
||||
.Toastify__toast--info {
|
||||
background: #3498db;
|
||||
}
|
||||
|
||||
.Toastify__toast--success {
|
||||
background: #28a745 !important;
|
||||
}
|
||||
|
||||
.Toastify__toast--warning {
|
||||
background: #ffc107!important;
|
||||
}
|
||||
|
||||
.Toastify__toast--error {
|
||||
background: #dc3545 !important;
|
||||
}
|
||||
|
||||
.Toastify__toast-body {
|
||||
margin: auto 0;
|
||||
-ms-flex: 1;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 480px) {
|
||||
.Toastify__toast {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.Toastify__close-button {
|
||||
color: #fff;
|
||||
font-weight: bold;
|
||||
font-size: 14px;
|
||||
background: transparent;
|
||||
outline: none;
|
||||
border: none;
|
||||
padding: 0;
|
||||
cursor: pointer;
|
||||
opacity: 0.7;
|
||||
transition: 0.3s ease;
|
||||
-ms-flex-item-align: start;
|
||||
align-self: flex-start;
|
||||
}
|
||||
|
||||
.Toastify__close-button--default {
|
||||
color: #000;
|
||||
opacity: 0.3;
|
||||
}
|
||||
|
||||
.Toastify__close-button:hover,
|
||||
.Toastify__close-button:focus {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
@keyframes Toastify__trackProgress {
|
||||
0% {
|
||||
transform: scaleX(1);
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: scaleX(0);
|
||||
}
|
||||
}
|
||||
|
||||
.Toastify__progress-bar {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 5px;
|
||||
z-index: 9999;
|
||||
opacity: 0.7;
|
||||
background-color: rgba(255, 255, 255, 0.7);
|
||||
transform-origin: left;
|
||||
}
|
||||
|
||||
.Toastify__progress-bar--animated {
|
||||
animation: Toastify__trackProgress linear 1 forwards;
|
||||
}
|
||||
|
||||
.Toastify__progress-bar--controlled {
|
||||
transition: transform .2s;
|
||||
}
|
||||
|
||||
.Toastify__progress-bar--rtl {
|
||||
right: 0;
|
||||
left: initial;
|
||||
transform-origin: right;
|
||||
}
|
||||
|
||||
.Toastify__progress-bar--default {
|
||||
background: linear-gradient(to right, #4cd964, #5ac8fa, #007aff, #34aadc, #5856d6, #ff2d55);
|
||||
}
|
||||
|
||||
@keyframes Toastify__bounceInRight {
|
||||
|
||||
from,
|
||||
60%,
|
||||
75%,
|
||||
90%,
|
||||
to {
|
||||
animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
|
||||
}
|
||||
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translate3d(3000px, 0, 0);
|
||||
}
|
||||
|
||||
60% {
|
||||
opacity: 1;
|
||||
transform: translate3d(-25px, 0, 0);
|
||||
}
|
||||
|
||||
75% {
|
||||
transform: translate3d(10px, 0, 0);
|
||||
}
|
||||
|
||||
90% {
|
||||
transform: translate3d(-5px, 0, 0);
|
||||
}
|
||||
|
||||
to {
|
||||
transform: none;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes Toastify__bounceOutRight {
|
||||
20% {
|
||||
opacity: 1;
|
||||
transform: translate3d(-20px, 0, 0);
|
||||
}
|
||||
|
||||
to {
|
||||
opacity: 0;
|
||||
transform: translate3d(2000px, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes Toastify__bounceInLeft {
|
||||
|
||||
from,
|
||||
60%,
|
||||
75%,
|
||||
90%,
|
||||
to {
|
||||
animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
|
||||
}
|
||||
|
||||
0% {
|
||||
opacity: 0;
|
||||
transform: translate3d(-3000px, 0, 0);
|
||||
}
|
||||
|
||||
60% {
|
||||
opacity: 1;
|
||||
transform: translate3d(25px, 0, 0);
|
||||
}
|
||||
|
||||
75% {
|
||||
transform: translate3d(-10px, 0, 0);
|
||||
}
|
||||
|
||||
90% {
|
||||
transform: translate3d(5px, 0, 0);
|
||||
}
|
||||
|
||||
to {
|
||||
transform: none;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes Toastify__bounceOutLeft {
|
||||
20% {
|
||||
opacity: 1;
|
||||
transform: translate3d(20px, 0, 0);
|
||||
}
|
||||
|
||||
to {
|
||||
opacity: 0;
|
||||
transform: translate3d(-2000px, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes Toastify__bounceInUp {
|
||||
|
||||
from,
|
||||
60%,
|
||||
75%,
|
||||
90%,
|
||||
to {
|
||||
animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
|
||||
}
|
||||
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translate3d(0, 3000px, 0);
|
||||
}
|
||||
|
||||
60% {
|
||||
opacity: 1;
|
||||
transform: translate3d(0, -20px, 0);
|
||||
}
|
||||
|
||||
75% {
|
||||
transform: translate3d(0, 10px, 0);
|
||||
}
|
||||
|
||||
90% {
|
||||
transform: translate3d(0, -5px, 0);
|
||||
}
|
||||
|
||||
to {
|
||||
transform: translate3d(0, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes Toastify__bounceOutUp {
|
||||
20% {
|
||||
transform: translate3d(0, -10px, 0);
|
||||
}
|
||||
|
||||
40%,
|
||||
45% {
|
||||
opacity: 1;
|
||||
transform: translate3d(0, 20px, 0);
|
||||
}
|
||||
|
||||
to {
|
||||
opacity: 0;
|
||||
transform: translate3d(0, -2000px, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes Toastify__bounceInDown {
|
||||
|
||||
from,
|
||||
60%,
|
||||
75%,
|
||||
90%,
|
||||
to {
|
||||
animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
|
||||
}
|
||||
|
||||
0% {
|
||||
opacity: 0;
|
||||
transform: translate3d(0, -3000px, 0);
|
||||
}
|
||||
|
||||
60% {
|
||||
opacity: 1;
|
||||
transform: translate3d(0, 25px, 0);
|
||||
}
|
||||
|
||||
75% {
|
||||
transform: translate3d(0, -10px, 0);
|
||||
}
|
||||
|
||||
90% {
|
||||
transform: translate3d(0, 5px, 0);
|
||||
}
|
||||
|
||||
to {
|
||||
transform: none;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes Toastify__bounceOutDown {
|
||||
20% {
|
||||
transform: translate3d(0, 10px, 0);
|
||||
}
|
||||
|
||||
40%,
|
||||
45% {
|
||||
opacity: 1;
|
||||
transform: translate3d(0, -20px, 0);
|
||||
}
|
||||
|
||||
to {
|
||||
opacity: 0;
|
||||
transform: translate3d(0, 2000px, 0);
|
||||
}
|
||||
}
|
||||
|
||||
.Toastify__bounce-enter--top-left,
|
||||
.Toastify__bounce-enter--bottom-left {
|
||||
animation-name: Toastify__bounceInLeft;
|
||||
}
|
||||
|
||||
.Toastify__bounce-enter--top-right,
|
||||
.Toastify__bounce-enter--bottom-right {
|
||||
animation-name: Toastify__bounceInRight;
|
||||
}
|
||||
|
||||
.Toastify__bounce-enter--top-center {
|
||||
animation-name: Toastify__bounceInDown;
|
||||
}
|
||||
|
||||
.Toastify__bounce-enter--bottom-center {
|
||||
animation-name: Toastify__bounceInUp;
|
||||
}
|
||||
|
||||
.Toastify__bounce-exit--top-left,
|
||||
.Toastify__bounce-exit--bottom-left {
|
||||
animation-name: Toastify__bounceOutLeft;
|
||||
}
|
||||
|
||||
.Toastify__bounce-exit--top-right,
|
||||
.Toastify__bounce-exit--bottom-right {
|
||||
animation-name: Toastify__bounceOutRight;
|
||||
}
|
||||
|
||||
.Toastify__bounce-exit--top-center {
|
||||
animation-name: Toastify__bounceOutUp;
|
||||
}
|
||||
|
||||
.Toastify__bounce-exit--bottom-center {
|
||||
animation-name: Toastify__bounceOutDown;
|
||||
}
|
||||
|
||||
@keyframes Toastify__zoomIn {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: scale3d(0.3, 0.3, 0.3);
|
||||
}
|
||||
|
||||
50% {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes Toastify__zoomOut {
|
||||
from {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
50% {
|
||||
opacity: 0;
|
||||
transform: scale3d(0.3, 0.3, 0.3);
|
||||
}
|
||||
|
||||
to {
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.Toastify__zoom-enter {
|
||||
animation-name: Toastify__zoomIn;
|
||||
}
|
||||
|
||||
.Toastify__zoom-exit {
|
||||
animation-name: Toastify__zoomOut;
|
||||
}
|
||||
|
||||
@keyframes Toastify__flipIn {
|
||||
from {
|
||||
transform: perspective(400px) rotate3d(1, 0, 0, 90deg);
|
||||
animation-timing-function: ease-in;
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
40% {
|
||||
transform: perspective(400px) rotate3d(1, 0, 0, -20deg);
|
||||
animation-timing-function: ease-in;
|
||||
}
|
||||
|
||||
60% {
|
||||
transform: perspective(400px) rotate3d(1, 0, 0, 10deg);
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
80% {
|
||||
transform: perspective(400px) rotate3d(1, 0, 0, -5deg);
|
||||
}
|
||||
|
||||
to {
|
||||
transform: perspective(400px);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes Toastify__flipOut {
|
||||
from {
|
||||
transform: perspective(400px);
|
||||
}
|
||||
|
||||
30% {
|
||||
transform: perspective(400px) rotate3d(1, 0, 0, -20deg);
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
to {
|
||||
transform: perspective(400px) rotate3d(1, 0, 0, 90deg);
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.Toastify__flip-enter {
|
||||
animation-name: Toastify__flipIn;
|
||||
}
|
||||
|
||||
.Toastify__flip-exit {
|
||||
animation-name: Toastify__flipOut;
|
||||
}
|
||||
|
||||
@keyframes Toastify__slideInRight {
|
||||
from {
|
||||
transform: translate3d(110%, 0, 0);
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
to {
|
||||
transform: translate3d(0, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes Toastify__slideInLeft {
|
||||
from {
|
||||
transform: translate3d(-110%, 0, 0);
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
to {
|
||||
transform: translate3d(0, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes Toastify__slideInUp {
|
||||
from {
|
||||
transform: translate3d(0, 110%, 0);
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
to {
|
||||
transform: translate3d(0, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes Toastify__slideInDown {
|
||||
from {
|
||||
transform: translate3d(0, -110%, 0);
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
to {
|
||||
transform: translate3d(0, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes Toastify__slideOutRight {
|
||||
from {
|
||||
transform: translate3d(0, 0, 0);
|
||||
}
|
||||
|
||||
to {
|
||||
visibility: hidden;
|
||||
transform: translate3d(110%, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes Toastify__slideOutLeft {
|
||||
from {
|
||||
transform: translate3d(0, 0, 0);
|
||||
}
|
||||
|
||||
to {
|
||||
visibility: hidden;
|
||||
transform: translate3d(-110%, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes Toastify__slideOutDown {
|
||||
from {
|
||||
transform: translate3d(0, 0, 0);
|
||||
}
|
||||
|
||||
to {
|
||||
visibility: hidden;
|
||||
transform: translate3d(0, 500px, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes Toastify__slideOutUp {
|
||||
from {
|
||||
transform: translate3d(0, 0, 0);
|
||||
}
|
||||
|
||||
to {
|
||||
visibility: hidden;
|
||||
transform: translate3d(0, -500px, 0);
|
||||
}
|
||||
}
|
||||
|
||||
.Toastify__slide-enter--top-left,
|
||||
.Toastify__slide-enter--bottom-left {
|
||||
animation-name: Toastify__slideInLeft;
|
||||
}
|
||||
|
||||
.Toastify__slide-enter--top-right,
|
||||
.Toastify__slide-enter--bottom-right {
|
||||
animation-name: Toastify__slideInRight;
|
||||
}
|
||||
|
||||
.Toastify__slide-enter--top-center {
|
||||
animation-name: Toastify__slideInDown;
|
||||
}
|
||||
|
||||
.Toastify__slide-enter--bottom-center {
|
||||
animation-name: Toastify__slideInUp;
|
||||
}
|
||||
|
||||
.Toastify__slide-exit--top-left,
|
||||
.Toastify__slide-exit--bottom-left {
|
||||
animation-name: Toastify__slideOutLeft;
|
||||
}
|
||||
|
||||
.Toastify__slide-exit--top-right,
|
||||
.Toastify__slide-exit--bottom-right {
|
||||
animation-name: Toastify__slideOutRight;
|
||||
}
|
||||
|
||||
.Toastify__slide-exit--top-center {
|
||||
animation-name: Toastify__slideOutUp;
|
||||
}
|
||||
|
||||
.Toastify__slide-exit--bottom-center {
|
||||
animation-name: Toastify__slideOutDown;
|
||||
}
|
||||
|
||||
/*# sourceMappingURL=ReactToastify.css.map */
|
|
@ -0,0 +1,7 @@
|
|||
define([], function() {
|
||||
return {
|
||||
"PropertyPaneDescription": "Description",
|
||||
"BasicGroupName": "Group Name",
|
||||
"DescriptionFieldLabel": "Description Field"
|
||||
}
|
||||
});
|
10
samples/react-msgraph-extension/src/webparts/graphextension/loc/mystrings.d.ts
vendored
Normal file
10
samples/react-msgraph-extension/src/webparts/graphextension/loc/mystrings.d.ts
vendored
Normal file
|
@ -0,0 +1,10 @@
|
|||
declare interface IGraphextensionWebPartStrings {
|
||||
PropertyPaneDescription: string;
|
||||
BasicGroupName: string;
|
||||
DescriptionFieldLabel: string;
|
||||
}
|
||||
|
||||
declare module 'GraphextensionWebPartStrings' {
|
||||
const strings: IGraphextensionWebPartStrings;
|
||||
export = strings;
|
||||
}
|
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-2.9/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