diff --git a/samples/react-content-query-online/.devcontainer/devcontainer.json b/samples/react-content-query-online/.devcontainer/devcontainer.json index 1c92f1353..142906b55 100644 --- a/samples/react-content-query-online/.devcontainer/devcontainer.json +++ b/samples/react-content-query-online/.devcontainer/devcontainer.json @@ -1,39 +1,38 @@ -// 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.11.0", - "image": "docker.io/m365pnp/spfx:1.11.0", - // 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, - 5432 - ], - "portsAttributes": { - "4321": { - "protocol": "https", - "label": "Manifest", - "onAutoForward": "silent", - "requireLocalPort": true - }, - "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 + "name": "SPFx 1.18.2", + "image": "docker.io/m365pnp/spfx:1.18.2", + "customizations": { + "vscode": { + "extensions": [ + "editorconfig.editorconfig", + "dbaeumer.vscode-eslint" + ] + } + }, + "forwardPorts": [ + 4321, + 35729, + 5432 + ], + "portsAttributes": { + "4321": { + "protocol": "https", + "label": "Manifest", + "onAutoForward": "silent", + "requireLocalPort": true + }, + "5432": { + "protocol": "https", + "label": "Workbench", + "onAutoForward": "silent" + }, + "35729": { + "protocol": "https", + "label": "LiveReload", + "onAutoForward": "silent", + "requireLocalPort": true + } + }, + "postCreateCommand": "bash .devcontainer/spfx-startup.sh", + "remoteUser": "node" +} diff --git a/samples/react-content-query-online/.devcontainer/spfx-startup.sh b/samples/react-content-query-online/.devcontainer/spfx-startup.sh index ca531bdf2..456d6aea8 100644 --- a/samples/react-content-query-online/.devcontainer/spfx-startup.sh +++ b/samples/react-content-query-online/.devcontainer/spfx-startup.sh @@ -7,9 +7,11 @@ 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 -cp ~/.gcb-serve-data/gcb-serve.cer ./spfx-dev-cert.cer -cp ~/.gcb-serve-data/gcb-serve.cer ./spfx-dev-cert.pem +# 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 diff --git a/samples/react-content-query-online/.nvmrc b/samples/react-content-query-online/.nvmrc new file mode 100644 index 000000000..eb800ed45 --- /dev/null +++ b/samples/react-content-query-online/.nvmrc @@ -0,0 +1 @@ +v18.19.0 diff --git a/samples/react-content-query-online/README.md b/samples/react-content-query-online/README.md index 20e836661..d50e694b6 100644 --- a/samples/react-content-query-online/README.md +++ b/samples/react-content-query-online/README.md @@ -14,14 +14,17 @@ While the original web part was based on an **XSLT** templating engine, this *Re | :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) ![Compatible with SharePoint Online](https://img.shields.io/badge/SharePoint%20Online-Compatible-green.svg) +This sample is optimally compatible with the following environment configuration: + +![SPFx 1.18.2](https://img.shields.io/badge/SPFx-1.18.2-green.svg) +![Node.js v16 | v18](https://img.shields.io/badge/Node.js-v16%20%7C%20v18-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") -![Local Workbench Incompatible](https://img.shields.io/badge/Local%20Workbench-Incompatible-red.svg "The solution requires access to content") +![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) diff --git a/samples/react-content-query-online/assets/sample.json b/samples/react-content-query-online/assets/sample.json index e5baba230..d89374c12 100644 --- a/samples/react-content-query-online/assets/sample.json +++ b/samples/react-content-query-online/assets/sample.json @@ -9,7 +9,7 @@ "The React Content Query Web Part is a modern version of the good old Content by Query Web Part that was introduced in SharePoint 2007. Built for SharePoint Online, this modern version is built against the new SharePoint Framework (SPFx) and uses the latest Web Stack practices. While the original Web Part was based on a XSLT templating engine, this React Web Part is based on the well known Handlebars templating engine, which empowers users to create simple, yet powerfull HTML templates for rendering the queried content. This new version also lets the user query any site collections which resides on the same domain url, add unlimited filters, query DateTime fields to the nearest minute rather than being limited to a day, and much more." ], "creationDateTime": "2021-01-07", - "updateDateTime": "2023-05-04", + "updateDateTime": "2024-03-31", "products": [ "SharePoint" ], @@ -20,7 +20,7 @@ }, { "key": "SPFX-VERSION", - "value": "1.11.0" + "value": "1.18.2" } ], "thumbnails": [ @@ -138,10 +138,15 @@ "name": "Abderahman Moujahid" }, { - "gitHubAccount": "ChrisLizon", - "name": "Chris Lizon", - "pictureUrl": "https://github.com/ChrisLizon.png" - } + "gitHubAccount": "ChrisLizon", + "name": "Chris Lizon", + "pictureUrl": "https://github.com/ChrisLizon.png" + }, + { + "gitHubAccount": "nemortu", + "name": "nemortu", + "pictureUrl": "https://github.com/nemortu.png" + } ], "references": [ { diff --git a/samples/react-content-query-online/src/common/helpers/CamlQueryHelper.ts b/samples/react-content-query-online/src/common/helpers/CamlQueryHelper.ts index 3fc2ee9ce..eb9026fbd 100644 --- a/samples/react-content-query-online/src/common/helpers/CamlQueryHelper.ts +++ b/samples/react-content-query-online/src/common/helpers/CamlQueryHelper.ts @@ -291,7 +291,9 @@ export class CamlQueryHelper { if (!url) { url = window.location.href; } + // eslint-disable-next-line no-useless-escape name = name.replace(/[\[\]]/g, "\\$&"); + // eslint-disable-next-line @rushstack/security/no-unsafe-regexp var regex = new RegExp("[?&]" + name + "(=([^&#]*)|&|#|$)"), results = regex.exec(url); if (!results) return null; diff --git a/samples/react-content-query-online/src/common/services/ContentQueryService.ts b/samples/react-content-query-online/src/common/services/ContentQueryService.ts index b66f3e6ac..16cae19b9 100644 --- a/samples/react-content-query-online/src/common/services/ContentQueryService.ts +++ b/samples/react-content-query-online/src/common/services/ContentQueryService.ts @@ -295,6 +295,7 @@ export class ContentQueryService implements IContentQueryService { this.listService.getListFields(webUrl, listId, ['InternalName', 'Title', 'Sortable'], 'Title').then((data: any) => { const sortableFields: any[] = data.value.filter((field) => { return field.Sortable == true; }); let options: IDropdownOption[] = [{ key: "", text: strings.queryFilterPanelStrings.queryFilterStrings.fieldSelectLabel }]; + // eslint-disable-next-line no-useless-escape const orderByOptions: IDropdownOption[] = sortableFields.map((field) => { return { key: field.InternalName, text: Text.format("{0} \{\{{1}\}\}", field.Title, field.InternalName) }; }); options = options.concat(orderByOptions); this.orderByOptions = options; @@ -371,7 +372,8 @@ export class ContentQueryService implements IContentQueryService { let items: IChecklistItem[] = fields.map((field) => { return { id: field.InternalName, - label: Text.format("{0} \{\{{1}\}\}", field.Title, field.InternalName) + // eslint-disable-next-line no-useless-escape + label: Text.format("{0} \{\{{1}\}}", field.Title, field.InternalName) }; }); this.viewFields = items; @@ -479,6 +481,7 @@ export class ContentQueryService implements IContentQueryService { * @param itemSelectorEnabled: Defines whether to render the item selector element in the template *************************************************************************************************/ public generateDefaultTemplate(viewFields: string[], itemSelectorEnabled: boolean): string { + // eslint-disable-next-line no-useless-escape let viewFieldsStr = viewFields.map((field) => { return Text.format(" {0}: \{\{{0}.textValue\}\}", field); }).join("\n"); let selectItemStr = "\n "; let template = Text.format(`