Merge branch 'main' into react-organization-chart

This commit is contained in:
Hugo Bernier 2024-10-12 11:57:16 -07:00 committed by GitHub
commit b8e86350ef
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
106 changed files with 140729 additions and 592348 deletions

View File

@ -3936,7 +3936,7 @@
"Sample SharePoint Framework application customizer showing how to create a tenant global NavBar and Footer NavBar for modern sites, reading menu items from the Term Store." "Sample SharePoint Framework application customizer showing how to create a tenant global NavBar and Footer NavBar for modern sites, reading menu items from the Term Store."
], ],
"creationDateTime": "2017-09-28", "creationDateTime": "2017-09-28",
"updateDateTime": "2017-09-28", "updateDateTime": "2024-10-05",
"products": [ "products": [
"SharePoint" "SharePoint"
], ],
@ -3947,7 +3947,7 @@
}, },
{ {
"key": "SPFX-VERSION", "key": "SPFX-VERSION",
"value": "1.3" "value": "1.20.0"
} }
], ],
"tags": [], "tags": [],
@ -5323,7 +5323,7 @@
"With the use of Rest calls, this sample command set shows how to manage list subscriptions (SharePoint webhooks) and take action to extend the webhook expiration date. The commandset will be added to the lists and libraries and will only be shown if there are any list subscriptions available on the list. The subscriptions that are accessible are shown when you click on the Commandset. The 'Renew subscription' action can be used in accordance with the subscription's expiration date. Given that the default number of days is 180, the subscription's (webhook expiration renewal date) renewal date is set to 179 days. " "With the use of Rest calls, this sample command set shows how to manage list subscriptions (SharePoint webhooks) and take action to extend the webhook expiration date. The commandset will be added to the lists and libraries and will only be shown if there are any list subscriptions available on the list. The subscriptions that are accessible are shown when you click on the Commandset. The 'Renew subscription' action can be used in accordance with the subscription's expiration date. Given that the default number of days is 180, the subscription's (webhook expiration renewal date) renewal date is set to 179 days. "
], ],
"creationDateTime": "2023-09-12", "creationDateTime": "2023-09-12",
"updateDateTime": "2023-09-12", "updateDateTime": "2024-10-03",
"products": [ "products": [
"SharePoint" "SharePoint"
], ],
@ -5334,7 +5334,7 @@
}, },
{ {
"key": "SPFX-VERSION", "key": "SPFX-VERSION",
"value": "1.17.4" "value": "1.20.0"
} }
], ],
"tags": [], "tags": [],

View File

@ -3936,7 +3936,7 @@
"Sample SharePoint Framework application customizer showing how to create a tenant global NavBar and Footer NavBar for modern sites, reading menu items from the Term Store." "Sample SharePoint Framework application customizer showing how to create a tenant global NavBar and Footer NavBar for modern sites, reading menu items from the Term Store."
], ],
"creationDateTime": "2017-09-28", "creationDateTime": "2017-09-28",
"updateDateTime": "2017-09-28", "updateDateTime": "2024-10-05",
"products": [ "products": [
"SharePoint" "SharePoint"
], ],
@ -3947,7 +3947,7 @@
}, },
{ {
"key": "SPFX-VERSION", "key": "SPFX-VERSION",
"value": "1.3" "value": "1.20.0"
} }
], ],
"tags": [], "tags": [],
@ -5323,7 +5323,7 @@
"With the use of Rest calls, this sample command set shows how to manage list subscriptions (SharePoint webhooks) and take action to extend the webhook expiration date. The commandset will be added to the lists and libraries and will only be shown if there are any list subscriptions available on the list. The subscriptions that are accessible are shown when you click on the Commandset. The 'Renew subscription' action can be used in accordance with the subscription's expiration date. Given that the default number of days is 180, the subscription's (webhook expiration renewal date) renewal date is set to 179 days. " "With the use of Rest calls, this sample command set shows how to manage list subscriptions (SharePoint webhooks) and take action to extend the webhook expiration date. The commandset will be added to the lists and libraries and will only be shown if there are any list subscriptions available on the list. The subscriptions that are accessible are shown when you click on the Commandset. The 'Renew subscription' action can be used in accordance with the subscription's expiration date. Given that the default number of days is 180, the subscription's (webhook expiration renewal date) renewal date is set to 179 days. "
], ],
"creationDateTime": "2023-09-12", "creationDateTime": "2023-09-12",
"updateDateTime": "2023-09-12", "updateDateTime": "2024-10-03",
"products": [ "products": [
"SharePoint" "SharePoint"
], ],
@ -5334,7 +5334,7 @@
}, },
{ {
"key": "SPFX-VERSION", "key": "SPFX-VERSION",
"value": "1.17.4" "value": "1.20.0"
} }
], ],
"tags": [], "tags": [],
@ -8248,7 +8248,7 @@
"This component is developed for the advanced usage of commenting the page or article etc. Page Comments lists will be created to store the comments." "This component is developed for the advanced usage of commenting the page or article etc. Page Comments lists will be created to store the comments."
], ],
"creationDateTime": "2020-02-05", "creationDateTime": "2020-02-05",
"updateDateTime": "2024-03-11", "updateDateTime": "2024-10-03",
"products": [ "products": [
"SharePoint" "SharePoint"
], ],
@ -8259,7 +8259,7 @@
}, },
{ {
"key": "SPFX-VERSION", "key": "SPFX-VERSION",
"value": "1.17.0" "value": "1.20.0"
}, },
{ {
"key": "PNPCONTROLS", "key": "PNPCONTROLS",
@ -12079,7 +12079,7 @@
"This Web Part allows you to manage events in a calendar. Uses a list of existing calendars on any website. The location and name of the list and the dates of the events to be displayed are defined in the properties of the web part." "This Web Part allows you to manage events in a calendar. Uses a list of existing calendars on any website. The location and name of the list and the dates of the events to be displayed are defined in the properties of the web part."
], ],
"creationDateTime": "2020-12-04", "creationDateTime": "2020-12-04",
"updateDateTime": "2024-06-28", "updateDateTime": "2024-10-01",
"products": [ "products": [
"SharePoint" "SharePoint"
], ],
@ -12090,7 +12090,7 @@
}, },
{ {
"key": "SPFX-VERSION", "key": "SPFX-VERSION",
"value": "1.12.1" "value": "1.16.1"
}, },
{ {
"key": "SPFX-TEAMSTAB", "key": "SPFX-TEAMSTAB",
@ -16056,7 +16056,7 @@
"description" "description"
], ],
"creationDateTime": "2022-04-20", "creationDateTime": "2022-04-20",
"updateDateTime": "2024-01-06", "updateDateTime": "2024-10-03",
"products": [ "products": [
"SharePoint" "SharePoint"
], ],
@ -16067,7 +16067,7 @@
}, },
{ {
"key": "SPFX-VERSION", "key": "SPFX-VERSION",
"value": "1.17.2" "value": "1.20.0"
} }
], ],
"thumbnails": [ "thumbnails": [
@ -19040,13 +19040,13 @@
"name": "pnp-sp-dev-spfx-web-parts-react-kanban-board", "name": "pnp-sp-dev-spfx-web-parts-react-kanban-board",
"source": "pnp", "source": "pnp",
"title": "Kanban Board Web part", "title": "Kanban Board Web part",
"shortDescription": "This solution contains an SPFx web part which shows a Kanban board using jqxKanban ReactJS component (from JQWidgets). The web part uses the default columns of the SharePoint Tasks list for showing the board's columns and the tasks.", "shortDescription": "This solution contains an SPFx web part which shows a Kanban board using Fluent UI. The web part uses the default columns of the SharePoint Tasks list for showing the board's columns and the tasks.",
"url": "https://github.com/pnp/sp-dev-fx-webparts/tree/main/samples/react-kanban-board", "url": "https://github.com/pnp/sp-dev-fx-webparts/tree/main/samples/react-kanban-board",
"longDescription": [ "longDescription": [
"This solution contains an SPFx web part which shows a Kanban board. The web part uses the default columns of the SharePoint Tasks list for showing the board's columns and the tasks." "This solution contains an SPFx web part which shows a Kanban board. The web part uses the default columns of the SharePoint Tasks list for showing the board's columns and the tasks."
], ],
"creationDateTime": "2020-07-02", "creationDateTime": "2020-07-02",
"updateDateTime": "2024-05-26", "updateDateTime": "2024-10-01",
"products": [ "products": [
"SharePoint" "SharePoint"
], ],
@ -19057,7 +19057,7 @@
}, },
{ {
"key": "SPFX-VERSION", "key": "SPFX-VERSION",
"value": "1.19.0" "value": "1.20.0"
}, },
{ {
"key": "SPFX-TEAMSTAB", "key": "SPFX-TEAMSTAB",
@ -19499,7 +19499,7 @@
"This list search web part allows the user to show data from lists or libraries." "This list search web part allows the user to show data from lists or libraries."
], ],
"creationDateTime": "2020-12-20", "creationDateTime": "2020-12-20",
"updateDateTime": "2022-07-11", "updateDateTime": "2024-10-02",
"products": [ "products": [
"SharePoint" "SharePoint"
], ],
@ -19510,7 +19510,7 @@
}, },
{ {
"key": "SPFX-VERSION", "key": "SPFX-VERSION",
"value": "1.11.0" "value": "1.20.0"
}, },
{ {
"key": "SPFX-SUPPORTSTHEMEVARIANTS", "key": "SPFX-SUPPORTSTHEMEVARIANTS",
@ -19574,7 +19574,7 @@
"authors": [ "authors": [
{ {
"gitHubAccount": "albegut", "gitHubAccount": "albegut",
"company": "Minsait", "company": "Hiberus",
"pictureUrl": "https://github.com/albegut.png", "pictureUrl": "https://github.com/albegut.png",
"name": "Alberto Gutierrez perez", "name": "Alberto Gutierrez perez",
"twitter": "albertogperez" "twitter": "albertogperez"
@ -19805,7 +19805,7 @@
"This sample web part demonstrates managing the list subscriptions (sharepoint webhooks) and action to renew the webhook expiration date using Rest calls. The webpart is to be added at Hubsite level or the sites associated to the hubsite, on selection of the site, it will list out the lists available. On list/library selection, the available subscriptions is displayed. Depending upon the expiry date of the subscription, 'Renew subscription' action can be performed. The subscription (webhook expiry renewal date) renewal date is set to 179 days, as the default days are 180. " "This sample web part demonstrates managing the list subscriptions (sharepoint webhooks) and action to renew the webhook expiration date using Rest calls. The webpart is to be added at Hubsite level or the sites associated to the hubsite, on selection of the site, it will list out the lists available. On list/library selection, the available subscriptions is displayed. Depending upon the expiry date of the subscription, 'Renew subscription' action can be performed. The subscription (webhook expiry renewal date) renewal date is set to 179 days, as the default days are 180. "
], ],
"creationDateTime": "2023-09-01", "creationDateTime": "2023-09-01",
"updateDateTime": "2023-09-01", "updateDateTime": "2024-10-02",
"products": [ "products": [
"SharePoint", "SharePoint",
"WebHooks", "WebHooks",
@ -19820,7 +19820,7 @@
}, },
{ {
"key": "SPFX-VERSION", "key": "SPFX-VERSION",
"value": "1.17.4" "value": "1.20.0"
} }
], ],
"thumbnails": [ "thumbnails": [
@ -26211,7 +26211,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-04-24", "updateDateTime": "2024-10-01",
"products": [ "products": [
"SharePoint" "SharePoint"
], ],
@ -26222,7 +26222,7 @@
}, },
{ {
"key": "SPFX-VERSION", "key": "SPFX-VERSION",
"value": "1.16.1" "value": "1.20.0"
}, },
{ {
"key": "SPFX-FULLPAGEAPP", "key": "SPFX-FULLPAGEAPP",

View File

@ -1,7 +1,7 @@
// For more information on how to run this SPFx project in a VS Code Remote Container, please visit https://aka.ms/spfx-devcontainer // 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.17.0", "name": "SPFx 1.20.0",
"image": "docker.io/m365pnp/spfx:1.17.0", "image": "docker.io/m365pnp/spfx:1.20.0",
// Set *default* container specific settings.json values on container create. // Set *default* container specific settings.json values on container create.
"settings": {}, "settings": {},
// Add the IDs of extensions you want installed when the container is created. // Add the IDs of extensions you want installed when the container is created.

View File

@ -1 +1 @@
v16.13.0 v18.18.0

View File

@ -2,7 +2,7 @@
"@microsoft/generator-sharepoint": { "@microsoft/generator-sharepoint": {
"isCreatingSolution": true, "isCreatingSolution": true,
"environment": "spo", "environment": "spo",
"version": "1.17.0", "version": "1.20.0",
"libraryName": "modern-page-comments", "libraryName": "modern-page-comments",
"libraryId": "cfa8dbcf-b32d-4de0-a6ba-af486007c2f2", "libraryId": "cfa8dbcf-b32d-4de0-a6ba-af486007c2f2",
"packageManager": "npm", "packageManager": "npm",
@ -11,7 +11,7 @@
"nodeVersion": "14.18.2", "nodeVersion": "14.18.2",
"sdkVersions": { "sdkVersions": {
"@microsoft/microsoft-graph-client": "3.0.2", "@microsoft/microsoft-graph-client": "3.0.2",
"@microsoft/teams-js": "2.9.1" "@microsoft/teams-js": "2.24.0"
} }
} }
} }

View File

@ -48,8 +48,8 @@
This sample is optimally compatible with the following environment configuration: This sample is optimally compatible with the following environment configuration:
![SPFx 1.17.0](https://img.shields.io/badge/SPFx-1.17.0-green.svg) ![SPFx 1.20.0](https://img.shields.io/badge/SPFx-1.20.0-green.svg)
![Node.js v16.13+](https://img.shields.io/badge/Node.js-v16.13+-green.svg) ![Node.js v18](https://img.shields.io/badge/Node.js-v18-green.svg)
![Compatible with SharePoint Online](https://img.shields.io/badge/SharePoint%20Online-Compatible-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 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") ![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")
@ -85,6 +85,7 @@ Version|Date|Comments
1.2.0.0|March 09, 2023|Upgraded to 1.16.1 1.2.0.0|March 09, 2023|Upgraded to 1.16.1
1.3.0.0|June 10, 2023|Upgraded to 1.17.0 1.3.0.0|June 10, 2023|Upgraded to 1.17.0
1.3.0.1|March 11, 2024|`this.pageurl` must be initialized before building `this.pastAtachmentPath` 1.3.0.1|March 11, 2024|`this.pageurl` must be initialized before building `this.pastAtachmentPath`
1.4.0.0|October 03, 2024|Upgraded to 1.20.0
## Minimal Path to Awesome ## Minimal Path to Awesome

View File

@ -9,7 +9,7 @@
"This component is developed for the advanced usage of commenting the page or article etc. Page Comments lists will be created to store the comments." "This component is developed for the advanced usage of commenting the page or article etc. Page Comments lists will be created to store the comments."
], ],
"creationDateTime": "2020-02-05", "creationDateTime": "2020-02-05",
"updateDateTime": "2024-03-11", "updateDateTime": "2024-10-03",
"products": [ "products": [
"SharePoint" "SharePoint"
], ],
@ -20,7 +20,7 @@
}, },
{ {
"key": "SPFX-VERSION", "key": "SPFX-VERSION",
"value": "1.17.0" "value": "1.20.0"
}, },
{ {
"key": "PNPCONTROLS", "key": "PNPCONTROLS",

View File

@ -3,7 +3,7 @@
"solution": { "solution": {
"name": "Advanced Comments Box", "name": "Advanced Comments Box",
"id": "cfa8dbcf-b32d-4de0-a6ba-af486007c2f2", "id": "cfa8dbcf-b32d-4de0-a6ba-af486007c2f2",
"version": "1.3.0.0", "version": "1.4.0.0",
"includeClientSideAssets": true, "includeClientSideAssets": true,
"isDomainIsolated": false, "isDomainIsolated": false,
"developer": { "developer": {

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
{ {
"name": "modern-page-comments", "name": "modern-page-comments",
"version": "1.3.0", "version": "1.4.0",
"private": true, "private": true,
"main": "lib/index.js", "main": "lib/index.js",
"scripts": { "scripts": {
@ -9,12 +9,13 @@
"test": "gulp test" "test": "gulp test"
}, },
"dependencies": { "dependencies": {
"@microsoft/sp-adaptive-card-extension-base": "1.17.0", "@fluentui/react": "8.106.4",
"@microsoft/sp-core-library": "1.17.0", "@microsoft/sp-adaptive-card-extension-base": "1.20.0",
"@microsoft/sp-lodash-subset": "1.17.0", "@microsoft/sp-core-library": "1.20.0",
"@microsoft/sp-office-ui-fabric-core": "1.17.0", "@microsoft/sp-lodash-subset": "1.20.0",
"@microsoft/sp-property-pane": "1.17.0", "@microsoft/sp-office-ui-fabric-core": "1.20.0",
"@microsoft/sp-webpart-base": "1.17.0", "@microsoft/sp-property-pane": "1.20.0",
"@microsoft/sp-webpart-base": "1.20.0",
"@pnp/sp": "^2.15.0", "@pnp/sp": "^2.15.0",
"@pnp/spfx-property-controls": "^3.13.0", "@pnp/spfx-property-controls": "^3.13.0",
"@types/jquery": "^2.0.60", "@types/jquery": "^2.0.60",
@ -26,22 +27,23 @@
"tslib": "2.3.1" "tslib": "2.3.1"
}, },
"devDependencies": { "devDependencies": {
"@microsoft/eslint-config-spfx": "1.17.0", "@microsoft/eslint-config-spfx": "1.20.2",
"@microsoft/eslint-plugin-spfx": "1.17.0", "@microsoft/eslint-plugin-spfx": "1.20.2",
"@microsoft/rush-stack-compiler-2.9": "0.7.16", "@microsoft/rush-stack-compiler-2.9": "0.7.16",
"@microsoft/rush-stack-compiler-4.5": "0.4.0", "@microsoft/rush-stack-compiler-4.5": "0.4.0",
"@microsoft/sp-build-web": "1.17.0", "@microsoft/rush-stack-compiler-4.7": "0.1.0",
"@microsoft/sp-module-interfaces": "1.17.0", "@microsoft/sp-build-web": "1.20.2",
"@rushstack/eslint-config": "2.5.1", "@microsoft/sp-module-interfaces": "1.20.2",
"@rushstack/eslint-config": "4.0.1",
"@types/es6-promise": "0.0.33", "@types/es6-promise": "0.0.33",
"@types/react": "17.0.45", "@types/react": "17.0.45",
"@types/webpack-env": "1.15.2", "@types/webpack-env": "1.15.2",
"ajv": "6.12.5", "ajv": "6.12.5",
"eslint": "8.7.0", "eslint": "8.57.0",
"gulp": "4.0.2", "gulp": "4.0.2",
"typescript": "4.5.5" "typescript": "4.7.4"
}, },
"engines": { "engines": {
"node": ">=16.13.0 <17.0.0" "node": ">=16.13.0 <17.0.0 || >=18.17.1 <19.0.0"
} }
} }

View File

@ -1,5 +1,5 @@
{ {
"extends": "./node_modules/@microsoft/rush-stack-compiler-4.5/includes/tsconfig-web.json", "extends": "./node_modules/@microsoft/rush-stack-compiler-4.7/includes/tsconfig-web.json",
"compilerOptions": { "compilerOptions": {
"target": "es5", "target": "es5",
"forceConsistentCasingInFileNames": true, "forceConsistentCasingInFileNames": true,
@ -11,16 +11,16 @@
"experimentalDecorators": true, "experimentalDecorators": true,
"skipLibCheck": true, "skipLibCheck": true,
"outDir": "lib", "outDir": "lib",
"noImplicitAny": false,
"inlineSources": false, "inlineSources": false,
"strictNullChecks": false, "strictNullChecks": false,
"noUnusedLocals": false, "noImplicitAny": false,
"typeRoots": [ "typeRoots": [
"./node_modules/@types", "./node_modules/@types",
"./node_modules/@microsoft" "./node_modules/@microsoft"
], ],
"types": [ "types": [
"webpack-env", "webpack-env"
], ],
"lib": [ "lib": [
"es5", "es5",
@ -32,6 +32,5 @@
"include": [ "include": [
"src/**/*.ts", "src/**/*.ts",
"src/**/*.tsx" "src/**/*.tsx"
], ]
"exclude": []
} }

View File

@ -4456,13 +4456,18 @@ is-glob@^4.0.0:
dependencies: dependencies:
is-extglob "^2.1.1" is-extglob "^2.1.1"
is-my-ip-valid@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/is-my-ip-valid/-/is-my-ip-valid-1.0.1.tgz#f7220d1146257c98672e6fba097a9f3f2d348442"
is-my-json-valid@^2.12.4: is-my-json-valid@^2.12.4:
version "2.16.0" version "2.20.6"
resolved "https://registry.yarnpkg.com/is-my-json-valid/-/is-my-json-valid-2.16.0.tgz#f079dd9bfdae65ee2038aae8acbc86ab109e3693" resolved "https://registry.yarnpkg.com/is-my-json-valid/-/is-my-json-valid-2.20.6.tgz#a9d89e56a36493c77bda1440d69ae0dc46a08387"
dependencies: dependencies:
generate-function "^2.0.0" generate-function "^2.0.0"
generate-object-property "^1.1.0" generate-object-property "^1.1.0"
jsonpointer "^4.0.0" is-my-ip-valid "^1.0.0"
jsonpointer "^5.0.0"
xtend "^4.0.0" xtend "^4.0.0"
is-npm@^1.0.0: is-npm@^1.0.0:
@ -4757,9 +4762,9 @@ jsonify@~0.0.0:
version "0.0.0" version "0.0.0"
resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.0.tgz#2c74b6ee41d93ca51b7b5aaee8f503631d252a73" resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.0.tgz#2c74b6ee41d93ca51b7b5aaee8f503631d252a73"
jsonpointer@^4.0.0: jsonpointer@^5.0.0:
version "4.0.1" version "5.0.1"
resolved "https://registry.yarnpkg.com/jsonpointer/-/jsonpointer-4.0.1.tgz#4fd92cb34e0e9db3c89c8622ecf51f9b978c6cb9" resolved "https://registry.yarnpkg.com/jsonpointer/-/jsonpointer-5.0.1.tgz#2110e0af0900fd37467b5907ecd13a7884a1b559"
jsprim@^1.2.2: jsprim@^1.2.2:
version "1.4.0" version "1.4.0"

View File

@ -1,7 +1,7 @@
// For more information on how to run this SPFx project in a VS Code Remote Container, please visit https://aka.ms/spfx-devcontainer // 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.12.1", "name": "SPFx 1.16.1",
"image": "docker.io/m365pnp/spfx:1.12.1", "image": "docker.io/m365pnp/spfx:1.16.1",
// Set *default* container specific settings.json values on container create. // Set *default* container specific settings.json values on container create.
"settings": {}, "settings": {},
// Add the IDs of extensions you want installed when the container is created. // Add the IDs of extensions you want installed when the container is created.

View File

@ -1 +1,2 @@
v12.13.0 v16.20.2
npm

View File

@ -1,28 +1,16 @@
{ {
"@pnp/generator-spfx": {
"framework": "react",
"pnpFramework": "reactjs.plus",
"pnp-libraries": [
"jquery@3",
"@pnp/pnpjs",
"@pnp/spfx-property-controls",
"@pnp/spfx-controls-react"
],
"pnp-ci": [
"azure"
],
"pnp-vetting": [
"webpack-analyzer",
"stylelint"
],
"spfxenv": "spo"
},
"@microsoft/generator-sharepoint": { "@microsoft/generator-sharepoint": {
"environment": "spo", "@microsoft/generator-sharepoint": {
"framework": "react", "nodeVersion": "16.20.2"
"plusBeta": true, },
"sdksVersions": {
"@microsoft/microsoft-graph-client": "3.0.2",
"@microsoft/teams-js": "2.4.1"
},
"plusBeta": false,
"isCreatingSolution": true, "isCreatingSolution": true,
"version": "1.12.1", "environment": "spo",
"version": "1.16.1",
"libraryName": "react-calendar", "libraryName": "react-calendar",
"libraryId": "3a13208b-3874-4036-9262-4edd22e88187", "libraryId": "3a13208b-3874-4036-9262-4edd22e88187",
"packageManager": "npm", "packageManager": "npm",

View File

@ -57,8 +57,8 @@ The Web Part checks the user's permissions for the View, Add, Edit, and Delete e
| 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 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.|
|Refer to <https://aka.ms/spfx-matrix> for more information on SPFx compatibility. | |Refer to <https://aka.ms/spfx-matrix> for more information on SPFx compatibility. |
![SPFx 1.12.1](https://img.shields.io/badge/SPFx-1.12.1-green.svg) ![SPFx 1.16.1](https://img.shields.io/badge/SPFx-1.16.1-green.svg)
![Node.js v14 | v12 | v10](https://img.shields.io/badge/Node.js-v14%20%7C%20v12%20%7C%20v10-green.svg) ![Node.js v16](https://img.shields.io/badge/Node.js-v16-green.svg)
![Compatible with SharePoint Online](https://img.shields.io/badge/SharePoint%20Online-Compatible-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 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") ![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")
@ -116,6 +116,7 @@ Version|Date|Comments
1.0.17|October 25, 2022|Fixed issue deleting events (#2693) 1.0.17|October 25, 2022|Fixed issue deleting events (#2693)
1.0.18|December 29, 2022|Fixed stylelint issue (#4029)| Cleaned up old Type script versions and Upgraded Type script version 1.0.18|December 29, 2022|Fixed stylelint issue (#4029)| Cleaned up old Type script versions and Upgraded Type script version
1.0.19|June 28, 2024| added filter by category | fixed the packages.json issues which prevent solution to build successfully. 1.0.19|June 28, 2024| added filter by category | fixed the packages.json issues which prevent solution to build successfully.
1.0.20|October 1, 2024| upgraded to SPFx 1.16.1
## Minimal Path to Awesome ## Minimal Path to Awesome

View File

@ -9,7 +9,7 @@
"This Web Part allows you to manage events in a calendar. Uses a list of existing calendars on any website. The location and name of the list and the dates of the events to be displayed are defined in the properties of the web part." "This Web Part allows you to manage events in a calendar. Uses a list of existing calendars on any website. The location and name of the list and the dates of the events to be displayed are defined in the properties of the web part."
], ],
"creationDateTime": "2020-12-04", "creationDateTime": "2020-12-04",
"updateDateTime": "2024-06-28", "updateDateTime": "2024-10-01",
"products": [ "products": [
"SharePoint" "SharePoint"
], ],
@ -20,7 +20,7 @@
}, },
{ {
"key": "SPFX-VERSION", "key": "SPFX-VERSION",
"value": "1.12.1" "value": "1.16.1"
}, },
{ {
"key": "SPFX-TEAMSTAB", "key": "SPFX-TEAMSTAB",

View File

@ -3,7 +3,7 @@
"solution": { "solution": {
"name": "react-calendar-client-side-solution", "name": "react-calendar-client-side-solution",
"id": "3a13208b-3874-4036-9262-4edd22e88187", "id": "3a13208b-3874-4036-9262-4edd22e88187",
"version": "1.0.19.0", "version": "1.0.20.0",
"includeClientSideAssets": true, "includeClientSideAssets": true,
"skipFeatureDeployment": true, "skipFeatureDeployment": true,
"isDomainIsolated": false "isDomainIsolated": false

View File

@ -0,0 +1,3 @@
{
"$schema": "https://developer.microsoft.com/json-schemas/core-build/sass.schema.json"
}

View File

@ -2,5 +2,5 @@
"$schema": "https://developer.microsoft.com/json-schemas/spfx-build/spfx-serve.schema.json", "$schema": "https://developer.microsoft.com/json-schemas/spfx-build/spfx-serve.schema.json",
"port": 4321, "port": 4321,
"https": true, "https": true,
"initialPage": "https://cotoso.sharepoint.com/_layouts/workbench.aspx" "initialPage": "https://contoso.sharepoint.com/_layouts/workbench.aspx"
} }

File diff suppressed because it is too large Load Diff

View File

@ -4,7 +4,7 @@
"version": "1.0.12", "version": "1.0.12",
"private": true, "private": true,
"engines": { "engines": {
"node": ">=12.13.0" "node": ">=16.20.2 <17.0.0"
}, },
"scripts": { "scripts": {
"build": "gulp bundle", "build": "gulp bundle",
@ -14,66 +14,62 @@
"test": "./node_modules/.bin/jest --config ./config/jest.config.json", "test": "./node_modules/.bin/jest --config ./config/jest.config.json",
"test:watch": "./node_modules/.bin/jest --config ./config/jest.config.json --watchAll" "test:watch": "./node_modules/.bin/jest --config ./config/jest.config.json --watchAll"
}, },
"dependencies": { "dependencies": {
"@fluentui/react": "8.85.1", "@fluentui/react": "8.85.1",
"@microsoft/sp-core-library": "1.12.1", "@microsoft/sp-adaptive-card-extension-base": "1.16.1",
"@microsoft/sp-lodash-subset": "1.12.1", "@microsoft/sp-core-library": "1.16.1",
"@microsoft/sp-office-ui-fabric-core": "1.12.1", "@microsoft/sp-lodash-subset": "1.16.1",
"@microsoft/sp-property-pane": "1.12.1", "@microsoft/sp-office-ui-fabric-core": "1.16.1",
"@microsoft/sp-webpart-base": "1.12.1", "@microsoft/sp-property-pane": "1.16.1",
"@pnp/pnpjs": "^1.3.0", "@microsoft/sp-webpart-base": "1.16.1",
"@pnp/spfx-controls-react": "1.21.3", "@pnp/graph": "2.11.0",
"@pnp/spfx-property-controls": "1.14.1", "@pnp/sp": "2.11.0",
"@types/draft-js": "^0.10.30", "@pnp/spfx-controls-react": "3.12.0",
"@types/globalize": "0.0.34", "@pnp/spfx-property-controls": "3.12.0",
"@types/jquery": "3.5.30", "jquery": "3.7.1",
"@types/react-big-calendar": "^0.24.6", "office-ui-fabric-react": "7.199.1",
"@uifabric/fluent-theme": "^0.16.7", "@uifabric/fluent-theme": "^0.16.7",
"browserslist": "4.23.1", "react": "17.0.1",
"react-big-calendar": "1.13.0",
"react-dom": "17.0.1",
"react-select": "5.2.2",
"string-format": "2.0.0",
"tslib": "2.3.1",
"underscore": "^1.13.6",
"draft-js": "^0.10.5", "draft-js": "^0.10.5",
"draftjs-to-html": "^0.8.4", "draftjs-to-html": "^0.8.4",
"globalize": "^1.4.2",
"immutable": "4.3.6",
"jquery": "3.7.1",
"moment": "2.30.1",
"office-ui-fabric-react": "7.156.0",
"react": "16.9.0",
"react-big-calendar": "^0.24.6",
"react-dom": "16.9.0",
"react-draft-wysiwyg": "1.15.0", "react-draft-wysiwyg": "1.15.0",
"react-select": "^4.3.1", "globalize": "^1.4.2",
"spfx-uifabric-themes": "^0.6.0", "immutable": "4.3.6"
"string-format": "^2.0.0", },
"typescript": "3.9.10", "devDependencies": {
"xml2js": "^0.4.19" "@microsoft/eslint-plugin-spfx": "1.16.1",
}, "@microsoft/rush-stack-compiler-4.5": "0.2.2",
"resolutions": { "@microsoft/sp-build-web": "1.16.1",
"@types/react": "16.7.22" "@microsoft/sp-module-interfaces": "1.16.1",
}, "@microsoft/sp-webpart-base": "1.16.1",
"devDependencies": { "@pnp/graph-commonjs": "2.11.0",
"@microsoft/rush-stack-compiler-3.9": "0.4.47", "@pnp/sp-commonjs": "2.11.0",
"@microsoft/sp-build-web": "1.20.1", "@rushstack/eslint-config": "2.5.1",
"@microsoft/sp-module-interfaces": "1.12.1", "@testing-library/jest-dom": "5.16.2",
"@microsoft/sp-tslint-rules": "1.12.1", "@testing-library/react": "12.1.2",
"@microsoft/sp-webpart-workbench": "1.12.1", "@types/jest": "26.0.4",
"@types/react": "16.9.36", "@types/react": "17.0.45",
"@types/react-dom": "16.9.8", "@types/react-big-calendar": "1.8.9",
"@types/webpack-env": "1.13.1", "@types/react-dom": "17.0.17",
"@types/string-format": "2.0.0",
"@types/underscore": "^1.11.4",
"@types/webpack-env": "1.15.2",
"@types/xml2js": "0.4.14", "@types/xml2js": "0.4.14",
"@voitanos/jest-preset-spfx-react16": "^1.1.0", "ajv": "6.12.5",
"ajv": "~5.2.2", "eslint": "8.7.0",
"eslint-plugin-react-hooks": "4.3.0",
"gulp": "4.0.2", "gulp": "4.0.2",
"gulp-sequence": "1.0.0", "gulp-sequence": "1.0.0",
"gulp-stylelint": "^8.0.0", "identity-obj-proxy": "^3.0.0",
"jest": "^23.6.0", "typescript": "4.5.5",
"karma-junit-reporter": "^1.2.0",
"stylelint": "^9.10.1",
"stylelint-config-standard": "^18.2.0",
"stylelint-scss": "^3.5.4",
"tslint": "^6.1.3",
"tslint-microsoft-contrib": "^6.2.0",
"webpack-bundle-analyzer": "^3.1.0" "webpack-bundle-analyzer": "^3.1.0"
}, },
"solution": { "solution": {
"developer": { "developer": {
"name": "", "name": "",

View File

@ -1167,12 +1167,12 @@ export class Event extends React.Component<IEventProps, IEventState> {
<div> <div>
<PeoplePicker <PeoplePicker
webAbsoluteUrl={this.props.siteUrl} webAbsoluteUrl={this.props.siteUrl}
context={this.props.context} context={this.props.context as any}
titleText={strings.AttendeesLabel} titleText={strings.AttendeesLabel}
principalTypes={[PrincipalType.User]} principalTypes={[PrincipalType.User]}
resolveDelay={1000} resolveDelay={1000}
showtooltip={true} showtooltip={true}
selectedItems={this.getPeoplePickerItems} //selectedItems={this.getPeoplePickerItems}
personSelectionLimit={10} personSelectionLimit={10}
defaultSelectedUsers={this.state.selectedUsers} defaultSelectedUsers={this.state.selectedUsers}
disabled={this.state.userPermissions.hasPermissionAdd || this.state.userPermissions.hasPermissionEdit ? false : true} disabled={this.state.userPermissions.hasPermissionAdd || this.state.userPermissions.hasPermissionEdit ? false : true}

View File

@ -1,13 +1,9 @@
// João Mendes
// March 2019
import { WebPartContext } from "@microsoft/sp-webpart-base"; import { WebPartContext } from "@microsoft/sp-webpart-base";
import { sp, Web, PermissionKind, RegionalSettings } from '@pnp/sp'; import { sp, Web, PermissionKind, RegionalSettings, ISiteUser, IRegionalSettings} from "@pnp/sp/presets/all";
import { graph, } from "@pnp/graph"; import { graph, } from "@pnp/graph";
import * as $ from 'jquery'; import * as $ from 'jquery';
import { IEventData } from './IEventData'; import { IEventData } from './IEventData';
import * as moment from 'moment'; import * as moment from 'moment';
import { SiteUser } from "@pnp/sp/src/siteusers";
import { IUserPermissions } from './IUserPermissions'; import { IUserPermissions } from './IUserPermissions';
import parseRecurrentEvent from './parseRecurrentEvent'; import parseRecurrentEvent from './parseRecurrentEvent';
import { IComboBoxOption } from '@fluentui/react'; import { IComboBoxOption } from '@fluentui/react';
@ -17,15 +13,14 @@ import { Text } from "@microsoft/sp-core-library";
// Class Services // Class Services
export default class spservices { export default class spservices {
constructor(private context: WebPartContext) { constructor(private context: WebPartContext) {
// Setuo Context to PnPjs and MSGraph // Setuo Context to PnPjs and MSGraph
sp.setup({ sp.setup({
spfxContext: this.context spfxContext: this.context as any
}); });
graph.setup({ graph.setup({
spfxContext: this.context spfxContext: this.context as any
}); });
// Init // Init
this.onInit(); this.onInit();
@ -77,7 +72,7 @@ export default class spservices {
public async addEvent(newEvent: IEventData, siteUrl: string, listId: string) { public async addEvent(newEvent: IEventData, siteUrl: string, listId: string) {
let results = null; let results = null;
try { try {
const web = new Web(siteUrl); const web = sp.web;
results = await web.lists.getById(listId).items.add({ results = await web.lists.getById(listId).items.add({
Title: newEvent.title, Title: newEvent.title,
@ -103,7 +98,6 @@ export default class spservices {
return results; return results;
} }
/** /**
* *
* *
@ -116,9 +110,7 @@ export default class spservices {
public async getEvent(siteUrl: string, listId: string, eventId: number): Promise<IEventData> { public async getEvent(siteUrl: string, listId: string, eventId: number): Promise<IEventData> {
let returnEvent: IEventData = undefined; let returnEvent: IEventData = undefined;
try { try {
const web = new Web(siteUrl); const web = sp.web;
//"Title","fRecurrence", "fAllDayEvent","EventDate", "EndDate", "Description","ID", "Location","Geolocation","ParticipantsPickerId"
const event = await web.lists.getById(listId).items.usingCaching().getById(eventId) const event = await web.lists.getById(listId).items.usingCaching().getById(eventId)
.select("RecurrenceID", "MasterSeriesItemID", "Id", "ID", "ParticipantsPickerId", "EventType", "Title", "Description", "EventDate", "EndDate", "Location", "Author/SipAddress", "Author/Title", "Geolocation", "fAllDayEvent", "fRecurrence", "RecurrenceData", "RecurrenceData", "Duration", "Category", "UID") .select("RecurrenceID", "MasterSeriesItemID", "Id", "ID", "ParticipantsPickerId", "EventType", "Title", "Description", "EventDate", "EndDate", "Location", "Author/SipAddress", "Author/Title", "Geolocation", "fAllDayEvent", "fRecurrence", "RecurrenceData", "RecurrenceData", "Duration", "Category", "UID")
.expand("Author") .expand("Author")
@ -173,11 +165,10 @@ export default class spservices {
// delete all recursive extentions before update recurrence event // delete all recursive extentions before update recurrence event
if (updateEvent.EventType.toString() == "1") await this.deleteRecurrenceExceptions(updateEvent, siteUrl, listId); if (updateEvent.EventType.toString() == "1") await this.deleteRecurrenceExceptions(updateEvent, siteUrl, listId);
const web = new Web(siteUrl); const web = sp.web;
const eventDate = await this.getUtcTime(updateEvent.EventDate); const eventDate = await this.getUtcTime(updateEvent.EventDate);
const endDate = await this.getUtcTime(updateEvent.EndDate); const endDate = await this.getUtcTime(updateEvent.EndDate);
//"Title","fRecurrence", "fAllDayEvent","EventDate", "EndDate", "Description","ID", "Location","Geolocation","ParticipantsPickerId"
let newItem: any = { let newItem: any = {
Title: updateEvent.title, Title: updateEvent.title,
Description: updateEvent.Description, Description: updateEvent.Description,
@ -211,7 +202,7 @@ export default class spservices {
public async deleteRecurrenceExceptions(event: IEventData, siteUrl: string, listId: string) { public async deleteRecurrenceExceptions(event: IEventData, siteUrl: string, listId: string) {
let results = null; let results = null;
try { try {
const web = new Web(siteUrl); const web = sp.web;
results = await web.lists.getById(listId).items results = await web.lists.getById(listId).items
.select('Id') .select('Id')
.filter(`EventType eq '3' or EventType eq '4' and MasterSeriesItemID eq '${event.Id}' `) .filter(`EventType eq '3' or EventType eq '4' and MasterSeriesItemID eq '${event.Id}' `)
@ -238,7 +229,7 @@ export default class spservices {
public async deleteEvent(event: IEventData, siteUrl: string, listId: string, recurrenceSeriesEdited: boolean) { public async deleteEvent(event: IEventData, siteUrl: string, listId: string, recurrenceSeriesEdited: boolean) {
let results = null; let results = null;
try { try {
const web = new Web(siteUrl); const web = sp.web;
// Exception Recurrence eventtype = 4 ? update to deleted Recurrence eventtype=3 // Exception Recurrence eventtype = 4 ? update to deleted Recurrence eventtype=3
switch (event.EventType.toString()) { switch (event.EventType.toString()) {
case '4': // Exception Recurrence Event case '4': // Exception Recurrence Event
@ -279,20 +270,19 @@ export default class spservices {
* *
* @param {number} userId * @param {number} userId
* @param {string} siteUrl * @param {string} siteUrl
* @returns {Promise<SiteUser>} * @returns {Promise<ISiteUser>}
* @memberof spservices * @memberof spservices
*/ */
public async getUserById(userId: number, siteUrl: string): Promise<SiteUser> { public async getUserById(userId: number, siteUrl: string): Promise<ISiteUser> {
let results: SiteUser = null; let results: ISiteUser = null;
if (!userId && !siteUrl) { if (!userId && !siteUrl) {
return null; return null;
} }
try { try {
const web = new Web(siteUrl); const web = sp.web;
results = await web.siteUsers.getById(userId).get(); results = await web.siteUsers.getById(userId).get();
//results = await web.siteUsers.getByLoginName(userId).get();
} catch (error) { } catch (error) {
return Promise.reject(error); return Promise.reject(error);
} }
@ -304,21 +294,20 @@ export default class spservices {
* *
* @param {string} loginName * @param {string} loginName
* @param {string} siteUrl * @param {string} siteUrl
* @returns {Promise<SiteUser>} * @returns {Promise<ISiteUser>}
* @memberof spservices * @memberof spservices
*/ */
public async getUserByLoginName(loginName: string, siteUrl: string): Promise<SiteUser> { public async getUserByLoginName(loginName: string, siteUrl: string): Promise<ISiteUser> {
let results: SiteUser = null; let results: ISiteUser = null;
if (!loginName && !siteUrl) { if (!loginName && !siteUrl) {
return null; return null;
} }
try { try {
const web = new Web(siteUrl); const web = sp.web;
await web.ensureUser(loginName); await web.ensureUser(loginName);
results = await web.siteUsers.getByLoginName(loginName).get(); results = await web.siteUsers.getByLoginName(loginName).get();
//results = await web.siteUsers.getByLoginName(userId).get();
} catch (error) { } catch (error) {
return Promise.reject(error); return Promise.reject(error);
} }
@ -354,9 +343,9 @@ export default class spservices {
let hasPermissionView: boolean = false; let hasPermissionView: boolean = false;
let userPermissions: IUserPermissions = undefined; let userPermissions: IUserPermissions = undefined;
try { try {
const web = new Web(siteUrl); const web = sp.web;
const userEffectivePermissions = await web.lists.getById(listId).effectiveBasePermissions.get(); const userEffectivePermissions = await web.lists.getById(listId).effectiveBasePermissions.get();
// ...
hasPermissionAdd = sp.web.lists.getById(listId).hasPermissions(userEffectivePermissions, PermissionKind.AddListItems); hasPermissionAdd = sp.web.lists.getById(listId).hasPermissions(userEffectivePermissions, PermissionKind.AddListItems);
hasPermissionDelete = sp.web.lists.getById(listId).hasPermissions(userEffectivePermissions, PermissionKind.DeleteListItems); hasPermissionDelete = sp.web.lists.getById(listId).hasPermissions(userEffectivePermissions, PermissionKind.DeleteListItems);
hasPermissionEdit = sp.web.lists.getById(listId).hasPermissions(userEffectivePermissions, PermissionKind.EditListItems); hasPermissionEdit = sp.web.lists.getById(listId).hasPermissions(userEffectivePermissions, PermissionKind.EditListItems);
@ -383,7 +372,7 @@ export default class spservices {
} }
try { try {
const web = new Web(siteUrl); const web = sp.web;
results = await web.lists.select("Title", "ID").filter('BaseTemplate eq 106').get(); results = await web.lists.select("Title", "ID").filter('BaseTemplate eq 106').get();
} catch (error) { } catch (error) {
@ -424,14 +413,14 @@ export default class spservices {
public async getChoiceFieldOptions(siteUrl: string, listId: string, fieldInternalName: string): Promise<{ key: string, text: string }[]> { public async getChoiceFieldOptions(siteUrl: string, listId: string, fieldInternalName: string): Promise<{ key: string, text: string }[]> {
let fieldOptions: { key: string, text: string }[] = []; let fieldOptions: { key: string, text: string }[] = [];
try { try {
const web = new Web(siteUrl); const web = sp.web;
const results = await web.lists.getById(listId) const results = await web.lists.getById(listId)
.fields .fields
.getByInternalNameOrTitle(fieldInternalName) .getByInternalNameOrTitle(fieldInternalName)
.select("Title", "InternalName", "Choices") .select("Title", "InternalName", "Choices")
.get(); .get();
if (results && results.Choices.length > 0) { if (results && results["Choices"].length > 0) {
for (const option of results.Choices) { for (const option of results["Choices"]) {
fieldOptions.push({ fieldOptions.push({
key: option, key: option,
text: option text: option
@ -468,7 +457,7 @@ export default class spservices {
} }
let camlQueryExpression = this.setUpQueryExpression(eventStartDate, eventEndDate, categories); let camlQueryExpression = this.setUpQueryExpression(eventStartDate, eventEndDate, categories);
const web = new Web(siteUrl); const web = sp.web;
const results = await web.lists.getById(listId).usingCaching().renderListDataAsStream( const results = await web.lists.getById(listId).usingCaching().renderListDataAsStream(
{ {
DatesInUtc: true, DatesInUtc: true,
@ -647,9 +636,9 @@ export default class spservices {
* @memberof spservices * @memberof spservices
*/ */
public async getSiteRegionalSettingsTimeZone(siteUrl: string) { public async getSiteRegionalSettingsTimeZone(siteUrl: string) {
let regionalSettings: RegionalSettings; let regionalSettings: IRegionalSettings;
try { try {
const web = new Web(siteUrl); const web = sp.web;
regionalSettings = await web.regionalSettings.timeZone.usingCaching().get(); regionalSettings = await web.regionalSettings.timeZone.usingCaching().get();
} catch (error) { } catch (error) {
@ -1201,7 +1190,4 @@ export default class spservices {
string = string.replace(/&amp;/g, '&'); string = string.replace(/&amp;/g, '&');
return string; return string;
} }
} }

View File

@ -184,7 +184,7 @@ class Year extends React.Component<IYearProps> {
let { date, ...props } = this.props; let { date, ...props } = this.props;
let range = this.range(date); let range = this.range(date);
const months = []; const months = [];
const firstMonth = dates.startOf(date, 'year'); const firstMonth = dates.startOf(new Date(this.props.date), 'year');
for (let i = 0; i < 12; i++) { for (let i = 0; i < 12; i++) {
months.push( months.push(

View File

@ -1,5 +1,5 @@
{ {
"extends": "./node_modules/@microsoft/rush-stack-compiler-3.9/includes/tsconfig-web.json", "extends": "./node_modules/@microsoft/rush-stack-compiler-4.5/includes/tsconfig-web.json",
"compilerOptions": { "compilerOptions": {
"target": "es5", "target": "es5",
"forceConsistentCasingInFileNames": true, "forceConsistentCasingInFileNames": true,
@ -14,14 +14,15 @@
"inlineSources": false, "inlineSources": false,
"strictNullChecks": false, "strictNullChecks": false,
"noUnusedLocals": false, "noUnusedLocals": false,
"allowJs": true,
"noImplicitAny": false,
"allowSyntheticDefaultImports": true, "allowSyntheticDefaultImports": true,
"typeRoots": [ "typeRoots": [
"./node_modules/@types", "./node_modules/@types",
"./node_modules/@microsoft" "./node_modules/@microsoft"
], ],
"types": [ "types": [
"webpack-env", "webpack-env"
"@types/jest"
], ],
"lib": [ "lib": [
"es5", "es5",

View File

@ -1,29 +0,0 @@
{
"extends": "./node_modules/@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
}
}

View File

@ -1,7 +1,7 @@
// For more information on how to run this SPFx project in a VS Code Remote Container, please visit https://aka.ms/spfx-devcontainer // 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.17.2", "name": "SPFx 1.20.0",
"image": "docker.io/m365pnp/spfx:1.17.2", "image": "docker.io/m365pnp/spfx:1.20.0",
// Set *default* container specific settings.json values on container create. // Set *default* container specific settings.json values on container create.
"settings": {}, "settings": {},
// Add the IDs of extensions you want installed when the container is created. // Add the IDs of extensions you want installed when the container is created.

View File

@ -1 +1 @@
v18.18.0 v18.19.0

View File

@ -16,7 +16,7 @@ This demos the use of the new [Fluent UI version 9](https://github.com/microsoft
| 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 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.|
|Refer to <https://aka.ms/spfx-matrix> for more information on SPFx compatibility. | |Refer to <https://aka.ms/spfx-matrix> for more information on SPFx compatibility. |
![SPFx 1.18.2](https://img.shields.io/badge/SPFx-1.18.2-green.svg) ![SPFx 1.20.0](https://img.shields.io/badge/SPFx-1.20.0-green.svg)
![Node.js v18](https://img.shields.io/badge/Node.js-v18-green.svg) ![Node.js v18](https://img.shields.io/badge/Node.js-v18-green.svg)
![Compatible with SharePoint Online](https://img.shields.io/badge/SharePoint%20Online-Compatible-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 2019](https://img.shields.io/badge/SharePoint%20Server%202019-Incompatible-red.svg "SharePoint Server 2019 requires SPFx 1.4.1 or lower")
@ -45,6 +45,7 @@ This demos the use of the new [Fluent UI version 9](https://github.com/microsoft
* [Nick Brown](https://github.com/techienickb) * [Nick Brown](https://github.com/techienickb)
## Version history ## Version history
Version|Date|Comments Version|Date|Comments
@ -54,6 +55,7 @@ Version|Date|Comments
1.0.2|January 18, 2023|Updated SPFx 1.16.1 1.0.2|January 18, 2023|Updated SPFx 1.16.1
1.0.2|May 15, 2023|Updated SPFx 1.17.2, latest Fluent UI 9 1.0.2|May 15, 2023|Updated SPFx 1.17.2, latest Fluent UI 9
1.0.4|January 6, 2023|Updated SPFx 1.18.2, latest Fluent UI 9, override to get package builds working 1.0.4|January 6, 2023|Updated SPFx 1.18.2, latest Fluent UI 9, override to get package builds working
1.0.5|October 3, 2024|Updated to SPFx 1.20.0, latest Fluent UI 9 (9.54.17)
- Clone this repository (or [download this solution as a .ZIP file](https://pnp.github.io/download-partial/?url=https://github.com/pnp/sp-dev-fx-webparts/tree/main/samples/react-fluentui-9) then unzip it) - Clone this repository (or [download this solution as a .ZIP file](https://pnp.github.io/download-partial/?url=https://github.com/pnp/sp-dev-fx-webparts/tree/main/samples/react-fluentui-9) then unzip it)
- From your command-line, change your current directory to the directory containing this sample (`react-fluentui-9`, located under `samples`) - From your command-line, change your current directory to the directory containing this sample (`react-fluentui-9`, located under `samples`)

View File

@ -10,7 +10,7 @@
"description" "description"
], ],
"creationDateTime": "2022-04-20", "creationDateTime": "2022-04-20",
"updateDateTime": "2024-01-06", "updateDateTime": "2024-10-03",
"products": [ "products": [
"SharePoint" "SharePoint"
], ],
@ -21,7 +21,7 @@
}, },
{ {
"key": "SPFX-VERSION", "key": "SPFX-VERSION",
"value": "1.17.2" "value": "1.20.0"
} }
], ],
"thumbnails": [ "thumbnails": [

View File

@ -12,25 +12,29 @@
"test": "gulp test" "test": "gulp test"
}, },
"dependencies": { "dependencies": {
"@fluentui/react-components": "^9.44.1", "@fluentui/react-components": "^9.54.17",
"@fluentui/react-migration-v8-v9": "^9.4.43", "@fluentui/react-migration-v8-v9": "^9.6.33",
"@microsoft/sp-component-base": "1.18.2", "@microsoft/sp-component-base": "^1.20.0",
"@microsoft/sp-core-library": "1.18.2", "@microsoft/sp-core-library": "^1.20.0",
"@microsoft/sp-lodash-subset": "1.18.2", "@microsoft/sp-lodash-subset": "^1.20.0",
"@microsoft/sp-office-ui-fabric-core": "1.18.2", "@microsoft/sp-office-ui-fabric-core": "^1.20.0",
"@microsoft/sp-property-pane": "1.18.2", "@microsoft/sp-property-pane": "1.20.0",
"@microsoft/sp-webpart-base": "1.18.2", "@microsoft/sp-webpart-base": "^1.20.0",
"i": "^0.3.7",
"npm": "^10.9.0",
"react": "17.0.1", "react": "17.0.1",
"react-dom": "17.0.1", "react-dom": "17.0.1",
"tslib": "2.3.1" "tslib": "2.3.1"
}, },
"devDependencies": { "devDependencies": {
"@microsoft/eslint-config-spfx": "1.18.2", "@microsoft/eslint-config-spfx": "^1.20.0",
"@microsoft/eslint-plugin-spfx": "1.18.2", "@microsoft/eslint-plugin-spfx": "^1.20.0",
"@microsoft/generator-sharepoint": "^1.20.0",
"@microsoft/rush-stack-compiler-4.7": "0.1.0", "@microsoft/rush-stack-compiler-4.7": "0.1.0",
"@microsoft/sp-build-web": "1.18.2", "@microsoft/sp-build-web": "^1.20.2",
"@microsoft/sp-module-interfaces": "1.18.2", "@microsoft/sp-module-interfaces": "^1.20.2",
"@rushstack/eslint-config": "2.5.1", "@rushstack/eslint-config": "^2.6.2",
"@rushstack/eslint-plugin": "^0.16.1",
"@types/react": "17.0.45", "@types/react": "17.0.45",
"@types/react-dom": "17.0.17", "@types/react-dom": "17.0.17",
"@types/webpack-env": "~1.15.2", "@types/webpack-env": "~1.15.2",

View File

@ -20,39 +20,6 @@ module.exports = {
'@rushstack/security/no-unsafe-regexp': 1, '@rushstack/security/no-unsafe-regexp': 1,
// STANDARDIZED BY: @typescript-eslint\eslint-plugin\dist\configs\recommended.json // STANDARDIZED BY: @typescript-eslint\eslint-plugin\dist\configs\recommended.json
'@typescript-eslint/adjacent-overload-signatures': 1, '@typescript-eslint/adjacent-overload-signatures': 1,
// STANDARDIZED BY: @typescript-eslint\eslint-plugin\dist\configs\recommended.json
//
// CONFIGURATION: By default, these are banned: String, Boolean, Number, Object, Symbol
'@typescript-eslint/ban-types': [
1,
{
'extendDefaults': false,
'types': {
'String': {
'message': 'Use \'string\' instead',
'fixWith': 'string'
},
'Boolean': {
'message': 'Use \'boolean\' instead',
'fixWith': 'boolean'
},
'Number': {
'message': 'Use \'number\' instead',
'fixWith': 'number'
},
'Object': {
'message': 'Use \'object\' instead, or else define a proper TypeScript type:'
},
'Symbol': {
'message': 'Use \'symbol\' instead',
'fixWith': 'symbol'
},
'Function': {
'message': 'The \'Function\' type accepts any function-like value.\nIt provides no type safety when calling the function, which can be a common source of bugs.\nIt also accepts things like class declarations, which will throw at runtime as they will not be called with \'new\'.\nIf you are expecting the function to accept certain arguments, you should explicitly define the function shape.'
}
}
}
],
// RATIONALE: Code is more readable when the type of every variable is immediately obvious. // RATIONALE: Code is more readable when the type of every variable is immediately obvious.
// Even if the compiler may be able to infer a type, this inference will be unavailable // Even if the compiler may be able to infer a type, this inference will be unavailable
// to a person who is reviewing a GitHub diff. This rule makes writing code harder, // to a person who is reviewing a GitHub diff. This rule makes writing code harder,
@ -79,7 +46,7 @@ module.exports = {
// This rule should be suppressed only in very special cases such as JSON.stringify() // This rule should be suppressed only in very special cases such as JSON.stringify()
// where the type really can be anything. Even if the type is flexible, another type // where the type really can be anything. Even if the type is flexible, another type
// may be more appropriate such as "unknown", "{}", or "Record<k,V>". // may be more appropriate such as "unknown", "{}", or "Record<k,V>".
'@typescript-eslint/no-explicit-any': 0, '@typescript-eslint/no-explicit-any': 1,
// RATIONALE: The #1 rule of promises is that every promise chain must be terminated by a catch() // RATIONALE: The #1 rule of promises is that every promise chain must be terminated by a catch()
// handler. Thus wherever a Promise arises, the code must either append a catch handler, // handler. Thus wherever a Promise arises, the code must either append a catch handler,
// or else return the object to a caller (who assumes this responsibility). Unterminated // or else return the object to a caller (who assumes this responsibility). Unterminated

View File

@ -1 +1 @@
v18.17.1 v18.20.3

View File

@ -1,9 +1,9 @@
{ {
"@microsoft/generator-sharepoint": { "@microsoft/generator-sharepoint": {
"nodeVersion": "18.17.1", "nodeVersion": "18.20.3",
"isCreatingSolution": true, "isCreatingSolution": true,
"environment": "spo", "environment": "spo",
"version": "1.19.0", "version": "1.20.0",
"libraryName": "react-kanban-board", "libraryName": "react-kanban-board",
"libraryId": "cccbd72b-7b89-4128-9348-0a4850ded8fd", "libraryId": "cccbd72b-7b89-4128-9348-0a4850ded8fd",
"packageManager": "npm", "packageManager": "npm",
@ -12,7 +12,7 @@
"plusBeta": false, "plusBeta": false,
"componentType": "webpart", "componentType": "webpart",
"sdkVersions": { "sdkVersions": {
"@microsoft/teams-js": "2.12.0", "@microsoft/teams-js": "2.24.0",
"@microsoft/microsoft-graph-client": "3.0.2" "@microsoft/microsoft-graph-client": "3.0.2"
} }
} }

View File

@ -20,7 +20,7 @@ The web part uses the default columns of the SharePoint Tasks list for showing t
| 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 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.|
|Refer to <https://aka.ms/spfx-matrix> for more information on SPFx compatibility. | |Refer to <https://aka.ms/spfx-matrix> for more information on SPFx compatibility. |
![SPFx 1.19.0](https://img.shields.io/badge/SPFx-1.19.0-green.svg) ![SPFx 1.20.0](https://img.shields.io/badge/SPFx-1.20.0-green.svg)
![Node.js v18 ](https://img.shields.io/badge/Node.js-v18-green.svg) ![Node.js v18 ](https://img.shields.io/badge/Node.js-v18-green.svg)
![Compatible with SharePoint Online](https://img.shields.io/badge/SharePoint%20Online-Compatible-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 2019](https://img.shields.io/badge/SharePoint%20Server%202019-Incompatible-red.svg "SharePoint Server 2019 requires SPFx 1.4.1 or lower")
@ -64,6 +64,8 @@ Version|Date|Comments
2.0.0.0|July 10, 2020| jqwidgets replaced with a custom Kanban Board based on Office UI Component and IE11 Support 2.0.0.0|July 10, 2020| jqwidgets replaced with a custom Kanban Board based on Office UI Component and IE11 Support
3.0.0.0|October 29, 2021| SPFx 1.13, PnPJS v2, PnP Controls v3 3.0.0.0|October 29, 2021| SPFx 1.13, PnPJS v2, PnP Controls v3
4.0.0.0|Jun 1, 2024| SPFx 1.19, PnPJS v4, Node 18 (Property-ListPicker and Property-Order not used from @pnp/spfx-property-controls because of an issue ) 4.0.0.0|Jun 1, 2024| SPFx 1.19, PnPJS v4, Node 18 (Property-ListPicker and Property-Order not used from @pnp/spfx-property-controls because of an issue )
5.0.0.0|Okt 1, 2024| SPFx 1.20, PnPJS v4, Node 18
[Read More about the implementation of this Board](./src/kanban/README.md) [Read More about the implementation of this Board](./src/kanban/README.md)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 MiB

After

Width:  |  Height:  |  Size: 320 KiB

View File

@ -3,13 +3,13 @@
"name": "pnp-sp-dev-spfx-web-parts-react-kanban-board", "name": "pnp-sp-dev-spfx-web-parts-react-kanban-board",
"source": "pnp", "source": "pnp",
"title": "Kanban Board Web part", "title": "Kanban Board Web part",
"shortDescription": "This solution contains an SPFx web part which shows a Kanban board using jqxKanban ReactJS component (from JQWidgets). The web part uses the default columns of the SharePoint Tasks list for showing the board\u0027s columns and the tasks.", "shortDescription": "This solution contains an SPFx web part which shows a Kanban board using Fluent UI. The web part uses the default columns of the SharePoint Tasks list for showing the board\u0027s columns and the tasks.",
"url": "https://github.com/pnp/sp-dev-fx-webparts/tree/main/samples/react-kanban-board", "url": "https://github.com/pnp/sp-dev-fx-webparts/tree/main/samples/react-kanban-board",
"longDescription": [ "longDescription": [
"This solution contains an SPFx web part which shows a Kanban board. The web part uses the default columns of the SharePoint Tasks list for showing the board\u0027s columns and the tasks." "This solution contains an SPFx web part which shows a Kanban board. The web part uses the default columns of the SharePoint Tasks list for showing the board\u0027s columns and the tasks."
], ],
"creationDateTime": "2020-07-02", "creationDateTime": "2020-07-02",
"updateDateTime": "2024-05-26", "updateDateTime": "2024-10-01",
"products": [ "products": [
"SharePoint" "SharePoint"
], ],
@ -20,7 +20,7 @@
}, },
{ {
"key": "SPFX-VERSION", "key": "SPFX-VERSION",
"value": "1.19.0" "value": "1.20.0"
}, },
{ {
"key": "SPFX-TEAMSTAB", "key": "SPFX-TEAMSTAB",

View File

@ -3,7 +3,7 @@
"solution": { "solution": {
"name": "react-kanban-board-client-side-solution", "name": "react-kanban-board-client-side-solution",
"id": "cccbd72b-7b89-4128-9348-0a4850ded8fd", "id": "cccbd72b-7b89-4128-9348-0a4850ded8fd",
"version": "4.0.0.0", "version": "5.0.0.0",
"includeClientSideAssets": true, "includeClientSideAssets": true,
"skipFeatureDeployment": true, "skipFeatureDeployment": true,
"isDomainIsolated": false, "isDomainIsolated": false,
@ -30,7 +30,7 @@
"title": "react-kanban-board KanbanBoardWebPart Feature", "title": "react-kanban-board KanbanBoardWebPart Feature",
"description": "The feature that activates KanbanBoardWebPart from the react-kanban-board solution.", "description": "The feature that activates KanbanBoardWebPart from the react-kanban-board solution.",
"id": "67cd5938-806b-4c79-b589-501f7f26998e", "id": "67cd5938-806b-4c79-b589-501f7f26998e",
"version": "4.0.0.0" "version": "5.0.0.0"
} }
] ]

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,7 @@
{ {
"name": "react-kanban-board", "name": "react-kanban-board",
"main": "lib/index.js", "main": "lib/index.js",
"version": "4.0.0", "version": "5.0.0",
"private": true, "private": true,
"engines": { "engines": {
"node": ">=18.17.1 <19.0.0" "node": ">=18.17.1 <19.0.0"
@ -13,12 +13,12 @@
}, },
"dependencies": { "dependencies": {
"@fluentui/react": "8.106.4", "@fluentui/react": "8.106.4",
"@microsoft/sp-adaptive-card-extension-base": "1.19.0", "@microsoft/sp-adaptive-card-extension-base": "1.20.0",
"@microsoft/sp-core-library": "1.19.0", "@microsoft/sp-core-library": "1.20.0",
"@microsoft/sp-lodash-subset": "1.19.0", "@microsoft/sp-lodash-subset": "1.20.0",
"@microsoft/sp-office-ui-fabric-core": "1.19.0", "@microsoft/sp-office-ui-fabric-core": "1.20.0",
"@microsoft/sp-property-pane": "1.19.0", "@microsoft/sp-property-pane": "1.20.0",
"@microsoft/sp-webpart-base": "1.19.0", "@microsoft/sp-webpart-base": "1.20.0",
"@pnp/sp": "^4.1.0", "@pnp/sp": "^4.1.0",
"@pnp/spfx-controls-react": "^3.18", "@pnp/spfx-controls-react": "^3.18",
"@pnp/spfx-property-controls": "^3.17", "@pnp/spfx-property-controls": "^3.17",
@ -28,17 +28,18 @@
"tslib": "2.3.1" "tslib": "2.3.1"
}, },
"devDependencies": { "devDependencies": {
"@microsoft/eslint-config-spfx": "1.20.1", "@microsoft/eslint-config-spfx": "1.20.2",
"@microsoft/eslint-plugin-spfx": "1.20.1", "@microsoft/eslint-plugin-spfx": "1.20.2",
"@microsoft/rush-stack-compiler-4.7": "0.1.0", "@microsoft/rush-stack-compiler-4.7": "0.1.0",
"@microsoft/sp-build-web": "1.20.1", "@microsoft/sp-build-web": "1.20.2",
"@microsoft/sp-module-interfaces": "1.20.1", "@microsoft/sp-module-interfaces": "1.20.2",
"@rushstack/eslint-config": "2.5.1", "@rushstack/eslint-config": "4.0.1",
"@types/react": "17.0.45", "@types/react": "17.0.45",
"@types/react-dom": "17.0.17", "@types/react-dom": "17.0.17",
"@types/webpack-env": "1.15.2", "@types/webpack-env": "1.15.2",
"@typescript-eslint/eslint-plugin": "^8.8.0",
"ajv": "6.12.5", "ajv": "6.12.5",
"eslint": "8.7.0", "eslint": "8.57.0",
"eslint-plugin-react-hooks": "4.3.0", "eslint-plugin-react-hooks": "4.3.0",
"gulp": "4.0.2", "gulp": "4.0.2",
"typescript": "4.7.4" "typescript": "4.7.4"

View File

@ -16,6 +16,7 @@ export interface IKanbanTaskManagedProps {
name: string; name: string;
displayName?: string; displayName?: string;
type: KanbanTaskMamagedPropertyType; type: KanbanTaskMamagedPropertyType;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
value: string | number | IPersonaProps | IPersonaProps[] | any; value: string | number | IPersonaProps | IPersonaProps[] | any;
renderer?: (name: string, value: object, type: KanbanTaskMamagedPropertyType) => JSX.Element; renderer?: (name: string, value: object, type: KanbanTaskMamagedPropertyType) => JSX.Element;
} }

View File

@ -17,9 +17,9 @@ export interface IKanbanBucketProps extends IKanbanBucket {
toggleCompleted?: (taskId: string) => void; toggleCompleted?: (taskId: string) => void;
addTask?: (bucket: string) => void; addTask?: (bucket: string) => void;
onDragStart: (event: any, taskId: string, bucket: string) => void; onDragStart: (event: React.DragEvent<HTMLDivElement>, taskId: string, bucket: string) => void;
onDragEnd: (event: any, taskId: string, bucket: string) => void; onDragEnd: (event: React.DragEvent<HTMLDivElement>, taskId: string, bucket: string) => void;

View File

@ -88,7 +88,7 @@ export class KanbanBucketConfigurator extends React.Component<IKanbanBucketConfi
onChange={(ev, checked) => { this.setState({ useColor: checked?checked:false }); }} /> onChange={(ev, checked) => { this.setState({ useColor: checked?checked:false }); }} />
{this.state.useColor && (<ColorPicker {this.state.useColor && (<ColorPicker
color={statebucket.color?statebucket.color:'white'} color={statebucket.color?statebucket.color:'white'}
onChange={(ev: any, colorObj: IColor) => { onChange={(ev, colorObj: IColor) => {
if (this.state.bucket) { if (this.state.bucket) {
const bucket = clone(this.state.bucket); const bucket = clone(this.state.bucket);
bucket.color = colorObj.str; bucket.color = colorObj.str;

View File

@ -49,7 +49,7 @@ export enum DialogState {
export class KanbanComponent extends React.Component<IKanbanComponentProps, IKanbanComponentState> { export class KanbanComponent extends React.Component<IKanbanComponentProps, IKanbanComponentState> {
private dragelement?: IKanbanTask; private dragelement?: IKanbanTask;
private bucketsref: any[]; private bucketsref: (HTMLDivElement|null)[];
constructor(props: IKanbanComponentProps) { constructor(props: IKanbanComponentProps) {
super(props); super(props);
@ -302,17 +302,15 @@ export class KanbanComponent extends React.Component<IKanbanComponentProps, IKan
} }
} }
private onDragLeave(event: any, bucket: string): void { private onDragLeave(event: React.DragEvent<HTMLDivElement>, bucket: string): void {
const index = findIndex(this.props.buckets, element => element.bucket === bucket); const index = findIndex(this.props.buckets, element => element.bucket === bucket);
if (index !== -1 && this.bucketsref.length > index) { if (index !== -1 && this.bucketsref.length > index && this.bucketsref[index] !== null) {
this.bucketsref[index]?.classList.remove(styles.dragover);
//&& this.bucketsref[index].classList.contains(styles.dragover)) {
this.bucketsref[index].classList.remove(styles.dragover);
} }
} }
private onDragEnd(event: any): void { private onDragEnd(event:React.DragEvent<HTMLDivElement>): void {
this.dragelement = undefined; this.dragelement = undefined;
this.setState({ this.setState({
@ -322,7 +320,7 @@ export class KanbanComponent extends React.Component<IKanbanComponentProps, IKan
}); });
} }
private onDragStart(event: any, taskId: string, bucket: string): void { private onDragStart(event: React.DragEvent<HTMLDivElement>, taskId: string, bucket: string): void {
console.log('onDragStart'); console.log('onDragStart');
const taskitem = this.props.tasks.filter(p => p.taskId === taskId); const taskitem = this.props.tasks.filter(p => p.taskId === taskId);
if (taskitem.length === 1) { if (taskitem.length === 1) {
@ -344,23 +342,22 @@ export class KanbanComponent extends React.Component<IKanbanComponentProps, IKan
} }
private onDragOver(event: any, targetbucket: string): void { private onDragOver(event: React.DragEvent<HTMLDivElement>, targetbucket: string): void {
event.preventDefault(); event.preventDefault();
console.log('onDragOver'); console.log('onDragOver');
if (this.dragelement && this.dragelement?.bucket !== targetbucket) { if (this.dragelement && this.dragelement?.bucket !== targetbucket) {
const index = findIndex(this.props.buckets, element => element.bucket === targetbucket); const index = findIndex(this.props.buckets, element => element.bucket === targetbucket);
if (index > -1 && this.bucketsref.length > index) { if (index > -1 && this.bucketsref.length > index && this.bucketsref[index] !== null) {
//&& this.bucketsref[index].classList.contains(styles.dragover)) { this.bucketsref[index]?.classList.add(styles.dragover);
this.bucketsref[index].classList.add(styles.dragover);
} }
} }
} }
private onDrop(event: any, targetbucket: string): void { private onDrop(event: React.DragEvent<HTMLDivElement>, targetbucket: string): void {
if (this.bucketsref && this.bucketsref.length > 0) { if (this.bucketsref && this.bucketsref.length > 0) {
this.bucketsref.forEach(x => { x.classList.remove(styles.dragover); }); this.bucketsref.forEach(x => { if(x!== null){ x.classList.remove(styles.dragover);} });
} }
if (this.dragelement && this.dragelement?.bucket !== targetbucket) { if (this.dragelement && this.dragelement?.bucket !== targetbucket) {
//event.dataTransfer.getData("text"); //event.dataTransfer.getData("text");

View File

@ -11,8 +11,8 @@ export interface IKanbanTaskProps extends IKanbanTask, IKanbanBoardTaskSettings
toggleCompleted?: (taskId: string) => void; toggleCompleted?: (taskId: string) => void;
openDetails: (taskId: string) => void; openDetails: (taskId: string) => void;
onDragStart: (event:any) => void; onDragStart: (event:React.DragEvent<HTMLDivElement>) => void;
onDragEnd: (event:any) => void; onDragEnd: (event:React.DragEvent<HTMLDivElement>) => void;
isMoving: boolean; isMoving: boolean;
} }

View File

@ -40,6 +40,7 @@ export default class KanbanTaskManagedProp extends React.Component<IKanbanTaskMa
//TODO maybe Formater //TODO maybe Formater
break; break;
case KanbanTaskMamagedPropertyType.percent: case KanbanTaskMamagedPropertyType.percent:
// eslint-disable-next-line @typescript-eslint/no-explicit-any
return (value?<span>{`${(value as any) * 100}%`} </span>:<span/>); return (value?<span>{`${(value as any) * 100}%`} </span>:<span/>);
//TODO maybe better Formater //TODO maybe better Formater
break; break;

View File

@ -0,0 +1,5 @@
require('@rushstack/eslint-config/patch/modern-module-resolution');
module.exports = {
extends: ['@microsoft/eslint-config-spfx/lib/profiles/react'],
parserOptions: { tsconfigRootDir: __dirname }
};

View File

@ -32,3 +32,4 @@ obj
# Styles Generated Code # Styles Generated Code
*.scss.ts *.scss.ts
*.scss.d.ts *.scss.d.ts
.heft

View File

@ -0,0 +1 @@
v18.19.0

View File

@ -1,12 +1,17 @@
{ {
"@microsoft/generator-sharepoint": { "@microsoft/generator-sharepoint": {
"version": "1.13.1", "version": "1.20.0",
"libraryName": "list-search-webpart", "libraryName": "list-search-webpart",
"libraryId": "8277f088-9c30-4f95-9c15-9c18a9d40a26", "libraryId": "8277f088-9c30-4f95-9c15-9c18a9d40a26",
"environment": "spo", "environment": "spo",
"packageManager": "npm", "packageManager": "npm",
"isCreatingSolution": false, "isCreatingSolution": false,
"isDomainIsolated": false, "isDomainIsolated": false,
"componentType": "webpart" "componentType": "webpart",
"nodeVersion": "18.19.0",
"sdkVersions": {
"@microsoft/teams-js": "2.24.0",
"@microsoft/microsoft-graph-client": "3.0.2"
}
} }
} }

View File

@ -63,8 +63,8 @@ This list search web part allows the user to show data from lists or libraries.
| 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 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.|
|Refer to <https://aka.ms/spfx-matrix> for more information on SPFx compatibility. | |Refer to <https://aka.ms/spfx-matrix> for more information on SPFx compatibility. |
![SPFx 1.13.1](https://img.shields.io/badge/SPFx-1.13.1-green.svg) ![SPFx 1.20.0](https://img.shields.io/badge/SPFx-1.20.0-green.svg)
![Node.js v14](https://img.shields.io/badge/Node.js-v14-green.svg) ![Node.js v18](https://img.shields.io/badge/Node.js-v18-green.svg)
![Compatible with SharePoint Online](https://img.shields.io/badge/SharePoint%20Online-Compatible-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 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") ![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")
@ -90,6 +90,7 @@ Version|Date|Comments
1.1.0|April 25, 2021|List item modern audience support 1.1.0|April 25, 2021|List item modern audience support
1.2.0|January 01, 2022|Upgraded for SPFx v1.13.1 1.2.0|January 01, 2022|Upgraded for SPFx v1.13.1
1.3.0|July 11, 2022|Fixes CAML issues 1.3.0|July 11, 2022|Fixes CAML issues
1.4.0|October 2, 2024|Upgraded for SPFx v1.20.0
## Minimal Path to Awesome ## Minimal Path to Awesome
@ -98,8 +99,8 @@ Version|Date|Comments
> This sample can also be opened with [VS Code Remote Development](https://code.visualstudio.com/docs/remote/remote-overview). Visit https://aka.ms/spfx-devcontainer for further instructions. > This sample can also be opened with [VS Code Remote Development](https://code.visualstudio.com/docs/remote/remote-overview). Visit https://aka.ms/spfx-devcontainer for further instructions.
* Clone this repository * Clone this repository
* From your command line, change your current directory to the directory containing this sample (react-list-search, located under samples)
* In the command line run: * In the command line run:
* Navigate to `list-search-webpart`
* `npm install` * `npm install`
* `gulp serve` * `gulp serve`
* Open the *workbench* on your Office 365 Developer tenant * Open the *workbench* on your Office 365 Developer tenant

View File

@ -9,7 +9,7 @@
"This list search web part allows the user to show data from lists or libraries." "This list search web part allows the user to show data from lists or libraries."
], ],
"creationDateTime": "2020-12-20", "creationDateTime": "2020-12-20",
"updateDateTime": "2022-07-11", "updateDateTime": "2024-10-02",
"products": [ "products": [
"SharePoint" "SharePoint"
], ],
@ -20,7 +20,7 @@
}, },
{ {
"key": "SPFX-VERSION", "key": "SPFX-VERSION",
"value": "1.11.0" "value": "1.20.0"
}, },
{ {
"key": "SPFX-SUPPORTSTHEMEVARIANTS", "key": "SPFX-SUPPORTSTHEMEVARIANTS",
@ -84,7 +84,7 @@
"authors": [ "authors": [
{ {
"gitHubAccount": "albegut", "gitHubAccount": "albegut",
"company": "Minsait", "company": "Hiberus",
"pictureUrl": "https://github.com/albegut.png", "pictureUrl": "https://github.com/albegut.png",
"name": "Alberto Gutierrez perez", "name": "Alberto Gutierrez perez",
"twitter": "albertogperez" "twitter": "albertogperez"

View File

@ -3,10 +3,21 @@
"solution": { "solution": {
"name": "list-search-webpart", "name": "list-search-webpart",
"id": "8277f088-9c30-4f95-9c15-9c18a9d40a26", "id": "8277f088-9c30-4f95-9c15-9c18a9d40a26",
"version": "1.2.0.0", "version": "1.4.0.0",
"includeClientSideAssets": true, "includeClientSideAssets": true,
"skipFeatureDeployment": true, "skipFeatureDeployment": true,
"isDomainIsolated": false, "isDomainIsolated": false,
"metadata": {
"shortDescription": {
"default": "list-search-webpart description"
},
"longDescription": {
"default": "list-search-webpart description"
},
"screenshotPaths": [],
"videoUrl": "",
"categories": []
},
"developer": { "developer": {
"name": "Alberto Gutierrez Perez", "name": "Alberto Gutierrez Perez",
"websiteUrl": "", "websiteUrl": "",
@ -14,6 +25,26 @@
"termsOfUseUrl": "", "termsOfUseUrl": "",
"mpnId": "" "mpnId": ""
}, },
"features": [
{
"title": "list-search-webpart ListSearchWebPart Feature",
"description": "The feature that activates ListSearchWebPart from the list-search-webpart solution.",
"id": "292daaa0-2474-445b-98f8-afa6ad4a9c92",
"version": "1.2.0.0",
"componentIds": [
"292daaa0-2474-445b-98f8-afa6ad4a9c92"
]
},
{
"title": "list-search-webpart ListSearchConsumerWebPartWebPart Feature",
"description": "The feature that activates ListSearchConsumerWebPartWebPart from the list-search-webpart solution.",
"id": "306e0650-db3c-443a-a698-12be6e6de1ad",
"version": "1.2.0.0",
"componentIds": [
"306e0650-db3c-443a-a698-12be6e6de1ad"
]
}
],
"webApiPermissionRequests": [ "webApiPermissionRequests": [
{ {
"resource": "Microsoft Graph", "resource": "Microsoft Graph",

View File

@ -0,0 +1,3 @@
{
"$schema": "https://developer.microsoft.com/json-schemas/core-build/sass.schema.json"
}

View File

@ -1,6 +1,6 @@
{ {
"$schema": "https://developer.microsoft.com/json-schemas/core-build/serve.schema.json", "$schema": "https://developer.microsoft.com/json-schemas/spfx-build/spfx-serve.schema.json",
"port": 4321, "port": 4321,
"https": true, "https": true,
"initialPage": "https://enter-your-SharePoint-site/_layouts/workbench.aspx" "initialPage": "https://{tenantDomain}/_layouts/workbench.aspx"
} }

View File

@ -1,6 +0,0 @@
{
"$schema": "https://raw.githubusercontent.com/s-KaiNet/spfx-fast-serve/master/schema/config.latest.schema.json",
"cli": {
"isLibraryComponent": false
}
}

View File

@ -1,24 +0,0 @@
/*
* User webpack settings file. You can add your own settings here.
* Changes from this file will be merged into the base webpack configuration file.
* This file will not be overwritten by the subsequent spfx-fast-serve calls.
*/
// you can add your project related webpack configuration here, it will be merged using webpack-merge module
// i.e. plugins: [new webpack.Plugin()]
const webpackConfig = {
}
// for even more fine-grained control, you can apply custom webpack settings using below function
const transformConfig = function (initialWebpackConfig) {
// transform the initial webpack config here, i.e.
// initialWebpackConfig.plugins.push(new webpack.Plugin()); etc.
return initialWebpackConfig;
}
module.exports = {
webpackConfig,
transformConfig
}

File diff suppressed because it is too large Load Diff

View File

@ -3,7 +3,9 @@
"version": "1.0.0", "version": "1.0.0",
"private": true, "private": true,
"main": "lib/index.js", "main": "lib/index.js",
"engines": "undefined", "engines": {
"node": ">=16.13.0 <17.0.0 || >=18.17.1 <19.0.0"
},
"scripts": { "scripts": {
"build": "gulp bundle", "build": "gulp bundle",
"clean": "gulp clean", "clean": "gulp clean",
@ -12,34 +14,43 @@
"allpackage": "gulp clean && gulp build --ship && gulp bundle --ship && gulp package-solution --ship", "allpackage": "gulp clean && gulp build --ship && gulp bundle --ship && gulp package-solution --ship",
"publish-please": "publish-please", "publish-please": "publish-please",
"prepublishOnly": "publish-please guard", "prepublishOnly": "publish-please guard",
"serve": "gulp bundle --custom-serve --max_old_space_size=4096 && fast-serve" "serve": "fast-serve"
}, },
"dependencies": { "dependencies": {
"@microsoft/sp-core-library": "1.13.1", "@fluentui/react": "8.106.4",
"@microsoft/sp-lodash-subset": "1.13.1", "@fluentui/react-components": "9.54.17",
"@microsoft/sp-office-ui-fabric-core": "1.13.1", "@microsoft/sp-adaptive-card-extension-base": "1.20.0",
"@microsoft/sp-property-pane": "1.13.1", "@microsoft/sp-core-library": "1.20.0",
"@microsoft/sp-webpart-base": "1.13.1", "@microsoft/sp-lodash-subset": "1.20.0",
"@pnp/graph": "2.4.0", "@microsoft/sp-office-ui-fabric-core": "1.20.0",
"@pnp/sp": "2.0.8", "@microsoft/sp-property-pane": "1.20.0",
"@pnp/spfx-controls-react": "2.4.0", "@microsoft/sp-webpart-base": "1.20.0",
"@pnp/spfx-property-controls": "3.3.0", "@pnp/graph": "4.5.0",
"office-ui-fabric-react": "7.174.1", "@pnp/sp": "4.5.0",
"react": "16.13.1", "@pnp/spfx-controls-react": "3.19.0",
"react-dom": "16.13.1", "@pnp/spfx-property-controls": "3.18.0",
"react": "17.0.1",
"react-dom": "17.0.1",
"react-js-pagination": "3.0.3", "react-js-pagination": "3.0.3",
"react-xml-parser": "1.1.6" "react-xml-parser": "1.1.6",
"tslib": "2.3.1"
}, },
"devDependencies": { "devDependencies": {
"@microsoft/rush-stack-compiler-3.9": "0.4.47", "@microsoft/eslint-config-spfx": "1.20.2",
"@microsoft/sp-build-web": "1.18.0", "@microsoft/eslint-plugin-spfx": "1.20.2",
"@microsoft/sp-module-interfaces": "1.13.1", "@microsoft/rush-stack-compiler-4.7": "0.1.0",
"@microsoft/sp-tslint-rules": "1.13.1", "@microsoft/sp-build-web": "1.20.2",
"@types/react": "16.9.51", "@microsoft/sp-module-interfaces": "1.20.2",
"@types/react-dom": "16.9.8", "@rushstack/eslint-config": "4.0.1",
"@types/webpack-env": "1.13.1", "@types/react": "17.0.45",
"ajv": "~6.12.3", "@types/react-dom": "17.0.17",
"@types/react-js-pagination": "^3.0.7",
"@types/webpack-env": "1.15.2",
"ajv": "6.12.5",
"eslint": "8.57.0",
"eslint-plugin-react-hooks": "4.3.0",
"gulp": "4.0.2", "gulp": "4.0.2",
"spfx-fast-serve-helpers": "~1.18.1" "spfx-fast-serve-helpers": "~1.20.0",
"typescript": "4.7.4"
} }
} }

View File

@ -3,63 +3,57 @@
"list-search-web-part": { "list-search-web-part": {
"dependencies": [ "dependencies": [
{ {
"componentId": "f9e737b7-f0df-4597-ba8c-3060f82380db", "componentId": "0d910c1c-13b9-4e1c-9aa4-b008c5e42d7d",
"componentName": "@microsoft/sp-property-pane", "componentName": "react",
"componentVersion": "1.13.1", "componentVersion": "17.0.1",
"isDirectDependency": true "isDirectDependency": true
}, },
{ {
"componentId": "1c6c9123-7aac-41f3-a376-3caea41ed83f", "componentId": "aa0a46ec-1505-43cd-a44a-93f3a5aa460a",
"componentName": "@microsoft/sp-loader", "componentName": "react-dom",
"componentVersion": "1.13.1", "componentVersion": "17.0.1",
"isDirectDependency": false "isDirectDependency": true
},
{
"componentId": "8217e442-8ed3-41fd-957d-b112e841286a",
"componentName": "@ms/sp-telemetry",
"componentVersion": "0.19.42",
"isDirectDependency": false
},
{
"componentId": "e40f8203-b39d-425a-a957-714852e33b79",
"componentName": "@microsoft/sp-dynamic-data",
"componentVersion": "1.13.1",
"isDirectDependency": false
},
{
"componentId": "73e1dc6c-8441-42cc-ad47-4bd3659f8a3a",
"componentName": "@microsoft/sp-lodash-subset",
"componentVersion": "1.13.1",
"isDirectDependency": false
}, },
{ {
"componentId": "7263c7d0-1d6a-45ec-8d85-d4d1d234171b", "componentId": "7263c7d0-1d6a-45ec-8d85-d4d1d234171b",
"componentName": "@microsoft/sp-core-library", "componentName": "@microsoft/sp-core-library",
"componentVersion": "1.13.1", "componentVersion": "1.20.0",
"isDirectDependency": false "isDirectDependency": true
}, },
{ {
"componentId": "01c4df03-e775-48cb-aa14-171ee5199a15", "componentId": "01c4df03-e775-48cb-aa14-171ee5199a15",
"componentName": "tslib", "componentName": "tslib",
"componentVersion": "1.10.0", "componentVersion": "2.3.1",
"isDirectDependency": false "isDirectDependency": false
}, },
{ {
"componentId": "2e09fb9b-13bb-48f2-859f-97d6fff71176", "componentId": "2e09fb9b-13bb-48f2-859f-97d6fff71176",
"componentName": "@ms/odsp-core-bundle", "componentName": "@ms/odsp-core-bundle",
"componentVersion": "1.1.192", "componentVersion": "1.4.195",
"isDirectDependency": false "isDirectDependency": false
}, },
{
"componentId": "f9e737b7-f0df-4597-ba8c-3060f82380db",
"componentName": "@microsoft/sp-property-pane",
"componentVersion": "1.20.0",
"isDirectDependency": true
},
{ {
"componentId": "78359e4b-07c2-43c6-8d0b-d060b4d577e8", "componentId": "78359e4b-07c2-43c6-8d0b-d060b4d577e8",
"componentName": "@microsoft/sp-diagnostics", "componentName": "@microsoft/sp-diagnostics",
"componentVersion": "1.13.1", "componentVersion": "1.20.0",
"isDirectDependency": false "isDirectDependency": false
}, },
{ {
"componentId": "1c4541f7-5c31-41aa-9fa8-fbc9dc14c0a8", "componentId": "73e1dc6c-8441-42cc-ad47-4bd3659f8a3a",
"componentName": "@microsoft/sp-page-context", "componentName": "@microsoft/sp-lodash-subset",
"componentVersion": "1.13.1", "componentVersion": "1.20.0",
"isDirectDependency": false
},
{
"componentId": "3173fefe-9995-49d1-a75d-a5caeaaba212",
"componentName": "@ms/sp-pages-content-panel-context",
"componentVersion": "0.1.0",
"isDirectDependency": false "isDirectDependency": false
}, },
{ {
@ -69,97 +63,188 @@
"isDirectDependency": false "isDirectDependency": false
}, },
{ {
"componentId": "c07208f0-ea3b-4c1a-9965-ac1b825211a6", "componentId": "63d75709-2785-4c91-97ad-489b171397d4",
"componentName": "@microsoft/sp-http", "componentName": "@ms/sp-fluentui-migration-reactdom-render-bundle",
"componentVersion": "1.13.1", "componentVersion": "0.1.0",
"isDirectDependency": false "isDirectDependency": false
}, },
{ {
"componentId": "0d910c1c-13b9-4e1c-9aa4-b008c5e42d7d", "componentId": "cc2cc925-b5be-41bb-880a-f0f8030c6aff",
"componentName": "react", "componentName": "@ms/odsp-utilities-bundle",
"componentVersion": "16.13.1", "componentVersion": "5.6.195",
"isDirectDependency": false "isDirectDependency": false
}, },
{ {
"componentId": "aa0a46ec-1505-43cd-a44a-93f3a5aa460a", "componentId": "8494e7d7-6b99-47b2-a741-59873e42f16f",
"componentName": "react-dom", "componentName": "@ms/sp-component-utilities",
"componentVersion": "16.13.1", "componentVersion": "12.52.18",
"isDirectDependency": false "isDirectDependency": false
}, },
{ {
"componentId": "467dc675-7cc5-4709-8aac-78e3b71bd2f6", "componentId": "8217e442-8ed3-41fd-957d-b112e841286a",
"componentName": "@microsoft/sp-component-base", "componentName": "@ms/sp-telemetry",
"componentVersion": "1.13.1", "componentVersion": "0.32.116",
"isDirectDependency": true "isDirectDependency": false
},
{
"componentId": "0ec74f52-38bc-4a51-ab82-7c91a2b399a2",
"componentName": "@ms/sp-fluentui-v9-utilities-bundle",
"componentVersion": "0.1.0",
"isDirectDependency": false
},
{
"componentId": "72ec0651-8a26-441c-87f2-77ec66884ca3",
"componentName": "@ms/sp-fluentui-v9-react-button-bundle",
"componentVersion": "0.1.0",
"isDirectDependency": false
},
{
"componentId": "396bbc17-3d18-4f43-8299-d99720d88e22",
"componentName": "@ms/office-ui-fabric-react-bundle",
"componentVersion": "1.19.6",
"isDirectDependency": false
},
{
"componentId": "fab65e60-a04f-4772-874c-10691e4afa4b",
"componentName": "@ms/sp-fluentui-migration-tooltip-bundle",
"componentVersion": "0.1.0",
"isDirectDependency": false
},
{
"componentId": "0ad7e31a-8df9-4659-add8-a32c8e40040d",
"componentName": "@ms/sp-fluentui-migration-button-bundle",
"componentVersion": "0.1.0",
"isDirectDependency": false
},
{
"componentId": "bf211556-3cf0-412c-9618-a4f0e7069ebf",
"componentName": "@ms/sp-heading-level",
"componentVersion": "0.1.0",
"isDirectDependency": false
},
{
"componentId": "ffe5c101-373a-4bd2-bebb-13082852bab0",
"componentName": "@ms/sp-fluentui-migration-label-bundle",
"componentVersion": "0.1.0",
"isDirectDependency": false
},
{
"componentId": "1c6c9123-7aac-41f3-a376-3caea41ed83f",
"componentName": "@microsoft/sp-loader",
"componentVersion": "1.20.0",
"isDirectDependency": false
},
{
"componentId": "8496636c-2300-4915-abef-20de64c98d8b",
"componentName": "@microsoft/sp-http-base",
"componentVersion": "1.20.0",
"isDirectDependency": false
},
{
"componentId": "1c4541f7-5c31-41aa-9fa8-fbc9dc14c0a8",
"componentName": "@microsoft/sp-page-context",
"componentVersion": "1.20.0",
"isDirectDependency": false
},
{
"componentId": "e40f8203-b39d-425a-a957-714852e33b79",
"componentName": "@microsoft/sp-dynamic-data",
"componentVersion": "1.20.0",
"isDirectDependency": false
}, },
{ {
"componentId": "974a7777-0990-4136-8fa6-95d80114c2e0", "componentId": "974a7777-0990-4136-8fa6-95d80114c2e0",
"componentName": "@microsoft/sp-webpart-base", "componentName": "@microsoft/sp-webpart-base",
"componentVersion": "1.13.1", "componentVersion": "1.20.0",
"isDirectDependency": true "isDirectDependency": true
},
{
"componentId": "467dc675-7cc5-4709-8aac-78e3b71bd2f6",
"componentName": "@microsoft/sp-component-base",
"componentVersion": "1.20.0",
"isDirectDependency": false
},
{
"componentId": "c07208f0-ea3b-4c1a-9965-ac1b825211a6",
"componentName": "@microsoft/sp-http",
"componentVersion": "1.20.0",
"isDirectDependency": false
},
{
"componentId": "aec2bbfd-a968-4d5b-a279-12e570f378e6",
"componentName": "@microsoft/sp-http-msgraph",
"componentVersion": "1.20.0",
"isDirectDependency": false
},
{
"componentId": "6d3c733c-8cb7-4871-bb22-b5b37c1d518d",
"componentName": "@ms/sp-safehtml",
"componentVersion": "0.4.0",
"isDirectDependency": false
},
{
"componentId": "42647dee-1f75-4b9f-b521-5c844a6c35cc",
"componentName": "@ms/sp-edit-customer-promise",
"componentVersion": "0.1.0",
"isDirectDependency": false
} }
] ],
"asyncChunks": {}
}, },
"list-search-consumer-web-part-web-part": { "list-search-consumer-web-part-web-part": {
"dependencies": [ "dependencies": [
{ {
"componentId": "f9e737b7-f0df-4597-ba8c-3060f82380db", "componentId": "0d910c1c-13b9-4e1c-9aa4-b008c5e42d7d",
"componentName": "@microsoft/sp-property-pane", "componentName": "react",
"componentVersion": "1.13.1", "componentVersion": "17.0.1",
"isDirectDependency": true "isDirectDependency": true
}, },
{ {
"componentId": "1c6c9123-7aac-41f3-a376-3caea41ed83f", "componentId": "aa0a46ec-1505-43cd-a44a-93f3a5aa460a",
"componentName": "@microsoft/sp-loader", "componentName": "react-dom",
"componentVersion": "1.13.1", "componentVersion": "17.0.1",
"isDirectDependency": false "isDirectDependency": true
}, },
{ {
"componentId": "8217e442-8ed3-41fd-957d-b112e841286a", "componentId": "f9e737b7-f0df-4597-ba8c-3060f82380db",
"componentName": "@ms/sp-telemetry", "componentName": "@microsoft/sp-property-pane",
"componentVersion": "0.19.42", "componentVersion": "1.20.0",
"isDirectDependency": false "isDirectDependency": true
}, },
{ {
"componentId": "e40f8203-b39d-425a-a957-714852e33b79", "componentId": "78359e4b-07c2-43c6-8d0b-d060b4d577e8",
"componentName": "@microsoft/sp-dynamic-data", "componentName": "@microsoft/sp-diagnostics",
"componentVersion": "1.13.1", "componentVersion": "1.20.0",
"isDirectDependency": false
},
{
"componentId": "73e1dc6c-8441-42cc-ad47-4bd3659f8a3a",
"componentName": "@microsoft/sp-lodash-subset",
"componentVersion": "1.13.1",
"isDirectDependency": false "isDirectDependency": false
}, },
{ {
"componentId": "7263c7d0-1d6a-45ec-8d85-d4d1d234171b", "componentId": "7263c7d0-1d6a-45ec-8d85-d4d1d234171b",
"componentName": "@microsoft/sp-core-library", "componentName": "@microsoft/sp-core-library",
"componentVersion": "1.13.1", "componentVersion": "1.20.0",
"isDirectDependency": false "isDirectDependency": false
}, },
{ {
"componentId": "01c4df03-e775-48cb-aa14-171ee5199a15", "componentId": "01c4df03-e775-48cb-aa14-171ee5199a15",
"componentName": "tslib", "componentName": "tslib",
"componentVersion": "1.10.0", "componentVersion": "2.3.1",
"isDirectDependency": false "isDirectDependency": false
}, },
{ {
"componentId": "2e09fb9b-13bb-48f2-859f-97d6fff71176", "componentId": "2e09fb9b-13bb-48f2-859f-97d6fff71176",
"componentName": "@ms/odsp-core-bundle", "componentName": "@ms/odsp-core-bundle",
"componentVersion": "1.1.192", "componentVersion": "1.4.195",
"isDirectDependency": false "isDirectDependency": false
}, },
{ {
"componentId": "78359e4b-07c2-43c6-8d0b-d060b4d577e8", "componentId": "73e1dc6c-8441-42cc-ad47-4bd3659f8a3a",
"componentName": "@microsoft/sp-diagnostics", "componentName": "@microsoft/sp-lodash-subset",
"componentVersion": "1.13.1", "componentVersion": "1.20.0",
"isDirectDependency": false "isDirectDependency": false
}, },
{ {
"componentId": "1c4541f7-5c31-41aa-9fa8-fbc9dc14c0a8", "componentId": "3173fefe-9995-49d1-a75d-a5caeaaba212",
"componentName": "@microsoft/sp-page-context", "componentName": "@ms/sp-pages-content-panel-context",
"componentVersion": "1.13.1", "componentVersion": "0.1.0",
"isDirectDependency": false "isDirectDependency": false
}, },
{ {
@ -169,36 +254,133 @@
"isDirectDependency": false "isDirectDependency": false
}, },
{ {
"componentId": "c07208f0-ea3b-4c1a-9965-ac1b825211a6", "componentId": "63d75709-2785-4c91-97ad-489b171397d4",
"componentName": "@microsoft/sp-http", "componentName": "@ms/sp-fluentui-migration-reactdom-render-bundle",
"componentVersion": "1.13.1", "componentVersion": "0.1.0",
"isDirectDependency": false "isDirectDependency": false
}, },
{ {
"componentId": "0d910c1c-13b9-4e1c-9aa4-b008c5e42d7d", "componentId": "cc2cc925-b5be-41bb-880a-f0f8030c6aff",
"componentName": "react", "componentName": "@ms/odsp-utilities-bundle",
"componentVersion": "16.13.1", "componentVersion": "5.6.195",
"isDirectDependency": false "isDirectDependency": false
}, },
{ {
"componentId": "aa0a46ec-1505-43cd-a44a-93f3a5aa460a", "componentId": "8494e7d7-6b99-47b2-a741-59873e42f16f",
"componentName": "react-dom", "componentName": "@ms/sp-component-utilities",
"componentVersion": "16.13.1", "componentVersion": "12.52.18",
"isDirectDependency": false
},
{
"componentId": "8217e442-8ed3-41fd-957d-b112e841286a",
"componentName": "@ms/sp-telemetry",
"componentVersion": "0.32.116",
"isDirectDependency": false
},
{
"componentId": "0ec74f52-38bc-4a51-ab82-7c91a2b399a2",
"componentName": "@ms/sp-fluentui-v9-utilities-bundle",
"componentVersion": "0.1.0",
"isDirectDependency": false
},
{
"componentId": "72ec0651-8a26-441c-87f2-77ec66884ca3",
"componentName": "@ms/sp-fluentui-v9-react-button-bundle",
"componentVersion": "0.1.0",
"isDirectDependency": false
},
{
"componentId": "396bbc17-3d18-4f43-8299-d99720d88e22",
"componentName": "@ms/office-ui-fabric-react-bundle",
"componentVersion": "1.19.6",
"isDirectDependency": false
},
{
"componentId": "fab65e60-a04f-4772-874c-10691e4afa4b",
"componentName": "@ms/sp-fluentui-migration-tooltip-bundle",
"componentVersion": "0.1.0",
"isDirectDependency": false
},
{
"componentId": "0ad7e31a-8df9-4659-add8-a32c8e40040d",
"componentName": "@ms/sp-fluentui-migration-button-bundle",
"componentVersion": "0.1.0",
"isDirectDependency": false
},
{
"componentId": "bf211556-3cf0-412c-9618-a4f0e7069ebf",
"componentName": "@ms/sp-heading-level",
"componentVersion": "0.1.0",
"isDirectDependency": false
},
{
"componentId": "ffe5c101-373a-4bd2-bebb-13082852bab0",
"componentName": "@ms/sp-fluentui-migration-label-bundle",
"componentVersion": "0.1.0",
"isDirectDependency": false
},
{
"componentId": "1c6c9123-7aac-41f3-a376-3caea41ed83f",
"componentName": "@microsoft/sp-loader",
"componentVersion": "1.20.0",
"isDirectDependency": false
},
{
"componentId": "8496636c-2300-4915-abef-20de64c98d8b",
"componentName": "@microsoft/sp-http-base",
"componentVersion": "1.20.0",
"isDirectDependency": false
},
{
"componentId": "1c4541f7-5c31-41aa-9fa8-fbc9dc14c0a8",
"componentName": "@microsoft/sp-page-context",
"componentVersion": "1.20.0",
"isDirectDependency": false
},
{
"componentId": "e40f8203-b39d-425a-a957-714852e33b79",
"componentName": "@microsoft/sp-dynamic-data",
"componentVersion": "1.20.0",
"isDirectDependency": false "isDirectDependency": false
}, },
{ {
"componentId": "974a7777-0990-4136-8fa6-95d80114c2e0", "componentId": "974a7777-0990-4136-8fa6-95d80114c2e0",
"componentName": "@microsoft/sp-webpart-base", "componentName": "@microsoft/sp-webpart-base",
"componentVersion": "1.13.1", "componentVersion": "1.20.0",
"isDirectDependency": true "isDirectDependency": true
}, },
{ {
"componentId": "467dc675-7cc5-4709-8aac-78e3b71bd2f6", "componentId": "467dc675-7cc5-4709-8aac-78e3b71bd2f6",
"componentName": "@microsoft/sp-component-base", "componentName": "@microsoft/sp-component-base",
"componentVersion": "1.13.1", "componentVersion": "1.20.0",
"isDirectDependency": false
},
{
"componentId": "c07208f0-ea3b-4c1a-9965-ac1b825211a6",
"componentName": "@microsoft/sp-http",
"componentVersion": "1.20.0",
"isDirectDependency": false
},
{
"componentId": "aec2bbfd-a968-4d5b-a279-12e570f378e6",
"componentName": "@microsoft/sp-http-msgraph",
"componentVersion": "1.20.0",
"isDirectDependency": false
},
{
"componentId": "6d3c733c-8cb7-4871-bb22-b5b37c1d518d",
"componentName": "@ms/sp-safehtml",
"componentVersion": "0.4.0",
"isDirectDependency": false
},
{
"componentId": "42647dee-1f75-4b9f-b521-5c844a6c35cc",
"componentName": "@ms/sp-edit-customer-promise",
"componentVersion": "0.1.0",
"isDirectDependency": false "isDirectDependency": false
} }
] ],
"asyncChunks": {}
} }
} }
} }

File diff suppressed because one or more lines are too long

View File

@ -1,3 +1,4 @@
@import '~@fluentui/react/dist/sass/References.scss';
@import '~@microsoft/sp-office-ui-fabric-core/dist/sass/SPFabricCore.scss'; @import '~@microsoft/sp-office-ui-fabric-core/dist/sass/SPFabricCore.scss';
.listSearch { .listSearch {
@include ms-Grid; @include ms-Grid;

View File

@ -15,15 +15,15 @@ import { PropertyFieldCollectionData, CustomCollectionFieldType } from '@pnp/spf
import { IListSearchProps } from './components/IListSearchProps'; import { IListSearchProps } from './components/IListSearchProps';
import ListSearch from './components/ListSearch'; import ListSearch from './components/ListSearch';
import * as strings from 'ListSearchWebPartStrings'; import * as strings from 'ListSearchWebPartStrings';
import { IMappingFieldData, IListData, IDetailListFieldData, ICompleteModalData, IRedirectData, ICustomOption, SitesLists, SiteList, ListsFields, ListField, SitesFields } from './model/IListConfigProps'; import { IMappingFieldData, IListData, IDetailListFieldData, IRedirectData, ICustomOption, SitesLists, SiteList, ListField, SitesFields, IBaseFieldData } from './model/IListConfigProps';
import { IPropertyFieldSite, PropertyFieldSitePicker, } from '@pnp/spfx-property-controls/lib/PropertyFieldSitePicker'; import { IPropertyFieldSite, PropertyFieldSitePicker, } from '@pnp/spfx-property-controls/lib/PropertyFieldSitePicker';
import { PropertyFieldNumber } from '@pnp/spfx-property-controls/lib/PropertyFieldNumber'; import { PropertyFieldNumber } from '@pnp/spfx-property-controls/lib/PropertyFieldNumber';
import { Placeholder } from "@pnp/spfx-controls-react/lib/Placeholder"; import { IPlaceholderProps, Placeholder } from "@pnp/spfx-controls-react/lib/Placeholder";
import { DisplayMode } from '@microsoft/sp-core-library'; import { DisplayMode } from '@microsoft/sp-core-library';
import { EmptyPropertyPane } from './custompropertyPane/EmptyPropertyPane'; import { EmptyPropertyPane } from './custompropertyPane/EmptyPropertyPane';
import { ThemeProvider, ThemeChangedEventArgs, IReadonlyTheme, DynamicProperty } from '@microsoft/sp-component-base'; import { ThemeProvider, ThemeChangedEventArgs, IReadonlyTheme, DynamicProperty } from '@microsoft/sp-component-base';
import { PropertyFieldMultiSelect } from '@pnp/spfx-property-controls/lib/PropertyFieldMultiSelect'; import { PropertyFieldMultiSelect } from '@pnp/spfx-property-controls/lib/PropertyFieldMultiSelect';
import { IDropdownOption } from 'office-ui-fabric-react/lib/components/Dropdown'; import { IDropdownOption } from '@fluentui/react';
import CustomCollectionDataField from './custompropertyPane/CustomCollectionDataField'; import CustomCollectionDataField from './custompropertyPane/CustomCollectionDataField';
import ListService from './services/ListService'; import ListService from './services/ListService';
import { IDynamicDataCallables, IDynamicDataPropertyDefinition } from '@microsoft/sp-dynamic-data'; import { IDynamicDataCallables, IDynamicDataPropertyDefinition } from '@microsoft/sp-dynamic-data';
@ -31,7 +31,7 @@ import { IDynamicItem } from './model/IDynamicItem';
import { PropertyPaneWebPartInformation } from '@pnp/spfx-property-controls/lib/PropertyPaneWebPartInformation'; import { PropertyPaneWebPartInformation } from '@pnp/spfx-property-controls/lib/PropertyPaneWebPartInformation';
import { SharePointFieldTypes, SharePointType } from './model/ISharePointFieldTypes'; import { SharePointFieldTypes, SharePointType } from './model/ISharePointFieldTypes';
import { IModalType } from './model/IModalType'; import { IModalType } from './model/IModalType';
import { find, has } from '@microsoft/sp-lodash-subset'; import { cloneDeep } from '@microsoft/sp-lodash-subset';
@ -65,7 +65,7 @@ export interface IListSearchWebPartProps {
onClickSelectedOption: string; onClickSelectedOption: string;
clickEnabled: boolean; clickEnabled: boolean;
ModalType: IModalType; ModalType: IModalType;
completeModalFields: Array<ICompleteModalData>; completeModalFields: Array<IBaseFieldData>;
redirectData: Array<IRedirectData>; redirectData: Array<IRedirectData>;
onRedirectIdQuery: string; onRedirectIdQuery: string;
onClickNumberOfClicksOption: string; onClickNumberOfClicksOption: string;
@ -87,7 +87,7 @@ export default class ListSearchWebPart extends BaseClientSideWebPart<IListSearch
private sitesLists: SitesLists = {}; private sitesLists: SitesLists = {};
private ListsFields: SitesFields = {}; private ListsFields: SitesFields = {};
constructor(props) { constructor() {
super(); super();
this.saveSiteCollectionLists = this.saveSiteCollectionLists.bind(this); this.saveSiteCollectionLists = this.saveSiteCollectionLists.bind(this);
this.saveSiteCollectionListsFields = this.saveSiteCollectionListsFields.bind(this); this.saveSiteCollectionListsFields = this.saveSiteCollectionListsFields.bind(this);
@ -147,7 +147,7 @@ export default class ListSearchWebPart extends BaseClientSideWebPart<IListSearch
} }
protected async onPropertyPaneConfigurationStart() { protected async onPropertyPaneConfigurationStart() {
await this.loadCollectionData(); return await this.loadCollectionData();
} }
private _handleThemeChangedEvent(args: ThemeChangedEventArgs): void { private _handleThemeChangedEvent(args: ThemeChangedEventArgs): void {
@ -156,22 +156,22 @@ export default class ListSearchWebPart extends BaseClientSideWebPart<IListSearch
} }
private async loadCollectionData() { private async loadCollectionData() {
let sitesListsInfo: Promise<any> = this.loadSitesLists(); const sitesListsInfo: Promise<void> = this.loadSitesLists();
let listsFieldsInfo: Promise<any> = this.loadListsFields(); const listsFieldsInfo: Promise<void> = this.loadListsFields();
await Promise.all([sitesListsInfo, listsFieldsInfo]); await Promise.all([sitesListsInfo, listsFieldsInfo]);
} }
private async loadSitesLists() { private async loadSitesLists() {
let listsDataPromises: Promise<Array<SiteList>>[] = []; const listsDataPromises: Promise<Array<SiteList>>[] = [];
let sites: string[] = []; const sites: string[] = [];
this.properties.sites.map((item, index, array) => { this.properties.sites.map((item, index, array) => {
if (array.indexOf(item) == index) { if (array.indexOf(item) == index) {
let service: ListService = new ListService(item.url, false); const service: ListService = new ListService(this.context, item.url, false);
listsDataPromises.push(service.getSiteListsTitle()); listsDataPromises.push(service.getSiteListsTitle());
sites.push(item.url); sites.push(item.url);
} }
}); });
let listData = await Promise.all(listsDataPromises); const listData = await Promise.all(listsDataPromises);
listData.map((lists, index) => { listData.map((lists, index) => {
this.saveSiteCollectionLists(sites[index], lists); this.saveSiteCollectionLists(sites[index], lists);
@ -180,7 +180,7 @@ export default class ListSearchWebPart extends BaseClientSideWebPart<IListSearch
private async loadListsFields() { private async loadListsFields() {
if (this.properties.listsCollectionData && this.properties.listsCollectionData.length > 0) { if (this.properties.listsCollectionData && this.properties.listsCollectionData.length > 0) {
let siteStructure = {}; const siteStructure: { [listId: string]: Array<string>; } = {};
this.properties.listsCollectionData.map(option => { this.properties.listsCollectionData.map(option => {
if (!siteStructure[option.SiteCollectionSource]) { if (!siteStructure[option.SiteCollectionSource]) {
siteStructure[option.SiteCollectionSource] = []; siteStructure[option.SiteCollectionSource] = [];
@ -188,12 +188,12 @@ export default class ListSearchWebPart extends BaseClientSideWebPart<IListSearch
siteStructure[option.SiteCollectionSource].push(option.ListSourceField); siteStructure[option.SiteCollectionSource].push(option.ListSourceField);
}); });
let listsDataPromises: Promise<any>[] = []; const listsDataPromises: Promise<Array<ListField>>[] = [];
let lists: string[] = []; const lists: string[] = [];
let sites: string[] = []; const sites: string[] = [];
Object.keys(siteStructure).map(site => { Object.keys(siteStructure).map(site => {
let service: ListService = new ListService(site, false); const service: ListService = new ListService(this.context, site, false);
siteStructure[site].map((list: string) => { siteStructure[site].map((list: string) => {
listsDataPromises.push(service.getListFields(list)); listsDataPromises.push(service.getListFields(list));
lists.push(list); lists.push(list);
@ -201,7 +201,7 @@ export default class ListSearchWebPart extends BaseClientSideWebPart<IListSearch
}); });
}); });
let listData = await Promise.all(listsDataPromises); const listData = await Promise.all(listsDataPromises);
listData.map((fields, index) => { listData.map((fields, index) => {
this.saveSiteCollectionListsFields(sites[index], lists[index], fields); this.saveSiteCollectionListsFields(sites[index], lists[index], fields);
@ -221,9 +221,9 @@ export default class ListSearchWebPart extends BaseClientSideWebPart<IListSearch
public render(): void { public render(): void {
let renderElement = null; let renderElement = null;
let isEditMode: boolean = this.displayMode === DisplayMode.Edit; const isEditMode: boolean = this.displayMode === DisplayMode.Edit;
if (!this.isConfig()) { if (!this.isConfig()) {
const placeholder: React.ReactElement<any> = React.createElement( const placeholder: React.ReactElement<IPlaceholderProps> = React.createElement(
Placeholder, Placeholder,
{ {
iconName: 'Edit', iconName: 'Edit',
@ -240,7 +240,7 @@ export default class ListSearchWebPart extends BaseClientSideWebPart<IListSearch
if (this.properties.clickEnabled) { if (this.properties.clickEnabled) {
this.setSelectedOnClickOption(this.properties.onClickSelectedOption); this.setSelectedOnClickOption(this.properties.onClickSelectedOption);
} }
let sercheableFields = this.properties.detailListFieldsCollectionData.filter(fieldData => { if (fieldData.Searcheable) return fieldData.ColumnTitle; }); const sercheableFields = this.properties.detailListFieldsCollectionData.filter(fieldData => { if (fieldData.Searcheable) return fieldData.ColumnTitle; });
if (this.properties.ShowListName && this.properties.detailListFieldsCollectionData.find(field => field.IsListTitle)) { if (this.properties.ShowListName && this.properties.detailListFieldsCollectionData.find(field => field.IsListTitle)) {
this.properties.ListNameTitle = this.properties.detailListFieldsCollectionData.find(field => field.IsListTitle).ColumnTitle; this.properties.ListNameTitle = this.properties.detailListFieldsCollectionData.find(field => field.IsListTitle).ColumnTitle;
@ -250,7 +250,7 @@ export default class ListSearchWebPart extends BaseClientSideWebPart<IListSearch
this.properties.SiteNameTitle = this.properties.detailListFieldsCollectionData.find(field => field.IsSiteTitle).ColumnTitle; this.properties.SiteNameTitle = this.properties.detailListFieldsCollectionData.find(field => field.IsSiteTitle).ColumnTitle;
} }
let queryText: string = ""; let queryText = "";
if (this.properties.initialQueryEnabled) { if (this.properties.initialQueryEnabled) {
queryText = this.properties.initialQueryOption === "simpleText" ? this.properties.initialQueryText : this.properties.dynamicQueryText.tryGetValue(); queryText = this.properties.initialQueryOption === "simpleText" ? this.properties.initialQueryText : this.properties.dynamicQueryText.tryGetValue();
} }
@ -308,7 +308,8 @@ export default class ListSearchWebPart extends BaseClientSideWebPart<IListSearch
} }
ReactDom.render(renderElement, this.domElement); // eslint-disable-next-line @typescript-eslint/no-explicit-any
ReactDom.render(renderElement as any, this.domElement);
} }
private isEmpty(str: string) { private isEmpty(str: string) {
@ -328,6 +329,7 @@ export default class ListSearchWebPart extends BaseClientSideWebPart<IListSearch
return true; return true;
} }
// eslint-disable-next-line @typescript-eslint/no-explicit-any
protected async onPropertyPaneFieldChanged(propertyPath: string, oldValue: any, newValue: any) { protected async onPropertyPaneFieldChanged(propertyPath: string, oldValue: any, newValue: any) {
super.onPropertyPaneFieldChanged(propertyPath, oldValue, newValue); super.onPropertyPaneFieldChanged(propertyPath, oldValue, newValue);
switch (propertyPath) { switch (propertyPath) {
@ -399,8 +401,8 @@ export default class ListSearchWebPart extends BaseClientSideWebPart<IListSearch
case "displayFieldsCollectionData": case "displayFieldsCollectionData":
{ {
if (newValue && newValue.length > 0) { if (newValue && newValue.length > 0) {
this.properties.ShowSiteTitle = newValue.some(field => field.IsSiteTitle); this.properties.ShowSiteTitle = newValue.some((field: { IsSiteTitle: boolean; }) => field.IsSiteTitle);
this.properties.ShowListName = newValue.some(field => field.IsListTitle); this.properties.ShowListName = newValue.some((field: { IsListTitle: boolean; }) => field.IsListTitle);
} }
break; break;
} }
@ -408,18 +410,18 @@ export default class ListSearchWebPart extends BaseClientSideWebPart<IListSearch
{ {
if (newValue && oldValue) { if (newValue && oldValue) {
if (newValue.length > 0 && oldValue.length < newValue.length) { if (newValue.length > 0 && oldValue.length < newValue.length) {
await newValue.map(async site => { await newValue.map(async (site: { url: string; }) => {
if (oldValue.indexOf(site) < 0) { if (oldValue.indexOf(site) < 0) {
let service: ListService = new ListService(site.url, false); const service: ListService = new ListService(this.context, site.url, false);
let lists: Array<SiteList> = await service.getSiteListsTitle(); const lists: Array<SiteList> = await service.getSiteListsTitle();
this.saveSiteCollectionLists(site.url, lists); this.saveSiteCollectionLists(site.url, lists);
} }
}); });
} }
else { else {
let difference = oldValue.filter(x => newValue.indexOf(x) === -1); const difference = (oldValue as IPropertyFieldSite[]).filter((x: IPropertyFieldSite) => newValue.indexOf(x) === -1);
difference.map(site => { difference.map((site: IPropertyFieldSite) => {
this.properties.listsCollectionData = this.properties.listsCollectionData.filter(item => item.SiteCollectionSource != site.url); this.properties.listsCollectionData = this.properties.listsCollectionData.filter(item => item.SiteCollectionSource != site.url);
this.properties.mappingFieldsCollectionData = this.properties.mappingFieldsCollectionData.filter(item => item.SiteCollectionSource != site.url); this.properties.mappingFieldsCollectionData = this.properties.mappingFieldsCollectionData.filter(item => item.SiteCollectionSource != site.url);
}); });
@ -524,8 +526,8 @@ export default class ListSearchWebPart extends BaseClientSideWebPart<IListSearch
} }
private getDistinctSiteCollectionSourceOptions(): IDropdownOption[] { private getDistinctSiteCollectionSourceOptions(): IDropdownOption[] {
let options: IDropdownOption[] = []; const options: IDropdownOption[] = [];
let siteOptions = this.properties.listsCollectionData && this.properties.listsCollectionData.map(option => option.SiteCollectionSource); const siteOptions = this.properties.listsCollectionData && this.properties.listsCollectionData.map(option => option.SiteCollectionSource);
if (siteOptions) { if (siteOptions) {
siteOptions.map((item, index, array) => { siteOptions.map((item, index, array) => {
if (array.indexOf(item) == index) { if (array.indexOf(item) == index) {
@ -546,29 +548,29 @@ export default class ListSearchWebPart extends BaseClientSideWebPart<IListSearch
protected getPropertyPaneConfiguration(): IPropertyPaneConfiguration { protected getPropertyPaneConfiguration(): IPropertyPaneConfiguration {
let SiteTitleOptions: IPropertyPaneDropdownOption[] = []; const SiteTitleOptions: IPropertyPaneDropdownOption[] = [];
SiteTitleOptions.push({ key: "id", text: "Id" }); SiteTitleOptions.push({ key: "id", text: "Id" });
SiteTitleOptions.push({ key: "title", text: "Title" }); SiteTitleOptions.push({ key: "title", text: "Title" });
SiteTitleOptions.push({ key: "url", text: "Url" }); SiteTitleOptions.push({ key: "url", text: "Url" });
let emptyProperty = new EmptyPropertyPane(); const emptyProperty = new EmptyPropertyPane();
let SiteNamePropertyToShowPropertyPane = this.properties.ShowSiteTitle ? PropertyPaneDropdown('SiteNamePropertyToShow', { const SiteNamePropertyToShowPropertyPane = this.properties.ShowSiteTitle ? PropertyPaneDropdown('SiteNamePropertyToShow', {
label: strings.GeneralFieldsPropertiesSiteProperty, label: strings.GeneralFieldsPropertiesSiteProperty,
disabled: !this.properties.ShowSiteTitle, disabled: !this.properties.ShowSiteTitle,
options: SiteTitleOptions options: SiteTitleOptions
}) : emptyProperty; }) : emptyProperty;
let GeneralFilterPlaceHolderPropertyPane = this.properties.GeneralFilter ? PropertyPaneTextField('GeneralFilterPlaceHolderText', { const GeneralFilterPlaceHolderPropertyPane = this.properties.GeneralFilter ? PropertyPaneTextField('GeneralFilterPlaceHolderText', {
label: strings.FilterPropertiesGeneralFilterPlaceHolder, label: strings.FilterPropertiesGeneralFilterPlaceHolder,
}) : emptyProperty; }) : emptyProperty;
let GeneralFilterInitialQueryEnabled = this.properties.GeneralFilter ? PropertyPaneToggle('initialQueryEnabled', { const GeneralFilterInitialQueryEnabled = this.properties.GeneralFilter ? PropertyPaneToggle('initialQueryEnabled', {
label: strings.GeneralFilterInitialQueryEnabled, label: strings.GeneralFilterInitialQueryEnabled,
checked: this.properties.initialQueryEnabled, checked: this.properties.initialQueryEnabled,
}) : emptyProperty; }) : emptyProperty;
let GeneralFilterInitialQueryOption = this.properties.initialQueryEnabled ? PropertyPaneDropdown('initialQueryOption', { const GeneralFilterInitialQueryOption = this.properties.initialQueryEnabled ? PropertyPaneDropdown('initialQueryOption', {
label: strings.GeneralFilterInitialQueryOption, label: strings.GeneralFilterInitialQueryOption,
options: options:
[ [
@ -581,12 +583,12 @@ export default class ListSearchWebPart extends BaseClientSideWebPart<IListSearch
] ]
}) : emptyProperty; }) : emptyProperty;
let GeneralFilterInitialQueryText = this.properties.initialQueryEnabled && this.properties.initialQueryOption === "simpleText" ? PropertyPaneTextField('initialQueryText', { const GeneralFilterInitialQueryText = this.properties.initialQueryEnabled && this.properties.initialQueryOption === "simpleText" ? PropertyPaneTextField('initialQueryText', {
label: strings.GeneralFilterInitialQueryTextValue, label: strings.GeneralFilterInitialQueryTextValue,
}) : emptyProperty; }) : emptyProperty;
let GeneralFilterConnection = this.properties.initialQueryEnabled && this.properties.initialQueryOption === "dynamicData" && this.properties.GeneralFilter ? PropertyPaneDynamicFieldSet({ const GeneralFilterConnection = this.properties.initialQueryEnabled && this.properties.initialQueryOption === "dynamicData" && this.properties.GeneralFilter ? PropertyPaneDynamicFieldSet({
label: strings.GeneralFilterConnection, label: strings.GeneralFilterConnection,
fields: [ fields: [
PropertyPaneDynamicField('dynamicQueryText', { PropertyPaneDynamicField('dynamicQueryText', {
@ -595,7 +597,7 @@ export default class ListSearchWebPart extends BaseClientSideWebPart<IListSearch
] ]
}) : emptyProperty; }) : emptyProperty;
let IndividualFilterPositionPropertyPane = this.properties.IndividualColumnFilter ? PropertyFieldMultiSelect('IndividualFilterPosition', { const IndividualFilterPositionPropertyPane = this.properties.IndividualColumnFilter ? PropertyFieldMultiSelect('IndividualFilterPosition', {
key: 'multiSelect', key: 'multiSelect',
label: strings.FilterPropertiesIndividualFilterPostion, label: strings.FilterPropertiesIndividualFilterPostion,
options: [ options: [
@ -611,24 +613,24 @@ export default class ListSearchWebPart extends BaseClientSideWebPart<IListSearch
selectedKeys: this.properties.IndividualFilterPosition selectedKeys: this.properties.IndividualFilterPosition
}) : emptyProperty; }) : emptyProperty;
let ClearAlFiltersBtnTextPropertyPane = this.properties.ShowClearAllFilters ? PropertyPaneTextField('ClearAllFiltersBtnText', { const ClearAlFiltersBtnTextPropertyPane = this.properties.ShowClearAllFilters ? PropertyPaneTextField('ClearAllFiltersBtnText', {
label: strings.FilterPropertiesClearAllBtnText, label: strings.FilterPropertiesClearAllBtnText,
}) : emptyProperty; }) : emptyProperty;
let clearAllFiltersBtnColorOptions: IPropertyPaneDropdownOption[] = []; const clearAllFiltersBtnColorOptions: IPropertyPaneDropdownOption[] = [];
clearAllFiltersBtnColorOptions.push({ key: "white", text: "White" }); clearAllFiltersBtnColorOptions.push({ key: "white", text: "White" });
clearAllFiltersBtnColorOptions.push({ key: "theme", text: "Theme" }); clearAllFiltersBtnColorOptions.push({ key: "theme", text: "Theme" });
let ClearAlFiltersBtnColorPropertyPane = this.properties.ShowClearAllFilters ? PropertyPaneDropdown('ClearAllFiltersBtnColor', { const ClearAlFiltersBtnColorPropertyPane = this.properties.ShowClearAllFilters ? PropertyPaneDropdown('ClearAllFiltersBtnColor', {
label: strings.FilterPropertiesClearAllBtnColor, label: strings.FilterPropertiesClearAllBtnColor,
options: clearAllFiltersBtnColorOptions options: clearAllFiltersBtnColorOptions
}) : emptyProperty; }) : emptyProperty;
let ItemCountTextFieldPropertyPane = this.properties.ShowItemCount ? PropertyPaneTextField('ItemCountText', { const ItemCountTextFieldPropertyPane = this.properties.ShowItemCount ? PropertyPaneTextField('ItemCountText', {
label: strings.GeneralPropertiesItemCountText, label: strings.GeneralPropertiesItemCountText,
placeholder: strings.GeneralPropertiesItemCountPlaceholder placeholder: strings.GeneralPropertiesItemCountPlaceholder
}) : emptyProperty; }) : emptyProperty;
let ItemsInPagePropertyPane = this.properties.ShowPagination && !this.properties.groupedByField ? PropertyFieldNumber("ItemsInPage", { const ItemsInPagePropertyPane = this.properties.ShowPagination && !this.properties.groupedByField ? PropertyFieldNumber("ItemsInPage", {
key: "ItemsInPage", key: "ItemsInPage",
label: strings.GeneralPropertiesItemPerPage, label: strings.GeneralPropertiesItemPerPage,
value: this.properties.ItemsInPage || null, value: this.properties.ItemsInPage || null,
@ -643,7 +645,7 @@ export default class ListSearchWebPart extends BaseClientSideWebPart<IListSearch
} }
}) : emptyProperty; }) : emptyProperty;
let groupByFieldPropertyPane = this.properties.groupedByField ? PropertyPaneDropdown('groupByField', { const groupByFieldPropertyPane = this.properties.groupedByField ? PropertyPaneDropdown('groupByField', {
label: strings.GroupFieldOptionsToSelect, label: strings.GroupFieldOptionsToSelect,
selectedKey: this.properties.groupByField, selectedKey: this.properties.groupByField,
options: this.properties.detailListFieldsCollectionData.filter(field => !field.IsFileIcon).map(field => { options: this.properties.detailListFieldsCollectionData.filter(field => !field.IsFileIcon).map(field => {
@ -651,19 +653,19 @@ export default class ListSearchWebPart extends BaseClientSideWebPart<IListSearch
}), }),
}) : emptyProperty; }) : emptyProperty;
let cacheTimePropertyPane = this.properties.UseCache ? PropertyFieldNumber("minutesToCache", { const cacheTimePropertyPane = this.properties.UseCache ? PropertyFieldNumber("minutesToCache", {
key: "minutesToCache", key: "minutesToCache",
label: strings.MinutesToCacheData, label: strings.MinutesToCacheData,
value: this.properties.minutesToCache || null, value: this.properties.minutesToCache || null,
}) : emptyProperty; }) : emptyProperty;
let CacheTypePropertyPane = this.properties.UseCache ? PropertyPaneDropdown('CacheType', { const CacheTypePropertyPane = this.properties.UseCache ? PropertyPaneDropdown('CacheType', {
label: strings.LblCacheType, label: strings.LblCacheType,
selectedKey: "local", selectedKey: "local",
options: [{ key: "local", text: "Local" }, { key: "session", text: "Session" }] options: [{ key: "local", text: "Local" }, { key: "session", text: "Session" }]
}) : emptyProperty; }) : emptyProperty;
let onclickEventOptionPropertyPane = this.properties.clickEnabled ? PropertyPaneDropdown('onClickSelectedOption', { const onclickEventOptionPropertyPane = this.properties.clickEnabled ? PropertyPaneDropdown('onClickSelectedOption', {
label: strings.OnClickOptionsToSelect, label: strings.OnClickOptionsToSelect,
selectedKey: this.properties.onClickSelectedOption || "simpleModal", selectedKey: this.properties.onClickSelectedOption || "simpleModal",
options: [ options: [
@ -694,7 +696,7 @@ export default class ListSearchWebPart extends BaseClientSideWebPart<IListSearch
], ],
}) : emptyProperty; }) : emptyProperty;
let onClickNumberOfClicksOptionPropertyPane = this.properties.clickEnabled ? PropertyPaneDropdown('onClickNumberOfClicksOption', { const onClickNumberOfClicksOptionPropertyPane = this.properties.clickEnabled ? PropertyPaneDropdown('onClickNumberOfClicksOption', {
label: strings.OnClickNumberOfClickOptionsToSelect, label: strings.OnClickNumberOfClickOptionsToSelect,
selectedKey: this.properties.onClickNumberOfClicksOption || "twoClicks", selectedKey: this.properties.onClickNumberOfClicksOption || "twoClicks",
options: [ options: [
@ -709,7 +711,7 @@ export default class ListSearchWebPart extends BaseClientSideWebPart<IListSearch
], ],
}) : emptyProperty; }) : emptyProperty;
let onClickCompleteModalPropertyPane = this.properties.clickEnabled && this.properties.ModalType === IModalType.Complete ? PropertyFieldCollectionData("completeModalFields", { const onClickCompleteModalPropertyPane = this.properties.clickEnabled && this.properties.ModalType === IModalType.Complete ? PropertyFieldCollectionData("completeModalFields", {
key: "completeModalFields", key: "completeModalFields",
label: strings.CompleteModalFieldSelector, label: strings.CompleteModalFieldSelector,
panelHeader: strings.CompleteModalHeaderSelector, panelHeader: strings.CompleteModalHeaderSelector,
@ -729,7 +731,7 @@ export default class ListSearchWebPart extends BaseClientSideWebPart<IListSearch
title: strings.CompleteModalFieldsList, title: strings.CompleteModalFieldsList,
type: CustomCollectionFieldType.custom, type: CustomCollectionFieldType.custom,
required: true, required: true,
onCustomRender: (field, value, onUpdate, item, itemId, onError) => { onCustomRender: (field, value, onUpdate, item) => {
return ( return (
CustomCollectionDataField.getListPickerBySiteOptions(this.properties.listsCollectionData, field, item, onUpdate) CustomCollectionDataField.getListPickerBySiteOptions(this.properties.listsCollectionData, field, item, onUpdate)
); );
@ -740,7 +742,7 @@ export default class ListSearchWebPart extends BaseClientSideWebPart<IListSearch
title: strings.CompleteModalFieldsListField, title: strings.CompleteModalFieldsListField,
type: CustomCollectionFieldType.custom, type: CustomCollectionFieldType.custom,
required: true, required: true,
onCustomRender: (field, value, onUpdate, item: ICompleteModalData, itemId, onError) => { onCustomRender: (field, value, onUpdate, item: IBaseFieldData) => {
if (item.SiteCollectionSource && item.ListSourceField) { if (item.SiteCollectionSource && item.ListSourceField) {
return ( return (
CustomCollectionDataField.getFieldPickerByList(this.ListsFields[item.SiteCollectionSource][item.ListSourceField], field, item, onUpdate, this.updateFieldType, this.getCustomsOptions()) CustomCollectionDataField.getFieldPickerByList(this.ListsFields[item.SiteCollectionSource][item.ListSourceField], field, item, onUpdate, this.updateFieldType, this.getCustomsOptions())
@ -759,7 +761,7 @@ export default class ListSearchWebPart extends BaseClientSideWebPart<IListSearch
title: strings.CollectionDataFieldsRenderType, title: strings.CollectionDataFieldsRenderType,
type: CustomCollectionFieldType.custom, type: CustomCollectionFieldType.custom,
required: true, required: true,
onCustomRender: (field, value, onUpdate, item, itemId, onError) => { onCustomRender: (field, value, onUpdate, item) => {
if (item.SiteCollectionSource && item.ListSourceField && item.SourceField) { if (item.SiteCollectionSource && item.ListSourceField && item.SourceField) {
return ( return (
CustomCollectionDataField.getPickerByStringOptions(this.GetRenderOptionsByType(item.SPFieldType), field, item, onUpdate, undefined) CustomCollectionDataField.getPickerByStringOptions(this.GetRenderOptionsByType(item.SPFieldType), field, item, onUpdate, undefined)
@ -770,7 +772,7 @@ export default class ListSearchWebPart extends BaseClientSideWebPart<IListSearch
] ]
}) : emptyProperty; }) : emptyProperty;
let onclickRedirectPropertyPane = this.properties.clickEnabled && this.properties.ModalType === IModalType.Redirect ? PropertyFieldCollectionData("redirectData", { const onclickRedirectPropertyPane = this.properties.clickEnabled && this.properties.ModalType === IModalType.Redirect ? PropertyFieldCollectionData("redirectData", {
key: "redirectData", key: "redirectData",
label: strings.redirectDataFieldSelector, label: strings.redirectDataFieldSelector,
panelHeader: strings.redirectDataHeaderSelector, panelHeader: strings.redirectDataHeaderSelector,
@ -789,7 +791,7 @@ export default class ListSearchWebPart extends BaseClientSideWebPart<IListSearch
title: strings.redirectDataFieldsList, title: strings.redirectDataFieldsList,
type: CustomCollectionFieldType.custom, type: CustomCollectionFieldType.custom,
required: true, required: true,
onCustomRender: (field, value, onUpdate, item, itemId, onError) => { onCustomRender: (field, value, onUpdate, item) => {
return ( return (
CustomCollectionDataField.getListPickerBySiteOptions(this.properties.listsCollectionData, field, item, onUpdate) CustomCollectionDataField.getListPickerBySiteOptions(this.properties.listsCollectionData, field, item, onUpdate)
); );
@ -804,7 +806,7 @@ export default class ListSearchWebPart extends BaseClientSideWebPart<IListSearch
] ]
}) : emptyProperty; }) : emptyProperty;
let onClickRedirectIdQueryParamProperyPane = this.properties.clickEnabled && this.properties.ModalType === IModalType.Redirect ? PropertyPaneTextField('onRedirectIdQuery', { const onClickRedirectIdQueryParamProperyPane = this.properties.clickEnabled && this.properties.ModalType === IModalType.Redirect ? PropertyPaneTextField('onRedirectIdQuery', {
label: strings.OnclickRedirectIdText, label: strings.OnclickRedirectIdText,
}) : emptyProperty; }) : emptyProperty;
@ -823,7 +825,8 @@ export default class ListSearchWebPart extends BaseClientSideWebPart<IListSearch
PropertyFieldSitePicker('sites', { PropertyFieldSitePicker('sites', {
label: strings.SitesSelector, label: strings.SitesSelector,
initialSites: this.properties.sites || [], initialSites: this.properties.sites || [],
context: this.context, // eslint-disable-next-line @typescript-eslint/no-explicit-any
context: this.context as any,
multiSelect: true, multiSelect: true,
onPropertyChange: (propertyPath, oldValue, newValue) => this.onPropertyPaneFieldChanged(propertyPath, oldValue, newValue), onPropertyChange: (propertyPath, oldValue, newValue) => this.onPropertyPaneFieldChanged(propertyPath, oldValue, newValue),
properties: this.properties, properties: this.properties,
@ -841,8 +844,8 @@ export default class ListSearchWebPart extends BaseClientSideWebPart<IListSearch
id: "SiteCollectionSource", id: "SiteCollectionSource",
title: strings.CollectionDataSiteCollectionTitle, title: strings.CollectionDataSiteCollectionTitle,
type: CustomCollectionFieldType.custom, type: CustomCollectionFieldType.custom,
onCustomRender: (field, value, onUpdate, item, itemId, onError) => { onCustomRender: (field, value, onUpdate, item) => {
let sites = this.properties.sites.map(site => { return site.url; }); const sites = this.properties.sites.map(site => { return site.url; });
return ( return (
CustomCollectionDataField.getPickerByStringOptions(sites, field, item, onUpdate, this.handleSourceSiteChange) CustomCollectionDataField.getPickerByStringOptions(sites, field, item, onUpdate, this.handleSourceSiteChange)
); );
@ -854,7 +857,7 @@ export default class ListSearchWebPart extends BaseClientSideWebPart<IListSearch
title: strings.CollectionDataListTitle, title: strings.CollectionDataListTitle,
type: CustomCollectionFieldType.custom, type: CustomCollectionFieldType.custom,
required: true, required: true,
onCustomRender: (field, value, onUpdate, item, itemId, onError) => { onCustomRender: (field, value, onUpdate, item) => {
if (item.SiteCollectionSource) { if (item.SiteCollectionSource) {
return ( return (
CustomCollectionDataField.getListPicker(this.sitesLists[item.SiteCollectionSource], field, item, onUpdate, this.setNewListFields) CustomCollectionDataField.getListPicker(this.sitesLists[item.SiteCollectionSource], field, item, onUpdate, this.setNewListFields)
@ -933,7 +936,7 @@ export default class ListSearchWebPart extends BaseClientSideWebPart<IListSearch
id: "IsSiteTitle", id: "IsSiteTitle",
title: strings.detailListFieldsIsSiteColumn, title: strings.detailListFieldsIsSiteColumn,
type: CustomCollectionFieldType.custom, type: CustomCollectionFieldType.custom,
onCustomRender: (field, value, onUpdate, item, itemId, onError) => { onCustomRender: (field, value, onUpdate, item) => {
return ( return (
CustomCollectionDataField.getDisabledCheckBoxField(field, item, onUpdate) CustomCollectionDataField.getDisabledCheckBoxField(field, item, onUpdate)
); );
@ -943,7 +946,7 @@ export default class ListSearchWebPart extends BaseClientSideWebPart<IListSearch
id: "IsListTitle", id: "IsListTitle",
title: strings.detailListFieldsIsListColumn, title: strings.detailListFieldsIsListColumn,
type: CustomCollectionFieldType.custom, type: CustomCollectionFieldType.custom,
onCustomRender: (field, value, onUpdate, item, itemId, onError) => { onCustomRender: (field, value, onUpdate, item) => {
return ( return (
CustomCollectionDataField.getDisabledCheckBoxField(field, item, onUpdate) CustomCollectionDataField.getDisabledCheckBoxField(field, item, onUpdate)
); );
@ -953,7 +956,7 @@ export default class ListSearchWebPart extends BaseClientSideWebPart<IListSearch
id: "IsFileIcon", id: "IsFileIcon",
title: strings.detailListFieldsIsFileIconColumn, title: strings.detailListFieldsIsFileIconColumn,
type: CustomCollectionFieldType.custom, type: CustomCollectionFieldType.custom,
onCustomRender: (field, value, onUpdate, item, itemId, onError) => { onCustomRender: (field, value, onUpdate, item) => {
return ( return (
CustomCollectionDataField.getDisabledCheckBoxField(field, item, onUpdate) CustomCollectionDataField.getDisabledCheckBoxField(field, item, onUpdate)
); );
@ -992,7 +995,7 @@ export default class ListSearchWebPart extends BaseClientSideWebPart<IListSearch
title: strings.CollectionDataFieldsList, title: strings.CollectionDataFieldsList,
type: CustomCollectionFieldType.custom, type: CustomCollectionFieldType.custom,
required: true, required: true,
onCustomRender: (field, value, onUpdate, item: IMappingFieldData, itemId, onError) => { onCustomRender: (field, value, onUpdate, item: IMappingFieldData) => {
return ( return (
CustomCollectionDataField.getListPickerBySiteOptions(this.properties.listsCollectionData, field, item, onUpdate, this.UpdateListNameById) CustomCollectionDataField.getListPickerBySiteOptions(this.properties.listsCollectionData, field, item, onUpdate, this.UpdateListNameById)
); );
@ -1003,7 +1006,7 @@ export default class ListSearchWebPart extends BaseClientSideWebPart<IListSearch
title: strings.CollectionDataFieldsListField, title: strings.CollectionDataFieldsListField,
type: CustomCollectionFieldType.custom, type: CustomCollectionFieldType.custom,
required: true, required: true,
onCustomRender: (field, value, onUpdate, item: IMappingFieldData, itemId, onError) => { onCustomRender: (field, value, onUpdate, item: IMappingFieldData) => {
if (item.SiteCollectionSource && item.ListSourceField) { if (item.SiteCollectionSource && item.ListSourceField) {
return ( return (
CustomCollectionDataField.getFieldPickerByList(this.ListsFields[item.SiteCollectionSource][item.ListSourceField], field, item, onUpdate, this.updateFieldType) CustomCollectionDataField.getFieldPickerByList(this.ListsFields[item.SiteCollectionSource][item.ListSourceField], field, item, onUpdate, this.updateFieldType)
@ -1016,7 +1019,7 @@ export default class ListSearchWebPart extends BaseClientSideWebPart<IListSearch
title: strings.CollectionDataFieldsTargetField, title: strings.CollectionDataFieldsTargetField,
type: CustomCollectionFieldType.custom, type: CustomCollectionFieldType.custom,
required: true, required: true,
onCustomRender: (field, value, onUpdate, item: IMappingFieldData, itemId, onError) => { onCustomRender: (field, value, onUpdate, item: IMappingFieldData, _itemId, onError) => {
if (item.SiteCollectionSource && item.ListSourceField && item.SourceField) { if (item.SiteCollectionSource && item.ListSourceField && item.SourceField) {
return ( return (
CustomCollectionDataField.getPickerByStringOptions(this.properties.detailListFieldsCollectionData.filter(column => IDetailListFieldData.IsGeneralColumn(column)).map(option => { return option.ColumnTitle; }), field, item, onUpdate, this.onMappingColumnChanged, onError) CustomCollectionDataField.getPickerByStringOptions(this.properties.detailListFieldsCollectionData.filter(column => IDetailListFieldData.IsGeneralColumn(column)).map(option => { return option.ColumnTitle; }), field, item, onUpdate, this.onMappingColumnChanged, onError)
@ -1029,7 +1032,7 @@ export default class ListSearchWebPart extends BaseClientSideWebPart<IListSearch
title: strings.CollectionDataFieldsRenderType, title: strings.CollectionDataFieldsRenderType,
type: CustomCollectionFieldType.custom, type: CustomCollectionFieldType.custom,
required: true, required: true,
onCustomRender: (field, value, onUpdate, item, itemId, onError) => { onCustomRender: (field, value, onUpdate, item) => {
if (item.SiteCollectionSource && item.ListSourceField && item.SourceField) { if (item.SiteCollectionSource && item.ListSourceField && item.SourceField) {
return ( return (
CustomCollectionDataField.getPickerByStringOptions(this.GetRenderOptionsByType(item.SPFieldType), field, item, onUpdate, undefined) CustomCollectionDataField.getPickerByStringOptions(this.GetRenderOptionsByType(item.SPFieldType), field, item, onUpdate, undefined)
@ -1195,13 +1198,14 @@ export default class ListSearchWebPart extends BaseClientSideWebPart<IListSearch
return result; return result;
} }
private onMappingColumnChanged(item: IMappingFieldData, fieldId: string, option: any, updateFunction: any, errorFunction: any) { // eslint-disable-next-line @typescript-eslint/no-explicit-any
let errorMsg: string = ""; private onMappingColumnChanged(item: IMappingFieldData, fieldId: string, option: IDropdownOption<any>, updateFunction: (fieldId: string, key: string) => void, errorFunction: (fieldId: string, key: string) => void) {
let alreadyMapped = this.properties.mappingFieldsCollectionData && this.properties.mappingFieldsCollectionData.filter(element => element.TargetField === option.key); let errorMsg = "";
const alreadyMapped = this.properties.mappingFieldsCollectionData && this.properties.mappingFieldsCollectionData.filter(element => element.TargetField === option.key);
if (alreadyMapped && alreadyMapped.length > 0) { if (alreadyMapped && alreadyMapped.length > 0) {
let sameType = alreadyMapped.filter(element => element.SPFieldType == item.SPFieldType); const sameType = alreadyMapped.filter(element => element.SPFieldType == item.SPFieldType);
if (sameType && sameType.length === alreadyMapped.length) { if (sameType && sameType.length === alreadyMapped.length) {
let sameOrigin = alreadyMapped.filter(element => element.SiteCollectionSource == item.SiteCollectionSource && element.ListSourceField == item.ListSourceField); const sameOrigin = alreadyMapped.filter(element => element.SiteCollectionSource == item.SiteCollectionSource && element.ListSourceField == item.ListSourceField);
if (sameOrigin && sameOrigin.length > 0) { if (sameOrigin && sameOrigin.length > 0) {
errorMsg = strings.LblErrorSameColumn; errorMsg = strings.LblErrorSameColumn;
} }
@ -1210,7 +1214,7 @@ export default class ListSearchWebPart extends BaseClientSideWebPart<IListSearch
errorMsg = strings.LblErrorDiferentRender; errorMsg = strings.LblErrorDiferentRender;
} }
} }
updateFunction(fieldId, option.key); updateFunction(fieldId, option.key as string);
errorFunction(fieldId, errorMsg); errorFunction(fieldId, errorMsg);
} }
@ -1220,38 +1224,47 @@ export default class ListSearchWebPart extends BaseClientSideWebPart<IListSearch
private saveSiteCollectionListsFields(site: string, listId: string, fields: ListField[]) { private saveSiteCollectionListsFields(site: string, listId: string, fields: ListField[]) {
if (this.ListsFields[site] == undefined) { if (this.ListsFields[site] == undefined) {
this.ListsFields[site] = []; this.ListsFields[site] = {};
} }
this.ListsFields[site][listId] = fields; this.ListsFields[site][listId] = fields;
} }
private async setNewListFields(row: IListData, fieldId: string, option: IDropdownOption, updateFunction: any, errorFunction: any) { // eslint-disable-next-line @typescript-eslint/no-explicit-any
private async setNewListFields(row: IListData, fieldId: string, option: IDropdownOption, updateFunction: (fieldId: string, value: any) => void) {
updateFunction(fieldId, option.key); updateFunction(fieldId, option.key);
row.ListSourceFieldName = option.text; row.ListSourceFieldName = option.text;
if (this.ListsFields[row.SiteCollectionSource] == undefined) { if (this.ListsFields[row.SiteCollectionSource] == undefined) {
this.ListsFields[row.SiteCollectionSource] = []; this.ListsFields[row.SiteCollectionSource] = {};
} }
let service: ListService = new ListService(row.SiteCollectionSource, false); const service: ListService = new ListService(this.context, row.SiteCollectionSource, false);
let fields: ListField[] = await service.getListFields(option.key.toString()); const fields: ListField[] = await service.getListFields(option.key.toString());
this.ListsFields[row.SiteCollectionSource][option.key] = fields; this.ListsFields[row.SiteCollectionSource][option.key] = cloneDeep(fields);
} }
// eslint-disable-next-line @typescript-eslint/no-explicit-any
private updateFieldType(row: any, fieldId: string, option: any, updateFunction: (fieldId: string, value: any) => void) { private updateFieldType(row: any, fieldId: string, option: any, updateFunction: (fieldId: string, value: any) => void) {
updateFunction(fieldId, option.key); updateFunction(fieldId, option.key);
row.SPFieldType = SharePointFieldTypes.GetSPFieldTypeByString(option.FieldType); row.SPFieldType = SharePointFieldTypes.GetSPFieldTypeByString(option.FieldType);
} }
private handleSourceSiteChange(row: IListData, fieldId: string, option: IDropdownOption, updateFunction: any, errorFunction: any) { private handleSourceSiteChange(
row: IListData,
fieldId: string,
option: IDropdownOption,
// eslint-disable-next-line @typescript-eslint/no-explicit-any
updateFunction: (fieldId: string, value: any) => void
) {
updateFunction(fieldId, option.key); updateFunction(fieldId, option.key);
if (row && this.properties.listsCollectionData) { if (row && this.properties.listsCollectionData) {
let savedValue = this.properties.listsCollectionData.find(element => element.uniqueId === row.uniqueId); const savedValue = this.properties.listsCollectionData.find(element => element.uniqueId === row.uniqueId);
if (savedValue && savedValue.SiteCollectionSource != option.key) { if (savedValue && savedValue.SiteCollectionSource != option.key) {
row.ListSourceField = undefined; row.ListSourceField = undefined;
} }
} }
} }
private UpdateListNameById(row: IMappingFieldData, fieldId: string, option: IDropdownOption, updateFunction: (fieldId: string, value: any) => void, errorFunction: any) { // eslint-disable-next-line @typescript-eslint/no-explicit-any
private UpdateListNameById(row: IMappingFieldData, fieldId: string, option: IDropdownOption, updateFunction: (fieldId: string, value: any) => void) {
updateFunction(fieldId, option.key); updateFunction(fieldId, option.key);
row.ListSourceFieldName = option.text; row.ListSourceFieldName = option.text;
} }

View File

@ -1,5 +1,5 @@
import { WebPartContext } from "@microsoft/sp-webpart-base"; import { WebPartContext } from "@microsoft/sp-webpart-base";
import { IMappingFieldData, IListData, IDetailListFieldData, ICompleteModalData, IRedirectData } from "../model/IListConfigProps"; import { IMappingFieldData, IListData, IDetailListFieldData, IRedirectData, IBaseFieldData } from "../model/IListConfigProps";
import { IPropertyFieldSite, } from '@pnp/spfx-property-controls/lib/PropertyFieldSitePicker'; import { IPropertyFieldSite, } from '@pnp/spfx-property-controls/lib/PropertyFieldSitePicker';
import { IReadonlyTheme } from '@microsoft/sp-component-base'; import { IReadonlyTheme } from '@microsoft/sp-component-base';
import { SharePointType } from "../model/ISharePointFieldTypes"; import { SharePointType } from "../model/ISharePointFieldTypes";
@ -38,7 +38,7 @@ export interface IListSearchProps {
minutesToCache: number; minutesToCache: number;
clickEnabled: boolean; clickEnabled: boolean;
ModalType: IModalType; ModalType: IModalType;
completeModalFields: Array<ICompleteModalData>; completeModalFields: Array<IBaseFieldData>;
redirectData: Array<IRedirectData>; redirectData: Array<IRedirectData>;
onRedirectIdQuery: string; onRedirectIdQuery: string;
onSelectedItem: (item: IDynamicItem) => void; onSelectedItem: (item: IDynamicItem) => void;

View File

@ -1,4 +1,4 @@
import { IColumn } from 'office-ui-fabric-react'; import { IColumn } from '@fluentui/react';
import IResult from '../model/IResult'; import IResult from '../model/IResult';
import { SharePointType } from '../model/ISharePointFieldTypes'; import { SharePointType } from '../model/ISharePointFieldTypes';

View File

@ -13,30 +13,30 @@ import {
IGroup, IGroup,
DetailsHeader, DetailsHeader,
DetailsListLayoutMode, DetailsListLayoutMode,
} from 'office-ui-fabric-react/lib/DetailsList'; } from '@fluentui/react';
import { import {
getTheme, getTheme,
IconButton, IconButton,
MessageBar, MessageBar,
MessageBarType, MessageBarType,
ShimmeredDetailsList ShimmeredDetailsList
} from 'office-ui-fabric-react'; } from '@fluentui/react';
import { SearchBox } from 'office-ui-fabric-react/lib/SearchBox'; import { SearchBox } from '@fluentui/react';
import Pagination from "react-js-pagination"; import Pagination from "react-js-pagination";
import { IReadonlyTheme } from '@microsoft/sp-component-base'; import { IReadonlyTheme } from '@microsoft/sp-component-base';
import { IIconProps } from 'office-ui-fabric-react/lib/Icon'; import { IIconProps } from '@fluentui/react';
import { DefaultButton, PrimaryButton } from 'office-ui-fabric-react'; import { DefaultButton, PrimaryButton } from '@fluentui/react';
import { Icon, ITheme } from 'office-ui-fabric-react'; import { Icon, ITheme } from '@fluentui/react';
import { Shimmer } from 'office-ui-fabric-react/lib/Shimmer'; import { Shimmer } from '@fluentui/react';
import { Modal } from 'office-ui-fabric-react/lib/Modal'; import { Modal } from '@fluentui/react';
import { Log } from '@microsoft/sp-core-library'; import { Log } from '@microsoft/sp-core-library';
import { Toggle } from 'office-ui-fabric-react/lib/Toggle'; import { Toggle } from '@fluentui/react';
import { SharePointType } from '../model/ISharePointFieldTypes'; import { SharePointType } from '../model/ISharePointFieldTypes';
import { Persona, PersonaSize } from 'office-ui-fabric-react/lib/Persona'; import { Persona, PersonaSize } from '@fluentui/react';
import { Facepile, OverflowButtonType, IFacepilePersona } from 'office-ui-fabric-react/lib/Facepile'; import { Facepile, OverflowButtonType, IFacepilePersona } from '@fluentui/react';
import StringUtils from '../services/Utils'; import StringUtils from '../services/Utils';
import { Image, IImageProps, ImageFit } from 'office-ui-fabric-react/lib/Image'; import { Image, IImageProps, ImageFit } from '@fluentui/react';
import { Link } from 'office-ui-fabric-react'; import { Link } from '@fluentui/react';
import { FileTypeIcon, ApplicationType, IconType, ImageSize } from "@pnp/spfx-controls-react/lib/FileTypeIcon"; import { FileTypeIcon, ApplicationType, IconType, ImageSize } from "@pnp/spfx-controls-react/lib/FileTypeIcon";
import IUserField from '../model/IUserField'; import IUserField from '../model/IUserField';
import IUrlField from '../model/IUrlField'; import IUrlField from '../model/IUrlField';
@ -47,6 +47,8 @@ import IResult from '../model/IResult';
import { IListSearchListQuery, IMapQuery } from '../model/IMapQuery'; import { IListSearchListQuery, IMapQuery } from '../model/IMapQuery';
import { WebPartTitle } from "@pnp/spfx-controls-react/lib/WebPartTitle"; import { WebPartTitle } from "@pnp/spfx-controls-react/lib/WebPartTitle";
import GraphService from '../services/GraphService'; import GraphService from '../services/GraphService';
import { List } from 'lodash';
import { getKeyValue } from '../utils/ObjectUtils';
const LOG_SOURCE = "IListdSearchWebPart"; const LOG_SOURCE = "IListdSearchWebPart";
@ -57,7 +59,7 @@ export default class IListdSearchWebPart extends React.Component<IListSearchProp
private keymapQuerys: IMapQuery = {}; private keymapQuerys: IMapQuery = {};
private _graphService: GraphService; private _graphService: GraphService;
constructor(props: IListSearchProps, state: IListSearchState) { constructor(props: IListSearchProps) {
super(props); super(props);
this.state = { this.state = {
activePage: 1, activePage: 1,
@ -81,7 +83,7 @@ export default class IListdSearchWebPart extends React.Component<IListSearchProp
} }
public componentDidUpdate(prevProps: Readonly<IListSearchProps>, prevState: Readonly<IListSearchState>, snapshot?: any): void { public componentDidUpdate(prevProps: Readonly<IListSearchProps>): void {
if (prevProps != this.props) { if (prevProps != this.props) {
this.setState({ items: null, filterItems: null, isLoading: true, columns: [] }); this.setState({ items: null, filterItems: null, isLoading: true, columns: [] });
this.getData(); this.getData();
@ -92,12 +94,12 @@ export default class IListdSearchWebPart extends React.Component<IListSearchProp
this.getData(); this.getData();
} }
public componentDidCatch(error, info) { componentDidCatch(error: Error, errorInfo: React.ErrorInfo): void {
Log.warn(LOG_SOURCE, `Component throw exception ${info}`, this.props.Context.serviceScope); Log.warn(LOG_SOURCE, `Component throw exception ${errorInfo}`, this.props.Context.serviceScope);
this.SetError(error, "ComponentDidCatch"); this.SetError(error, "ComponentDidCatch");
} }
private SetError(error: any, methodName: string) { private SetError(error: Error, methodName: string) {
Log.warn(LOG_SOURCE, `${methodName} set an error`, this.props.Context.serviceScope); Log.warn(LOG_SOURCE, `${methodName} set an error`, this.props.Context.serviceScope);
Log.error(LOG_SOURCE, error, this.props.Context.serviceScope); Log.error(LOG_SOURCE, error, this.props.Context.serviceScope);
this.setState({ this.setState({
@ -109,13 +111,13 @@ export default class IListdSearchWebPart extends React.Component<IListSearchProp
private async getData() { private async getData() {
try { try {
let result: any[] = await this.readListsItems(); let result: Array<IResult> = await this.readListsItems();
if (this.props.ItemLimit) { if (this.props.ItemLimit) {
result = result.slice(0, this.props.ItemLimit); result = result.slice(0, this.props.ItemLimit);
} }
let groupedItems = []; let groupedItems: IGroupedItems[] = [];
if (this.props.groupByField) { if (this.props.groupByField) {
groupedItems = this._groupBy(result, this.props.groupByField, this.props.groupByFieldType); groupedItems = this._groupBy(result, this.props.groupByField, this.props.groupByFieldType);
} }
@ -131,26 +133,27 @@ export default class IListdSearchWebPart extends React.Component<IListSearchProp
} }
} }
private async readListsItems(): Promise<Array<any>> { private async readListsItems(): Promise<Array<IResult>> {
this.generateKeymap(); this.generateKeymap();
let itemPromise: Array<Promise<Array<any>>> = []; const itemPromise: Array<Promise<Array<IResult>>> = [];
Object.keys(this.keymapQuerys).map(site => { Object.keys(this.keymapQuerys).map(site => {
let listService: ListService = new ListService(site, this.props.UseCache, this.props.minutesToCache, this.props.CacheType); const listService: ListService = new ListService(this.props.Context, site, this.props.UseCache, this.props.minutesToCache, this.props.CacheType);
let siteProperties = this.props.Sites.filter(siteInformation => siteInformation.url === site); const siteProperties = find(this.props.Sites, siteInformation => siteInformation.url === site);
Object.keys(this.keymapQuerys[site]).map(listQuery => { Object.keys(this.keymapQuerys[site]).map(listQuery => {
itemPromise.push(listService.getListItems( itemPromise.push(listService.getListItems(
this.keymapQuerys[site][listQuery], this.keymapQuerys[site][listQuery],
this.props.ListNameTitle, this.props.ListNameTitle,
this.props.SiteNameTitle, this.props.SiteNameTitle,
siteProperties[0][this.props.SiteNamePropertyToShow], // eslint-disable-next-line @typescript-eslint/no-explicit-any
getKeyValue(siteProperties, this.props.SiteNamePropertyToShow as any),
this.props.ItemLimit, this.props.ItemLimit,
this._graphService)); this._graphService));
}); });
}); });
let items = await Promise.all(itemPromise); const items = await Promise.all(itemPromise);
let result = []; const result: IResult[] = [];
items.map(partialResult => { items.map(partialResult => {
result.push(...partialResult); result.push(...partialResult);
}); });
@ -159,18 +162,19 @@ export default class IListdSearchWebPart extends React.Component<IListSearchProp
} }
private AddColumnsToDisplay(): IColumn[] { private AddColumnsToDisplay(): IColumn[] {
let columns: IColumn[] = []; const columns: IColumn[] = [];
this.props.detailListFieldsCollectionData.sort().map(column => { this.props.detailListFieldsCollectionData.sort().map(column => {
let mappingType = this.props.mappingFieldsCollectionData.find(e => e.TargetField === column.ColumnTitle); const mappingType = this.props.mappingFieldsCollectionData.find(e => e.TargetField === column.ColumnTitle);
columns.push({ key: column.ColumnTitle, name: column.ColumnTitle, fieldName: column.ColumnTitle, minWidth: column.MinColumnWidth || 50, maxWidth: column.MaxColumnWidth, isResizable: true, data: mappingType ? mappingType.SPFieldType : (column.IsFileIcon ? SharePointType.FileIcon : SharePointType.Text), onColumnClick: this._onColumnClick, isIconOnly: column.IsFileIcon }); columns.push({ key: column.ColumnTitle, name: column.ColumnTitle, fieldName: column.ColumnTitle, minWidth: column.MinColumnWidth || 50, maxWidth: column.MaxColumnWidth, isResizable: true, data: mappingType ? mappingType.SPFieldType : (column.IsFileIcon ? SharePointType.FileIcon : SharePointType.Text), onColumnClick: this._onColumnClick, isIconOnly: column.IsFileIcon });
}); });
return columns; return columns;
} }
// eslint-disable-next-line @typescript-eslint/no-explicit-any
private setNewFilterState(items: any[], generalFilter: string, collapseAllGroups: boolean, columnFilters: IColumnFilter[]) { private setNewFilterState(items: any[], generalFilter: string, collapseAllGroups: boolean, columnFilters: IColumnFilter[]) {
if (this.props.groupByField) { if (this.props.groupByField) {
let groupedItems = this._groupBy(items, this.props.groupByField, this.props.groupByFieldType); const groupedItems = this._groupBy(items, this.props.groupByField, this.props.groupByFieldType);
if (collapseAllGroups) { if (collapseAllGroups) {
this.groups.map(group => group.isCollapsed = true); this.groups.map(group => group.isCollapsed = true);
} }
@ -182,9 +186,9 @@ export default class IListdSearchWebPart extends React.Component<IListSearchProp
} }
private _getDetailListGroups(groupedItems: IGroupedItems[]) { private _getDetailListGroups(groupedItems: IGroupedItems[]) {
let groupedElements: number = 0; let groupedElements = 0;
this.groups = this.props.groupByField && groupedItems && groupedItems.map(group => { this.groups = this.props.groupByField && groupedItems && groupedItems.map(group => {
let result = { key: group.GroupName, name: group.GroupName, startIndex: groupedElements, count: group.Items.length, level: 0 }; const result = { key: group.GroupName, name: group.GroupName, startIndex: groupedElements, count: group.Items.length, level: 0 };
groupedElements += group.Items.length; groupedElements += group.Items.length;
return result; return result;
}); });
@ -200,8 +204,8 @@ export default class IListdSearchWebPart extends React.Component<IListSearchProp
} }
} }
else { else {
let listQueryInfo = find(this.props.listsCollectionData, list => list.SiteCollectionSource == item.SiteCollectionSource && list.ListSourceField == item.ListSourceField); const listQueryInfo = find(this.props.listsCollectionData, list => list.SiteCollectionSource == item.SiteCollectionSource && list.ListSourceField == item.ListSourceField);
let newQueryListItem: IListSearchListQuery = { const newQueryListItem: IListSearchListQuery = {
list: { Id: item.ListSourceField, Title: item.ListSourceFieldName }, list: { Id: item.ListSourceField, Title: item.ListSourceFieldName },
audienceEnabled: listQueryInfo.AudienceEnabled, audienceEnabled: listQueryInfo.AudienceEnabled,
fields: [{ originalField: item.SourceField, newField: item.TargetField, fieldType: item.SPFieldType }], fields: [{ originalField: item.SourceField, newField: item.TargetField, fieldType: item.SPFieldType }],
@ -212,15 +216,15 @@ export default class IListdSearchWebPart extends React.Component<IListSearchProp
} }
} }
else { else {
let listQueryInfo = find(this.props.listsCollectionData, list => list.SiteCollectionSource == item.SiteCollectionSource && list.ListSourceField == item.ListSourceField); const listQueryInfo = find(this.props.listsCollectionData, list => list.SiteCollectionSource == item.SiteCollectionSource && list.ListSourceField == item.ListSourceField);
let newQueryListItem: IListSearchListQuery = { const newQueryListItem: IListSearchListQuery = {
list: { Id: item.ListSourceField, Title: item.ListSourceFieldName }, list: { Id: item.ListSourceField, Title: item.ListSourceFieldName },
audienceEnabled: listQueryInfo.AudienceEnabled, audienceEnabled: listQueryInfo.AudienceEnabled,
fields: [{ originalField: item.SourceField, newField: item.TargetField, fieldType: item.SPFieldType }], fields: [{ originalField: item.SourceField, newField: item.TargetField, fieldType: item.SPFieldType }],
camlQuery: listQueryInfo && listQueryInfo.Query, camlQuery: listQueryInfo && listQueryInfo.Query,
viewName: listQueryInfo && listQueryInfo.ListView viewName: listQueryInfo && listQueryInfo.ListView
}; };
this.keymapQuerys[item.SiteCollectionSource] = []; this.keymapQuerys[item.SiteCollectionSource] = {};
this.keymapQuerys[item.SiteCollectionSource][item.ListSourceField] = newQueryListItem; this.keymapQuerys[item.SiteCollectionSource][item.ListSourceField] = newQueryListItem;
} }
}); });
@ -228,10 +232,10 @@ export default class IListdSearchWebPart extends React.Component<IListSearchProp
public filterColumnListItems(propertyName: string, propertyValue: string, columnType: SharePointType) { public filterColumnListItems(propertyName: string, propertyValue: string, columnType: SharePointType) {
try { try {
let isNewFilter: boolean = true; let isNewFilter = true;
let clearFilter: boolean = false; let clearFilter = false;
let isMoreRestricted: boolean = false; let isMoreRestricted = false;
let newFitlers: IColumnFilter[] = this.state.columnFilters.filter(filter => { const newFitlers: IColumnFilter[] = this.state.columnFilters.filter(filter => {
if (filter.columnName === propertyName) { if (filter.columnName === propertyName) {
isMoreRestricted = filter.filterToApply.length < propertyValue.length; isMoreRestricted = filter.filterToApply.length < propertyValue.length;
filter.filterToApply = propertyValue; filter.filterToApply = propertyValue;
@ -248,7 +252,7 @@ export default class IListdSearchWebPart extends React.Component<IListSearchProp
if (isNewFilter) newFitlers.push({ columnName: propertyName, filterToApply: propertyValue, columnType }); if (isNewFilter) newFitlers.push({ columnName: propertyName, filterToApply: propertyValue, columnType });
let itemsToRefine = (clearFilter || this.state.generalFilter) ? this.filterListItemsByGeneralFilter(this.state.generalFilter, true, false, this.state.items, this.state.filterItems) const itemsToRefine = (clearFilter || this.state.generalFilter) ? this.filterListItemsByGeneralFilter(this.state.generalFilter, true, false, this.state.items, this.state.filterItems)
: (isMoreRestricted ? this.state.filterItems : this.state.items); : (isMoreRestricted ? this.state.filterItems : this.state.items);
this.filterListItemsByColumnsFilter(itemsToRefine, newFitlers, false); this.filterListItemsByColumnsFilter(itemsToRefine, newFitlers, false);
@ -258,13 +262,15 @@ export default class IListdSearchWebPart extends React.Component<IListSearchProp
} }
} }
// eslint-disable-next-line @typescript-eslint/no-explicit-any
public filterListItemsByColumnsFilter(itemsToRefine: any[], newFilters: IColumnFilter[], isFromClearGeneralFilter: boolean) { public filterListItemsByColumnsFilter(itemsToRefine: any[], newFilters: IColumnFilter[], isFromClearGeneralFilter: boolean) {
if (this.props.IndividualColumnFilter) { if (this.props.IndividualColumnFilter) {
let newItems: Array<any> = []; // eslint-disable-next-line @typescript-eslint/no-explicit-any
const newItems: Array<any> = [];
itemsToRefine.map(item => { itemsToRefine.map(item => {
let itemFounded: boolean = true; let itemFounded = true;
newFilters.map(filter => { newFilters.map(filter => {
let value = this.GetItemValueFieldByFieldType(item, filter.columnName, filter.columnType); const value = this.GetItemValueFieldByFieldType(item, filter.columnName, filter.columnType);
if (value == undefined || value == "" || value.toString().toLowerCase().indexOf(filter.filterToApply.toLowerCase()) < 0) { if (value == undefined || value == "" || value.toString().toLowerCase().indexOf(filter.filterToApply.toLowerCase()) < 0) {
itemFounded = false; itemFounded = false;
} }
@ -281,12 +287,14 @@ export default class IListdSearchWebPart extends React.Component<IListSearchProp
public filterListItemsByGeneralFilter(valueToFilter: string, isClearFilter: boolean, reloadComponents: boolean, allItems: IResult[], filteredItems: IResult[]) { public filterListItemsByGeneralFilter(valueToFilter: string, isClearFilter: boolean, reloadComponents: boolean, allItems: IResult[], filteredItems: IResult[]) {
if (valueToFilter && valueToFilter.length > 0) { if (valueToFilter && valueToFilter.length > 0) {
let filterItems: Array<any> = []; // eslint-disable-next-line @typescript-eslint/no-explicit-any
let itemsToFilter = (isClearFilter || valueToFilter.length < this.state.generalFilter.length) ? allItems : filteredItems; const filterItems: Array<any> = [];
const itemsToFilter = (isClearFilter || valueToFilter.length < this.state.generalFilter.length) ? allItems : filteredItems;
itemsToFilter.map(item => { itemsToFilter.map(item => {
this.props.GeneralSearcheableFields.map(field => { this.props.GeneralSearcheableFields.map(field => {
if (filterItems.indexOf(item) < 0) { if (filterItems.indexOf(item) < 0) {
if (item[field.ColumnTitle] && item[field.ColumnTitle].toString().toLowerCase().indexOf(valueToFilter.toLowerCase()) > -1) { // eslint-disable-next-line @typescript-eslint/no-explicit-any
if (getKeyValue(item, field.ColumnTitle as any) && getKeyValue(item, field.ColumnTitle as any).toString().toLowerCase().indexOf(valueToFilter.toLowerCase()) > -1) {
filterItems.push(item); filterItems.push(item);
return item; return item;
} }
@ -323,12 +331,12 @@ export default class IListdSearchWebPart extends React.Component<IListSearchProp
private _onRenderDetails(detailsFooterProps: IDetailsFooterProps, showSearchBox: boolean, isHeader: boolean): JSX.Element { private _onRenderDetails(detailsFooterProps: IDetailsFooterProps, showSearchBox: boolean, isHeader: boolean): JSX.Element {
if (this.props.IndividualColumnFilter) { if (this.props.IndividualColumnFilter) {
let _renderDetailsFooterItemColumn: IDetailsRowBaseProps['onRenderItemColumn'] = (item, index, column) => { const _renderDetailsFooterItemColumn: IDetailsRowBaseProps['onRenderItemColumn'] = (item, index, column) => {
let filter: IColumnFilter = this.state.columnFilters.find(colFilter => colFilter.columnName == column.name); const filter: IColumnFilter = this.state.columnFilters.find(colFilter => colFilter.columnName == column.name);
if (this.props.IndividualColumnFilter && showSearchBox && column.data != SharePointType.FileIcon) { if (this.props.IndividualColumnFilter && showSearchBox && column.data != SharePointType.FileIcon) {
return ( return (
<SearchBox placeholder={column.name} iconProps={filterIcon} value={filter ? filter.filterToApply : ""} <SearchBox placeholder={column.name} iconProps={filterIcon} value={filter ? filter.filterToApply : ""}
underlined={true} onChange={(ev, value) => this.filterColumnListItems(column.name, value, column.data)} onClear={(ev) => this.filterColumnListItems(column.name, "", SharePointType.Text)} /> underlined={true} onChange={(_, value) => this.filterColumnListItems(column.name, value, column.data)} onClear={() => this.filterColumnListItems(column.name, "", SharePointType.Text)} />
); );
} }
else { else {
@ -355,7 +363,7 @@ export default class IListdSearchWebPart extends React.Component<IListSearchProp
} }
} }
private handlePageChange(pageNumber) { private handlePageChange(pageNumber: number) {
this.setState({ activePage: pageNumber }); this.setState({ activePage: pageNumber });
} }
@ -367,15 +375,17 @@ export default class IListdSearchWebPart extends React.Component<IListSearchProp
return this.props.IndividualColumnFilter && this.props.IndividualFilterPosition && this.props.IndividualFilterPosition.indexOf(position) > -1; return this.props.IndividualColumnFilter && this.props.IndividualFilterPosition && this.props.IndividualFilterPosition.indexOf(position) > -1;
} }
// eslint-disable-next-line @typescript-eslint/no-explicit-any
private _getItems(): Array<any> { private _getItems(): Array<any> {
let result = []; // eslint-disable-next-line @typescript-eslint/no-explicit-any
let result: any[] = [];
if (this.state.filterItems) { if (this.state.filterItems) {
if (this.props.groupByField) { if (this.props.groupByField) {
this.state.groupedItems.map(group => { result = [...result, ...group.Items]; }); this.state.groupedItems.map(group => { result = [...result, ...group.Items]; });
} }
else { else {
if (this.props.ShowPagination) { if (this.props.ShowPagination) {
let start = this.props.ItemsInPage * (this.state.activePage - 1); const start = this.props.ItemsInPage * (this.state.activePage - 1);
result = this.state.filterItems.slice(start, start + this.props.ItemsInPage); result = this.state.filterItems.slice(start, start + this.props.ItemsInPage);
} }
else { else {
@ -399,16 +409,16 @@ export default class IListdSearchWebPart extends React.Component<IListSearchProp
} }
private async GetCompleteItemData(item: IResult) { private async GetCompleteItemData(item: IResult) {
let listService: ListService = new ListService(item.SiteUrl, this.props.UseCache, this.props.minutesToCache, this.props.CacheType); const listService: ListService = new ListService(this.props.Context, item.SiteUrl, this.props.UseCache, this.props.minutesToCache, this.props.CacheType);
let completeItemQueryOptions: IListSearchListQuery = { const completeItemQueryOptions: IListSearchListQuery = {
list: item.List, list: item.List,
audienceEnabled: true, audienceEnabled: true,
fields: this.props.completeModalFields && this.props.completeModalFields.filter(field => field.SiteCollectionSource == item.SiteUrl && fields: this.props.completeModalFields && this.props.completeModalFields.filter(field => field.SiteCollectionSource == item.SiteUrl &&
field.ListSourceField == item.List.Id).map(field => { return { originalField: field.SourceField, newField: field.TargetField, fieldType: field.SPFieldType }; }) field.ListSourceField == item.List.Id).map(field => { return { originalField: field.SourceField, newField: field.TargetField, fieldType: field.SPFieldType }; })
}; };
let completeItem = await listService.getListItemById(completeItemQueryOptions, item.Id); const completeItem = await listService.getListItemById(completeItemQueryOptions, item.Id);
if (completeItem) { if (completeItem) {
completeItem.SiteUrl = item.SiteUrl; completeItem.SiteUrl = item.SiteUrl;
completeItem.ListName = item.ListName; completeItem.ListName = item.ListName;
@ -428,10 +438,10 @@ export default class IListdSearchWebPart extends React.Component<IListSearchProp
} }
case IModalType.Redirect: case IModalType.Redirect:
{ {
let config = this.props.redirectData.filter(f => f.SiteCollectionSource == this.state.selectedItem.SiteUrl && f.ListSourceField == this.state.selectedItem.List.Id); const config = this.props.redirectData.filter(f => f.SiteCollectionSource == this.state.selectedItem.SiteUrl && f.ListSourceField == this.state.selectedItem.List.Id);
if (config && config.length > 0) { if (config && config.length > 0) {
if (this.props.onRedirectIdQuery) { if (this.props.onRedirectIdQuery) {
var url = new URL(config[0].Url); const url = new URL(config[0].Url);
url.searchParams.append(this.props.onRedirectIdQuery, this.state.selectedItem.Id.toString()); url.searchParams.append(this.props.onRedirectIdQuery, this.state.selectedItem.Id.toString());
window.location.replace(url.toString()); window.location.replace(url.toString());
} }
@ -569,6 +579,7 @@ export default class IListdSearchWebPart extends React.Component<IListSearchProp
return result; return result;
} }
// eslint-disable-next-line @typescript-eslint/no-explicit-any
private getOnRowClickRender(detailrow: any, defaultRender: any): JSX.Element { private getOnRowClickRender(detailrow: any, defaultRender: any): JSX.Element {
return this.props.clickEnabled ? return this.props.clickEnabled ?
this.props.oneClickOption ? this.props.oneClickOption ?
@ -585,10 +596,12 @@ export default class IListdSearchWebPart extends React.Component<IListSearchProp
</>; </>;
} }
// eslint-disable-next-line @typescript-eslint/no-explicit-any
private _renderItemColumn(item: any, index: number, column: IColumn): JSX.Element { private _renderItemColumn(item: any, index: number, column: IColumn): JSX.Element {
return this.GetJSXElementByType(item, column.fieldName, column.data); return this.GetJSXElementByType(item, column.fieldName, column.data);
} }
// eslint-disable-next-line @typescript-eslint/no-explicit-any
private GetModalBodyRenderByFieldType(item: any, propertyName: string, fieldType: SharePointType): JSX.Element { private GetModalBodyRenderByFieldType(item: any, propertyName: string, fieldType: SharePointType): JSX.Element {
let result = this.GetJSXElementByType(item, propertyName, fieldType, true); let result = this.GetJSXElementByType(item, propertyName, fieldType, true);
@ -605,8 +618,8 @@ export default class IListdSearchWebPart extends React.Component<IListSearchProp
private GetFileIconByFileType(extesion: string): JSX.Element { private GetFileIconByFileType(extesion: string): JSX.Element {
let result; let result;
let size = ImageSize.small; const size = ImageSize.small;
let type = IconType.image; const type = IconType.image;
switch (extesion) { switch (extesion) {
case "doc": case "doc":
case "docm": case "docm":
@ -679,10 +692,11 @@ export default class IListdSearchWebPart extends React.Component<IListSearchProp
return result; return result;
} }
private GetJSXElementByType(item: any, fieldName: string, fieldType: SharePointType, ommitCamlQuery: boolean = false): JSX.Element { // eslint-disable-next-line @typescript-eslint/no-explicit-any
const value: any = this.GetItemValueFieldByFieldType(item, fieldName, fieldType, ommitCamlQuery); private GetJSXElementByType(item: any, fieldName: string, fieldType: SharePointType, ommitCamlQuery = false): JSX.Element {
const value = this.GetItemValueFieldByFieldType(item, fieldName, fieldType, ommitCamlQuery);
const { semanticColors }: IReadonlyTheme = this.props.themeVariant; const { semanticColors }: IReadonlyTheme = this.props.themeVariant;
let result: JSX.Element = <span></span>; let result: JSX.Element = <span/>;
switch (fieldType) { switch (fieldType) {
case SharePointType.FileIcon: case SharePointType.FileIcon:
{ {
@ -707,7 +721,7 @@ export default class IListdSearchWebPart extends React.Component<IListSearchProp
/>; />;
} }
else { else {
result = <span></span>; result = <span/>;
} }
} }
break; break;
@ -715,12 +729,13 @@ export default class IListdSearchWebPart extends React.Component<IListSearchProp
case SharePointType.UserMulti: case SharePointType.UserMulti:
{ {
if (this.props.AnyCamlQuery && !ommitCamlQuery && value && value.length > 0) { if (this.props.AnyCamlQuery && !ommitCamlQuery && value && value.length > 0) {
result = <span>{value.map((val, index) => { // eslint-disable-next-line @typescript-eslint/no-explicit-any
result = <span>{value.map((val: any, index: number) => {
if (index + 1 == value.length) { if (index + 1 == value.length) {
return <span style={{ color: semanticColors.bodyText }}>{val}</span>; return <span key={index} style={{ color: semanticColors.bodyText }}>{val}</span>;
} }
else { else {
return <span style={{ color: semanticColors.bodyText }}>{val}<br></br></span>; return <span key={index} style={{ color: semanticColors.bodyText }}>{val}<br/></span>;
} }
})} })}
</span>; </span>;
@ -740,7 +755,7 @@ export default class IListdSearchWebPart extends React.Component<IListSearchProp
/>; />;
} }
else { else {
result = <span></span>; result = <span/>;
} }
} }
break; break;
@ -748,18 +763,19 @@ export default class IListdSearchWebPart extends React.Component<IListSearchProp
case SharePointType.TaxonomyMulti: case SharePointType.TaxonomyMulti:
{ {
if (value) { if (value) {
result = <span>{value.map((val, index) => { // eslint-disable-next-line @typescript-eslint/no-explicit-any
result = <span>{value.map((val: any, index: number) => {
if (index + 1 == value.length) { if (index + 1 == value.length) {
return <span style={{ color: semanticColors.bodyText }}>{val}</span>; return <span key={`${fieldType}-${index}`} style={{ color: semanticColors.bodyText }}>{val}</span>;
} }
else { else {
return <span style={{ color: semanticColors.bodyText }}>{val}<br></br></span>; return <span key={`${fieldType}-${index}`} style={{ color: semanticColors.bodyText }}>{val}<br/></span>;
} }
})} })}
</span>; </span>;
} }
else { else {
result = <span></span>; result = <span/>;
} }
break; break;
} }
@ -768,39 +784,41 @@ export default class IListdSearchWebPart extends React.Component<IListSearchProp
result = <Link style={{ color: semanticColors.bodyText }} href="#">{value}</Link>; result = <Link style={{ color: semanticColors.bodyText }} href="#">{value}</Link>;
} }
else { else {
result = <span></span>; result = <span/>;
} }
break; break;
case SharePointType.ChoiceMulti: case SharePointType.ChoiceMulti:
if (value) { if (value) {
result = <span>{value.map((val, index) => { // eslint-disable-next-line @typescript-eslint/no-explicit-any
result = <span>{value.map((val: any, index: number) => {
if (index + 1 == value.length) { if (index + 1 == value.length) {
return <span style={{ color: semanticColors.bodyText }}>{val}</span>; return <span key={`${fieldType}-${index}`} style={{ color: semanticColors.bodyText }}>{val}</span>;
} }
else { else {
return <span style={{ color: semanticColors.bodyText }}>{val}<br></br></span>; return <span key={`${fieldType}-${index}`} style={{ color: semanticColors.bodyText }}>{val}<br/></span>;
} }
})} })}
</span>; </span>;
} }
else { else {
result = <span></span>; result = <span/>;
} }
break; break;
case SharePointType.LookupMulti: case SharePointType.LookupMulti:
if (value) { if (value) {
result = <span>{value.map((val, index) => { // eslint-disable-next-line @typescript-eslint/no-explicit-any
result = <span>{value.map((val: any, index: number) => {
if (index + 1 == value.length) { if (index + 1 == value.length) {
return <Link style={{ color: semanticColors.bodyText }} href="#">{val}</Link>; return <Link key={`${fieldType}-${index}`} style={{ color: semanticColors.bodyText }} href="#">{val}</Link>;
} }
else { else {
return <span><Link style={{ color: semanticColors.bodyText }} href="#">{val}</Link><br></br></span>; return <span key={`${fieldType}-${index}`}><Link style={{ color: semanticColors.bodyText }} href="#">{val}</Link><br/></span>;
} }
})} })}
</span>; </span>;
} }
else { else {
result = <span></span>; result = <span/>;
} }
break; break;
case SharePointType.Url: case SharePointType.Url:
@ -808,7 +826,7 @@ export default class IListdSearchWebPart extends React.Component<IListSearchProp
result = <Link href={value.Url} style={{ color: semanticColors.bodyText }}>{value.Description}</Link>; result = <Link href={value.Url} style={{ color: semanticColors.bodyText }}>{value.Description}</Link>;
} }
else { else {
result = <span></span>; result = <span/>;
} }
break; break;
case SharePointType.Image: case SharePointType.Image:
@ -828,17 +846,17 @@ export default class IListdSearchWebPart extends React.Component<IListSearchProp
/>; />;
} }
else { else {
result = <span></span>; result = <span/>;
} }
break; break;
} }
case SharePointType.NoteFullHtml: case SharePointType.NoteFullHtml:
{ {
if (value) { if (value) {
result = <span dangerouslySetInnerHTML={{ __html: value }}></span>; result = <span dangerouslySetInnerHTML={{ __html: value }}/>;
} }
else { else {
result = <span></span>; result = <span/>;
} }
break; break;
} }
@ -850,9 +868,11 @@ export default class IListdSearchWebPart extends React.Component<IListSearchProp
return result; return result;
} }
private GetItemValueFieldByFieldType(item: any, field: string, type: SharePointType, ommitCamlQuery: boolean = false, setGroupByEmptyValue: boolean = false): any { // eslint-disable-next-line @typescript-eslint/no-explicit-any
private GetItemValueFieldByFieldType(item: any, field: string, type: SharePointType, ommitCamlQuery = false, setGroupByEmptyValue = false): any {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
let result: any; let result: any;
let value = item[field]; const value = item[field];
switch (type) { switch (type) {
case SharePointType.FileIcon: case SharePointType.FileIcon:
{ {
@ -873,7 +893,7 @@ export default class IListdSearchWebPart extends React.Component<IListSearchProp
} }
else { else {
if (!isEmpty(value)) { if (!isEmpty(value)) {
let user: IUserField = { Name: value.Title, Email: StringUtils.GetUserEmail(value.Name) }; const user: IUserField = { Name: value.Title, Email: StringUtils.GetUserEmail(value.Name) };
result = user; result = user;
} }
} }
@ -883,7 +903,7 @@ export default class IListdSearchWebPart extends React.Component<IListSearchProp
case SharePointType.Image: case SharePointType.Image:
{ {
if (!isEmpty(value)) { if (!isEmpty(value)) {
let url: IUrlField = { Url: value.Url, Description: value.Description }; const url: IUrlField = { Url: value.Url, Description: value.Description };
result = url; result = url;
} }
break; break;
@ -915,8 +935,8 @@ export default class IListdSearchWebPart extends React.Component<IListSearchProp
} }
else { else {
if (value && value.length > 0) { if (value && value.length > 0) {
let personas: IFacepilePersona[] = value.map(user => { const personas: IFacepilePersona[] = value.map((user: { Name: string; Title: string; }) => {
let email = StringUtils.GetUserEmail(user.Name); const email = StringUtils.GetUserEmail(user.Name);
return { imageUrl: email ? `/_layouts/15/userphoto.aspx?UserName=${email}` : undefined, personaName: user.Title, imageInitials: StringUtils.GetUserInitials(user.Title), }; return { imageUrl: email ? `/_layouts/15/userphoto.aspx?UserName=${email}` : undefined, personaName: user.Title, imageInitials: StringUtils.GetUserInitials(user.Title), };
}); });
result = personas; result = personas;
@ -950,7 +970,7 @@ export default class IListdSearchWebPart extends React.Component<IListSearchProp
result = value ? value.split(';') : ""; result = value ? value.split(';') : "";
} }
else { else {
result = value && value.map(val => { return val.Title; }); result = value && value.map((val: { Title: string; }) => { return val.Title; });
} }
break; break;
} }
@ -994,7 +1014,7 @@ export default class IListdSearchWebPart extends React.Component<IListSearchProp
} }
case SharePointType.TaxonomyMulti: case SharePointType.TaxonomyMulti:
{ {
result = value && value.map(tax => { return tax.Label; }); result = value && value.map((tax: { Label: string; }) => { return tax.Label; });
break; break;
} }
default: default:
@ -1007,10 +1027,11 @@ export default class IListdSearchWebPart extends React.Component<IListSearchProp
return result || (setGroupByEmptyValue ? strings.GroupByEmptyValue : result); return result || (setGroupByEmptyValue ? strings.GroupByEmptyValue : result);
} }
private _groupBy(array, groupByField: string, groupByFieldType: SharePointType): IGroupedItems[] { // eslint-disable-next-line @typescript-eslint/no-explicit-any
private _groupBy(array: List<any>, groupByField: string, groupByFieldType: SharePointType): IGroupedItems[] {
let resArray: IGroupedItems[] = []; let resArray: IGroupedItems[] = [];
try { try {
let elementsInGroups = groupBy(array, item => this.GetItemValueFieldByFieldType(item, groupByField, groupByFieldType, false, true)); const elementsInGroups = groupBy(array, item => this.GetItemValueFieldByFieldType(item, groupByField, groupByFieldType, false, true));
resArray = Object.keys(elementsInGroups).sort().map(group => { resArray = Object.keys(elementsInGroups).sort().map(group => {
return { GroupName: group, Items: elementsInGroups[group] }; return { GroupName: group, Items: elementsInGroups[group] };
}); });
@ -1043,10 +1064,12 @@ export default class IListdSearchWebPart extends React.Component<IListSearchProp
}); });
if (this.props.groupByField) { if (this.props.groupByField) {
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
const newGroupedElements = this.state.groupedItems.map(group => { return { GroupName: group.GroupName, Items: this._copyAndSort(group.Items, currColumn.fieldName!, currColumn.isSortedDescending) }; }); const newGroupedElements = this.state.groupedItems.map(group => { return { GroupName: group.GroupName, Items: this._copyAndSort(group.Items, currColumn.fieldName!, currColumn.isSortedDescending) }; });
this.setState({ columns: newColumns, groupedItems: newGroupedElements }); this.setState({ columns: newColumns, groupedItems: newGroupedElements });
} }
else { else {
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
const newItems = this._copyAndSort(this.state.filterItems, currColumn.fieldName!, currColumn.isSortedDescending); const newItems = this._copyAndSort(this.state.filterItems, currColumn.fieldName!, currColumn.isSortedDescending);
this.setState({ columns: newColumns, filterItems: newItems }); this.setState({ columns: newColumns, filterItems: newItems });
} }
@ -1056,13 +1079,13 @@ export default class IListdSearchWebPart extends React.Component<IListSearchProp
public render(): React.ReactElement<IListSearchProps> { public render(): React.ReactElement<IListSearchProps> {
const { semanticColors }: IReadonlyTheme = this.props.themeVariant; const { semanticColors }: IReadonlyTheme = this.props.themeVariant;
let clearAllButton = this.props.ClearAllFiltersBtnColor == "white" ? <DefaultButton text={this.props.ClearAllFiltersBtnText} className={styles.btn} onClick={(ev) => this._clearAllFilters()} /> : const clearAllButton = this.props.ClearAllFiltersBtnColor == "white" ? <DefaultButton text={this.props.ClearAllFiltersBtnText} className={styles.btn} onClick={() => this._clearAllFilters()} /> :
<PrimaryButton text={this.props.ClearAllFiltersBtnText} className={styles.btn} onClick={(ev) => this._clearAllFilters()} />; <PrimaryButton text={this.props.ClearAllFiltersBtnText} className={styles.btn} onClick={() => this._clearAllFilters()} />;
return ( return (
<div className={styles.listSearch} style={{ backgroundColor: semanticColors.bodyBackground, color: semanticColors.bodyText }}> <div className={styles.listSearch} style={{ backgroundColor: semanticColors.bodyBackground, color: semanticColors.bodyText }}>
<div className={styles.row}> <div className={styles.row}>
<div className={styles.column}> <div className={styles.column}>
<WebPartTitle title={this.props.title} updateProperty={(value: string) => this.props.updateTitle(value)} displayMode={this.props.displayMode} placeholder={strings.WebPartTitlePlaceHolder}></WebPartTitle> <WebPartTitle title={this.props.title} updateProperty={(value: string) => this.props.updateTitle(value)} displayMode={this.props.displayMode} placeholder={strings.WebPartTitlePlaceHolder}/>
{this.state.errorMsg ? {this.state.errorMsg ?
<MessageBar <MessageBar
messageBarType={MessageBarType.error} messageBarType={MessageBarType.error}
@ -1089,7 +1112,7 @@ export default class IListdSearchWebPart extends React.Component<IListSearchProp
<div className={styles.rowData}> <div className={styles.rowData}>
<div className={styles.colData}> <div className={styles.colData}>
{this.props.ShowItemCount && {this.props.ShowItemCount &&
<Shimmer isDataLoaded={!this.state.isLoading} width={"25%"}><div className={styles.template_resultCount}>{this.props.ItemCountText.replace("{itemCount}", `${this.state.filterItems ? this.state.filterItems.length : 0}`)}</div></Shimmer> <Shimmer isDataLoaded={!this.state.isLoading} width={"25%"}><div className={styles.template_resultCount}>{this.props.ItemCountText?.replace("{itemCount}", `${this.state.filterItems ? this.state.filterItems.length : 0}`)}</div></Shimmer>
} }
<ShimmeredDetailsList <ShimmeredDetailsList
enableShimmer={this.state.isLoading} enableShimmer={this.state.isLoading}

View File

@ -1,18 +0,0 @@
import * as React from 'react';
import { Dropdown } from 'office-ui-fabric-react/lib/components/Dropdown';
import { ICustomCollectionField } from '@pnp/spfx-property-controls/lib/PropertyFieldCollectionData';
import { IPropertyPaneDropdownOption } from '@microsoft/sp-property-pane';
export default class CustomCheckBox {
private static getCustomCollectionDropDown(options: IPropertyPaneDropdownOption[], field: ICustomCollectionField, row: any, updateFunction: any, errorFunction?: any, customOnchangeFunction?: any): JSX.Element {
return (<Dropdown placeholder={field.placeholder || field.title}
options={options.sort((a, b) => { return a.text.localeCompare(b.text); })}
selectedKey={row[field.id] || null}
required={field.required}
onChange={(evt, option, index) => customOnchangeFunction ? customOnchangeFunction(row, field.id, option, updateFunction, errorFunction) : updateFunction(field.id, option.key)}
onRenderOption={field.onRenderOption}
className="PropertyFieldCollectionData__panel__dropdown-field" />);
}
}

View File

@ -1,28 +1,47 @@
import * as React from 'react'; import * as React from 'react';
import { Dropdown } from 'office-ui-fabric-react/lib/components/Dropdown'; import { Dropdown, IDropdownOption } from '@fluentui/react';
import { ICustomCollectionField } from '@pnp/spfx-property-controls/lib/PropertyFieldCollectionData'; import { ICustomCollectionField } from '@pnp/spfx-property-controls/lib/PropertyFieldCollectionData';
import { TextField } from 'office-ui-fabric-react/lib/components/TextField'; import { TextField } from '@fluentui/react';
import { IMappingFieldData, IListData, ICustomOption, SiteList, ListField, IBaseFieldData } from '../model/IListConfigProps'; import { IListData, ICustomOption, SiteList, ListField } from '../model/IListConfigProps';
import { IPropertyPaneDropdownOption } from '@microsoft/sp-property-pane'; import { IPropertyPaneDropdownOption } from '@microsoft/sp-property-pane';
import styles from '../ListSearchWebPart.module.scss'; import styles from '../ListSearchWebPart.module.scss';
import { Checkbox } from 'office-ui-fabric-react/lib/components/Checkbox'; import { Checkbox } from '@fluentui/react';
export default class CustomCollectionDataField { export default class CustomCollectionDataField {
private static getCustomCollectionDropDown(options: IPropertyPaneDropdownOption[], field: ICustomCollectionField, row: any, updateFunction: (fieldId: string, value: any) => void, errorFunction?: (fieldId: string, value: string) => void, customOnchangeFunction?: any): JSX.Element { private static getCustomCollectionDropDown(
options: IPropertyPaneDropdownOption[],
field: ICustomCollectionField,
// eslint-disable-next-line @typescript-eslint/no-explicit-any
row: any,
// eslint-disable-next-line @typescript-eslint/no-explicit-any
updateFunction: (fieldId: string, value: any) => void,
errorFunction?: (fieldId: string, value: string) => void,
// eslint-disable-next-line @typescript-eslint/no-explicit-any
customOnchangeFunction?: (row: any, fieldId: string, option: IDropdownOption<any>, updateFunction: (fieldId: string, value: any) => void, errorFunction: (fieldId: string, value: string) => void) => void
): JSX.Element {
return (<Dropdown placeholder={field.placeholder || field.title} return (<Dropdown placeholder={field.placeholder || field.title}
options={options.sort((a, b) => { return a.text.localeCompare(b.text); })} options={options.sort((a, b) => { return a.text.localeCompare(b.text); })}
selectedKey={row[field.id] || null} selectedKey={row[field.id] || null}
required={field.required} required={field.required}
onChange={(evt, option, index) => customOnchangeFunction ? customOnchangeFunction(row, field.id, option, updateFunction, errorFunction) : updateFunction(field.id, option.key)} onChange={(evt, option) => customOnchangeFunction ? customOnchangeFunction(row, field.id, option, updateFunction, errorFunction) : updateFunction(field.id, option.key)}
onRenderOption={field.onRenderOption} onRenderOption={field.onRenderOption}
className="PropertyFieldCollectionData__panel__dropdown-field" />); className="PropertyFieldCollectionData__panel__dropdown-field" />);
} }
public static getListPickerBySiteOptions(possibleOptions: Array<IListData>, field: ICustomCollectionField, row: any, updateFunction: (fieldId: string, value: any) => void, customOnChange?: any): JSX.Element { public static getListPickerBySiteOptions(
let currentOptions = []; possibleOptions: Array<IListData>,
field: ICustomCollectionField,
// eslint-disable-next-line @typescript-eslint/no-explicit-any
row: any,
// eslint-disable-next-line @typescript-eslint/no-explicit-any
updateFunction: (fieldId: string, value: any) => void,
// eslint-disable-next-line @typescript-eslint/no-explicit-any
customOnChange?: (row: any, fieldId: string, option: IDropdownOption<any>, updateFunction: (fieldId: string, value: any) => void, errorFunction: (fieldId: string, value: string) => void) => void,
): JSX.Element {
const currentOptions: IPropertyPaneDropdownOption[] = [];
possibleOptions.filter(option => { possibleOptions.filter(option => {
if (row.SiteCollectionSource && option.SiteCollectionSource == row.SiteCollectionSource) { if (row.SiteCollectionSource && option.SiteCollectionSource == row.SiteCollectionSource) {
currentOptions.push({ currentOptions.push({
@ -34,24 +53,54 @@ export default class CustomCollectionDataField {
return this.getCustomCollectionDropDown(currentOptions, field, row, updateFunction, null, customOnChange); return this.getCustomCollectionDropDown(currentOptions, field, row, updateFunction, null, customOnChange);
} }
public static getListPicker(possibleOptions: Array<SiteList>, field: ICustomCollectionField, row: any, updateFunction: (fieldId: string, value: any) => void, customOnChange: any, customError?: (fieldId: string, value: string) => string): JSX.Element { public static getListPicker(
let options = []; possibleOptions: Array<SiteList>,
field: ICustomCollectionField,
// eslint-disable-next-line @typescript-eslint/no-explicit-any
row: any,
// eslint-disable-next-line @typescript-eslint/no-explicit-any
updateFunction: (fieldId: string, value: any) => void,
// eslint-disable-next-line @typescript-eslint/no-explicit-any
customOnChange: (row: any, fieldId: string, option: IDropdownOption<any>, updateFunction: (fieldId: string, value: any) => void, errorFunction: (fieldId: string, value: string) => void) => void,
customError?: (fieldId: string, value: string) => string
): JSX.Element {
let options: IPropertyPaneDropdownOption[] = [];
if (possibleOptions) { if (possibleOptions) {
options = possibleOptions.map(option => { return { key: option.Id, text: option.Title }; }); options = possibleOptions.map(option => { return { key: option.Id, text: option.Title }; });
} }
return this.getCustomCollectionDropDown(options, field, row, updateFunction, customError, customOnChange); return this.getCustomCollectionDropDown(options, field, row, updateFunction, customError, customOnChange);
} }
public static getPickerByStringOptions(possibleOptions: Array<string>, field: ICustomCollectionField, row: any, updateFunction: (fieldId: string, value: any) => void, customOnChange: any, customError?: (fieldId: string, value: string) => void): JSX.Element { public static getPickerByStringOptions(
let options = []; possibleOptions: Array<string>,
field: ICustomCollectionField,
// eslint-disable-next-line @typescript-eslint/no-explicit-any
row: any,
// eslint-disable-next-line @typescript-eslint/no-explicit-any
updateFunction: (fieldId: string, value: any) => void,
// eslint-disable-next-line @typescript-eslint/no-explicit-any
customOnChange: (row: any, fieldId: string, option: IDropdownOption<any>, updateFunction: (fieldId: string, value: any) => void, errorFunction: (fieldId: string, value: string) => void) => void,
customError?: (fieldId: string, value: string) => void
): JSX.Element {
let options: IPropertyPaneDropdownOption[] = [];
if (possibleOptions) { if (possibleOptions) {
options = possibleOptions.map(option => { return { key: option, text: option }; }); options = possibleOptions.map(option => { return { key: option, text: option }; });
} }
return this.getCustomCollectionDropDown(options, field, row, updateFunction, customError, customOnChange); return this.getCustomCollectionDropDown(options, field, row, updateFunction, customError, customOnChange);
} }
public static getFieldPickerByList(possibleOptions: Array<ListField>, field: ICustomCollectionField, row: any, updateFunction: (fieldId: string, value: any) => void, customOnchangeFunction?: any, customOptions?: Array<ICustomOption>): JSX.Element { public static getFieldPickerByList(
let options = []; possibleOptions: Array<ListField>,
field: ICustomCollectionField,
// eslint-disable-next-line @typescript-eslint/no-explicit-any
row: any,
// eslint-disable-next-line @typescript-eslint/no-explicit-any
updateFunction: (fieldId: string, value: any) => void,
// eslint-disable-next-line @typescript-eslint/no-explicit-any
customOnChange: (row: any, fieldId: string, option: IDropdownOption<any>, updateFunction: (fieldId: string, value: any) => void, errorFunction: (fieldId: string, value: string) => void) => void,
customOptions?: Array<ICustomOption>
): JSX.Element {
let options: IPropertyPaneDropdownOption[] = [];
if (possibleOptions) { if (possibleOptions) {
options = possibleOptions.map(option => { return { key: option.InternalName, text: option.Title, title: option.InternalName, FieldType: option.TypeAsString }; }); options = possibleOptions.map(option => { return { key: option.InternalName, text: option.Title, title: option.InternalName, FieldType: option.TypeAsString }; });
} }
@ -60,13 +109,13 @@ export default class CustomCollectionDataField {
options.push({ options.push({
key: option.Key, key: option.Key,
text: option.Option, text: option.Option,
FieldType: option.CustomData
}); });
}); });
} }
return this.getCustomCollectionDropDown(options, field, row, updateFunction, null, customOnchangeFunction); return this.getCustomCollectionDropDown(options, field, row, updateFunction, null, customOnChange);
} }
// eslint-disable-next-line @typescript-eslint/no-explicit-any
public static getDisabledTextField(field: ICustomCollectionField, item: any, updateFunction: (fieldId: string, value: any) => void): JSX.Element { public static getDisabledTextField(field: ICustomCollectionField, item: any, updateFunction: (fieldId: string, value: any) => void): JSX.Element {
return <TextField placeholder={field.placeholder || field.title return <TextField placeholder={field.placeholder || field.title
} }
@ -79,6 +128,7 @@ export default class CustomCollectionDataField {
inputClassName="PropertyFieldCollectionData__panel__string-field" />; inputClassName="PropertyFieldCollectionData__panel__string-field" />;
} }
// eslint-disable-next-line @typescript-eslint/no-explicit-any
public static getDisabledCheckBoxField(field: ICustomCollectionField, item: any, updateFunction: (fieldId: string, value: any) => void): JSX.Element { public static getDisabledCheckBoxField(field: ICustomCollectionField, item: any, updateFunction: (fieldId: string, value: any) => void): JSX.Element {
return <Checkbox checked={item[field.id] ? item[field.id] : false} return <Checkbox checked={item[field.id] ? item[field.id] : false}
onChange={(ev, value) => updateFunction(field.id, value)} onChange={(ev, value) => updateFunction(field.id, value)}

View File

@ -2,7 +2,7 @@
//Code from https://kaboodlesoftware.com/2019/10/04/a-rather-useful-empty-spfx-property-pane-control/ //Code from https://kaboodlesoftware.com/2019/10/04/a-rather-useful-empty-spfx-property-pane-control/
import { IPropertyPaneField, PropertyPaneFieldType, IPropertyPaneCustomFieldProps } from "@microsoft/sp-property-pane"; import { IPropertyPaneField, PropertyPaneFieldType, IPropertyPaneCustomFieldProps } from "@microsoft/sp-property-pane";
export class EmptyPropertyPane implements IPropertyPaneField<any> { export class EmptyPropertyPane implements IPropertyPaneField<IPropertyPaneCustomFieldProps> {
public type: PropertyPaneFieldType = PropertyPaneFieldType.Custom; public type: PropertyPaneFieldType = PropertyPaneFieldType.Custom;
public targetProperty: string; public targetProperty: string;

View File

@ -1,3 +1,4 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
export interface ICamlQueryXml { export interface ICamlQueryXml {
name: string; name: string;
attributes: IViewField | undefined; attributes: IViewField | undefined;

View File

@ -27,10 +27,6 @@ export interface IMappingFieldData extends IBaseFieldData {
sortIdx: number; sortIdx: number;
} }
export interface ICompleteModalData extends IBaseFieldData {
}
export interface IRedirectData { export interface IRedirectData {
SiteCollectionSource: string; SiteCollectionSource: string;
ListSourceField: string; ListSourceField: string;
@ -60,7 +56,7 @@ export interface SiteList {
} }
export interface SitesFields { export interface SitesFields {
[siteName: string]: Array<ListsFields>; [siteName: string]: ListsFields;
} }
export interface ListsFields { export interface ListsFields {

View File

@ -2,11 +2,11 @@ import { SiteList } from "./IListConfigProps";
import { SharePointType } from "./ISharePointFieldTypes"; import { SharePointType } from "./ISharePointFieldTypes";
export interface IMapQuery { export interface IMapQuery {
[site: string]: Array<IMapQueryList>; [site: string]: IMapQueryList;
} }
export interface IMapQueryList { export interface IMapQueryList {
[list: string]: Array<IListSearchListQuery>; [list: string]: IListSearchListQuery;
} }
export interface IListSearchListQuery { export interface IListSearchListQuery {
@ -14,6 +14,12 @@ export interface IListSearchListQuery {
audienceEnabled: boolean; audienceEnabled: boolean;
camlQuery?: string; camlQuery?: string;
viewName?: string; viewName?: string;
fields: Array<{ originalField: string, newField: string, fieldType: SharePointType }>; fields: Array<IListSearchListQueryItem>;
}
export interface IListSearchListQueryItem{
originalField: string;
newField: string;
fieldType: SharePointType;
} }

View File

@ -1,6 +1,8 @@
import { SiteList } from "./IListConfigProps"; import { SiteList } from "./IListConfigProps";
export default interface IResult { export default interface IResult {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
[key: string]: any;
FileExtension: string; FileExtension: string;
SiteUrl: string; SiteUrl: string;
ListName: string; //Field to display list name in detail list ListName: string; //Field to display list name in detail list
@ -9,9 +11,9 @@ export default interface IResult {
UniqueId: string; UniqueId: string;
ServerUrl: string; ServerUrl: string;
FileLeafRef: string; FileLeafRef: string;
OData__ModernAudienceTargetUserField:Audience[]; OData__ModernAudienceTargetUserField: Audience[];
} }
interface Audience{ interface Audience {
Name: string; Name: string;
} }

View File

@ -1,5 +1,6 @@
export interface ISessionStorageElement export interface ISessionStorageElement
{ {
hasExpired:boolean; hasExpired:boolean;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
elements: Array<any>; elements: Array<any>;
} }

View File

@ -1,23 +1,20 @@
import { graph } from "@pnp/graph"; import { graphfi, GraphFI, SPFx } from "@pnp/graph";
import "@pnp/graph/users"; import "@pnp/graph/users";
import "@pnp/graph/groups"; import "@pnp/graph/groups";
import { WebPartContext } from "@microsoft/sp-webpart-base"; import { WebPartContext } from "@microsoft/sp-webpart-base";
import { PnPClientStorage } from "@pnp/common"; import { PnPClientStorage } from "@pnp/common";
import IGraphService from "./IGraphService";
let _graph: GraphFI
export default class GraphService implements IGraphService { export default class GraphService {
private _storage: PnPClientStorage; private _storage: PnPClientStorage;
private _localStorageKey: string = 'userGroups'; private _localStorageKey = 'userGroups';
// 1 day // 1 day
private _expiredTimeMillisecons: number = 8.64e+7; private _expiredTimeMillisecons = 8.64e+7;
public constructor(spfxContext: WebPartContext) { public constructor(spfxContext: WebPartContext) {
graph.setup({ _graph = graphfi().using(SPFx(spfxContext));
spfxContext
});
this._storage = new PnPClientStorage(); this._storage = new PnPClientStorage();
} }
@ -26,7 +23,7 @@ export default class GraphService implements IGraphService {
this._storage.local.deleteExpired(); this._storage.local.deleteExpired();
let userGroups = this._storage.local.get(this._localStorageKey); let userGroups = this._storage.local.get(this._localStorageKey);
if (!userGroups) { if (!userGroups) {
userGroups = await graph.me.getMemberGroups(); userGroups = await _graph.me.getMemberGroups();
this._storage.local.put(this._localStorageKey, userGroups, new Date(new Date().getTime() + this._expiredTimeMillisecons)); this._storage.local.put(this._localStorageKey, userGroups, new Date(new Date().getTime() + this._expiredTimeMillisecons));
} }
return userGroups; return userGroups;

View File

@ -1,4 +0,0 @@
export default interface IGraphService {
getTransitiveMemberOf(): Promise<Array<string>>;
}

View File

@ -1,10 +0,0 @@
import { ListField } from "../model/IListConfigProps";
import { IListSearchListQuery } from "../model/IMapQuery";
import GraphService from "./GraphService";
export default interface IListService {
getListItems(listQueryOptions: IListSearchListQuery, listPropertyName: string, sitePropertyName: string, sitePropertyValue: string, rowLimit: number, graphService?: GraphService): Promise<Array<any>>;
getListItemById(listQueryOptions: IListSearchListQuery, itemId: number): Promise<any>;
getSiteListsTitle(): Promise<Array<any>>;
getListFields(listTitle: string): Promise<Array<ListField>>;
}

View File

@ -1,80 +1,92 @@
import { sp } from '@pnp/sp'; import { spfi, SPFI, SPFx } from "@pnp/sp";
import { AssignFrom } from "@pnp/core";
import { InjectHeaders, Caching } from "@pnp/queryable";
import { dateAdd } from "@pnp/core";
import '@pnp/sp/webs'; import '@pnp/sp/webs';
import "@pnp/sp/lists"; import "@pnp/sp/lists";
import "@pnp/sp/items"; import "@pnp/sp/items";
import "@pnp/sp/views"; import "@pnp/sp/views";
import "@pnp/sp/fields"; import "@pnp/sp/fields";
import IListService from "./IListService";
import { ICamlQuery } from "@pnp/sp/lists"; import { ICamlQuery } from "@pnp/sp/lists";
import { ICamlQueryXml } from '../model/ICamlQueryXml'; import XMLParser, { XMLElement } from 'react-xml-parser';
import XMLParser from 'react-xml-parser';
import { IWeb, Web } from '@pnp/sp/webs';
import { SharePointType } from '../model/ISharePointFieldTypes'; import { SharePointType } from '../model/ISharePointFieldTypes';
import IResult from '../model/IResult'; import IResult from '../model/IResult';
import { intersection, isEmpty } from '@microsoft/sp-lodash-subset'; import { intersection, isEmpty } from '@microsoft/sp-lodash-subset';
import { ListField, SiteList } from '../model/IListConfigProps'; import { ListField, SiteList } from '../model/IListConfigProps';
import { IListSearchListQuery } from '../model/IMapQuery'; import { IListSearchListQuery, IListSearchListQueryItem } from '../model/IMapQuery';
import GraphService from './GraphService'; import GraphService from './GraphService';
import { WebPartContext } from "@microsoft/sp-webpart-base";
import { getKeyValue, setKeyValue } from "../utils/ObjectUtils";
export interface QueryHelperEntity { export interface QueryHelperEntity {
viewFields: string[]; viewFields: string[];
expandFields: string[]; expandFields: string[];
} }
export default class ListService {
private static sourceSP: SPFI;
export default class ListService implements IListService {
private web: IWeb;
private baseUrl: string; private baseUrl: string;
private _sp: SPFI;
private static SharePointOnlineAudienceOOTBFieldName = "OData__ModernAudienceTargetUserField"; private static SharePointOnlineAudienceOOTBFieldName = "OData__ModernAudienceTargetUserField";
public static MAX_TOP: number = 5000; public static MAX_TOP = 5000;
constructor(siteUrl: string, useCache: boolean, cacheTime?: number, cacheType?: "session" | "local") { private GetSourceSP(context: WebPartContext, useCache: boolean, cacheTime?: number, cacheType?: "session" | "local") {
sp.setup({ if (!ListService.sourceSP) {
defaultCachingStore: useCache ? cacheType : undefined, ListService.sourceSP = spfi().using(SPFx(context)).using(InjectHeaders(
defaultCachingTimeoutSeconds: useCache ? (cacheTime * 60) : undefined, {
sp: {
headers: {
Accept: 'application/json;odata=nometadata' Accept: 'application/json;odata=nometadata'
}, }
baseUrl: siteUrl ));
},
}); if (useCache) {
this.web = Web(siteUrl); ListService.sourceSP.using((Caching({
store: cacheType,
expireFunc: () => dateAdd(new Date, "minute", cacheTime)
})));
}
}
}
constructor(context: WebPartContext, siteUrl: string, useCache: boolean, cacheTime?: number, cacheType?: "session" | "local") {
this.GetSourceSP(context, useCache, cacheTime, cacheType);
this.baseUrl = siteUrl; this.baseUrl = siteUrl;
this._sp = spfi(siteUrl).using(AssignFrom(ListService.sourceSP.web));
} }
public async getListItems(listQueryOptions: IListSearchListQuery, listPropertyName: string, sitePropertyName: string, sitePropertyValue: string, rowLimit: number, graphService?: GraphService): Promise<Array<IResult>> { public async getListItems(listQueryOptions: IListSearchListQuery, listPropertyName: string, sitePropertyName: string, sitePropertyValue: string, rowLimit: number, graphService?: GraphService): Promise<Array<IResult>> {
try { try {
let camlQuery: boolean = false; const camlQuery = false;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
let items: any = undefined; let items: any = undefined;
let queryConfig: QueryHelperEntity = this.GetViewFieldsWithId(listQueryOptions, !isEmpty(listQueryOptions.camlQuery) || !isEmpty(listQueryOptions.viewName), false); const queryConfig: QueryHelperEntity = this.GetViewFieldsWithId(listQueryOptions, !isEmpty(listQueryOptions.camlQuery) || !isEmpty(listQueryOptions.viewName), false);
if (listQueryOptions.camlQuery) { if (listQueryOptions.camlQuery) {
let query = this.getCamlQueryWithViewFieldsAndRowLimit(listQueryOptions.camlQuery, queryConfig, rowLimit); const query = this.getCamlQueryWithViewFieldsAndRowLimit(listQueryOptions.camlQuery, queryConfig, rowLimit);
items = await this.getListItemsByCamlQuery(listQueryOptions.list.Id, query, queryConfig); items = await this.getListItemsByCamlQuery(listQueryOptions.list.Id, query, queryConfig);
items = items.map(m => m.FieldValuesAsText); // eslint-disable-next-line @typescript-eslint/no-explicit-any
items = items.map((m: { FieldValuesAsText: any; }) => m.FieldValuesAsText);
} }
else { else {
if (listQueryOptions.viewName) { if (listQueryOptions.viewName) {
let viewInfo: any = await this.web.lists.getById(listQueryOptions.list.Id).views.getByTitle(listQueryOptions.viewName).select("ViewQuery").get(); // eslint-disable-next-line @typescript-eslint/no-explicit-any
let query = this.getCamlQueryWithViewFieldsAndRowLimit(`<View><Query>${viewInfo.ViewQuery}</Query></View>`, queryConfig, rowLimit); const viewInfo: any = await this._sp.web.lists.getById(listQueryOptions.list.Id).views.getByTitle(listQueryOptions.viewName).select("ViewQuery")();
const query = this.getCamlQueryWithViewFieldsAndRowLimit(`<View><Query>${viewInfo.ViewQuery}</Query></View>`, queryConfig, rowLimit);
items = await this.getListItemsByCamlQuery(listQueryOptions.list.Id, query, queryConfig); items = await this.getListItemsByCamlQuery(listQueryOptions.list.Id, query, queryConfig);
items = items.map(m => m.FieldValuesAsText); // eslint-disable-next-line @typescript-eslint/no-explicit-any
items = items.map((m: { FieldValuesAsText: any; }) => m.FieldValuesAsText);
} }
else { else {
items = await sp.web.lists.getById(listQueryOptions.list.Id).items items = await this._sp.web.lists.getById(listQueryOptions.list.Id).items
.select(queryConfig.viewFields.join(',')) .select(queryConfig.viewFields.join(','))
.top(rowLimit || ListService.MAX_TOP) .top(rowLimit || ListService.MAX_TOP)
.expand(queryConfig.expandFields.join(',')).usingCaching().get(); .expand(queryConfig.expandFields.join(','))();
} }
} }
if (listQueryOptions.audienceEnabled && graphService) { if (listQueryOptions.audienceEnabled && graphService) {
let userGroups: string[] = await graphService.getTransitiveMemberOf(); const userGroups: string[] = await graphService.getTransitiveMemberOf();
items = this.getAudienceItems(items, userGroups); items = this.getAudienceItems(items, userGroups);
} }
let mappedItems = items.map((i: IResult) => { const mappedItems = items.map((i: IResult) => {
i.FileExtension = this.GetFileExtension(i.FileLeafRef); i.FileExtension = this.GetFileExtension(i.FileLeafRef);
i.SiteUrl = this.baseUrl; i.SiteUrl = this.baseUrl;
i.ListName = listQueryOptions.list.Title; i.ListName = listQueryOptions.list.Title;
@ -85,10 +97,12 @@ export default class ListService implements IListService {
}); });
if (listPropertyName) { if (listPropertyName) {
i[listPropertyName] = listQueryOptions.list.Title; // eslint-disable-next-line @typescript-eslint/no-explicit-any
setKeyValue(i, listPropertyName as any, listQueryOptions.list.Title);
} }
if (sitePropertyName) { if (sitePropertyName) {
i[sitePropertyName] = sitePropertyValue; // eslint-disable-next-line @typescript-eslint/no-explicit-any
setKeyValue(i, sitePropertyName as any, sitePropertyValue);
} }
return i; return i;
}); });
@ -98,10 +112,11 @@ export default class ListService implements IListService {
} }
} }
// eslint-disable-next-line @typescript-eslint/no-explicit-any
public async getListItemById(listQueryOptions: IListSearchListQuery, itemId: number): Promise<any> { public async getListItemById(listQueryOptions: IListSearchListQuery, itemId: number): Promise<any> {
try { try {
let queryConfig: QueryHelperEntity = this.GetViewFieldsWithId(listQueryOptions, false, true); const queryConfig: QueryHelperEntity = this.GetViewFieldsWithId(listQueryOptions, false, true);
return this.web.lists.getById(listQueryOptions.list.Id).items.getById(itemId).select(queryConfig.viewFields.join(',')).expand(queryConfig.expandFields.join(',')).usingCaching().get(); return this._sp.web.lists.getById(listQueryOptions.list.Id).items.getById(itemId).select(queryConfig.viewFields.join(',')).expand(queryConfig.expandFields.join(','))();
} catch (error) { } catch (error) {
return Promise.reject(error); return Promise.reject(error);
} }
@ -109,7 +124,7 @@ export default class ListService implements IListService {
public async getSiteListsTitle(): Promise<Array<SiteList>> { public async getSiteListsTitle(): Promise<Array<SiteList>> {
try { try {
return this.web.lists.filter('Hidden eq false').select('Title,Id').get(); return this._sp.web.lists.filter('Hidden eq false').select('Title,Id')();
} catch (error) { } catch (error) {
return Promise.reject(error); return Promise.reject(error);
} }
@ -117,18 +132,19 @@ export default class ListService implements IListService {
public async getListFields(listId: string): Promise<Array<ListField>> { public async getListFields(listId: string): Promise<Array<ListField>> {
try { try {
return this.web.lists.getById(listId).fields.select('EntityPropertyName,Title,InternalName,TypeAsString').get(); return this._sp.web.lists.getById(listId).fields.select('EntityPropertyName,Title,InternalName,TypeAsString')();
} catch (error) { } catch (error) {
return Promise.reject(error); return Promise.reject(error);
} }
} }
private getAudienceItems(itemsToFilter: IResult[], userGroups: string[]) { private getAudienceItems(itemsToFilter: IResult[], userGroups: string[]) {
let results: IResult[] = []; const results: IResult[] = [];
userGroups && itemsToFilter.map(item => { if (userGroups) {
let itemAudiencesIds: string[] = item.OData__ModernAudienceTargetUserField && item.OData__ModernAudienceTargetUserField.map(audience => { return audience.Name.split("|")[2]; }); itemsToFilter.map(item => {
const itemAudiencesIds: string[] = item.OData__ModernAudienceTargetUserField && item.OData__ModernAudienceTargetUserField.map(audience => { return audience.Name.split("|")[2]; });
if (itemAudiencesIds) { if (itemAudiencesIds) {
let matches: string[] = intersection(itemAudiencesIds, userGroups); const matches: string[] = intersection(itemAudiencesIds, userGroups);
if (matches && matches.length > 0) { if (matches && matches.length > 0) {
results.push(item); results.push(item);
} }
@ -137,13 +153,14 @@ export default class ListService implements IListService {
results.push(item); results.push(item);
} }
}); });
}
return results; return results;
} }
private GetViewFieldsWithId(listQueryOptions: IListSearchListQuery, isCamlQuery: boolean, isItemId: boolean): QueryHelperEntity { private GetViewFieldsWithId(listQueryOptions: IListSearchListQuery, isCamlQuery: boolean, isItemId: boolean): QueryHelperEntity {
let result: QueryHelperEntity = { expandFields: [], viewFields: ['ServerUrl', 'FileLeafRef', 'Id', 'UniqueId'] }; const result: QueryHelperEntity = { expandFields: [], viewFields: ['ServerUrl', 'FileLeafRef', 'Id', 'UniqueId'] };
let hasToAddFieldsAsText: boolean = false; let hasToAddFieldsAsText = false;
listQueryOptions.fields.map(field => { listQueryOptions.fields.map(field => {
switch (field.fieldType) { switch (field.fieldType) {
case SharePointType.User: case SharePointType.User:
@ -209,15 +226,17 @@ export default class ListService implements IListService {
return result; return result;
} }
private GetItemValue(item: any, field: any, fromCamlQuery: boolean): any { private GetItemValue(item: IResult, field: IListSearchListQueryItem, fromCamlQuery: boolean): IResult {
switch (field.fieldType) { switch (field.fieldType) {
case SharePointType.Lookup: case SharePointType.Lookup:
case SharePointType.LookupMulti: case SharePointType.LookupMulti:
if (fromCamlQuery) { if (fromCamlQuery) {
item[field.newField] = item['FieldValuesAsText'][field.originalField]; // eslint-disable-next-line @typescript-eslint/no-explicit-any
setKeyValue(item, field.newField as any, getKeyValue(item, `FieldValuesAsText.${field.originalField}` as any));
} }
else { else {
item[field.newField] = item[field.originalField]; // eslint-disable-next-line @typescript-eslint/no-explicit-any
setKeyValue(item, field.newField as any, getKeyValue(item, field.originalField as any));
if (field.newField !== field.originalField) { if (field.newField !== field.originalField) {
delete item[field.originalField]; delete item[field.originalField];
} }
@ -257,8 +276,8 @@ export default class ListService implements IListService {
item[field.newField] = item['FieldValuesAsText'][field.originalField]; item[field.newField] = item['FieldValuesAsText'][field.originalField];
} }
else { else {
let taxonomyValues = item["TaxCatchAll"]; const taxonomyValues = item["TaxCatchAll"];
let taxonomyTerm = taxonomyValues.find(t => t.ID === item[field.originalField].WssId); const taxonomyTerm = taxonomyValues.find((t: { ID: number; }) => t.ID === item[field.originalField].WssId);
if (taxonomyTerm) { if (taxonomyTerm) {
item[field.newField] = taxonomyTerm; item[field.newField] = taxonomyTerm;
} }
@ -292,12 +311,13 @@ export default class ListService implements IListService {
return item; return item;
} }
// eslint-disable-next-line @typescript-eslint/no-explicit-any
private async getListItemsByCamlQuery(listId: string, camlQuery: string, queryConfig: QueryHelperEntity): Promise<Array<any>> { private async getListItemsByCamlQuery(listId: string, camlQuery: string, queryConfig: QueryHelperEntity): Promise<Array<any>> {
try { try {
const caml: ICamlQuery = { const caml: ICamlQuery = {
ViewXml: camlQuery, ViewXml: camlQuery,
}; };
return this.web.lists.getById(listId).usingCaching().getItemsByCAMLQuery(caml, queryConfig.expandFields.join(',')); return this._sp.web.lists.getById(listId).getItemsByCAMLQuery(caml, queryConfig.expandFields.join(','));
} catch (error) { } catch (error) {
return Promise.reject(error); return Promise.reject(error);
} }
@ -305,24 +325,24 @@ export default class ListService implements IListService {
private getCamlQueryWithViewFieldsAndRowLimit(camlQuery: string, queryConfig: QueryHelperEntity, rowLimit: number): string { private getCamlQueryWithViewFieldsAndRowLimit(camlQuery: string, queryConfig: QueryHelperEntity, rowLimit: number): string {
try { try {
let XmlParser = new XMLParser(); const XmlParser = new XMLParser();
let xml: ICamlQueryXml = XmlParser.parseFromString(camlQuery); const xml: XMLElement = XmlParser.parseFromString(camlQuery);
let rowLimitXml: ICamlQueryXml = { name: "RowLimit", value: rowLimit ? rowLimit.toString() : "0", attributes: undefined, children: [] }; const rowLimitXml: XMLElement = { name: "RowLimit", value: rowLimit ? rowLimit.toString() : "0", attributes: undefined, children: [] };
let viewFieldsChildren: ICamlQueryXml[] = queryConfig.viewFields.map(viewField => { const viewFieldsChildren: XMLElement[] = queryConfig.viewFields.map(viewField => {
return { name: "FieldRef", attributes: { Name: viewField }, value: "", children: [] }; return { name: "FieldRef", attributes: { Name: viewField }, value: "", children: [] };
}); });
let viewFieldsXml: ICamlQueryXml = { name: "ViewFields", value: "", children: viewFieldsChildren, attributes: undefined }; const viewFieldsXml: XMLElement = { name: "ViewFields", value: "", children: viewFieldsChildren, attributes: undefined };
let queryXml: ICamlQueryXml; let queryXml: XMLElement;
xml.children.map(child => { xml.children.map(child => {
if (child.name == "Query") { if (child.name == "Query") {
queryXml = child; queryXml.value = child.value;
} }
if (child.name == "RowLimit") { //If the user set a camlquery with row limit or the view has row limit, it is not override if (child.name == "RowLimit") { //If the user set a camlquery with row limit or the view has row limit, it is not override
rowLimitXml = child; rowLimitXml.value = child.value;
} }
}); });
@ -330,7 +350,7 @@ export default class ListService implements IListService {
xml.children = [viewFieldsXml, rowLimitXml, queryXml]; xml.children = [viewFieldsXml, rowLimitXml, queryXml];
} }
let result: string = XmlParser.toString(xml); const result: string = XmlParser.toString(xml);
return result.replace("</RowLimit></RowLimit>", "</RowLimit>"); return result.replace("</RowLimit></RowLimit>", "</RowLimit>");
} catch (error) { } catch (error) {
return `getCamlQueryWithViewFieldsAndRowLimit -> ${error.message}`; return `getCamlQueryWithViewFieldsAndRowLimit -> ${error.message}`;
@ -339,7 +359,7 @@ export default class ListService implements IListService {
} }
private GetFileExtension(filename: string): string { private GetFileExtension(filename: string): string {
var re = /(?:\.([^.]+))?$/; const re = /(?:\.([^.]+))?$/;
return re.exec(filename)[1] ? re.exec(filename)[1].toLowerCase() : undefined; return re.exec(filename)[1] ? re.exec(filename)[1].toLowerCase() : undefined;
} }
} }

View File

@ -2,16 +2,16 @@ export default class StringUtils {
public static GetUserInitials(text: string): string { public static GetUserInitials(text: string): string {
if (text) { if (text) {
let initials = text.match(/\b\w/g) || []; const initials = text.match(/\b\w/g) || [];
text = ((initials.shift() || '') + (initials.pop() || '')).toUpperCase(); text = ((initials.shift() || '') + (initials.pop() || '')).toUpperCase();
} }
return text; return text;
} }
public static GetUserEmail(text: string): string { public static GetUserEmail(text: string): string {
let result: string = ""; let result = "";
if (text && text.indexOf('|') > 0) { if (text && text.indexOf('|') > 0) {
let splited = text.split('|'); const splited = text.split('|');
if (splited && splited.length > 1) { if (splited && splited.length > 1) {
result = splited[2]; result = splited[2];
} }

View File

@ -0,0 +1,18 @@
declare module 'react-xml-parser' {
interface XMLElement {
name: string;
attributes: {
[name: string]: string;
};
value: string;
children: XMLElement[];
getElementsByTagName?(tagName: string): XMLElement[];
}
export default class XMLParser {
constructor();
public parseFromString(string: string): XMLElement;
public toString(xml: XMLElement): string;
}
}

View File

@ -0,0 +1,3 @@
export const getKeyValue = <T, K extends keyof T>(obj: T, key: K): T[K] => obj[key];
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export const setKeyValue = <T, K extends keyof T>(obj: T, key: K, value: any): T[K] => obj[key] = value;

View File

@ -1,3 +1,4 @@
@import '~@fluentui/react/dist/sass/References.scss';
@import '~@microsoft/sp-office-ui-fabric-core/dist/sass/SPFabricCore.scss'; @import '~@microsoft/sp-office-ui-fabric-core/dist/sass/SPFabricCore.scss';
.listSearchConsumerWebPart { .listSearchConsumerWebPart {

View File

@ -2,7 +2,7 @@ import * as React from 'react';
import styles from './ListSearchConsumerWebPart.module.scss'; import styles from './ListSearchConsumerWebPart.module.scss';
import { IListSearchConsumerProps } from './IListSearchConsumerProps'; import { IListSearchConsumerProps } from './IListSearchConsumerProps';
export default class ListSearchConsumer extends React.Component<IListSearchConsumerProps, {}> { export default class ListSearchConsumer extends React.Component<IListSearchConsumerProps, undefined> {
public render(): React.ReactElement<IListSearchConsumerProps> { public render(): React.ReactElement<IListSearchConsumerProps> {
return ( return (
<div className={styles.listSearchConsumerWebPart}> <div className={styles.listSearchConsumerWebPart}>

View File

@ -1,6 +1,7 @@
{ {
"extends": "./node_modules/@microsoft/rush-stack-compiler-3.9/includes/tsconfig-web.json", "extends": "./node_modules/@microsoft/rush-stack-compiler-4.7/includes/tsconfig-web.json",
"compilerOptions": { "compilerOptions": {
"noImplicitAny": true,
"target": "es6", "target": "es6",
"forceConsistentCasingInFileNames": true, "forceConsistentCasingInFileNames": true,
"module": "esnext", "module": "esnext",

View File

@ -1,30 +0,0 @@
{
"extends": "./node_modules/@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": false,
"no-with-statement": true,
"semicolon": true,
"trailing-comma": false,
"typedef": false,
"typedef-whitespace": false,
"use-named-parameter": true,
"variable-name": false,
"whitespace": false
}
}

View File

@ -11,6 +11,8 @@ import { IECBProps } from './IECBProps';
import { IEmployeeListViewProps } from './IEmployeeListViewProps'; import { IEmployeeListViewProps } from './IEmployeeListViewProps';
import { IEmployeeListViewState } from './IEmployeeListViewState'; import { IEmployeeListViewState } from './IEmployeeListViewState';
import { SPHpttClient, SPHttpClientResponse } from "@microsoft/sp-http";
export default class EmployeeListView extends React.Component<IEmployeeListViewProps, IEmployeeListViewState> { export default class EmployeeListView extends React.Component<IEmployeeListViewProps, IEmployeeListViewState> {
private items : IListItem[]; private items : IListItem[];
@ -103,7 +105,7 @@ export default class EmployeeListView extends React.Component<IEmployeeListViewP
// var self: EmployeeListView = this; // var self: EmployeeListView = this;
// const apiUrl = `${this.props.siteUrl}/_api/web/lists/GetByTitle('Employees')/Items?$select=Firstname,Lastname,Street,StreetNo,Salary,EmployeeLocation/Title&$expand=EmployeeLocation`; // const apiUrl = `${this.props.siteUrl}/_api/web/lists/GetByTitle('Employees')/Items?$select=Firstname,Lastname,Street,StreetNo,Salary,EmployeeLocation/Title&$expand=EmployeeLocation`;
// this.props.spHttpClient.get(apiUrl, SPHttpClient.configurations.v1) // this.props.spHttpClient.get(apiUrl, SPHttpClient.configurations.v1)
// .then((response: HttpClientResponse) => { // .then((response: SPHttpClientResponse) => {
// return response.json(); // return response.json();
// }) // })
// .then((response: { value: IListItem[] }): void => { // .then((response: { value: IListItem[] }): void => {

View File

@ -20,11 +20,12 @@ module.exports = {
'@rushstack/security/no-unsafe-regexp': 1, '@rushstack/security/no-unsafe-regexp': 1,
// STANDARDIZED BY: @typescript-eslint\eslint-plugin\dist\configs\recommended.json // STANDARDIZED BY: @typescript-eslint\eslint-plugin\dist\configs\recommended.json
'@typescript-eslint/adjacent-overload-signatures': 1, '@typescript-eslint/adjacent-overload-signatures': 1,
'@typescript-eslint/no-unused-expressions': 0,
// STANDARDIZED BY: @typescript-eslint\eslint-plugin\dist\configs\recommended.json // STANDARDIZED BY: @typescript-eslint\eslint-plugin\dist\configs\recommended.json
// //
// CONFIGURATION: By default, these are banned: String, Boolean, Number, Object, Symbol // CONFIGURATION: By default, these are banned: String, Boolean, Number, Object, Symbol
'@typescript-eslint/ban-types': [ '@typescript-eslint/ban-types': [
1, 0,
{ {
'extendDefaults': false, 'extendDefaults': false,
'types': { 'types': {

Binary file not shown.

View File

@ -2,12 +2,12 @@
"@microsoft/generator-sharepoint": { "@microsoft/generator-sharepoint": {
"plusBeta": false, "plusBeta": false,
"isCreatingSolution": true, "isCreatingSolution": true,
"nodeVersion": "16.18.1", "nodeVersion": "18.18.2",
"sdksVersions": { "sdksVersions": {
"@microsoft/microsoft-graph-client": "3.0.2", "@microsoft/microsoft-graph-client": "3.0.2",
"@microsoft/teams-js": "2.9.1" "@microsoft/teams-js": "2.24.0"
}, },
"version": "1.17.4", "version": "1.20.0",
"libraryName": "react-manage-hublevel-list-subscriptions", "libraryName": "react-manage-hublevel-list-subscriptions",
"libraryId": "e2c0325f-7b70-4738-b4cf-568be2bdf627", "libraryId": "e2c0325f-7b70-4738-b4cf-568be2bdf627",
"environment": "spo", "environment": "spo",

View File

@ -27,8 +27,8 @@ This sample web part demonstrates managing the list subscriptions (sharepoint we
| 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 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.|
|Refer to <https://aka.ms/spfx-matrix> for more information on SPFx compatibility. | |Refer to <https://aka.ms/spfx-matrix> for more information on SPFx compatibility. |
![SPFx 1.17.4](https://img.shields.io/badge/SPFx-1.17.4-green.svg) ![SPFx 1.20.0](https://img.shields.io/badge/SPFx-1.20.0-green.svg)
![Node.js v16 | v14](https://img.shields.io/badge/Node.js-v16%20%7C%20v14-green.svg) ![Node.js v18](https://img.shields.io/badge/Node.js-v18.18.2-green.svg)
![Compatible with SharePoint Online](https://img.shields.io/badge/SharePoint%20Online-Compatible-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 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") ![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")
@ -52,6 +52,10 @@ This web part requires access to lists and libraries to perform renewing the web
- in the command-line run: - in the command-line run:
- `npm install` - `npm install`
- `gulp serve` - `gulp serve`
- if you use spfx-fast-serve, in the command-line run:
- `spfx-fast-serve`
- `npm install`
- `npm run serve`
> This sample can also be opened with [VS Code Remote Development](https://code.visualstudio.com/docs/remote/remote-overview). Visit https://aka.ms/spfx-devcontainer for further instructions. > This sample can also be opened with [VS Code Remote Development](https://code.visualstudio.com/docs/remote/remote-overview). Visit https://aka.ms/spfx-devcontainer for further instructions.
@ -64,6 +68,7 @@ This web part requires access to lists and libraries to perform renewing the web
Version|Date|Comments Version|Date|Comments
-------|----|-------- -------|----|--------
1.0|September 9, 2023|Initial release 1.0|September 9, 2023|Initial release
2.0|October 02, 2024|Initial release
## Help ## Help

View File

@ -9,7 +9,7 @@
"This sample web part demonstrates managing the list subscriptions (sharepoint webhooks) and action to renew the webhook expiration date using Rest calls. The webpart is to be added at Hubsite level or the sites associated to the hubsite, on selection of the site, it will list out the lists available. On list/library selection, the available subscriptions is displayed. Depending upon the expiry date of the subscription, 'Renew subscription' action can be performed. The subscription (webhook expiry renewal date) renewal date is set to 179 days, as the default days are 180. " "This sample web part demonstrates managing the list subscriptions (sharepoint webhooks) and action to renew the webhook expiration date using Rest calls. The webpart is to be added at Hubsite level or the sites associated to the hubsite, on selection of the site, it will list out the lists available. On list/library selection, the available subscriptions is displayed. Depending upon the expiry date of the subscription, 'Renew subscription' action can be performed. The subscription (webhook expiry renewal date) renewal date is set to 179 days, as the default days are 180. "
], ],
"creationDateTime": "2023-09-01", "creationDateTime": "2023-09-01",
"updateDateTime": "2023-09-01", "updateDateTime": "2024-10-02",
"products": [ "products": [
"SharePoint", "SharePoint",
"WebHooks", "WebHooks",
@ -24,7 +24,7 @@
}, },
{ {
"key": "SPFX-VERSION", "key": "SPFX-VERSION",
"value": "1.17.4" "value": "1.20.0"
} }
], ],
"thumbnails": [ "thumbnails": [

View File

@ -13,4 +13,10 @@ build.rig.getTasks = function () {
return result; return result;
}; };
/* fast-serve */
const { addFastServe } = require("spfx-fast-serve-helpers");
addFastServe(build);
/* end of fast-serve */
build.initialize(require('gulp')); build.initialize(require('gulp'));

File diff suppressed because it is too large Load Diff

View File

@ -3,46 +3,48 @@
"version": "0.0.1", "version": "0.0.1",
"private": true, "private": true,
"engines": { "engines": {
"node": ">=16.13.0 <17.0.0" "node": ">=16.13.0 <17.0.0 || >=18.17.1 <19.0.0"
}, },
"main": "lib/index.js", "main": "lib/index.js",
"scripts": { "scripts": {
"build": "gulp bundle", "build": "gulp bundle",
"clean": "gulp clean", "clean": "gulp clean",
"test": "gulp test" "test": "gulp test",
"serve": "fast-serve"
}, },
"dependencies": { "dependencies": {
"@fluentui/react": "^7.199.1", "@fluentui/react": "8.106.4",
"@microsoft/sp-component-base": "1.17.4", "@microsoft/sp-adaptive-card-extension-base": "1.20.0",
"@microsoft/sp-core-library": "1.17.4", "@microsoft/sp-component-base": "1.20.0",
"@microsoft/sp-lodash-subset": "1.17.4", "@microsoft/sp-core-library": "1.20.0",
"@microsoft/sp-office-ui-fabric-core": "1.17.4", "@microsoft/sp-lodash-subset": "1.20.0",
"@microsoft/sp-property-pane": "1.17.4", "@microsoft/sp-office-ui-fabric-core": "1.20.0",
"@microsoft/sp-webpart-base": "1.17.4", "@microsoft/sp-property-pane": "1.20.0",
"@microsoft/sp-webpart-base": "1.20.0",
"@pnp/graph": "^3.17.0", "@pnp/graph": "^3.17.0",
"@pnp/logging": "^3.17.0", "@pnp/logging": "^3.17.0",
"@pnp/queryable": "^3.17.0", "@pnp/queryable": "^3.17.0",
"@pnp/sp": "^3.17.0", "@pnp/sp": "^3.17.0",
"@pnp/spfx-controls-react": "^3.15.0", "@pnp/spfx-controls-react": "^3.15.0",
"office-ui-fabric-react": "^7.199.1",
"react": "17.0.1", "react": "17.0.1",
"react-dom": "17.0.1", "react-dom": "17.0.1",
"tslib": "2.3.1" "tslib": "2.3.1"
}, },
"devDependencies": { "devDependencies": {
"@microsoft/eslint-config-spfx": "1.17.4", "@microsoft/eslint-config-spfx": "1.20.2",
"@microsoft/eslint-plugin-spfx": "1.17.4", "@microsoft/eslint-plugin-spfx": "1.20.2",
"@microsoft/rush-stack-compiler-4.5": "0.5.0", "@microsoft/rush-stack-compiler-4.7": "0.1.0",
"@microsoft/sp-build-web": "1.17.4", "@microsoft/sp-build-web": "1.20.2",
"@microsoft/sp-module-interfaces": "1.17.4", "@microsoft/sp-module-interfaces": "1.20.2",
"@rushstack/eslint-config": "2.5.1", "@rushstack/eslint-config": "4.0.1",
"@types/react": "17.0.45", "@types/react": "17.0.45",
"@types/react-dom": "17.0.17", "@types/react-dom": "17.0.17",
"@types/webpack-env": "~1.15.2", "@types/webpack-env": "~1.15.2",
"ajv": "^6.12.5", "ajv": "^6.12.5",
"eslint": "8.7.0", "eslint": "8.57.0",
"eslint-plugin-react-hooks": "4.3.0", "eslint-plugin-react-hooks": "4.3.0",
"gulp": "4.0.2", "gulp": "4.0.2",
"typescript": "4.5.5" "spfx-fast-serve-helpers": "~1.20.0",
"typescript": "4.7.4"
} }
} }

View File

@ -7,7 +7,7 @@ import {
DetailsList, DetailsListLayoutMode, SelectionMode, DetailsList, DetailsListLayoutMode, SelectionMode,
IColumn, mergeStyles, Spinner, /* IColumn, mergeStyles, Spinner, /*
ProgressIndicator,ITooltipHostStyles,*/ Link ProgressIndicator,ITooltipHostStyles,*/ Link
} from 'office-ui-fabric-react'; } from '@fluentui/react';
import { RestService } from '../../Services/RestService'; import { RestService } from '../../Services/RestService';

View File

@ -1,7 +1,7 @@
import { WebPartContext } from "@microsoft/sp-webpart-base"; import { WebPartContext } from "@microsoft/sp-webpart-base";
import {IDropdownOption} from '@fluentui/react'; import {IDropdownOption} from '@fluentui/react';
import { DisplayMode } from '@microsoft/sp-core-library'; import { DisplayMode } from '@microsoft/sp-core-library';
import {MessageBarType} from 'office-ui-fabric-react'; import {MessageBarType} from '@fluentui/react';
export interface IManageHublevelSubscriptionsProps { export interface IManageHublevelSubscriptionsProps {
_context: WebPartContext; _context: WebPartContext;

View File

@ -7,13 +7,13 @@ import { IManageHublevelSubscriptionsProps,
from './IManageHublevelSubscriptions'; from './IManageHublevelSubscriptions';
import { import {
Spinner Spinner
} from 'office-ui-fabric-react'; } from '@fluentui/react';
import { SearchService } from '../../Services/SearchService'; import { SearchService } from '../../Services/SearchService';
import { RestService } from '../../Services/RestService'; import { RestService } from '../../Services/RestService';
import HubSiteMapper from '../../Mapper/HubSiteMapper'; import HubSiteMapper from '../../Mapper/HubSiteMapper';
import SubscriptionDashboard from '../DashboardComponent/SubscriptionDashboard'; import SubscriptionDashboard from '../DashboardComponent/SubscriptionDashboard';
import { WebPartTitle } from '@pnp/spfx-controls-react'; import { WebPartTitle } from '@pnp/spfx-controls-react';
import {MessageBar, MessageBarType} from 'office-ui-fabric-react'; import {MessageBar, MessageBarType} from '@fluentui/react';
export default class ReactManageHublevelSubscriptions export default class ReactManageHublevelSubscriptions
extends React.Component<IManageHublevelSubscriptionsProps, IManageHublevelSubscriptionsState> { extends React.Component<IManageHublevelSubscriptionsProps, IManageHublevelSubscriptionsState> {

View File

@ -1,5 +1,5 @@
{ {
"extends": "./node_modules/@microsoft/rush-stack-compiler-4.5/includes/tsconfig-web.json", "extends": "./node_modules/@microsoft/rush-stack-compiler-4.7/includes/tsconfig-web.json",
"compilerOptions": { "compilerOptions": {
"target": "es5", "target": "es5",
"forceConsistentCasingInFileNames": true, "forceConsistentCasingInFileNames": true,

View File

@ -1,7 +1,7 @@
{ {
"@microsoft/generator-sharepoint": { "@microsoft/generator-sharepoint": {
"libraryName": "pnp-script-editor", "libraryName": "pnp-script-editor",
"version": "1.19.0", "version": "1.20.0",
"environment": "spo", "environment": "spo",
"isDomainIsolated": false, "isDomainIsolated": false,
"libraryId": "1425175f-3ed8-44d2-8fc4-dd1497191294", "libraryId": "1425175f-3ed8-44d2-8fc4-dd1497191294",
@ -10,7 +10,7 @@
"componentType": "webpart", "componentType": "webpart",
"nodeVersion": "16.20.0", "nodeVersion": "16.20.0",
"sdkVersions": { "sdkVersions": {
"@microsoft/teams-js": "2.12.0", "@microsoft/teams-js": "2.24.0",
"@microsoft/microsoft-graph-client": "3.0.2" "@microsoft/microsoft-graph-client": "3.0.2"
} }
} }

Some files were not shown because too many files have changed in this diff Show More