From 4ec42297f15e6515757fa88ab6a62efd7c62c188 Mon Sep 17 00:00:00 2001 From: Hugo Bernier Date: Sat, 11 Mar 2023 22:13:53 -0500 Subject: [PATCH] Updated readme, added container and fixed linting issues --- .../.devcontainer/devcontainer.json | 39 +++++++++++++++++++ .../.devcontainer/spfx-startup.sh | 33 ++++++++++++++++ .../react-advanced-page-properties/README.md | 19 ++++----- .../AdvancedPagePropertiesWebPart.ts | 15 ++++--- .../components/AdvancedPageProperties.tsx | 15 ++++--- .../models/PageProperty.ts | 1 + .../advancedPageProperties/utilities/Log.ts | 8 ++-- .../upgrade-report.md | 1 - 8 files changed, 105 insertions(+), 26 deletions(-) create mode 100644 samples/react-advanced-page-properties/.devcontainer/devcontainer.json create mode 100644 samples/react-advanced-page-properties/.devcontainer/spfx-startup.sh delete mode 100644 samples/react-advanced-page-properties/upgrade-report.md diff --git a/samples/react-advanced-page-properties/.devcontainer/devcontainer.json b/samples/react-advanced-page-properties/.devcontainer/devcontainer.json new file mode 100644 index 000000000..d0df53099 --- /dev/null +++ b/samples/react-advanced-page-properties/.devcontainer/devcontainer.json @@ -0,0 +1,39 @@ +// For more information on how to run this SPFx project in a VS Code Remote Container, please visit https://aka.ms/spfx-devcontainer +{ + "name": "SPFx 1.16.1", + "image": "docker.io/m365pnp/spfx:1.16.1", + // Set *default* container specific settings.json values on container create. + "settings": {}, + // Add the IDs of extensions you want installed when the container is created. + "extensions": [ + "editorconfig.editorconfig", + "dbaeumer.vscode-eslint" + ], + // Use 'forwardPorts' to make a list of ports inside the container available locally. + "forwardPorts": [ + 4321, + 35729 + ], + "portsAttributes": { + "4321": { + "protocol": "https", + "label": "Manifest", + "onAutoForward": "silent", + "requireLocalPort": true + }, + // Not needed for SPFx>= 1.12.1 + // "5432": { + // "protocol": "https", + // "label": "Workbench", + // "onAutoForward": "silent" + // }, + "35729": { + "protocol": "https", + "label": "LiveReload", + "onAutoForward": "silent", + "requireLocalPort": true + } + }, + "postCreateCommand": "bash .devcontainer/spfx-startup.sh", + "remoteUser": "node" +} \ No newline at end of file diff --git a/samples/react-advanced-page-properties/.devcontainer/spfx-startup.sh b/samples/react-advanced-page-properties/.devcontainer/spfx-startup.sh new file mode 100644 index 000000000..456d6aea8 --- /dev/null +++ b/samples/react-advanced-page-properties/.devcontainer/spfx-startup.sh @@ -0,0 +1,33 @@ +echo +echo -e "\e[1;94mInstalling Node dependencies\e[0m" +npm install + +## commands to create dev certificate and copy it to the root folder of the project +echo +echo -e "\e[1;94mGenerating dev certificate\e[0m" +gulp trust-dev-cert + +# Convert the generated PEM certificate to a CER certificate +openssl x509 -inform PEM -in ~/.rushstack/rushstack-serve.pem -outform DER -out ./spfx-dev-cert.cer + +# Copy the PEM ecrtificate for non-Windows hosts +cp ~/.rushstack/rushstack-serve.pem ./spfx-dev-cert.pem + +## add *.cer to .gitignore to prevent certificates from being saved in repo +if ! grep -Fxq '*.cer' ./.gitignore + then + echo "# .CER Certificates" >> .gitignore + echo "*.cer" >> .gitignore +fi + +## add *.pem to .gitignore to prevent certificates from being saved in repo +if ! grep -Fxq '*.pem' ./.gitignore + then + echo "# .PEM Certificates" >> .gitignore + echo "*.pem" >> .gitignore +fi + +echo +echo -e "\e[1;92mReady!\e[0m" + +echo -e "\n\e[1;94m**********\nOptional: if you plan on using gulp serve, don't forget to add the container certificate to your local machine. Please visit https://aka.ms/spfx-devcontainer for more information\n**********" \ No newline at end of file diff --git a/samples/react-advanced-page-properties/README.md b/samples/react-advanced-page-properties/README.md index 518eca23f..7a6404b5d 100644 --- a/samples/react-advanced-page-properties/README.md +++ b/samples/react-advanced-page-properties/README.md @@ -13,22 +13,22 @@ Attempts to replicate the functionality of Page Properties with the following im ![see the difference](./assets/diff-screencap.png) - ## Compatibility | :warning: Important | |:---------------------------| -| Every SPFx version is only compatible with specific version(s) of Node.js. In order to be able to build this sample, please ensure that the version of Node on your workstation matches one of the versions listed in this section. This sample will not work on a different version of Node.| +| Every SPFx version is optimally compatible with specific versions of Node.js. In order to be able to build this sample, you need to ensure that the version of Node on your workstation matches one of the versions listed in this section. This sample will not work on a different version of Node.| |Refer to for more information on SPFx compatibility. | -![SPFx 1.11](https://img.shields.io/badge/SPFx-1.11.0-green.svg) -![Node.js v10](https://img.shields.io/badge/Node.js-v10-green.svg) +This sample is optimally compatible with the following environment configuration: + +![SPFx 1.16.1](https://img.shields.io/badge/SPFx-1.16.1-green.svg) +![Node.js v16 | v14 | v12](https://img.shields.io/badge/Node.js-v16%20%7C%20v14%20%7C%20v12-green.svg) ![Compatible with SharePoint Online](https://img.shields.io/badge/SharePoint%20Online-Compatible-green.svg) ![Does not work with SharePoint 2019](https://img.shields.io/badge/SharePoint%20Server%202019-Incompatible-red.svg "SharePoint Server 2019 requires SPFx 1.4.1 or lower") ![Does not work with SharePoint 2016 (Feature Pack 2)](https://img.shields.io/badge/SharePoint%20Server%202016%20(Feature%20Pack%202)-Incompatible-red.svg "SharePoint Server 2016 Feature Pack 2 requires SPFx 1.1") -![Teams Incompatible](https://img.shields.io/badge/Teams-Incompatible-lightgrey.svg) -![Local Workbench Incompatible](https://img.shields.io/badge/Local%20Workbench-Incompatible-red.svg "This solution requires access to information about the hosting page") -![Hosted Workbench Compatible](https://img.shields.io/badge/Hosted%20Workbench-Compatible-yellow.svg "Works better when placed on a modern site page.") +![Local Workbench Unsupported](https://img.shields.io/badge/Local%20Workbench-Unsupported-red.svg "Local workbench is no longer available as of SPFx 1.13 and above") +![Hosted Workbench Compatible](https://img.shields.io/badge/Hosted%20Workbench-Compatible-green.svg) ![Compatible with Remote Containers](https://img.shields.io/badge/Remote%20Containers-Compatible-green.svg) ## Applies to @@ -44,8 +44,9 @@ None ## Contributors -- [Mike Homol](https://homol.work), Principal Consultant, [ThreeWill](https://threewill.com/) -- Abderahman Moujahid +- [Mike Homol](https://github.com/mhomol), Principal> Consultant, [ThreeWill](https://threewill.com/) +- [Abderahman Moujahid](https://github.com/Abderahman88) +- [Valeras Narbutas](https://github.com/ValerasNarbutas) ## Version history diff --git a/samples/react-advanced-page-properties/src/webparts/advancedPageProperties/AdvancedPagePropertiesWebPart.ts b/samples/react-advanced-page-properties/src/webparts/advancedPageProperties/AdvancedPagePropertiesWebPart.ts index 7b98bd0f8..95f2564a1 100644 --- a/samples/react-advanced-page-properties/src/webparts/advancedPageProperties/AdvancedPagePropertiesWebPart.ts +++ b/samples/react-advanced-page-properties/src/webparts/advancedPageProperties/AdvancedPagePropertiesWebPart.ts @@ -79,6 +79,7 @@ export default class AdvancedPagePropertiesWebPart extends BaseClientSideWebPart this._availableProperties = []; Log.Write(`${_fields.length.toString()} fields retrieved!`); + // eslint-disable-next-line @typescript-eslint/no-explicit-any _fields.forEach((field: any) => { if (!field.FromBaseType && !field.Hidden && field.SchemaXml.indexOf("ShowInListSettings=\"FALSE\"") === -1 && field.TypeAsString !== "Boolean" && field.TypeAsString !== "Note") { @@ -97,20 +98,23 @@ export default class AdvancedPagePropertiesWebPart extends BaseClientSideWebPart return Version.parse('1.0'); } - protected onAddButtonClick (value: any) { + // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unused-vars + protected onAddButtonClick (_value: any) { this.properties.selectedProperties.push(this._availableProperties[0].key.toString()); } + // eslint-disable-next-line @typescript-eslint/no-explicit-any protected onDeleteButtonClick (value: any) { Log.Write(value.toString()); - var removed = this.properties.selectedProperties.splice(value, 1); + const removed = this.properties.selectedProperties.splice(value, 1); Log.Write(`${removed[0]} removed.`); } - protected onPropertyPaneFieldChanged(propertyPath: string, oldValue: any, newValue: any): void { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + protected onPropertyPaneFieldChanged(propertyPath: string, _oldValue: any, newValue: any): void { if (propertyPath.indexOf("selectedProperty") >= 0) { Log.Write('Selected Property identified'); - let index: number = _.toInteger(propertyPath.replace("selectedProperty", "")); + const index: number = _.toInteger(propertyPath.replace("selectedProperty", "")); this.properties.selectedProperties[index] = newValue; } } @@ -125,7 +129,8 @@ export default class AdvancedPagePropertiesWebPart extends BaseClientSideWebPart Log.Write(`getPropertyPaneConfiguration`); // Initialize with the Title entry - var propDrops: IPropertyPaneField[] = []; + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const propDrops: IPropertyPaneField[] = []; propDrops.push(PropertyPaneTextField('title', { label: strings.TitleFieldLabel })); diff --git a/samples/react-advanced-page-properties/src/webparts/advancedPageProperties/components/AdvancedPageProperties.tsx b/samples/react-advanced-page-properties/src/webparts/advancedPageProperties/components/AdvancedPageProperties.tsx index 83fe263c5..ba1cd7f00 100644 --- a/samples/react-advanced-page-properties/src/webparts/advancedPageProperties/components/AdvancedPageProperties.tsx +++ b/samples/react-advanced-page-properties/src/webparts/advancedPageProperties/components/AdvancedPageProperties.tsx @@ -7,7 +7,6 @@ import { useState, useEffect, useRef } from 'react'; import { PageProperty } from '../models'; import { getSP } from '../utilities/pnpjs-config'; -import { DateTimeFieldFormatType, DateTimeFieldFriendlyFormatType, FieldTypes, IField, IFieldInfo } from "@pnp/sp/fields/types"; import "@pnp/sp/webs"; import "@pnp/sp/lists"; import "@pnp/sp/fields"; @@ -35,13 +34,14 @@ const AdvancedPageProperties: React.FunctionComponent { if (pagePropValues !== undefined && pagePropValues !== null) { - var retVal = _.map(pagePropValues, (prop) => { + const retVal = _.map(pagePropValues, (prop) => { return ( <>
{prop.info.Title} - {prop.info.TypeAsString}
@@ -125,10 +127,11 @@ const AdvancedPageProperties: React.FunctionComponent { - var retVal = _.map(prop.values, (val) => { + const retVal = _.map(prop.values, (val) => { if (val !== null && val !== "") { switch (prop.info.TypeAsString) { case "URL": + // eslint-disable-next-line no-case-declarations const url_parts = val.split(","); return ( {url_parts[1]} diff --git a/samples/react-advanced-page-properties/src/webparts/advancedPageProperties/models/PageProperty.ts b/samples/react-advanced-page-properties/src/webparts/advancedPageProperties/models/PageProperty.ts index 5578ff435..9c103db8e 100644 --- a/samples/react-advanced-page-properties/src/webparts/advancedPageProperties/models/PageProperty.ts +++ b/samples/react-advanced-page-properties/src/webparts/advancedPageProperties/models/PageProperty.ts @@ -2,5 +2,6 @@ import { IFieldInfo } from "@pnp/sp/fields"; export interface PageProperty { info: IFieldInfo; + // eslint-disable-next-line @typescript-eslint/no-explicit-any values: any[]; } diff --git a/samples/react-advanced-page-properties/src/webparts/advancedPageProperties/utilities/Log.ts b/samples/react-advanced-page-properties/src/webparts/advancedPageProperties/utilities/Log.ts index 61387cce4..cfec54087 100644 --- a/samples/react-advanced-page-properties/src/webparts/advancedPageProperties/utilities/Log.ts +++ b/samples/react-advanced-page-properties/src/webparts/advancedPageProperties/utilities/Log.ts @@ -2,13 +2,11 @@ import * as strings from "AdvancedPagePropertiesWebPartStrings"; export class Log { private static readonly logStyle: string = "background: crimson; padding: 5px; border-radius: 5px; color: white"; - constructor() { - } - public static Write(s: string, always: boolean = false) { - let d = new Date(); - let dateStr = d.getHours() + ':' + d.getMinutes() + ':' + d.getSeconds() + '.' + d.getMilliseconds(); + public static Write(s: string, always = false):void { + const d = new Date(); + const dateStr = d.getHours() + ':' + d.getMinutes() + ':' + d.getSeconds() + '.' + d.getMilliseconds(); if (window.location.search.indexOf("debug") >= 0 || always) { console.log(`%c${strings.LogAppName} >> ${dateStr} >> ${s}`, Log.logStyle); diff --git a/samples/react-advanced-page-properties/upgrade-report.md b/samples/react-advanced-page-properties/upgrade-report.md deleted file mode 100644 index bb74678af..000000000 --- a/samples/react-advanced-page-properties/upgrade-report.md +++ /dev/null @@ -1 +0,0 @@ -Project doesn't need to be upgraded