Merge branch 'master' of https://github.com/SharePoint/sp-dev-fx-webparts into master
This commit is contained in:
commit
37a0a4b646
10
README.md
10
README.md
|
@ -74,10 +74,16 @@ Once the npm packages are installed, run the following command to preview your w
|
|||
gulp serve
|
||||
```
|
||||
|
||||
## Authors
|
||||
This repository's contributors are all community members who volunteered their time to share code samples. Work is done as an open source community project, which each sample contained in their own solution.
|
||||
|
||||
## Contributions
|
||||
|
||||
These samples are direct from the feature teams, SharePoint PnP core team (http://aka.ms/m365pnp) or shared by the community. We welcome your input on issues and suggestions for new samples. We do also welcome community contributions around the client-side web parts. If there's any questions around that, just let us know.
|
||||
These samples are direct from the feature teams, SharePoint PnP core team (http://aka.ms/m365pnp) or shared by the community. We welcome your input on issues and suggestions for new samples. We do also welcome community contributions around the client-side web parts. If you have any questions, just let us know.
|
||||
|
||||
Please have a look on our [Contribution Guidance](./.github/CONTRIBUTING.md) before submitting your pull requests, so that we can get your contribution processed as fast as possible. Thx.
|
||||
Please have a look on our [Contribution Guidance](./.github/CONTRIBUTING.md) before submitting your pull requests, so that we can get your contribution processed as fast as possible.
|
||||
|
||||
## Code of Conduct
|
||||
This repository has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments.
|
||||
|
||||
> Sharing is caring!
|
||||
|
|
|
@ -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,33 @@
|
|||
# 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
|
||||
*.scss.d.ts
|
|
@ -0,0 +1,12 @@
|
|||
{
|
||||
"@microsoft/generator-sharepoint": {
|
||||
"isCreatingSolution": true,
|
||||
"environment": "spo",
|
||||
"version": "1.9.1",
|
||||
"libraryName": "react-graph-cascading-managed-metadata",
|
||||
"libraryId": "cdc626ca-e9a7-4d1d-bded-a574bc5e61d0",
|
||||
"packageManager": "npm",
|
||||
"isDomainIsolated": false,
|
||||
"componentType": "webpart"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,72 @@
|
|||
# Cascading managed metadata using Graph API (beta)
|
||||
|
||||
## Summary
|
||||
|
||||
This web part shows how to use the Microsoft Graph APIs (beta) for Taxonomy to get the data.
|
||||
|
||||
### Functionality
|
||||
|
||||
![Cascading managed metadata](./assets/cmmd.gif)
|
||||
|
||||
### Termstore
|
||||
|
||||
![Term store](./assets/termstore.png)
|
||||
|
||||
## Used SharePoint Framework Version
|
||||
|
||||
![SPFx v1.11.0](https://img.shields.io/badge/SPFx-1.11.0-green.svg)
|
||||
|
||||
## Applies to
|
||||
|
||||
* [SharePoint Framework Developer](https://docs.microsoft.com/sharepoint/dev/spfx/sharepoint-framework-overview)
|
||||
* [Office 365 developer tenant](https://docs.microsoft.com/sharepoint/dev/spfx/set-up-your-developer-tenant)
|
||||
|
||||
## Pre-requisites
|
||||
|
||||
* Set up the termset structure as shown in the image above.
|
||||
* For the cities, get the required latitude and longitude.
|
||||
* Set the description of the city term as `latitude;longitude` (as highlighted for the term `London` in the image above).
|
||||
|
||||
|
||||
## Solution
|
||||
|
||||
Solution|Author(s)
|
||||
--------|---------
|
||||
react-graph-cascading-managed-metadata| Anoop Tatti ([@anooptells](https://twitter.com/anooptells))
|
||||
|
||||
## Version history
|
||||
|
||||
Version|Date|Comments
|
||||
-------|----|--------
|
||||
1.0.0|Aug 24, 2020|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`
|
||||
|
||||
## Features
|
||||
|
||||
This sample illustrates the following concepts on top of the SharePoint Framework:
|
||||
|
||||
* Get data terms using Microsoft Graph API (beta).
|
||||
* React Hooks
|
||||
* Using async / await for the async calls
|
||||
* Caching the data in session storage
|
||||
* Usage of PnP SPFx controls (Maps and Placeholder)
|
||||
* Office UI fabric components
|
||||
|
||||
### Enhancements
|
||||
|
||||
* Currently, this web part supports 2-level cascading. So there is scope to enhance this such that it supports more levels of cascading dynamically.
|
||||
* Currently, this web part reads latitude and longitude from description of the city terms. If there is a way of getting these from the custom properties of the city terms, then that needs to be implemented.
|
||||
|
||||
<img src="https://telemetry.sharepointpnp.com/sp-dev-fx-webparts/samples/react-graph-cascading-managed-metadata" />
|
Binary file not shown.
After Width: | Height: | Size: 761 KiB |
Binary file not shown.
After Width: | Height: | Size: 31 KiB |
|
@ -0,0 +1,19 @@
|
|||
{
|
||||
"$schema": "https://developer.microsoft.com/json-schemas/spfx-build/config.2.0.schema.json",
|
||||
"version": "2.0",
|
||||
"bundles": {
|
||||
"cascading-managed-metadata-web-part": {
|
||||
"components": [
|
||||
{
|
||||
"entrypoint": "./lib/webparts/cascadingManagedMetadata/CascadingManagedMetadataWebPart.js",
|
||||
"manifest": "./src/webparts/cascadingManagedMetadata/CascadingManagedMetadataWebPart.manifest.json"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"externals": {},
|
||||
"localizedResources": {
|
||||
"CascadingManagedMetadataWebPartStrings": "lib/webparts/cascadingManagedMetadata/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-cascading-managed-metadata",
|
||||
"accessKey": "<!-- ACCESS KEY -->"
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
{
|
||||
"$schema": "https://developer.microsoft.com/json-schemas/spfx-build/package-solution.schema.json",
|
||||
"solution": {
|
||||
"name": "react-graph-cascading-managed-metadata-client-side-solution",
|
||||
"id": "cdc626ca-e9a7-4d1d-bded-a574bc5e61d0",
|
||||
"version": "1.0.0.0",
|
||||
"includeClientSideAssets": true,
|
||||
"skipFeatureDeployment": true,
|
||||
"isDomainIsolated": false
|
||||
},
|
||||
"paths": {
|
||||
"zippedPackage": "solution/react-graph-cascading-managed-metadata.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,36 @@
|
|||
'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.`);
|
||||
|
||||
const argv = build.rig.getYargs().argv;
|
||||
const useCustomServe = argv['custom-serve'];
|
||||
const fs = require("fs");
|
||||
const workbenchApi = require("@microsoft/sp-webpart-workbench/lib/api");
|
||||
|
||||
if (useCustomServe) {
|
||||
build.tslintCmd.enabled = false;
|
||||
|
||||
const ensureWorkbenchSubtask = build.subTask('ensure-workbench-task', function (gulp, buildOptions, done) {
|
||||
this.log('Creating workbench.html file...');
|
||||
try {
|
||||
workbenchApi.default["/workbench"]();
|
||||
} catch (e) { }
|
||||
|
||||
done();
|
||||
});
|
||||
|
||||
build.rig.addPostBuildTask(build.task('ensure-workbench', ensureWorkbenchSubtask));
|
||||
|
||||
build.configureWebpack.mergeConfig({
|
||||
additionalConfiguration: (generatedConfiguration) => {
|
||||
fs.writeFileSync("./temp/_webpack_config.json", JSON.stringify(generatedConfiguration, null, 2));
|
||||
return generatedConfiguration;
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
build.initialize(require('gulp'));
|
||||
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,53 @@
|
|||
{
|
||||
"name": "react-graph-cascading-managed-metadata",
|
||||
"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",
|
||||
"serve": "cross-env NODE_OPTIONS=--max_old_space_size=4096 gulp bundle --custom-serve && cross-env NODE_OPTIONS=--max_old_space_size=4096 webpack-dev-server --mode development --config ./webpack.js --env.env=dev"
|
||||
},
|
||||
"dependencies": {
|
||||
"@microsoft/sp-core-library": "1.11.0",
|
||||
"@microsoft/sp-lodash-subset": "1.11.0",
|
||||
"@microsoft/sp-office-ui-fabric-core": "1.11.0",
|
||||
"@microsoft/sp-property-pane": "1.11.0",
|
||||
"@microsoft/sp-webpart-base": "1.11.0",
|
||||
"@pnp/spfx-controls-react": "1.19.0",
|
||||
"office-ui-fabric-react": "6.214.0",
|
||||
"react": "16.8.5",
|
||||
"react-dom": "16.8.5"
|
||||
},
|
||||
"resolutions": {
|
||||
"@types/react": "16.8.8"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@microsoft/rush-stack-compiler-2.9": "0.7.16",
|
||||
"@microsoft/rush-stack-compiler-3.3": "0.3.5",
|
||||
"@microsoft/sp-build-web": "1.11.0",
|
||||
"@microsoft/sp-module-interfaces": "1.11.0",
|
||||
"@microsoft/sp-tslint-rules": "1.11.0",
|
||||
"@microsoft/sp-webpart-workbench": "1.11.0",
|
||||
"@types/chai": "3.4.34",
|
||||
"@types/mocha": "2.2.38",
|
||||
"ajv": "~5.2.2",
|
||||
"cross-env": "7.0.2",
|
||||
"css-loader": "3.4.2",
|
||||
"css-modules-typescript-loader": "4.0.0",
|
||||
"del": "5.1.0",
|
||||
"fork-ts-checker-webpack-plugin": "4.1.0",
|
||||
"gulp": "~3.9.1",
|
||||
"node-sass": "4.13.1",
|
||||
"sass-loader": "8.0.2",
|
||||
"style-loader": "1.1.3",
|
||||
"ts-loader": "6.2.1",
|
||||
"webpack": "4.42.0",
|
||||
"webpack-cli": "3.3.11",
|
||||
"webpack-dev-server": "3.10.3"
|
||||
}
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
// A file is required to be in the root of the /src directory by the TypeScript compiler
|
|
@ -0,0 +1,27 @@
|
|||
{
|
||||
"$schema": "https://developer.microsoft.com/json-schemas/spfx/client-side-web-part-manifest.schema.json",
|
||||
"id": "d3ff339d-201a-4f48-860c-0a3e435c0ad6",
|
||||
"alias": "CascadingManagedMetadataWebPart",
|
||||
"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": "Cascading Managed Metadata" },
|
||||
"description": { "default": "Gets the data from termstore using Microsoft Graph" },
|
||||
"officeFabricIconFontName": "DependencyAdd",
|
||||
"properties": {
|
||||
"termSetId": ""
|
||||
}
|
||||
}]
|
||||
}
|
|
@ -0,0 +1,93 @@
|
|||
import * as React from 'react';
|
||||
import * as ReactDom from 'react-dom';
|
||||
import { Version, DisplayMode } from '@microsoft/sp-core-library';
|
||||
import {
|
||||
BaseClientSideWebPart,
|
||||
IPropertyPaneConfiguration,
|
||||
PropertyPaneTextField
|
||||
} from '@microsoft/sp-webpart-base';
|
||||
|
||||
import * as strings from 'CascadingManagedMetadataWebPartStrings';
|
||||
import CascadingManagedMetadata from './components/CascadingManagedMetadata';
|
||||
import { MSGraph } from './services/MSGraph';
|
||||
|
||||
export interface ICascadingManagedMetadataWebPartProps {
|
||||
termSetId: string;
|
||||
}
|
||||
|
||||
export default class CascadingManagedMetadataWebPart extends BaseClientSideWebPart<ICascadingManagedMetadataWebPartProps> {
|
||||
|
||||
private _placeholder = null;
|
||||
|
||||
public async render(): Promise<void> {
|
||||
await MSGraph.Init(this.context);
|
||||
let renderElement = null;
|
||||
//TODO: Use function to check if GUID?
|
||||
if (this.properties.termSetId && this.properties.termSetId.length == 36) {
|
||||
renderElement = React.createElement(
|
||||
CascadingManagedMetadata,
|
||||
{
|
||||
termSetId: this.properties.termSetId
|
||||
}
|
||||
);
|
||||
} else {
|
||||
if (this.displayMode === DisplayMode.Edit) {
|
||||
const { Placeholder } = await import(
|
||||
/* webpackChunkName: 'cascadingManagedMetadata-property-pane' */
|
||||
'@pnp/spfx-controls-react/lib/Placeholder'
|
||||
);
|
||||
this._placeholder = Placeholder;
|
||||
|
||||
const placeholder: React.ReactElement<any> = React.createElement(
|
||||
this._placeholder,
|
||||
{
|
||||
iconName: 'Edit',
|
||||
iconText: 'Configure your webpart',
|
||||
description: 'Please configure the web part.',
|
||||
buttonLabel: 'Configure',
|
||||
onConfigure: this._onConfigure.bind(this)
|
||||
}
|
||||
);
|
||||
renderElement = placeholder;
|
||||
} else {
|
||||
renderElement = React.createElement('div', null);
|
||||
}
|
||||
}
|
||||
|
||||
ReactDom.render(renderElement, this.domElement);
|
||||
}
|
||||
|
||||
private _onConfigure = () => {
|
||||
this.context.propertyPane.open();
|
||||
}
|
||||
|
||||
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('termSetId', {
|
||||
label: strings.TermSetIdFieldLabel
|
||||
})
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
};
|
||||
}
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
@import '~office-ui-fabric-react/dist/sass/References.scss';
|
||||
|
||||
.cascadingManagedMetadata {
|
||||
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
// This file is automatically generated.
|
||||
// Please do not change this file!
|
||||
interface CssExports {
|
||||
'button': string;
|
||||
'cascadingManagedMetadata': string;
|
||||
'column': string;
|
||||
'container': string;
|
||||
'description': string;
|
||||
'label': string;
|
||||
'ms-Grid': string;
|
||||
'row': string;
|
||||
'subTitle': string;
|
||||
'title': string;
|
||||
}
|
||||
export const cssExports: CssExports;
|
||||
export default cssExports;
|
|
@ -0,0 +1,99 @@
|
|||
import * as React from 'react';
|
||||
import styles from './CascadingManagedMetadata.module.scss';
|
||||
import { ICascadingManagedMetadataProps } from './ICascadingManagedMetadataProps';
|
||||
import { MSGraph } from '../services/MSGraph';
|
||||
import { ITerms } from '../../interfaces';
|
||||
|
||||
import { Dropdown, IDropdownOption } from 'office-ui-fabric-react/lib/Dropdown';
|
||||
import { MessageBar, MessageBarType } from 'office-ui-fabric-react/lib/MessageBar';
|
||||
import { Map, ICoordinates } from "@pnp/spfx-controls-react/lib/Map";
|
||||
import { MMDService } from '../services/MMDService';
|
||||
|
||||
|
||||
const CascadingManagedMetadata: React.SFC<ICascadingManagedMetadataProps> = (props) => {
|
||||
|
||||
const [countriesList, setCountriesList] = React.useState<IDropdownOption[]>([]);
|
||||
const [citiesList, setCitiesList] = React.useState<IDropdownOption[]>([]);
|
||||
const [selectedCityCoordinates, setSelectedCityCoordinates] = React.useState<string>(null);
|
||||
const [selectedCity, setSelectedCity] = React.useState<string>(null);
|
||||
const [coordinates, setCoordinates] = React.useState<ICoordinates>({ latitude: null, longitude: null });
|
||||
|
||||
React.useEffect(() => {
|
||||
_getCountries().then(countries => {
|
||||
const options: IDropdownOption[] = countries.value.map(c => ({ key: c.id, text: c.labels[0].name }));
|
||||
setCountriesList(options);
|
||||
});
|
||||
}, []);
|
||||
|
||||
//* Get the country terms i.e. level 1 children using Graph
|
||||
const _getCountries = async (): Promise<ITerms> => {
|
||||
let countries: ITerms = await MSGraph.Get(`/termStore/sets/${props.termSetId}/children`, "beta");
|
||||
return (countries);
|
||||
};
|
||||
|
||||
//* Get the city terms under a country i.e. level 2 children using Graph
|
||||
const _onCountryChange = (event: React.FormEvent<HTMLDivElement>, item: IDropdownOption): void => {
|
||||
setCoordinates({ latitude: null, longitude: null });
|
||||
setSelectedCityCoordinates(null);
|
||||
setSelectedCity(null);
|
||||
let countryTermId: string = item.key.toString();
|
||||
|
||||
MMDService.GetTermsAsDropdownOptions(`/termStore/sets/${props.termSetId}/terms/${countryTermId}/children`, countryTermId, true).then(options => {
|
||||
setCitiesList(options);
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
//* Extract co-ordinates from key of the dropdown option
|
||||
//* The key will contain the description of the term
|
||||
//* The description of the term will be of the format latitude;longitude
|
||||
const _onCityChange = (event: React.FormEvent<HTMLDivElement>, item: IDropdownOption): void => {
|
||||
setSelectedCity(item.text);
|
||||
setSelectedCityCoordinates(item.key.toString());
|
||||
const [lat, long] = item.key.toString().split(';');
|
||||
const coordinates: ICoordinates = {
|
||||
latitude: isNaN(Number(lat)) ? null : Number(lat),
|
||||
longitude: isNaN(Number(long)) ? null : Number(long)
|
||||
};
|
||||
setCoordinates(coordinates);
|
||||
};
|
||||
|
||||
return (
|
||||
<div>
|
||||
<Dropdown
|
||||
label="Country"
|
||||
placeHolder="Select a country"
|
||||
options={countriesList}
|
||||
onChange={_onCountryChange} />
|
||||
|
||||
<Dropdown
|
||||
label="City"
|
||||
selectedKey={selectedCityCoordinates}
|
||||
placeHolder="Select a city"
|
||||
options={citiesList}
|
||||
onChange={_onCityChange} />
|
||||
{
|
||||
coordinates.latitude && coordinates.longitude ?
|
||||
(
|
||||
<React.Fragment>
|
||||
<Map
|
||||
titleText={`Map of our office in ${selectedCity}`}
|
||||
coordinates={coordinates}
|
||||
zoom={15}
|
||||
enableSearch={false} />
|
||||
</React.Fragment>
|
||||
) :
|
||||
(
|
||||
<div style={{ marginTop: "15px" }}>
|
||||
<MessageBar messageBarType={MessageBarType.warning}>
|
||||
{selectedCity ? "To see the map, please check if the coordinates have been configured correctly."
|
||||
: "To see the map, please select a city."}
|
||||
</MessageBar>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default CascadingManagedMetadata;
|
|
@ -0,0 +1,3 @@
|
|||
export interface ICascadingManagedMetadataProps {
|
||||
termSetId: string;
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
define([], function() {
|
||||
return {
|
||||
"PropertyPaneDescription": "Properties",
|
||||
"BasicGroupName": "Basic",
|
||||
"TermSetIdFieldLabel": "Termset Id"
|
||||
}
|
||||
});
|
|
@ -0,0 +1,10 @@
|
|||
declare interface ICascadingManagedMetadataWebPartStrings {
|
||||
PropertyPaneDescription: string;
|
||||
BasicGroupName: string;
|
||||
TermSetIdFieldLabel: string;
|
||||
}
|
||||
|
||||
declare module 'CascadingManagedMetadataWebPartStrings' {
|
||||
const strings: ICascadingManagedMetadataWebPartStrings;
|
||||
export = strings;
|
||||
}
|
|
@ -0,0 +1,65 @@
|
|||
import { ITerms, IOption } from "../../interfaces";
|
||||
import { MSGraph } from "./MSGraph";
|
||||
import { IDropdownOption } from "office-ui-fabric-react/lib/Dropdown";
|
||||
|
||||
export class MMDService {
|
||||
|
||||
private static _sessionStorageKey: string = "CMMD_Options";
|
||||
|
||||
public static async GetTermsAsDropdownOptions(apiUrl: string, parent: string, tryFromCache: boolean): Promise<IDropdownOption[]> {
|
||||
|
||||
let options: IDropdownOption[] = [];
|
||||
if (tryFromCache) {
|
||||
let optionsFromCache: IOption[] = this._fetchFromSessionStorge();
|
||||
if (optionsFromCache.length) {
|
||||
let requiredOptionsFromCache = optionsFromCache.filter(o => o.parent == parent);
|
||||
if (requiredOptionsFromCache.length) {
|
||||
options = requiredOptionsFromCache.map(r => ({ key: r.key, text: r.text }));
|
||||
return options;
|
||||
}
|
||||
}
|
||||
}
|
||||
//Get data using Graph
|
||||
return await this._getTermsAsDropdownOptionsUsingGraph(apiUrl, parent);
|
||||
}
|
||||
|
||||
private static async _getTermsAsDropdownOptionsUsingGraph(apiUrl: string, parent: string): Promise<IDropdownOption[]> {
|
||||
let terms: ITerms = await MSGraph.Get(apiUrl, "beta");
|
||||
if (terms.value) {
|
||||
//* Set key as description of the term
|
||||
//* Description will be of the format latitude;longitude
|
||||
//* This will be used to render maps
|
||||
const options: IDropdownOption[] = terms.value.map(t => ({
|
||||
key: t.descriptions[0] ? t.descriptions[0].description : t.id,
|
||||
text: t.labels[0].name }));
|
||||
let optionsToStoreInCache: IOption[] = options.map(o => ({
|
||||
key: o.key.toString(),
|
||||
text: o.text,
|
||||
parent
|
||||
}));
|
||||
let optionsFromCache: IOption[] = this._fetchFromSessionStorge();
|
||||
optionsToStoreInCache = [...optionsFromCache, ...optionsToStoreInCache];
|
||||
window.sessionStorage.setItem(this._sessionStorageKey, JSON.stringify(optionsToStoreInCache));
|
||||
console.log("Options added in cache");
|
||||
return options;
|
||||
} else {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
private static _fetchFromSessionStorge(): IOption[] {
|
||||
let result: IOption[] = [];
|
||||
let stringResult: string = window.sessionStorage.getItem(this._sessionStorageKey);
|
||||
if (stringResult) {
|
||||
try {
|
||||
result = JSON.parse(stringResult);
|
||||
if(result.length) {
|
||||
console.log("Fetched options from cache");
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,90 @@
|
|||
//* Thank you Mikael Svenson
|
||||
|
||||
import { WebPartContext } from '@microsoft/sp-webpart-base';
|
||||
import { GraphError } from '@microsoft/microsoft-graph-client';
|
||||
import { MSGraphClient } from '@microsoft/sp-http';
|
||||
|
||||
export class MSGraph {
|
||||
private static _graphClient: MSGraphClient;
|
||||
public static async Init(context: WebPartContext) {
|
||||
this._graphClient = await context.msGraphClientFactory.getClient();
|
||||
}
|
||||
|
||||
public static async Get(apiUrl: string, version: string = "v1.0", selectProperties?: string[], expandProperties?: string[], filter?: string): Promise<any> {
|
||||
var p = new Promise<string>(async (resolve, reject) => {
|
||||
let query = this._graphClient.api(apiUrl).version(version);
|
||||
if (selectProperties && selectProperties.length > 0) {
|
||||
query = query.select(selectProperties);
|
||||
}
|
||||
if (filter && filter.length > 0) {
|
||||
query = query.filter(filter);
|
||||
}
|
||||
if (expandProperties && expandProperties.length > 0) {
|
||||
query = query.expand(expandProperties);
|
||||
}
|
||||
|
||||
let callback = (error: GraphError, response: any, rawResponse?: any) => {
|
||||
if (error) {
|
||||
reject(error);
|
||||
} else {
|
||||
resolve(response);
|
||||
}
|
||||
};
|
||||
await query.get(callback);
|
||||
});
|
||||
return p;
|
||||
}
|
||||
|
||||
public static async Patch(apiUrl: string, version: string = "v1.0", content: any): Promise<any> {
|
||||
var p = new Promise<string>(async (resolve, reject) => {
|
||||
if (typeof (content) === "object") {
|
||||
content = JSON.stringify(content);
|
||||
}
|
||||
|
||||
let query = this._graphClient.api(apiUrl).version(version);
|
||||
let callback = (error: GraphError, _response: any, rawResponse?: any) => {
|
||||
if (error) {
|
||||
reject(error);
|
||||
} else {
|
||||
resolve();
|
||||
}
|
||||
};
|
||||
await query.update(content, callback);
|
||||
});
|
||||
return p;
|
||||
}
|
||||
|
||||
public static async Post(apiUrl: string, version: string = "v1.0", content: any): Promise<any> {
|
||||
var p = new Promise<string>(async (resolve, reject) => {
|
||||
if (typeof (content) === "object") {
|
||||
content = JSON.stringify(content);
|
||||
}
|
||||
|
||||
let query = this._graphClient.api(apiUrl).version(version);
|
||||
let callback = (error: GraphError, response: any, rawResponse?: any) => {
|
||||
if (error) {
|
||||
reject(error);
|
||||
} else {
|
||||
resolve(response);
|
||||
}
|
||||
};
|
||||
await query.post(content, callback);
|
||||
});
|
||||
return p;
|
||||
}
|
||||
|
||||
public static async Delete(apiUrl: string, version: string = "v1.0"): Promise<any> {
|
||||
var p = new Promise<string>(async (resolve, reject) => {
|
||||
let query = this._graphClient.api(apiUrl).version(version);
|
||||
let callback = (error: GraphError, response: any, rawResponse?: any) => {
|
||||
if (error) {
|
||||
reject(error);
|
||||
} else {
|
||||
resolve(response);
|
||||
}
|
||||
};
|
||||
await query.delete(callback);
|
||||
});
|
||||
return p;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
export interface IDescription {
|
||||
description: string;
|
||||
languageTag: string;
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
export interface ILabel {
|
||||
name: string;
|
||||
isDefault: boolean;
|
||||
languageTag: string;
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
export interface IOption {
|
||||
key: string;
|
||||
text: string;
|
||||
parent: string;
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
import { IDescription } from "./IDescription";
|
||||
import { ILabel } from "./ILabel";
|
||||
|
||||
export interface ITerm {
|
||||
id: string;
|
||||
createdDateTime: Date;
|
||||
lastModifiedDateTime: Date;
|
||||
labels: ILabel[];
|
||||
descriptions: IDescription[];
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
import { ITerm } from "./ITerm";
|
||||
|
||||
export interface ITerms {
|
||||
value: ITerm[];
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
export { ILabel } from './ILabel';
|
||||
export { IDescription } from './IDescription';
|
||||
export { ITerm } from './ITerm';
|
||||
export { ITerms } from './ITerms';
|
||||
export { IOption } from './IOption';
|
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
|
||||
}
|
||||
}
|
|
@ -0,0 +1,259 @@
|
|||
const path = require("path");
|
||||
const fs = require("fs");
|
||||
const webpack = require("webpack");
|
||||
const resolve = require("path").resolve;
|
||||
const CertStore = require("@microsoft/gulp-core-build-serve/lib/CertificateStore");
|
||||
const CertificateStore = CertStore.CertificateStore || CertStore.default;
|
||||
const ForkTsCheckerWebpackPlugin = require("fork-ts-checker-webpack-plugin");
|
||||
const del = require("del");
|
||||
const port = 4321;
|
||||
const host = "https://localhost:" + port;
|
||||
|
||||
///
|
||||
// Transforms define("<guid>", ...) to web part specific define("<web part id_version", ...)
|
||||
// the same approach is used inside copyAssets SPFx build step
|
||||
///
|
||||
class DynamicLibraryPlugin {
|
||||
constructor(options) {
|
||||
this.opitons = options;
|
||||
}
|
||||
|
||||
apply(compiler) {
|
||||
compiler.hooks.emit.tap("DynamicLibraryPlugin", compilation => {
|
||||
for (const assetId in this.opitons.modulesMap) {
|
||||
const moduleMap = this.opitons.modulesMap[assetId];
|
||||
|
||||
if (compilation.assets[assetId]) {
|
||||
const rawValue = compilation.assets[assetId].children[0]._value;
|
||||
compilation.assets[assetId].children[0]._value = rawValue.replace(this.opitons.libraryName, moduleMap.id + "_" + moduleMap.version);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
// Removes *.module.scss.ts on the first execution in order prevent conflicts with *.module.scss.d.ts
|
||||
// generated by css-modules-typescript-loader
|
||||
///
|
||||
class ClearCssModuleDefinitionsPlugin {
|
||||
constructor(options) {
|
||||
this.options = options || {};
|
||||
}
|
||||
|
||||
apply(compiler) {
|
||||
compiler.hooks.done.tap("FixStylesPlugin", stats => {
|
||||
if (!this.options.deleted) {
|
||||
|
||||
setTimeout(() => {
|
||||
del.sync(["src/**/*.module.scss.ts"]);
|
||||
}, 3000);
|
||||
|
||||
this.options.deleted = true;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
let baseConfig = {
|
||||
target: "web",
|
||||
mode: "development",
|
||||
devtool: "source-map",
|
||||
resolve: {
|
||||
extensions: [".ts", ".tsx", ".js"],
|
||||
modules: ["node_modules"]
|
||||
},
|
||||
context: path.resolve(__dirname),
|
||||
module: {
|
||||
rules: [
|
||||
{
|
||||
test: /\.tsx?$/,
|
||||
loader: "ts-loader",
|
||||
options: {
|
||||
transpileOnly: true,
|
||||
compilerOptions: {
|
||||
declarationMap: false
|
||||
}
|
||||
},
|
||||
exclude: /node_modules/
|
||||
},
|
||||
{
|
||||
use: [{
|
||||
loader: "@microsoft/loader-cased-file",
|
||||
options: {
|
||||
name: "[name:lower]_[hash].[ext]"
|
||||
}
|
||||
}],
|
||||
test: /\.(jpe?g|png|woff|eot|ttf|svg|gif|dds)$/i
|
||||
},
|
||||
{
|
||||
use: [{
|
||||
loader: "html-loader"
|
||||
}],
|
||||
test: /\.html$/
|
||||
},
|
||||
{
|
||||
test: /\.css$/,
|
||||
use: [
|
||||
{
|
||||
loader: "@microsoft/loader-load-themed-styles",
|
||||
options: {
|
||||
async: true
|
||||
}
|
||||
},
|
||||
{
|
||||
loader: "css-loader"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
test: function (fileName) {
|
||||
return fileName.endsWith(".module.scss"); // scss modules support
|
||||
},
|
||||
use: [
|
||||
{
|
||||
loader: "@microsoft/loader-load-themed-styles",
|
||||
options: {
|
||||
async: true
|
||||
}
|
||||
},
|
||||
"css-modules-typescript-loader",
|
||||
{
|
||||
loader: "css-loader",
|
||||
options: {
|
||||
modules: {
|
||||
localIdentName: "[local]_[hash:base64:8]"
|
||||
}
|
||||
}
|
||||
}, // translates CSS into CommonJS
|
||||
"sass-loader" // compiles Sass to CSS, using Node Sass by default
|
||||
]
|
||||
},
|
||||
{
|
||||
test: function (fileName) {
|
||||
return !fileName.endsWith(".module.scss") && fileName.endsWith(".scss"); // just regular .scss
|
||||
},
|
||||
use: [
|
||||
{
|
||||
loader: "@microsoft/loader-load-themed-styles",
|
||||
options: {
|
||||
async: true
|
||||
}
|
||||
},
|
||||
"css-loader", // translates CSS into CommonJS
|
||||
"sass-loader" // compiles Sass to CSS, using Node Sass by default
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
plugins: [
|
||||
new ForkTsCheckerWebpackPlugin({
|
||||
tslint: true
|
||||
}),
|
||||
new ClearCssModuleDefinitionsPlugin(),
|
||||
new webpack.DefinePlugin({
|
||||
"process.env.NODE_ENV": JSON.stringify(process.env.NODE_ENV),
|
||||
"process.env.DEBUG": JSON.stringify(true),
|
||||
"DEBUG": JSON.stringify(true)
|
||||
})],
|
||||
devServer: {
|
||||
hot: false,
|
||||
contentBase: resolve(__dirname),
|
||||
publicPath: host + "/dist/",
|
||||
host: "localhost",
|
||||
port: port,
|
||||
disableHostCheck: true,
|
||||
historyApiFallback: true,
|
||||
open: true,
|
||||
writeToDisk: false,
|
||||
openPage: host + "/temp/workbench.html",
|
||||
stats: {
|
||||
preset: "errors-only",
|
||||
colors: true,
|
||||
chunks: false,
|
||||
modules: false,
|
||||
assets: false
|
||||
},
|
||||
proxy: { // url re-write for resources to be served directly from src folder
|
||||
"/lib/**/loc/*.js": {
|
||||
target: host,
|
||||
pathRewrite: { "^/lib": "/src" },
|
||||
secure: false
|
||||
}
|
||||
},
|
||||
headers: {
|
||||
"Access-Control-Allow-Origin": "*",
|
||||
},
|
||||
https: {
|
||||
cert: CertificateStore.instance.certificateData,
|
||||
key: CertificateStore.instance.keyData
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
const createConfig = function () {
|
||||
// remove old css module TypeScript definitions
|
||||
del.sync(["dist/*.js", "dist/*.map"]);
|
||||
|
||||
// we need only "externals", "output" and "entry" from the original webpack config
|
||||
let originalWebpackConfig = require("./temp/_webpack_config.json");
|
||||
baseConfig.externals = originalWebpackConfig.externals;
|
||||
baseConfig.output = originalWebpackConfig.output;
|
||||
|
||||
baseConfig.entry = getEntryPoints(originalWebpackConfig.entry);
|
||||
|
||||
baseConfig.output.publicPath = host + "/dist/";
|
||||
|
||||
const manifest = require("./temp/manifests.json");
|
||||
const modulesMap = {};
|
||||
const originalEntries = Object.keys(originalWebpackConfig.entry);
|
||||
|
||||
for (const jsModule of manifest) {
|
||||
if (jsModule.loaderConfig
|
||||
&& jsModule.loaderConfig.entryModuleId
|
||||
&& originalEntries.indexOf(jsModule.loaderConfig.entryModuleId) !== -1) {
|
||||
modulesMap[jsModule.loaderConfig.entryModuleId + ".js"] = {
|
||||
id: jsModule.id,
|
||||
version: jsModule.version
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
baseConfig.plugins.push(new DynamicLibraryPlugin({
|
||||
modulesMap: modulesMap,
|
||||
libraryName: originalWebpackConfig.output.library
|
||||
}));
|
||||
|
||||
return baseConfig;
|
||||
}
|
||||
|
||||
function getEntryPoints(entry) {
|
||||
// fix: ".js" entry needs to be ".ts"
|
||||
// also replaces the path form /lib/* to /src/*
|
||||
let newEntry = {};
|
||||
let libSearchRegexp;
|
||||
if (path.sep === "/") {
|
||||
libSearchRegexp = /\/lib\//gi;
|
||||
} else {
|
||||
libSearchRegexp = /\\lib\\/gi;
|
||||
}
|
||||
|
||||
const srcPathToReplace = path.sep + "src" + path.sep;
|
||||
|
||||
for (const key in entry) {
|
||||
let entryPath = entry[key];
|
||||
if (entryPath.indexOf("bundle-entries") === -1) {
|
||||
entryPath = entryPath.replace(libSearchRegexp, srcPathToReplace).slice(0, -3) + ".ts";
|
||||
} else {
|
||||
// replace paths and extensions in bundle file
|
||||
let bundleContent = fs.readFileSync(entryPath).toString();
|
||||
bundleContent = bundleContent.replace(libSearchRegexp, srcPathToReplace).replace(/\.js/gi, ".ts");
|
||||
fs.writeFileSync(entryPath, bundleContent);
|
||||
}
|
||||
newEntry[key] = entryPath;
|
||||
}
|
||||
|
||||
return newEntry;
|
||||
}
|
||||
|
||||
module.exports = createConfig();
|
|
@ -25,6 +25,8 @@ Each Site has a symbol indicate if it is SharePoint Site, Group, Group and OnDri
|
|||
If the Group has a microsoft team associated and user has permissions to access the symbol of teams will be displayed.
|
||||
|
||||
|
||||
|
||||
|
||||
![MySites](./assets/MySites.gif)
|
||||
|
||||
![MySites](./assets/Screenshot%202020-08-06%20at%2013.50.51.png)
|
||||
|
@ -56,6 +58,7 @@ react-my-sites|João Mendes
|
|||
Version|Date|Comments
|
||||
-------|----|--------
|
||||
1.0.0|August 6, 2020|Initial release
|
||||
1.0.1|August 29, 2020|Additional updates
|
||||
|
||||
## Disclaimer
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
"solution": {
|
||||
"name": "react-my-sites-client-side-solution",
|
||||
"id": "ad28b382-886b-4b2a-9646-92de8a0b1d13",
|
||||
"version": "1.0.0.0",
|
||||
"version": "1.0.1.0",
|
||||
"includeClientSideAssets": true,
|
||||
"skipFeatureDeployment": true,
|
||||
"isDomainIsolated": false,
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "react-my-sites",
|
||||
"version": "0.0.1",
|
||||
"version": "1.0.1",
|
||||
"private": true,
|
||||
"main": "lib/index.js",
|
||||
"engines": {
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
export enum Filters {
|
||||
"SharePoint",
|
||||
"All",
|
||||
"Group",
|
||||
"OneDrive",
|
||||
"All",
|
||||
"SharePoint",
|
||||
"Site"
|
||||
}
|
||||
|
|
|
@ -49,7 +49,8 @@ export const useUserSites = () => {
|
|||
const getUserSites = async (
|
||||
searchString?: string,
|
||||
itemsPerPage?: number,
|
||||
filter?: Filters
|
||||
filter?: Filters,
|
||||
site?:string
|
||||
): Promise<SearchResults> => {
|
||||
let searchResults: SearchResults = null;
|
||||
let _filter: string = "";
|
||||
|
@ -62,12 +63,17 @@ export const useUserSites = () => {
|
|||
_filter = ` GroupId:a* OR GroupId:b* OR GroupId:c* OR GroupId:d* OR GroupId:e* OR GroupId:f* OR GroupId:g* OR GroupId:h* OR GroupId:i* OR GroupId:j* OR GroupId:k* OR GroupId:l* OR GroupId:m* OR GroupId:n* OR GroupId:o* OR GroupId:p* OR GroupId:q* OR GroupId:r* OR GroupId:s* OR GroupId:t* OR GroupId:u* OR GroupId:v* OR GroupId:w* OR GroupId:x* OR GroupId:y* OR GroupId:z* OR GroupId:1* OR GroupId:2* OR GroupId:3* OR GroupId:4* OR GroupId:5* OR GroupId:6* OR GroupId:7* OR GroupId:8* OR GroupId:9* OR GroupId:0*`;
|
||||
break;
|
||||
case Filters.OneDrive:
|
||||
_filter = " SiteGroup:Onedrive";
|
||||
_filter = " WebTemplate:SPSPERS"; // OneDrive
|
||||
// _filter = " SiteGroup:Onedrive";
|
||||
break;
|
||||
case Filters.SharePoint:
|
||||
_filter =
|
||||
" SiteGroup:SharePoint AND NOT(GroupId:b* OR GroupId:c* OR GroupId:d* OR GroupId:e* OR GroupId:f* OR GroupId:g* OR GroupId:h* OR GroupId:i* OR GroupId:j* OR GroupId:k* OR GroupId:l* OR GroupId:m* OR GroupId:n* OR GroupId:o* OR GroupId:p* OR GroupId:q* OR GroupId:r* OR GroupId:s* OR GroupId:t* OR GroupId:u* OR GroupId:v* OR GroupId:w* OR GroupId:x* OR GroupId:y* OR GroupId:z* OR GroupId:1* OR GroupId:2* OR GroupId:3* OR GroupId:4* OR GroupId:5* OR GroupId:6* OR GroupId:7* OR GroupId:8* OR GroupId:9* OR GroupId:0*)";
|
||||
break;
|
||||
case Filters.Site:
|
||||
_filter = `Path:${site}`;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
const q = SearchQueryBuilder(
|
||||
|
@ -79,6 +85,11 @@ export const useUserSites = () => {
|
|||
Direction: SortDirection.Descending,
|
||||
})
|
||||
.selectProperties(
|
||||
"ParentLink",
|
||||
"SPSiteURL",
|
||||
"SiteID",
|
||||
"SPWebUrl",
|
||||
"WebId",
|
||||
"SiteLogo",
|
||||
"SiteClosed",
|
||||
"RelatedHubSites",
|
||||
|
@ -94,8 +105,10 @@ export const useUserSites = () => {
|
|||
"ModifiedById",
|
||||
"LastModifiedTime",
|
||||
"OriginalPath",
|
||||
"Path",
|
||||
"Title",
|
||||
"Created"
|
||||
"Created",
|
||||
"WebTemplate"
|
||||
);
|
||||
const results = await sp.search(q);
|
||||
searchResults = results; // set the current results
|
||||
|
@ -103,5 +116,47 @@ export const useUserSites = () => {
|
|||
return searchResults;
|
||||
};
|
||||
|
||||
return { getUserSites, checkGroupHasTeam };
|
||||
// Get User Sites
|
||||
const getUserWebs = async (
|
||||
|
||||
): Promise<SearchResults> => {
|
||||
let searchResults: SearchResults = null;
|
||||
const q = SearchQueryBuilder(
|
||||
`(contentclass:STS_Web)`
|
||||
)
|
||||
.rowLimit(100000)
|
||||
.selectProperties(
|
||||
"ParentLink",
|
||||
"SPSiteURL",
|
||||
"SiteID",
|
||||
"SPWebUrl",
|
||||
"WebId",
|
||||
"SiteLogo",
|
||||
"SiteClosed",
|
||||
"RelatedHubSites",
|
||||
"IsHubSite",
|
||||
"GroupId",
|
||||
"RelatedGroupId",
|
||||
"SiteGroup",
|
||||
"Author",
|
||||
"CreatedBy",
|
||||
"CreatedById",
|
||||
"AccountName",
|
||||
"ModifiedBy",
|
||||
"ModifiedById",
|
||||
"LastModifiedTime",
|
||||
"OriginalPath",
|
||||
"Path",
|
||||
"Title",
|
||||
"Created",
|
||||
"WebTemplate"
|
||||
);
|
||||
const results = await sp.search(q);
|
||||
searchResults = results; // set the current results
|
||||
console.log("webs",searchResults);
|
||||
return searchResults;
|
||||
};
|
||||
|
||||
|
||||
return { getUserSites, checkGroupHasTeam, getUserWebs };
|
||||
};
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import { IContextualMenuProps } from "office-ui-fabric-react";
|
||||
|
||||
export interface IMySitesState {
|
||||
sites: any[];
|
||||
|
@ -9,4 +10,7 @@ export interface IMySitesState {
|
|||
totalPages:number;
|
||||
searchValue:string;
|
||||
currentFilter?:number;
|
||||
currentFilterName?:string;
|
||||
currentSelectedSite?:string;
|
||||
filterMenuProps: IContextualMenuProps;
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import * as React from "react";
|
||||
import { Filters} from '../../../../Entities/EnumFilters';
|
||||
import { Filters } from "../../../../Entities/EnumFilters";
|
||||
import "./paginationOverride.module.scss";
|
||||
import { IMySitesProps } from "./IMySitesProps";
|
||||
import { escape } from "@microsoft/sp-lodash-subset";
|
||||
|
@ -18,6 +18,7 @@ import {
|
|||
IContextualMenuItem,
|
||||
FontIcon,
|
||||
Label,
|
||||
ContextualMenuItemType,
|
||||
} from "office-ui-fabric-react";
|
||||
import { WebPartTitle } from "@pnp/spfx-controls-react";
|
||||
import { useUserSites } from "../../../../Hooks/useUserSites";
|
||||
|
@ -31,7 +32,11 @@ import _ from "lodash";
|
|||
import { MSGraphClient } from "@microsoft/sp-http";
|
||||
|
||||
let _searchResults: SearchResults = null;
|
||||
let _msGraphClient:MSGraphClient = undefined;
|
||||
let _msGraphClient: MSGraphClient = undefined;
|
||||
let _filterMenuProps: IContextualMenuProps = undefined;
|
||||
|
||||
// Get Hook functions
|
||||
const { getUserSites, getUserWebs } = useUserSites();
|
||||
|
||||
export const MySites: React.FunctionComponent<IMySitesProps> = (
|
||||
props: IMySitesProps
|
||||
|
@ -47,12 +52,11 @@ export const MySites: React.FunctionComponent<IMySitesProps> = (
|
|||
},
|
||||
webPartTile: {
|
||||
fontWeight: 500,
|
||||
marginBottom: 20
|
||||
marginBottom: 20,
|
||||
},
|
||||
});
|
||||
// Document Card Styles
|
||||
|
||||
|
||||
// state
|
||||
const [state, setState] = React.useState<IMySitesState>({
|
||||
errorMessage: "",
|
||||
|
@ -61,32 +65,40 @@ export const MySites: React.FunctionComponent<IMySitesProps> = (
|
|||
hasError: false,
|
||||
title: props.title,
|
||||
currentPage: 1,
|
||||
totalPages: 50,
|
||||
totalPages: 0,
|
||||
searchValue: "",
|
||||
currentFilter: Filters.All,
|
||||
currentFilterName: "All",
|
||||
currentSelectedSite: undefined,
|
||||
filterMenuProps: undefined,
|
||||
});
|
||||
|
||||
const filterIcon: IIconProps = { iconName: "Filter" };
|
||||
|
||||
// Get Hook functions
|
||||
const { getUserSites } = useUserSites();
|
||||
|
||||
// get User Sites
|
||||
const _getUserSites = async (
|
||||
searchString?: string,
|
||||
currentFilter?: Filters
|
||||
currentFilter?: Filters,
|
||||
currentFilterName?:string,
|
||||
site?:string
|
||||
) => {
|
||||
try {
|
||||
console.log('tiles var', props.themeVariant);
|
||||
setState({ ...state, isLoading: true });
|
||||
const { itemsPerPage } = props;
|
||||
const searchResults = await getUserSites(searchString, itemsPerPage, currentFilter);
|
||||
const searchResults = await getUserSites(
|
||||
searchString,
|
||||
itemsPerPage,
|
||||
currentFilter,
|
||||
site
|
||||
);
|
||||
_searchResults = searchResults;
|
||||
let _totalPages: number = searchResults.TotalRows / itemsPerPage;
|
||||
const _modulus: number = searchResults.TotalRows % itemsPerPage;
|
||||
_totalPages =
|
||||
_modulus > 0 ? toInteger(_totalPages) + 1 : toInteger(_totalPages);
|
||||
|
||||
setState({
|
||||
...state,
|
||||
searchValue: "",
|
||||
currentPage: 1,
|
||||
totalPages: _totalPages,
|
||||
|
@ -95,7 +107,11 @@ export const MySites: React.FunctionComponent<IMySitesProps> = (
|
|||
hasError: false,
|
||||
errorMessage: "",
|
||||
sites: _searchResults.PrimarySearchResults,
|
||||
currentFilter: currentFilter
|
||||
currentFilter: currentFilter,
|
||||
currentSelectedSite: site,
|
||||
currentFilterName: currentFilterName,
|
||||
// tslint:disable-next-line: no-use-before-declare
|
||||
filterMenuProps: _filterMenuProps,
|
||||
});
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
|
@ -108,110 +124,154 @@ export const MySites: React.FunctionComponent<IMySitesProps> = (
|
|||
}
|
||||
};
|
||||
|
||||
const _Filtersites = async (filter: string) => {
|
||||
setState({ ...state, isLoading: true });
|
||||
let _filteredSites: any[] = [];
|
||||
const _Filtersites = async (filter: string, site?:string) => {
|
||||
|
||||
switch (filter) {
|
||||
case "All":
|
||||
setState({...state,currentFilter: Filters.All});
|
||||
await _getUserSites('', Filters.All);
|
||||
await _getUserSites("", Filters.All, "All");
|
||||
break;
|
||||
case "Groups":
|
||||
setState({...state,currentFilter: Filters.Group});
|
||||
await _getUserSites('', Filters.Group);
|
||||
await _getUserSites("", Filters.Group, "Groups");
|
||||
break;
|
||||
case "OneDrive":
|
||||
setState({...state,currentFilter: Filters.OneDrive});
|
||||
await _getUserSites('', Filters.OneDrive);
|
||||
await _getUserSites("", Filters.OneDrive, "OneDrive");
|
||||
break;
|
||||
case "SharePoint":
|
||||
setState({...state,currentFilter: Filters.SharePoint});
|
||||
await _getUserSites('', Filters.SharePoint);
|
||||
await _getUserSites("", Filters.SharePoint, "SharePoint");
|
||||
break;
|
||||
default:
|
||||
setState({ ...state, isLoading: false });
|
||||
break;
|
||||
await _getUserSites("", Filters.Site, filter, site);
|
||||
}
|
||||
};
|
||||
|
||||
const filterMenuProps: IContextualMenuProps = {
|
||||
items: [
|
||||
{
|
||||
key: "0",
|
||||
text: "All",
|
||||
iconProps: { iconName: "ThumbnailView" },
|
||||
onClick: (
|
||||
ev:
|
||||
| React.MouseEvent<HTMLElement, MouseEvent>
|
||||
| React.KeyboardEvent<HTMLElement>,
|
||||
item: IContextualMenuItem
|
||||
) => {
|
||||
_Filtersites(item.text);
|
||||
},
|
||||
},
|
||||
{
|
||||
key: "1",
|
||||
text: "SharePoint",
|
||||
iconProps: { iconName: "SharepointAppIcon16" },
|
||||
onClick: (
|
||||
ev:
|
||||
| React.MouseEvent<HTMLElement, MouseEvent>
|
||||
| React.KeyboardEvent<HTMLElement>,
|
||||
item: IContextualMenuItem
|
||||
) => {
|
||||
_Filtersites(item.text);
|
||||
},
|
||||
},
|
||||
{
|
||||
key: "2",
|
||||
text: "Groups",
|
||||
iconProps: { iconName: "Group" },
|
||||
onClick: (
|
||||
ev:
|
||||
| React.MouseEvent<HTMLElement, MouseEvent>
|
||||
| React.KeyboardEvent<HTMLElement>,
|
||||
item: IContextualMenuItem
|
||||
) => {
|
||||
_Filtersites(item.text);
|
||||
},
|
||||
},
|
||||
{
|
||||
key: "3",
|
||||
text: "OneDrive",
|
||||
iconProps: { iconName: "onedrive" },
|
||||
onClick: (
|
||||
ev:
|
||||
| React.MouseEvent<HTMLElement, MouseEvent>
|
||||
| React.KeyboardEvent<HTMLElement>,
|
||||
item: IContextualMenuItem
|
||||
) => {
|
||||
_Filtersites(item.text);
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
// useEffect component did mount or modified
|
||||
React.useEffect(() => {
|
||||
(async () => {
|
||||
_msGraphClient = await props.context.msGraphClientFactory.getClient();
|
||||
await _getUserSites("",state.currentFilter);
|
||||
|
||||
const _sitesWithSubSties = await getUserWebs();
|
||||
console.log("subsites", _sitesWithSubSties);
|
||||
const _uniqweb = _.uniqBy(
|
||||
_sitesWithSubSties.PrimarySearchResults,
|
||||
"ParentLink"
|
||||
);
|
||||
|
||||
|
||||
_filterMenuProps = {
|
||||
|
||||
items: [
|
||||
{
|
||||
key: "0",
|
||||
text: "All",
|
||||
iconProps: { iconName: "ThumbnailView" },
|
||||
onClick: (
|
||||
ev:
|
||||
| React.MouseEvent<HTMLElement, MouseEvent>
|
||||
| React.KeyboardEvent<HTMLElement>,
|
||||
item: IContextualMenuItem
|
||||
) => {
|
||||
_Filtersites(item.text);
|
||||
},
|
||||
},
|
||||
{
|
||||
key: "1",
|
||||
text: "SharePoint",
|
||||
iconProps: { iconName: "SharepointAppIcon16" },
|
||||
onClick: (
|
||||
ev:
|
||||
| React.MouseEvent<HTMLElement, MouseEvent>
|
||||
| React.KeyboardEvent<HTMLElement>,
|
||||
item: IContextualMenuItem
|
||||
) => {
|
||||
_Filtersites(item.text);
|
||||
},
|
||||
},
|
||||
{
|
||||
key: "2",
|
||||
text: "Groups",
|
||||
iconProps: { iconName: "Group" },
|
||||
onClick: (
|
||||
ev:
|
||||
| React.MouseEvent<HTMLElement, MouseEvent>
|
||||
| React.KeyboardEvent<HTMLElement>,
|
||||
item: IContextualMenuItem
|
||||
) => {
|
||||
_Filtersites(item.text);
|
||||
},
|
||||
},
|
||||
{
|
||||
key: "3",
|
||||
text: "OneDrive",
|
||||
iconProps: { iconName: "onedrive" },
|
||||
onClick: (
|
||||
ev:
|
||||
| React.MouseEvent<HTMLElement, MouseEvent>
|
||||
| React.KeyboardEvent<HTMLElement>,
|
||||
item: IContextualMenuItem
|
||||
) => {
|
||||
_Filtersites(item.text);
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
|
||||
if (_sitesWithSubSties.PrimarySearchResults.length > 0){
|
||||
_filterMenuProps.items.push(
|
||||
{
|
||||
key: 'sites',
|
||||
itemType: ContextualMenuItemType.Header,
|
||||
text: 'Sites with Sub Sites',
|
||||
itemProps: {
|
||||
lang: 'en-us',
|
||||
},
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
// Add Site Collections with sub
|
||||
for (const web of _uniqweb) {
|
||||
// tslint:disable-next-line: no-use-before-declare
|
||||
const _lastHasPosition: number = (web.ParentLink as string).lastIndexOf(
|
||||
"/"
|
||||
);
|
||||
const _siteName: string = (web.ParentLink as string).substring(
|
||||
_lastHasPosition + 1
|
||||
);
|
||||
// tslint:disable-next-line: no-use-before-declare
|
||||
_filterMenuProps.items.push({
|
||||
key: web.ParentLink,
|
||||
text: _siteName,
|
||||
iconProps: { iconName: "DrillExpand" },
|
||||
onClick: (
|
||||
ev:
|
||||
| React.MouseEvent<HTMLElement, MouseEvent>
|
||||
| React.KeyboardEvent<HTMLElement>,
|
||||
item: IContextualMenuItem
|
||||
) => {
|
||||
// tslint:disable-next-line: no-use-before-declare
|
||||
_Filtersites(item.text, item.key);
|
||||
},
|
||||
});
|
||||
}
|
||||
await _getUserSites("", state.currentFilter, state.currentFilterName);
|
||||
})();
|
||||
}, [props.title, props.itemsPerPage]);
|
||||
|
||||
// On Search Sites
|
||||
const _onSearch = async (value: string) => {
|
||||
await _getUserSites(value,state.currentFilter);
|
||||
await _getUserSites(value, state.currentFilter,state.currentFilterName, state.currentSelectedSite);
|
||||
};
|
||||
|
||||
// On Search Sites
|
||||
const _onClear = async (ev: any) => {
|
||||
await _getUserSites("",state.currentFilter);
|
||||
await _getUserSites("", state.currentFilter,state.currentFilterName, state.currentSelectedSite);
|
||||
};
|
||||
|
||||
|
||||
// Render component
|
||||
if (state.hasError) { // render message error
|
||||
// Render component
|
||||
if (state.hasError) {
|
||||
// render message error
|
||||
return (
|
||||
<MessageBar messageBarType={MessageBarType.error}>
|
||||
{state.errorMessage}
|
||||
|
@ -229,9 +289,8 @@ export const MySites: React.FunctionComponent<IMySitesProps> = (
|
|||
themeVariant={props.themeVariant}
|
||||
updateProperty={props.updateProperty}
|
||||
className={stylesComponent.webPartTile}
|
||||
|
||||
/>
|
||||
<Stack horizontal horizontalAlign="end" tokens={{ childrenGap: 10 }}>
|
||||
<Stack horizontal verticalAlign="center" horizontalAlign="end" wrap tokens={{ childrenGap: 5 }}>
|
||||
<SearchBox
|
||||
placeholder="Search my sites"
|
||||
underlined={true}
|
||||
|
@ -246,10 +305,11 @@ export const MySites: React.FunctionComponent<IMySitesProps> = (
|
|||
/>
|
||||
<CommandButton
|
||||
iconProps={filterIcon}
|
||||
text={Filters[state.currentFilter]}
|
||||
menuProps={filterMenuProps}
|
||||
text={state.currentFilterName}
|
||||
menuProps={state.filterMenuProps}
|
||||
disabled={false}
|
||||
checked={true}
|
||||
title="filter"
|
||||
/>
|
||||
</Stack>
|
||||
{state.isLoading ? (
|
||||
|
@ -259,29 +319,40 @@ export const MySites: React.FunctionComponent<IMySitesProps> = (
|
|||
></Spinner>
|
||||
) : (
|
||||
<>
|
||||
{ // has sites ?
|
||||
|
||||
state.sites.length > 0 ?
|
||||
<div className={stylesComponent.containerTiles}>
|
||||
{state.sites.map((site:any, i: number) => {
|
||||
return (
|
||||
<SiteTile
|
||||
site={site}
|
||||
msGraphClient={_msGraphClient}
|
||||
themeVariant={props.themeVariant}
|
||||
></SiteTile>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
:
|
||||
<>
|
||||
<Stack horizontal verticalAlign="center" horizontalAlign="center" tokens={{childrenGap: 20}} styles={{root: {marginTop: 50}}}>
|
||||
<FontIcon iconName="Tiles" style={{fontSize: 48}}></FontIcon>
|
||||
<Label styles={{root:{fontSize: 26}}}>No Sites Found </Label>
|
||||
</Stack>
|
||||
</>
|
||||
|
||||
}
|
||||
{
|
||||
// has sites ?
|
||||
state.sites.length > 0 ? (
|
||||
<div className={stylesComponent.containerTiles}>
|
||||
{state.sites.map((site: any, i: number) => {
|
||||
return (
|
||||
<SiteTile
|
||||
site={site}
|
||||
msGraphClient={_msGraphClient}
|
||||
themeVariant={props.themeVariant}
|
||||
></SiteTile>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
) : (
|
||||
<>
|
||||
<Stack
|
||||
horizontal
|
||||
verticalAlign="center"
|
||||
horizontalAlign="center"
|
||||
tokens={{ childrenGap: 20 }}
|
||||
styles={{ root: { marginTop: 50 } }}
|
||||
>
|
||||
<FontIcon
|
||||
iconName="Tiles"
|
||||
style={{ fontSize: 48 }}
|
||||
></FontIcon>
|
||||
<Label styles={{ root: { fontSize: 26 } }}>
|
||||
No Sites Found{" "}
|
||||
</Label>
|
||||
</Stack>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
{state.totalPages > 1 && (
|
||||
<>
|
||||
|
@ -296,7 +367,7 @@ export const MySites: React.FunctionComponent<IMySitesProps> = (
|
|||
color="primary"
|
||||
count={state.totalPages}
|
||||
page={state.currentPage}
|
||||
onChange={async (event:any, page:number) => {
|
||||
onChange={async (event: any, page: number) => {
|
||||
const rs = await _searchResults.getPage(page);
|
||||
_searchResults = rs;
|
||||
setState({
|
||||
|
|
|
@ -94,10 +94,9 @@ export const SiteTile: React.FunctionComponent<ISiteTileProps> = (
|
|||
fontSize: 20,
|
||||
color: props.themeVariant ? props.themeVariant.palette.themePrimary: 'white',
|
||||
marginTop: 8,
|
||||
marginRight: 16,
|
||||
marginRight: 7,
|
||||
},
|
||||
};
|
||||
|
||||
const DocumentCardActivityStyles: Partial<IDocumentCardActivityStyles> = {
|
||||
root: { paddingBottom: 0 },
|
||||
};
|
||||
|
@ -107,7 +106,6 @@ export const SiteTile: React.FunctionComponent<ISiteTileProps> = (
|
|||
|
||||
};
|
||||
|
||||
|
||||
let _activityUserEmail: string = "N/A";
|
||||
let _activityUser: string = "N/A";
|
||||
let _activityDate: string = "N/A";
|
||||
|
@ -124,6 +122,8 @@ export const SiteTile: React.FunctionComponent<ISiteTileProps> = (
|
|||
OriginalPath,
|
||||
CreatedBy,
|
||||
Created,
|
||||
IsHubSite,
|
||||
WebTemplate
|
||||
|
||||
} = props.site;
|
||||
|
||||
|
@ -208,7 +208,7 @@ export const SiteTile: React.FunctionComponent<ISiteTileProps> = (
|
|||
previewImages={[
|
||||
{
|
||||
previewImageSrc:
|
||||
SiteGroup == "OneDrive" ? _siteLogoOndrive : _siteLogoSP,
|
||||
WebTemplate == "SPSPERS" ? _siteLogoOndrive : _siteLogoSP,
|
||||
width: 68,
|
||||
height: 68,
|
||||
imageFit: ImageFit.cover,
|
||||
|
@ -229,15 +229,22 @@ export const SiteTile: React.FunctionComponent<ISiteTileProps> = (
|
|||
/>
|
||||
|
||||
)}
|
||||
{GroupId && (
|
||||
|
||||
{GroupId && GroupId !== "00000000-0000-0000-0000-000000000000" && ( // (is groupId = undefined or 000000-0000-0000-0000000000000 guid) this is showned is some personal drives
|
||||
<Icon
|
||||
styles={groupIconStyles}
|
||||
iconName="Group"
|
||||
title="Office 365 Group"
|
||||
></Icon>
|
||||
)}
|
||||
|
||||
{SiteGroup == "OneDrive" && (
|
||||
{IsHubSite == "true" && (
|
||||
<Icon
|
||||
styles={groupIconStyles}
|
||||
iconName="DrillExpand"
|
||||
title="is Hub Site"
|
||||
></Icon>
|
||||
)}
|
||||
{WebTemplate == "SPSPERS" && (
|
||||
<Icon
|
||||
styles={groupIconStyles}
|
||||
iconName="onedrive"
|
||||
|
|
|
@ -1,30 +1,29 @@
|
|||
{
|
||||
"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
|
||||
}
|
||||
}
|
||||
{
|
||||
"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-with-statement": true,
|
||||
"semicolon": true,
|
||||
"trailing-comma": false,
|
||||
"typedef": false,
|
||||
"typedef-whitespace": false,
|
||||
"use-named-parameter": true,
|
||||
"variable-name": false,
|
||||
"whitespace": false
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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,8 @@
|
|||
{
|
||||
"@microsoft/generator-sharepoint": {
|
||||
"version": "1.4.0",
|
||||
"libraryName": "react-upgrade-me",
|
||||
"libraryId": "c32676e6-9536-4db1-b59f-62c7be23f38b",
|
||||
"environment": "onprem"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,50 @@
|
|||
# Upgrade Me
|
||||
|
||||
## Summary
|
||||
|
||||
This web part does nothing, really. It is intended to be used to test upgrading SPFx web parts and demonstrating incompatibility issues between versions of SPFx and Node.js.
|
||||
|
||||
![picture of the web part in action](./assets/react-upgrade-me.png)
|
||||
|
||||
## Used SharePoint Framework Version
|
||||
|
||||
![1.4.1](https://img.shields.io/badge/version-1.4.1-green.svg)
|
||||
|
||||
## Applies to
|
||||
|
||||
* [SharePoint Framework](https://docs.microsoft.com/sharepoint/dev/spfx/sharepoint-framework-overview)
|
||||
* [Office 365 tenant](https://docs.microsoft.com/sharepoint/dev/spfx/set-up-your-development-environment)
|
||||
|
||||
|
||||
## Prerequisites
|
||||
|
||||
You'll need the [CLI for Microsoft 365](https://pnp.github.io/cli-microsoft365/) in order to perform an upgrade.
|
||||
|
||||
## Solution
|
||||
|
||||
Solution|Author(s)
|
||||
--------|---------
|
||||
react-upgrade-me | Hugo Bernier ([Tahoe Ninjas](https://tahoeninjas.blog), [@bernierh](https://twitter.com/bernierh))
|
||||
|
||||
## Version history
|
||||
|
||||
Version|Date|Comments
|
||||
-------|----|--------
|
||||
1.0|August 26, 2020|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
|
||||
|
||||
Not applicable.
|
||||
|
||||
|
||||
## Features
|
||||
|
||||
This web part really does nothing. It is intended to be used with the CLI for Microsoft 365 [SPFx Project Upgrade](https://pnp.github.io/cli-microsoft365/cmd/spfx/project/project-upgrade/).
|
||||
|
||||
<img src="https://telemetry.sharepointpnp.com/sp-dev-fx-webparts/samples/react-upgrade-me" />
|
Binary file not shown.
After Width: | Height: | Size: 63 KiB |
|
@ -0,0 +1,18 @@
|
|||
{
|
||||
"version": "2.0",
|
||||
"$schema": "https://dev.office.com/json-schemas/spfx-build/config.2.0.schema.json",
|
||||
"externals": {},
|
||||
"localizedResources": {
|
||||
"UpgradeMeWebPartStrings": "lib/webparts/upgradeMe/loc/{locale}.js"
|
||||
},
|
||||
"bundles": {
|
||||
"upgrade-me-web-part": {
|
||||
"components": [
|
||||
{
|
||||
"entrypoint": "./lib/webparts/upgradeMe/UpgradeMeWebPart.js",
|
||||
"manifest": "./src/webparts/upgradeMe/UpgradeMeWebPart.manifest.json"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
{
|
||||
"$schema": "https://dev.office.com/json-schemas/spfx-build/copy-assets.schema.json",
|
||||
"deployCdnPath": "temp/deploy"
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
"$schema": "https://dev.office.com/json-schemas/spfx-build/deploy-azure-storage.schema.json",
|
||||
"workingDir": "./temp/deploy/",
|
||||
"account": "<!-- STORAGE ACCOUNT NAME -->",
|
||||
"container": "react-upgrade-me",
|
||||
"accessKey": "<!-- ACCESS KEY -->"
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
{
|
||||
"$schema": "https://dev.office.com/json-schemas/spfx-build/package-solution.schema.json",
|
||||
"solution": {
|
||||
"name": "react-upgrade-me-client-side-solution",
|
||||
"id": "c32676e6-9536-4db1-b59f-62c7be23f38b",
|
||||
"version": "1.0.0.0",
|
||||
"includeClientSideAssets": true
|
||||
},
|
||||
"paths": {
|
||||
"zippedPackage": "solution/react-upgrade-me.sppkg"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
{
|
||||
"$schema": "https://dev.office.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,45 @@
|
|||
{
|
||||
"$schema": "https://dev.office.com/json-schemas/core-build/tslint.schema.json",
|
||||
// Display errors as warnings
|
||||
"displayAsWarning": true,
|
||||
// The TSLint task may have been configured with several custom lint rules
|
||||
// before this config file is read (for example lint rules from the tslint-microsoft-contrib
|
||||
// project). If true, this flag will deactivate any of these rules.
|
||||
"removeExistingRules": true,
|
||||
// When true, the TSLint task is configured with some default TSLint "rules.":
|
||||
"useDefaultConfigAsBase": false,
|
||||
// Since removeExistingRules=true and useDefaultConfigAsBase=false, there will be no lint rules
|
||||
// which are active, other than the list of rules below.
|
||||
"lintConfig": {
|
||||
// Opt-in to Lint rules which help to eliminate bugs in JavaScript
|
||||
"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-case": true,
|
||||
"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,
|
||||
"valid-typeof": true,
|
||||
"variable-name": false,
|
||||
"whitespace": false
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
{
|
||||
"$schema": "https://dev.office.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,34 @@
|
|||
{
|
||||
"name": "react-upgrade-me",
|
||||
"version": "0.0.1",
|
||||
"private": true,
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "gulp bundle",
|
||||
"clean": "gulp clean",
|
||||
"test": "gulp test"
|
||||
},
|
||||
"dependencies": {
|
||||
"@microsoft/sp-core-library": "1.4.1",
|
||||
"@microsoft/sp-lodash-subset": "1.4.1",
|
||||
"@microsoft/sp-office-ui-fabric-core": "1.4.1",
|
||||
"@microsoft/sp-webpart-base": "1.4.1",
|
||||
"@types/react": "15.6.6",
|
||||
"@types/react-addons-shallow-compare": "0.14.17",
|
||||
"@types/react-dom": "15.5.6",
|
||||
"@types/webpack-env": ">=1.12.1 <1.14.0",
|
||||
"react": "15.6.2",
|
||||
"react-dom": "15.4.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@microsoft/sp-build-web": "1.4.1",
|
||||
"@microsoft/sp-module-interfaces": "1.4.1",
|
||||
"@microsoft/sp-webpart-workbench": "~1.1.0",
|
||||
"@types/chai": ">=3.4.34 <3.6.0",
|
||||
"@types/mocha": ">=2.2.33 <2.6.0",
|
||||
"ajv": "5.2.2",
|
||||
"gulp": "~3.9.1"
|
||||
}
|
||||
}
|
File diff suppressed because one or more lines are too long
|
@ -0,0 +1,57 @@
|
|||
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 'UpgradeMeWebPartStrings';
|
||||
import UpgradeMe from './components/UpgradeMe';
|
||||
import { IUpgradeMeProps } from './components/IUpgradeMeProps';
|
||||
|
||||
export interface IUpgradeMeWebPartProps {
|
||||
description: string;
|
||||
}
|
||||
|
||||
export default class UpgradeMeWebPart extends BaseClientSideWebPart<IUpgradeMeWebPartProps> {
|
||||
|
||||
public render(): void {
|
||||
|
||||
const element: React.ReactElement<IUpgradeMeProps > = React.createElement(
|
||||
UpgradeMe,
|
||||
{
|
||||
description: this.properties.description
|
||||
}
|
||||
);
|
||||
|
||||
ReactDom.render(element, 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,3 @@
|
|||
export interface IUpgradeMeProps {
|
||||
description: string;
|
||||
}
|
|
@ -0,0 +1,75 @@
|
|||
@import '~@microsoft/sp-office-ui-fabric-core/dist/sass/SPFabricCore.scss';
|
||||
|
||||
.upgradeMe {
|
||||
.container {
|
||||
max-width: 700px;
|
||||
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-white;
|
||||
background-color: $ms-color-themeDark;
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.column {
|
||||
@include ms-Grid-col;
|
||||
@include ms-lg10;
|
||||
@include ms-xl8;
|
||||
@include ms-xlPush2;
|
||||
@include ms-lgPush1;
|
||||
}
|
||||
|
||||
.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;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.button {
|
||||
// Our button
|
||||
text-decoration: none;
|
||||
height: 32px;
|
||||
|
||||
// Primary Button
|
||||
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,22 @@
|
|||
import * as React from 'react';
|
||||
import styles from './UpgradeMe.module.scss';
|
||||
import { IUpgradeMeProps } from './IUpgradeMeProps';
|
||||
import { escape } from '@microsoft/sp-lodash-subset';
|
||||
|
||||
export default class UpgradeMe extends React.Component<IUpgradeMeProps, {}> {
|
||||
public render(): React.ReactElement<IUpgradeMeProps> {
|
||||
return (
|
||||
<div className={ styles.upgradeMe }>
|
||||
<div className={ styles.container }>
|
||||
<div className={ styles.row }>
|
||||
<div className={ styles.column }>
|
||||
<span className={ styles.title }>Upgrade Me!</span>
|
||||
<p className={ styles.subTitle }>This web part does nothing. It is intended to be used to demonstrate how to upgrade SPFx solutions and to demonstrate incompatibilities between versions of SPFx/Node.js</p>
|
||||
<p className={ styles.description }>{escape(this.props.description)}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
define([], function() {
|
||||
return {
|
||||
"PropertyPaneDescription": "You should use this web part to test upgrading solutions.",
|
||||
"BasicGroupName": "Group Name",
|
||||
"DescriptionFieldLabel": "Description Field"
|
||||
}
|
||||
});
|
|
@ -0,0 +1,10 @@
|
|||
declare interface IUpgradeMeWebPartStrings {
|
||||
PropertyPaneDescription: string;
|
||||
BasicGroupName: string;
|
||||
DescriptionFieldLabel: string;
|
||||
}
|
||||
|
||||
declare module 'UpgradeMeWebPartStrings' {
|
||||
const strings: IUpgradeMeWebPartStrings;
|
||||
export = strings;
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"target": "es5",
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"module": "commonjs",
|
||||
"jsx": "react",
|
||||
"declaration": true,
|
||||
"sourceMap": true,
|
||||
"experimentalDecorators": true,
|
||||
"skipLibCheck": true,
|
||||
"typeRoots": [
|
||||
"./node_modules/@types",
|
||||
"./node_modules/@microsoft"
|
||||
],
|
||||
"types": [
|
||||
"es6-promise",
|
||||
"webpack-env"
|
||||
],
|
||||
"lib": [
|
||||
"es5",
|
||||
"dom",
|
||||
"es2015.collection"
|
||||
]
|
||||
}
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
/**
|
||||
* @file index.ts
|
||||
* Type definitions for Microsoft SPFx projects
|
||||
*/
|
||||
|
||||
/**
|
||||
* Global definition for UNIT_TEST builds.
|
||||
* Code that is wrapped inside an if (UNIT_TEST) {...}
|
||||
* block will not be included in the final bundle when the
|
||||
* --ship flag is specified.
|
||||
*/
|
||||
declare const UNIT_TEST: boolean;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
* Global definition for NPM package builds
|
||||
*/
|
||||
declare const NPM_BUILD: boolean;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
* Global defintion for SharePoint Online builds
|
||||
*/
|
||||
declare const DATACENTER: boolean;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
* Global definition for BUILD_NUMBER
|
||||
*/
|
||||
declare const BUILD_NUMBER: string;
|
|
@ -0,0 +1 @@
|
|||
/// <reference path="@ms/odsp.d.ts" />
|
|
@ -2,7 +2,7 @@
|
|||
"@microsoft/generator-sharepoint": {
|
||||
"isCreatingSolution": true,
|
||||
"environment": "spo",
|
||||
"version": "1.10.0",
|
||||
"version": "1.11.0",
|
||||
"libraryName": "react-visio",
|
||||
"libraryId": "0ad401f1-b158-4626-8e71-cf27b1f4848d",
|
||||
"packageManager": "npm",
|
||||
|
|
|
@ -8,7 +8,7 @@ This sample shows how the [Visio JavaScript APIs](https://docs.microsoft.com/off
|
|||
|
||||
## Used SharePoint Framework Version
|
||||
|
||||
![drop](https://img.shields.io/badge/drop-1.10.0-green.svg)
|
||||
![SPFx 1.11.0](https://img.shields.io/badge/drop-1.11.0-green.svg)
|
||||
|
||||
## Applies to
|
||||
|
||||
|
@ -30,6 +30,7 @@ This sample shows how the [Visio JavaScript APIs](https://docs.microsoft.com/off
|
|||
|
||||
| Version | Date | Comments |
|
||||
| ------- | ------------------ | -------------------- |
|
||||
| 1.6 | August 25, 2020 | Update to SPFx 1.11.0 |
|
||||
| 1.5 | February 20, 2019 | Update to SPFx 1.10.0 |
|
||||
| 1.4 | September 20, 2019 | Update to SPFx 1.9.1 |
|
||||
| 1.3 | April 4, 2019 | Update readme |
|
||||
|
|
|
@ -3,10 +3,17 @@
|
|||
"solution": {
|
||||
"name": "react-visio-client-side-solution",
|
||||
"id": "0ad401f1-b158-4626-8e71-cf27b1f4848d",
|
||||
"version": "1.0.0.0",
|
||||
"version": "1.6.0.0",
|
||||
"includeClientSideAssets": true,
|
||||
"skipFeatureDeployment": true,
|
||||
"isDomainIsolated": false
|
||||
"isDomainIsolated": false,
|
||||
"developer": {
|
||||
"name": "Contoso",
|
||||
"privacyUrl": "https://contoso.com/privacy",
|
||||
"termsOfUseUrl": "https://contoso.com/terms-of-use",
|
||||
"websiteUrl": "https://contoso.com/my-app",
|
||||
"mpnId": "000000"
|
||||
}
|
||||
},
|
||||
"paths": {
|
||||
"zippedPackage": "solution/react-visio.sppkg"
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "react-visio",
|
||||
"version": "0.0.1",
|
||||
"version": "1.6.0",
|
||||
"private": true,
|
||||
"main": "lib/index.js",
|
||||
"engines": {
|
||||
|
@ -12,29 +12,29 @@
|
|||
"test": "gulp test"
|
||||
},
|
||||
"dependencies": {
|
||||
"@microsoft/sp-core-library": "1.10.0",
|
||||
"@microsoft/sp-lodash-subset": "1.10.0",
|
||||
"@microsoft/sp-office-ui-fabric-core": "1.10.0",
|
||||
"@microsoft/sp-property-pane": "1.10.0",
|
||||
"@microsoft/sp-webpart-base": "1.10.0",
|
||||
"@types/es6-promise": "0.0.33",
|
||||
"@microsoft/sp-core-library": "1.11.0",
|
||||
"@microsoft/sp-lodash-subset": "1.11.0",
|
||||
"@microsoft/sp-office-ui-fabric-core": "1.11.0",
|
||||
"@microsoft/sp-property-pane": "1.11.0",
|
||||
"@microsoft/sp-webpart-base": "1.11.0",
|
||||
"@types/office-js": "0.0.101",
|
||||
"@types/react": "16.8.8",
|
||||
"@types/react-dom": "16.8.3",
|
||||
"@types/webpack-env": "1.13.1",
|
||||
"office-ui-fabric-react": "6.189.2",
|
||||
"office-ui-fabric-react": "6.214.0",
|
||||
"react": "16.8.5",
|
||||
"react-dom": "16.8.5"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@microsoft/rush-stack-compiler-2.9": "0.7.16",
|
||||
"@microsoft/rush-stack-compiler-3.3": "0.3.5",
|
||||
"@microsoft/sp-build-web": "1.10.0",
|
||||
"@microsoft/sp-module-interfaces": "1.10.0",
|
||||
"@microsoft/sp-tslint-rules": "1.10.0",
|
||||
"@microsoft/sp-webpart-workbench": "1.10.0",
|
||||
"@microsoft/sp-build-web": "1.11.0",
|
||||
"@microsoft/sp-module-interfaces": "1.11.0",
|
||||
"@microsoft/sp-tslint-rules": "1.11.0",
|
||||
"@microsoft/sp-webpart-workbench": "1.11.0",
|
||||
"@types/chai": "3.4.34",
|
||||
"@types/es6-promise": "0.0.33",
|
||||
"@types/mocha": "2.2.38",
|
||||
"@types/react": "16.8.8",
|
||||
"@types/react-dom": "16.8.3",
|
||||
"@types/webpack-env": "1.13.1",
|
||||
"ajv": "~5.2.2",
|
||||
"gulp": "~3.9.1"
|
||||
},
|
||||
|
|
|
@ -30,7 +30,8 @@
|
|||
]
|
||||
},
|
||||
"include": [
|
||||
"src/**/*.ts"
|
||||
"src/**/*.ts",
|
||||
"src/**/*.tsx"
|
||||
],
|
||||
"exclude": [
|
||||
"node_modules",
|
||||
|
|
|
@ -1,202 +0,0 @@
|
|||
# Upgrade project C:\Users\joelf\Dev\GitHub\sp-dev-fx-webparts\samples\react-visio to v1.10.0
|
||||
|
||||
Date: 2/29/2020
|
||||
|
||||
## Findings
|
||||
|
||||
Following is the list of steps required to upgrade your project to SharePoint Framework version 1.10.0. [Summary](#Summary) of the modifications is included at the end of the report.
|
||||
|
||||
### FN001001 @microsoft/sp-core-library | Required
|
||||
|
||||
Upgrade SharePoint Framework dependency package @microsoft/sp-core-library
|
||||
|
||||
Execute the following command:
|
||||
|
||||
```sh
|
||||
npm i -SE @microsoft/sp-core-library@1.10.0
|
||||
```
|
||||
|
||||
File: [./package.json](./package.json)
|
||||
|
||||
### FN001002 @microsoft/sp-lodash-subset | Required
|
||||
|
||||
Upgrade SharePoint Framework dependency package @microsoft/sp-lodash-subset
|
||||
|
||||
Execute the following command:
|
||||
|
||||
```sh
|
||||
npm i -SE @microsoft/sp-lodash-subset@1.10.0
|
||||
```
|
||||
|
||||
File: [./package.json](./package.json)
|
||||
|
||||
### FN001003 @microsoft/sp-office-ui-fabric-core | Required
|
||||
|
||||
Upgrade SharePoint Framework dependency package @microsoft/sp-office-ui-fabric-core
|
||||
|
||||
Execute the following command:
|
||||
|
||||
```sh
|
||||
npm i -SE @microsoft/sp-office-ui-fabric-core@1.10.0
|
||||
```
|
||||
|
||||
File: [./package.json](./package.json)
|
||||
|
||||
### FN001004 @microsoft/sp-webpart-base | Required
|
||||
|
||||
Upgrade SharePoint Framework dependency package @microsoft/sp-webpart-base
|
||||
|
||||
Execute the following command:
|
||||
|
||||
```sh
|
||||
npm i -SE @microsoft/sp-webpart-base@1.10.0
|
||||
```
|
||||
|
||||
File: [./package.json](./package.json)
|
||||
|
||||
### FN001021 @microsoft/sp-property-pane | Required
|
||||
|
||||
Install SharePoint Framework dependency package @microsoft/sp-property-pane
|
||||
|
||||
Execute the following command:
|
||||
|
||||
```sh
|
||||
npm i -SE @microsoft/sp-property-pane@1.10.0
|
||||
```
|
||||
|
||||
File: [./package.json](./package.json)
|
||||
|
||||
### FN002001 @microsoft/sp-build-web | Required
|
||||
|
||||
Upgrade SharePoint Framework dev dependency package @microsoft/sp-build-web
|
||||
|
||||
Execute the following command:
|
||||
|
||||
```sh
|
||||
npm i -DE @microsoft/sp-build-web@1.10.0
|
||||
```
|
||||
|
||||
File: [./package.json](./package.json)
|
||||
|
||||
### FN002002 @microsoft/sp-module-interfaces | Required
|
||||
|
||||
Upgrade SharePoint Framework dev dependency package @microsoft/sp-module-interfaces
|
||||
|
||||
Execute the following command:
|
||||
|
||||
```sh
|
||||
npm i -DE @microsoft/sp-module-interfaces@1.10.0
|
||||
```
|
||||
|
||||
File: [./package.json](./package.json)
|
||||
|
||||
### FN002003 @microsoft/sp-webpart-workbench | Required
|
||||
|
||||
Upgrade SharePoint Framework dev dependency package @microsoft/sp-webpart-workbench
|
||||
|
||||
Execute the following command:
|
||||
|
||||
```sh
|
||||
npm i -DE @microsoft/sp-webpart-workbench@1.10.0
|
||||
```
|
||||
|
||||
File: [./package.json](./package.json)
|
||||
|
||||
### FN002009 @microsoft/sp-tslint-rules | Required
|
||||
|
||||
Upgrade SharePoint Framework dev dependency package @microsoft/sp-tslint-rules
|
||||
|
||||
Execute the following command:
|
||||
|
||||
```sh
|
||||
npm i -DE @microsoft/sp-tslint-rules@1.10.0
|
||||
```
|
||||
|
||||
File: [./package.json](./package.json)
|
||||
|
||||
### FN002012 @microsoft/rush-stack-compiler-3.3 | Required
|
||||
|
||||
Install SharePoint Framework dev dependency package @microsoft/rush-stack-compiler-3.3
|
||||
|
||||
Execute the following command:
|
||||
|
||||
```sh
|
||||
npm i -DE @microsoft/rush-stack-compiler-3.3@0.3.5
|
||||
```
|
||||
|
||||
File: [./package.json](./package.json)
|
||||
|
||||
### FN010001 .yo-rc.json version | Recommended
|
||||
|
||||
Update version in .yo-rc.json
|
||||
|
||||
In file [./.yo-rc.json](./.yo-rc.json) update the code as follows:
|
||||
|
||||
```json
|
||||
{
|
||||
"@microsoft/generator-sharepoint": {
|
||||
"version": "1.10.0"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
File: [./.yo-rc.json](./.yo-rc.json)
|
||||
|
||||
### FN012017 tsconfig.json extends property | Required
|
||||
|
||||
Update tsconfig.json extends property
|
||||
|
||||
In file [./tsconfig.json](./tsconfig.json) update the code as follows:
|
||||
|
||||
```json
|
||||
{
|
||||
"extends": "./node_modules/@microsoft/rush-stack-compiler-3.3/includes/tsconfig-web.json"
|
||||
}
|
||||
```
|
||||
|
||||
File: [./tsconfig.json](./tsconfig.json)
|
||||
|
||||
### FN017001 Run npm dedupe | Optional
|
||||
|
||||
If, after upgrading npm packages, when building the project you have errors similar to: "error TS2345: Argument of type 'SPHttpClientConfiguration' is not assignable to parameter of type 'SPHttpClientConfiguration'", try running 'npm dedupe' to cleanup npm packages.
|
||||
|
||||
Execute the following command:
|
||||
|
||||
```sh
|
||||
npm dedupe
|
||||
```
|
||||
|
||||
File: [./package.json](./package.json)
|
||||
|
||||
## Summary
|
||||
|
||||
### Execute script
|
||||
|
||||
```sh
|
||||
npm i -SE @microsoft/sp-core-library@1.10.0 @microsoft/sp-lodash-subset@1.10.0 @microsoft/sp-office-ui-fabric-core@1.10.0 @microsoft/sp-webpart-base@1.10.0 @microsoft/sp-property-pane@1.10.0
|
||||
npm i -DE @microsoft/sp-build-web@1.10.0 @microsoft/sp-module-interfaces@1.10.0 @microsoft/sp-webpart-workbench@1.10.0 @microsoft/sp-tslint-rules@1.10.0 @microsoft/rush-stack-compiler-3.3@0.3.5
|
||||
```
|
||||
|
||||
### Modify files
|
||||
|
||||
#### [./.yo-rc.json](./.yo-rc.json)
|
||||
|
||||
Update version in .yo-rc.json:
|
||||
|
||||
```json
|
||||
{
|
||||
"@microsoft/generator-sharepoint": {
|
||||
"version": "1.10.0"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### [./tsconfig.json](./tsconfig.json)
|
||||
|
||||
Update tsconfig.json extends property:
|
||||
|
||||
```json
|
||||
{
|
||||
"extends": "./node_modules/@microsoft/rush-stack-compiler-3.3/includes/tsconfig-web.json"
|
||||
}
|
||||
```
|
Loading…
Reference in New Issue