Updated SPFx version and more (#280)

* Updated SPFx from 1.0.0 to 1.1.0

* Added closing div.
Updated logo.

* Include override.css using require instead of sass @import which no longer works in the build chain.

* Updated README with complete building steps

* Updated version to 1.0.0.1

* Updated to pull version from package.json

* Include bundled Office UI Frabework CSS to ensure proper grid.

* Added version info

* Added safeWithCustomScriptDisabled property

* Changed to static linking

* Added explicit reference to office-ui-fabric v2

* Removed test CSS

* Remove commented out code

* Remove empty lines

* Removed non-existant styles

* Externalize Office UI Fabric components and CSS to CDN - keeping CSS in the project for reference.
This commit is contained in:
Mikael Svenson 2017-08-10 22:06:47 +02:00 committed by Vesa Juvonen
parent ef0be61fd5
commit a254b685c1
9 changed files with 7837 additions and 25 deletions

View File

@ -66,6 +66,7 @@ react-script-editor | Mikael Svenson ([@mikaelsvenson](http://www.twitter.com/mi
Version|Date|Comments Version|Date|Comments
-------|----|-------- -------|----|--------
1.0|March 10th, 2017|Initial release 1.0|March 10th, 2017|Initial release
1.0.1|August 8th, 2017|Updated SPFx version and CSS loading
## Disclaimer ## 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.** **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.**
@ -73,12 +74,23 @@ Version|Date|Comments
--- ---
## Minimal Path to Awesome ## Minimal Path to Awesome
### Local testing
- Clone this repository - Clone this repository
- In the command line run: - In the command line run:
- `npm install` - `npm install`
- `gulp serve` - `gulp serve`
### Deploy
* Set CDN path in config\write-manifest.json to where you want to host the web part
* E.g.: https://<tenant>.sharepoint.com/sites/CDN/SiteAssets/SPFx/<partname>
* gulp --ship
* gulp package-solution --ship
* Copy contents of temp\deploy to the CDN folder
* Upload .sppkg file from sharepoint\solution to your tenant App Catalog
* E.g.: https://<tenant>.sharepoint.com/sites/AppCatalog/AppCatalog
* Add the web part to a site collection, and test it on a page
## Features ## Features
This web part illustrates the following concepts on top of the SharePoint Framework: This web part illustrates the following concepts on top of the SharePoint Framework:

View File

@ -6,5 +6,7 @@
"outputPath": "./dist/script-editor.bundle.js" "outputPath": "./dist/script-editor.bundle.js"
} }
], ],
"externals": {} "externals": {
"office-ui-fabric-react": "https://publiccdn.sharepointonline.com/techmikael.sharepoint.com/11510075fe4212d19d3e6d07c91981263dd697bf111cb1e5f0efb15de0ec08b382cde399/2.34.2/office-ui-fabric-react.bundle.min.js"
}
} }

View File

@ -2,7 +2,7 @@
"solution": { "solution": {
"name": "Modern Script Editor web part by Puzzlepart", "name": "Modern Script Editor web part by Puzzlepart",
"id": "1425175f-3ed8-44d2-8fc4-dd1497191294", "id": "1425175f-3ed8-44d2-8fc4-dd1497191294",
"version": "1.0.0.0" "version": "1.0.0.1"
}, },
"paths": { "paths": {
"zippedPackage": "solution/pzl-script-editor.sppkg" "zippedPackage": "solution/pzl-script-editor.sppkg"

View File

@ -7,21 +7,22 @@
}, },
"dependencies": { "dependencies": {
"@microsoft/sp-client-base": "~1.0.0", "@microsoft/sp-client-base": "~1.0.0",
"@microsoft/sp-core-library": "~1.0.0", "@microsoft/sp-core-library": "~1.1.0",
"@microsoft/sp-webpart-base": "~1.0.0", "@microsoft/sp-webpart-base": "~1.1.0",
"@types/react": "0.14.46", "@types/react": "0.14.46",
"@types/react-addons-shallow-compare": "0.14.17", "@types/react-addons-shallow-compare": "0.14.17",
"@types/react-addons-test-utils": "0.14.15", "@types/react-addons-test-utils": "0.14.15",
"@types/react-addons-update": "0.14.14", "@types/react-addons-update": "0.14.14",
"@types/react-dom": "0.14.18", "@types/react-dom": "0.14.18",
"@types/webpack-env": ">=1.12.1 <1.14.0", "@types/webpack-env": ">=1.12.1 <1.14.0",
"office-ui-fabric-react": "2.34.2",
"react": "15.4.2", "react": "15.4.2",
"react-dom": "15.4.2" "react-dom": "15.4.2"
}, },
"devDependencies": { "devDependencies": {
"@microsoft/sp-build-web": "~1.0.0", "@microsoft/sp-build-web": "~1.1.0",
"@microsoft/sp-module-interfaces": "~1.0.0", "@microsoft/sp-module-interfaces": "~1.1.0",
"@microsoft/sp-webpart-workbench": "~1.0.0", "@microsoft/sp-webpart-workbench": "~1.1.0",
"gulp": "~3.9.1", "gulp": "~3.9.1",
"@types/chai": ">=3.4.34 <3.6.0", "@types/chai": ">=3.4.34 <3.6.0",
"@types/mocha": ">=2.2.33 <2.6.0" "@types/mocha": ">=2.2.33 <2.6.0"

View File

@ -1,12 +1,17 @@
{ {
"$schema": "../../../node_modules/@microsoft/sp-module-interfaces/lib/manifestSchemas/jsonSchemas/clientSideComponentManifestSchema.json", "$schema": "../../../node_modules/@microsoft/sp-module-interfaces/lib/manifestSchemas/jsonSchemas/clientSideComponentManifestSchema.json",
"id": "3a328f0a-99c4-4b28-95ab-fe0847f657a3", "id": "3a328f0a-99c4-4b28-95ab-fe0847f657a3",
"alias": "ScriptEditorWebPart", "alias": "ScriptEditorWebPart",
"componentType": "WebPart", "componentType": "WebPart",
"version": "0.0.1", "version": "*", // The "*" signifies that the version should be taken from the package.json
"manifestVersion": 2, "manifestVersion": 2,
/**
* This property should only be set to true if it is certain that the webpart does not
* allow arbitrary scripts to be called
*/
"safeWithCustomScriptDisabled": false,
"preconfiguredEntries": [{ "preconfiguredEntries": [{
"groupId": "3a328f0a-99c4-4b28-95ab-fe0847f657a3", "groupId": "3a328f0a-99c4-4b28-95ab-fe0847f657a3",
"group": { "default": "Puzzlepart" }, "group": { "default": "Puzzlepart" },

View File

@ -12,14 +12,12 @@ import { IScriptEditorProps } from './components/IScriptEditorProps';
import { IScriptEditorWebPartProps } from './IScriptEditorWebPartProps'; import { IScriptEditorWebPartProps } from './IScriptEditorWebPartProps';
export default class ScriptEditorWebPart extends BaseClientSideWebPart<IScriptEditorWebPartProps> { export default class ScriptEditorWebPart extends BaseClientSideWebPart<IScriptEditorWebPartProps> {
public save: (script: string) => void = (script: string) => { public save: (script: string) => void = (script: string) => {
this.properties.script = script; this.properties.script = script;
this.render(); this.render();
} }
public render(): void { public render(): void {
const element: React.ReactElement<IScriptEditorProps> = React.createElement( const element: React.ReactElement<IScriptEditorProps> = React.createElement(
ScriptEditor, ScriptEditor,
{ {
@ -41,7 +39,11 @@ export default class ScriptEditorWebPart extends BaseClientSideWebPart<IScriptEd
} }
protected renderLogo(domElement: HTMLElement) { protected renderLogo(domElement: HTMLElement) {
domElement.innerHTML = '<div style="margin-top: 30px"><img src="//www.puzzlepart.com/wp-content/uploads/2017/02/Puzzlepart-Logo-Digital-webheader200.png" onerror="this.style.display = \'none\'";" style="width:50%; float:right">'; domElement.innerHTML = `
<div style="margin-top: 30px">
<div style="float:right">Author: <a href="mailto:mikael.svenson@puzzlepart.com" tabindex="-1">Mikael Svenson</a></div>
<div style="float:right"><img src="//www.puzzlepart.com/wp-content/uploads/2017/08/Pzl-LogoType-200.png" onerror="this.style.display = \'none\'";"></div>
</div>`;
} }
protected getPropertyPaneConfiguration(): IPropertyPaneConfiguration { protected getPropertyPaneConfiguration(): IPropertyPaneConfiguration {

View File

@ -1,4 +1,4 @@
@import url('overrides.css'); //@import url(https://publiccdn.sharepointonline.com/techmikael.sharepoint.com/11510075fe4212d19d3e6d07c91981263dd697bf111cb1e5f0efb15de0ec08b382cde399/5.0.1/office-ui-fabric.min.css);
.scriptEditor { .scriptEditor {
.container { .container {

View File

@ -1,16 +1,35 @@
import * as React from 'react'; import * as React from 'react';
import styles from './ScriptEditor.module.scss'; import styles from './ScriptEditor.module.scss';
import { IScriptEditorProps } from './IScriptEditorProps'; import { IScriptEditorProps } from './IScriptEditorProps';
import { Dialog, DialogType, DialogFooter, Button, ButtonType, TextField } from 'office-ui-fabric-react'; import { Dialog, DialogType, DialogFooter } from 'office-ui-fabric-react';
import { DefaultButton, PrimaryButton } from 'office-ui-fabric-react';
import { TextField } from 'office-ui-fabric-react';
import { loadStyles } from '@microsoft/load-themed-styles';
require('./overrides.css');
export default class ScriptEditor extends React.Component<IScriptEditorProps, any> { export default class ScriptEditor extends React.Component<IScriptEditorProps, any> {
constructor() { constructor() {
super(); super();
this.loadCss();
this.state = { this.state = {
showDialog: false showDialog: false
}; };
} }
public async loadCss() {
if (window["UIFabricLoaded"]) {
return;
}
const response = await fetch("https://publiccdn.sharepointonline.com/techmikael.sharepoint.com/11510075fe4212d19d3e6d07c91981263dd697bf111cb1e5f0efb15de0ec08b382cde399/5.0.1/office-ui-fabric.min.css");
if (response.ok) {
response.text().then((data: any) => {
loadStyles(data);
window["UIFabricLoaded"] = true;
this.forceUpdate();
});
}
}
public componentDidMount(): void { public componentDidMount(): void {
this.setState({ script: this.props.script, loaded: this.props.script }); this.setState({ script: this.props.script, loaded: this.props.script });
} }
@ -33,17 +52,20 @@ export default class ScriptEditor extends React.Component<IScriptEditorProps, an
} }
public render(): React.ReactElement<IScriptEditorProps> { public render(): React.ReactElement<IScriptEditorProps> {
if (!window["UIFabricLoaded"]) {
return <span />;
}
const viewMode = <span dangerouslySetInnerHTML={{ __html: this.state.script }}></span>; const viewMode = <span dangerouslySetInnerHTML={{ __html: this.state.script }}></span>;
return ( return (
<div> <div >
<div className={styles.scriptEditor}> <div className={styles.scriptEditor}>
<div className={styles.container}> <div className={styles.container}>
<div className={`ms-Grid-row ms-bgColor-themeDark ms-fontColor-white ${styles.row}`}> <div className={`pzl-Grid-row pzl-bgColor-themeDark pzl-fontColor-white ${styles.row}`}>
<div className="ms-Grid-col ms-u-lg10 ms-u-xl8 ms-u-xlPush2 ms-u-lgPush1"> <div className="pzl-Grid-col pzl-u-lg10 pzl-u-xl8 pzl-u-xlPush2 pzl-u-lgPush1">
<span className="ms-font-xl ms-fontColor-white">The Modern Script Editor web part!</span> <span className="pzl-font-xl pzl-fontColor-white">The Modern Script Editor web part!</span>
<p className="ms-font-l ms-fontColor-white"></p> <p className="pzl-font-l pzl-fontColor-white"></p>
<Button description='Opens the Sample Dialog' onClick={this._showDialog.bind(this)}>Edit snippet</Button> <DefaultButton description='Opens the Sample Dialog' onClick={this._showDialog.bind(this)}>Edit snippet</DefaultButton>
</div> </div>
</div> </div>
</div> </div>
@ -59,11 +81,11 @@ export default class ScriptEditor extends React.Component<IScriptEditorProps, an
> >
<TextField multiline rows={15} onChanged={this._onScriptEditorTextChanged.bind(this)} value={this.state.script} /> <TextField multiline rows={15} onChanged={this._onScriptEditorTextChanged.bind(this)} value={this.state.script} />
<DialogFooter> <DialogFooter>
<Button buttonType={ButtonType.primary} onClick={this._closeDialog.bind(this)}>Save</Button> <PrimaryButton onClick={this._closeDialog.bind(this)}>Save</PrimaryButton>
<Button onClick={this._cancelDialog.bind(this)}>Cancel</Button> <DefaultButton onClick={this._cancelDialog.bind(this)}>Cancel</DefaultButton>
</DialogFooter> </DialogFooter>
{viewMode} {viewMode}
</Dialog> </Dialog>
</div>); </div >);
} }
} }