Merge pull request #3666 from salascz/feature/script-editor-external-script

This commit is contained in:
Hugo Bernier 2023-05-13 14:48:49 -04:00 committed by GitHub
commit 26ec9b43cb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 59 additions and 18 deletions

View File

@ -1,7 +1,7 @@
# Script editor web part for modern pages built in React # Script editor web part for modern pages
This version works only for SharePoint Online. If you want a version for Sharepoint on-premises go to [react-script-editor-onprem](../react-script-editor-onprem). This version works only for SharePoint Online. If you want a version for SharePoint on-premises go to [react-script-editor-onprem](../react-script-editor-onprem).
**It's important you read and understand the notes on [deployment](#deploy-to-non-script-sites--modern-team-sites).** **It's important you read and understand the notes on [deployment](#deploy-to-non-script-sites--modern-team-sites).**
@ -130,7 +130,7 @@ By default this web part is not allowed on no-script sites, as it allows executi
If you however want to allow the web part for non-script sites like Office 365 Group modern team sites you have to edit `ScriptEditorWebPart.manifest.json` with the following change: If you however want to allow the web part for non-script sites like Office 365 Group modern team sites you have to edit `ScriptEditorWebPart.manifest.json` with the following change:
``` ```json
"requiresCustomScript": false "requiresCustomScript": false
``` ```
@ -138,7 +138,7 @@ If you however want to allow the web part for non-script sites like Office 365 G
By default you have to install this web part per site collection where you want it available. If you want it enabled by default on all sites you have to edit `package-solution.json` with the following change: By default you have to install this web part per site collection where you want it available. If you want it enabled by default on all sites you have to edit `package-solution.json` with the following change:
``` ```json
"skipFeatureDeployment": true "skipFeatureDeployment": true
``` ```
@ -171,6 +171,8 @@ This sample is optimally compatible with the following environment configuration
* [Mikael Svenson](https://github.com/wobba) * [Mikael Svenson](https://github.com/wobba)
* [Felix Bohnacker](https://github.com/felixbohnackerfelixbohnacker) * [Felix Bohnacker](https://github.com/felixbohnackerfelixbohnacker)
* [salascz](https://github.com/salascz)
* [Waldek Mastykarz](https://github.com/waldekmastykarz)
## Version history ## Version history
@ -198,11 +200,12 @@ Version|Date|Comments
1.0.19.0|August 31, 2022|Added support for section background color 1.0.19.0|August 31, 2022|Added support for section background color
1.0.20.0|October 10, 2022|Added sample html/script with self-executing function 1.0.20.0|October 10, 2022|Added sample html/script with self-executing function
1.0.21.0|March 11, 2023|Bump dependencies to allow react-script-editor to build under SPFx 1.16.1 1.0.21.0|March 11, 2023|Bump dependencies to allow react-script-editor to build under SPFx 1.16.1
1.0.22.0|April 24, 2023|Added support for script in external template
## Minimal Path to Awesome ## Minimal Path to Awesome
### Local testing ### Testing
* Clone this repository * Clone this repository
* In the command line run: * In the command line run:
@ -236,11 +239,11 @@ You can try looking at [issues related to this sample](https://github.com/pnp/sp
You can also try looking at [discussions related to this sample](https://github.com/pnp/sp-dev-fx-webparts/discussions?discussions_q=react-script-editor) and see what the community is saying. You can also try looking at [discussions related to this sample](https://github.com/pnp/sp-dev-fx-webparts/discussions?discussions_q=react-script-editor) and see what the community is saying.
If you encounter any issues while using this sample, [create a new issue](https://github.com/pnp/sp-dev-fx-webparts/issues/new?assignees=&labels=Needs%3A+Triage+%3Amag%3A%2Ctype%3Abug-suspected%2Csample%3A%20react-script-editor&template=bug-report.yml&sample=react-script-editor&authors=@wobba&title=react-script-editor%20-%20). If you encounter any issues while using this sample, [create a new issue](https://github.com/pnp/sp-dev-fx-webparts/issues/new?assignees=&labels=Needs%3A+Triage+%3Amag%3A%2Ctype%3Abug-suspected%2Csample%3A%20react-script-editor&template=bug-report.yml&sample=react-script-editor&authors=@wobba%20@salascz%20@felixbohnacker&title=react-script-editor%20-%20).
For questions regarding this sample, [create a new question](https://github.com/pnp/sp-dev-fx-webparts/issues/new?assignees=&labels=Needs%3A+Triage+%3Amag%3A%2Ctype%3Aquestion%2Csample%3A%20react-script-editor&template=question.yml&sample=react-script-editor&authors=@wobba&title=react-script-editor%20-%20). For questions regarding this sample, [create a new question](https://github.com/pnp/sp-dev-fx-webparts/issues/new?assignees=&labels=Needs%3A+Triage+%3Amag%3A%2Ctype%3Aquestion%2Csample%3A%20react-script-editor&template=question.yml&sample=react-script-editor&authors=@wobba%20@salascz%20@felixbohnacker&title=react-script-editor%20-%20).
Finally, if you have an idea for improvement, [make a suggestion](https://github.com/pnp/sp-dev-fx-webparts/issues/new?assignees=&labels=Needs%3A+Triage+%3Amag%3A%2Ctype%3Aenhancement%2Csample%3A%20react-script-editor&template=question.yml&sample=react-script-editor&authors=@wobba&title=react-script-editor%20-%20). Finally, if you have an idea for improvement, [make a suggestion](https://github.com/pnp/sp-dev-fx-webparts/issues/new?assignees=&labels=Needs%3A+Triage+%3Amag%3A%2Ctype%3Aenhancement%2Csample%3A%20react-script-editor&template=question.yml&sample=react-script-editor&authors=@wobba%20@salascz%20@felixbohnacker&title=react-script-editor%20-%20).
## Disclaimer ## Disclaimer

View File

@ -9,7 +9,7 @@
"Coming from old classic SharePoint pages you might have existing script solutions you want to re-use on a modern page without having to repackage it as a new SharePoint Framework web part." "Coming from old classic SharePoint pages you might have existing script solutions you want to re-use on a modern page without having to repackage it as a new SharePoint Framework web part."
], ],
"creationDateTime": "2019-10-13", "creationDateTime": "2019-10-13",
"updateDateTime": "2023-03-11", "updateDateTime": "2023-04-24",
"products": [ "products": [
"SharePoint" "SharePoint"
], ],
@ -57,7 +57,17 @@
"gitHubAccount": "felixbohnacker", "gitHubAccount": "felixbohnacker",
"pictureUrl": "https://github.com/felixbohnacker.png", "pictureUrl": "https://github.com/felixbohnacker.png",
"name": "Felix Bohnacker" "name": "Felix Bohnacker"
} },
{
"gitHubAccount": "salascz",
"name": "salascz",
"pictureUrl": "https://github.com/salascz.png"
},
{
"gitHubAccount": "wobba",
"name": "Mikael Svenson",
"pictureUrl": "https://github.com/wobba.png"
}
], ],
"references": [ "references": [
{ {

View File

@ -3,7 +3,7 @@
"solution": { "solution": {
"name": "Modern Script Editor web part by mikaelsvenson", "name": "Modern Script Editor web part by mikaelsvenson",
"id": "1425175f-3ed8-44d2-8fc4-dd1497191294", "id": "1425175f-3ed8-44d2-8fc4-dd1497191294",
"version": "1.0.21.0", "version": "1.0.22.0",
"includeClientSideAssets": true, "includeClientSideAssets": true,
"skipFeatureDeployment": false, "skipFeatureDeployment": false,
"isDomainIsolated": false, "isDomainIsolated": false,

View File

@ -1,12 +1,12 @@
{ {
"name": "pnp-script-editor", "name": "pnp-script-editor",
"version": "1.0.21", "version": "1.0.22",
"lockfileVersion": 2, "lockfileVersion": 2,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "pnp-script-editor", "name": "pnp-script-editor",
"version": "1.0.21", "version": "1.0.22",
"dependencies": { "dependencies": {
"@microsoft/sp-core-library": "1.16.1", "@microsoft/sp-core-library": "1.16.1",
"@microsoft/sp-loader": "1.16.1", "@microsoft/sp-loader": "1.16.1",

View File

@ -1,6 +1,6 @@
{ {
"name": "pnp-script-editor", "name": "pnp-script-editor",
"version": "1.0.21", "version": "1.0.22",
"private": true, "private": true,
"main": "lib/index.js", "main": "lib/index.js",
"resolutions": { "resolutions": {

View File

@ -1,5 +1,7 @@
export interface IScriptEditorWebPartProps { export interface IScriptEditorWebPartProps {
script: string; script: string;
useExternalScript: boolean;
externalScript?: string;
title: string; title: string;
removePadding: boolean; removePadding: boolean;
spPageContextInfo: boolean; spPageContextInfo: boolean;

View File

@ -11,6 +11,7 @@ import PropertyPaneLogo from './PropertyPaneLogo';
export default class ScriptEditorWebPart extends BaseClientSideWebPart<IScriptEditorWebPartProps> { export default class ScriptEditorWebPart extends BaseClientSideWebPart<IScriptEditorWebPartProps> {
public _propertyPaneHelper; public _propertyPaneHelper;
private _unqiueId; private _unqiueId;
private _externalScriptContent;
constructor() { constructor() {
super(); super();
@ -22,6 +23,18 @@ export default class ScriptEditorWebPart extends BaseClientSideWebPart<IScriptEd
this._propertyPaneHelper.initialValue = newVal; this._propertyPaneHelper.initialValue = newVal;
} }
protected async onInit(): Promise<void> {
if (this.properties.useExternalScript) {
try {
const prefix = this.properties.externalScript.indexOf('?') === -1 ? '?' : '&';
const response = await fetch(`${this.properties.externalScript}${prefix}pnp=${new Date().getTime()}`);
this._externalScriptContent = await response.text();
} catch (e) {
this._externalScriptContent = 'Failed to load external script.';
}
}
}
public render(): void { public render(): void {
this._unqiueId = this.context.instanceId; this._unqiueId = this.context.instanceId;
if (this.displayMode == DisplayMode.Read) { if (this.displayMode == DisplayMode.Read) {
@ -42,7 +55,7 @@ export default class ScriptEditorWebPart extends BaseClientSideWebPart<IScriptEd
} }
ReactDom.unmountComponentAtNode(this.domElement); ReactDom.unmountComponentAtNode(this.domElement);
this.domElement.innerHTML = this.properties.script; this.domElement.innerHTML = this.properties.useExternalScript ? this._externalScriptContent : this.properties.script;
this.executeScript(this.domElement); this.executeScript(this.domElement);
} else { } else {
this.renderEditor(); this.renderEditor();
@ -66,7 +79,7 @@ export default class ScriptEditorWebPart extends BaseClientSideWebPart<IScriptEd
); );
ReactDom.render(element, this.domElement); ReactDom.render(element, this.domElement);
} }
protected get dataVersion(): Version { protected get dataVersion(): Version {
return Version.parse('1.0'); return Version.parse('1.0');
} }
@ -108,9 +121,22 @@ export default class ScriptEditorWebPart extends BaseClientSideWebPart<IScriptEd
onText: "Enabled", onText: "Enabled",
offText: "Disabled" offText: "Disabled"
}), }),
this._propertyPaneHelper PropertyPaneToggle('useExternalScript', {
label: 'Use an external HTML Code instead of inline script',
onText: "Use external HTML Code",
offText: "Use inline script"
}),
]; ];
if (this.properties.useExternalScript) {
webPartOptions.push(PropertyPaneTextField("externalScript", {
label: "External HTML Code URL",
value: this.properties.externalScript,
}));
} else {
webPartOptions.push(this._propertyPaneHelper);
}
if (this.context.sdks.microsoftTeams) { if (this.context.sdks.microsoftTeams) {
let config = PropertyPaneToggle("teamsContext", { let config = PropertyPaneToggle("teamsContext", {
label: "Enable teams context as _teamsContexInfo", label: "Enable teams context as _teamsContexInfo",
@ -173,7 +199,7 @@ export default class ScriptEditorWebPart extends BaseClientSideWebPart<IScriptEd
// //
// Argument element is an element in the dom. // Argument element is an element in the dom.
private async executeScript(element: HTMLElement) { private async executeScript(element: HTMLElement) {
// clean up added script tags in case of smart re-load // clean up added script tags in case of smart re-load
const headTag = document.getElementsByTagName("head")[0] || document.documentElement; const headTag = document.getElementsByTagName("head")[0] || document.documentElement;
let scriptTags = headTag.getElementsByTagName("script"); let scriptTags = headTag.getElementsByTagName("script");
for (let i = 0; i < scriptTags.length; i++) { for (let i = 0; i < scriptTags.length; i++) {