Merge Refresh Rangers PR - Upgraded list search webpartto spfx 1.20.0 (#5274)

* AGP: upgraded to spfx version 1.19.0

* AGP: refactor tsconfig errors and eslint warnings

* AGP: upgraded to spfx 1.20.0

* AGP: updated sppkg version

* AGP: added .nvmrc

* AGP: upgraded readme

* AGP: fixed PR errors

---------

Co-authored-by: Alberto Gutierrez Perez <agutierrezp@hiberus.com>
This commit is contained in:
Alberto Gutierrez perez 2024-10-10 00:54:08 +02:00 committed by GitHub
parent aa504ab0b1
commit 6fc35606cc
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
39 changed files with 31825 additions and 490459 deletions

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
*.scss.ts
*.scss.d.ts
.heft

View File

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

View File

@ -1,12 +1,17 @@
{
"@microsoft/generator-sharepoint": {
"version": "1.13.1",
"version": "1.20.0",
"libraryName": "list-search-webpart",
"libraryId": "8277f088-9c30-4f95-9c15-9c18a9d40a26",
"environment": "spo",
"packageManager": "npm",
"isCreatingSolution": 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.|
|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)
![Node.js v14](https://img.shields.io/badge/Node.js-v14-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)
![Compatible with SharePoint Online](https://img.shields.io/badge/SharePoint%20Online-Compatible-green.svg)
![Does not work with SharePoint 2019](https://img.shields.io/badge/SharePoint%20Server%202019-Incompatible-red.svg "SharePoint Server 2019 requires SPFx 1.4.1 or lower")
![Does not work with SharePoint 2016 (Feature Pack 2)](https://img.shields.io/badge/SharePoint%20Server%202016%20(Feature%20Pack%202)-Incompatible-red.svg "SharePoint Server 2016 Feature Pack 2 requires SPFx 1.1")
@ -90,6 +90,7 @@ Version|Date|Comments
1.1.0|April 25, 2021|List item modern audience support
1.2.0|January 01, 2022|Upgraded for SPFx v1.13.1
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
@ -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.
* 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:
* Navigate to `list-search-webpart`
* `npm install`
* `gulp serve`
* 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."
],
"creationDateTime": "2020-12-20",
"updateDateTime": "2022-07-11",
"updateDateTime": "2024-10-02",
"products": [
"SharePoint"
],
@ -20,7 +20,7 @@
},
{
"key": "SPFX-VERSION",
"value": "1.11.0"
"value": "1.20.0"
},
{
"key": "SPFX-SUPPORTSTHEMEVARIANTS",
@ -84,7 +84,7 @@
"authors": [
{
"gitHubAccount": "albegut",
"company": "Minsait",
"company": "Hiberus",
"pictureUrl": "https://github.com/albegut.png",
"name": "Alberto Gutierrez perez",
"twitter": "albertogperez"

View File

@ -3,10 +3,21 @@
"solution": {
"name": "list-search-webpart",
"id": "8277f088-9c30-4f95-9c15-9c18a9d40a26",
"version": "1.2.0.0",
"version": "1.4.0.0",
"includeClientSideAssets": true,
"skipFeatureDeployment": true,
"isDomainIsolated": false,
"metadata": {
"shortDescription": {
"default": "list-search-webpart description"
},
"longDescription": {
"default": "list-search-webpart description"
},
"screenshotPaths": [],
"videoUrl": "",
"categories": []
},
"developer": {
"name": "Alberto Gutierrez Perez",
"websiteUrl": "",
@ -14,6 +25,26 @@
"termsOfUseUrl": "",
"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": [
{
"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,
"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",
"private": true,
"main": "lib/index.js",
"engines": "undefined",
"engines": {
"node": ">=16.13.0 <17.0.0 || >=18.17.1 <19.0.0"
},
"scripts": {
"build": "gulp bundle",
"clean": "gulp clean",
@ -12,34 +14,43 @@
"allpackage": "gulp clean && gulp build --ship && gulp bundle --ship && gulp package-solution --ship",
"publish-please": "publish-please",
"prepublishOnly": "publish-please guard",
"serve": "gulp bundle --custom-serve --max_old_space_size=4096 && fast-serve"
"serve": "fast-serve"
},
"dependencies": {
"@microsoft/sp-core-library": "1.13.1",
"@microsoft/sp-lodash-subset": "1.13.1",
"@microsoft/sp-office-ui-fabric-core": "1.13.1",
"@microsoft/sp-property-pane": "1.13.1",
"@microsoft/sp-webpart-base": "1.13.1",
"@pnp/graph": "2.4.0",
"@pnp/sp": "2.0.8",
"@pnp/spfx-controls-react": "2.4.0",
"@pnp/spfx-property-controls": "3.3.0",
"office-ui-fabric-react": "7.174.1",
"react": "16.13.1",
"react-dom": "16.13.1",
"@fluentui/react": "8.106.4",
"@fluentui/react-components": "9.54.17",
"@microsoft/sp-adaptive-card-extension-base": "1.20.0",
"@microsoft/sp-core-library": "1.20.0",
"@microsoft/sp-lodash-subset": "1.20.0",
"@microsoft/sp-office-ui-fabric-core": "1.20.0",
"@microsoft/sp-property-pane": "1.20.0",
"@microsoft/sp-webpart-base": "1.20.0",
"@pnp/graph": "4.5.0",
"@pnp/sp": "4.5.0",
"@pnp/spfx-controls-react": "3.19.0",
"@pnp/spfx-property-controls": "3.18.0",
"react": "17.0.1",
"react-dom": "17.0.1",
"react-js-pagination": "3.0.3",
"react-xml-parser": "1.1.6"
"react-xml-parser": "1.1.6",
"tslib": "2.3.1"
},
"devDependencies": {
"@microsoft/rush-stack-compiler-3.9": "0.4.47",
"@microsoft/sp-build-web": "1.18.0",
"@microsoft/sp-module-interfaces": "1.13.1",
"@microsoft/sp-tslint-rules": "1.13.1",
"@types/react": "16.9.51",
"@types/react-dom": "16.9.8",
"@types/webpack-env": "1.13.1",
"ajv": "~6.12.3",
"@microsoft/eslint-config-spfx": "1.20.2",
"@microsoft/eslint-plugin-spfx": "1.20.2",
"@microsoft/rush-stack-compiler-4.7": "0.1.0",
"@microsoft/sp-build-web": "1.20.2",
"@microsoft/sp-module-interfaces": "1.20.2",
"@rushstack/eslint-config": "4.0.1",
"@types/react": "17.0.45",
"@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",
"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": {
"dependencies": [
{
"componentId": "f9e737b7-f0df-4597-ba8c-3060f82380db",
"componentName": "@microsoft/sp-property-pane",
"componentVersion": "1.13.1",
"componentId": "0d910c1c-13b9-4e1c-9aa4-b008c5e42d7d",
"componentName": "react",
"componentVersion": "17.0.1",
"isDirectDependency": true
},
{
"componentId": "1c6c9123-7aac-41f3-a376-3caea41ed83f",
"componentName": "@microsoft/sp-loader",
"componentVersion": "1.13.1",
"isDirectDependency": false
},
{
"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": "aa0a46ec-1505-43cd-a44a-93f3a5aa460a",
"componentName": "react-dom",
"componentVersion": "17.0.1",
"isDirectDependency": true
},
{
"componentId": "7263c7d0-1d6a-45ec-8d85-d4d1d234171b",
"componentName": "@microsoft/sp-core-library",
"componentVersion": "1.13.1",
"isDirectDependency": false
"componentVersion": "1.20.0",
"isDirectDependency": true
},
{
"componentId": "01c4df03-e775-48cb-aa14-171ee5199a15",
"componentName": "tslib",
"componentVersion": "1.10.0",
"componentVersion": "2.3.1",
"isDirectDependency": false
},
{
"componentId": "2e09fb9b-13bb-48f2-859f-97d6fff71176",
"componentName": "@ms/odsp-core-bundle",
"componentVersion": "1.1.192",
"componentVersion": "1.4.195",
"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",
"componentName": "@microsoft/sp-diagnostics",
"componentVersion": "1.13.1",
"componentVersion": "1.20.0",
"isDirectDependency": false
},
{
"componentId": "1c4541f7-5c31-41aa-9fa8-fbc9dc14c0a8",
"componentName": "@microsoft/sp-page-context",
"componentVersion": "1.13.1",
"componentId": "73e1dc6c-8441-42cc-ad47-4bd3659f8a3a",
"componentName": "@microsoft/sp-lodash-subset",
"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
},
{
@ -69,97 +63,188 @@
"isDirectDependency": false
},
{
"componentId": "c07208f0-ea3b-4c1a-9965-ac1b825211a6",
"componentName": "@microsoft/sp-http",
"componentVersion": "1.13.1",
"componentId": "63d75709-2785-4c91-97ad-489b171397d4",
"componentName": "@ms/sp-fluentui-migration-reactdom-render-bundle",
"componentVersion": "0.1.0",
"isDirectDependency": false
},
{
"componentId": "0d910c1c-13b9-4e1c-9aa4-b008c5e42d7d",
"componentName": "react",
"componentVersion": "16.13.1",
"componentId": "cc2cc925-b5be-41bb-880a-f0f8030c6aff",
"componentName": "@ms/odsp-utilities-bundle",
"componentVersion": "5.6.195",
"isDirectDependency": false
},
{
"componentId": "aa0a46ec-1505-43cd-a44a-93f3a5aa460a",
"componentName": "react-dom",
"componentVersion": "16.13.1",
"componentId": "8494e7d7-6b99-47b2-a741-59873e42f16f",
"componentName": "@ms/sp-component-utilities",
"componentVersion": "12.52.18",
"isDirectDependency": false
},
{
"componentId": "467dc675-7cc5-4709-8aac-78e3b71bd2f6",
"componentName": "@microsoft/sp-component-base",
"componentVersion": "1.13.1",
"isDirectDependency": true
"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
},
{
"componentId": "974a7777-0990-4136-8fa6-95d80114c2e0",
"componentName": "@microsoft/sp-webpart-base",
"componentVersion": "1.13.1",
"componentVersion": "1.20.0",
"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": {
"dependencies": [
{
"componentId": "f9e737b7-f0df-4597-ba8c-3060f82380db",
"componentName": "@microsoft/sp-property-pane",
"componentVersion": "1.13.1",
"componentId": "0d910c1c-13b9-4e1c-9aa4-b008c5e42d7d",
"componentName": "react",
"componentVersion": "17.0.1",
"isDirectDependency": true
},
{
"componentId": "1c6c9123-7aac-41f3-a376-3caea41ed83f",
"componentName": "@microsoft/sp-loader",
"componentVersion": "1.13.1",
"isDirectDependency": false
"componentId": "aa0a46ec-1505-43cd-a44a-93f3a5aa460a",
"componentName": "react-dom",
"componentVersion": "17.0.1",
"isDirectDependency": true
},
{
"componentId": "8217e442-8ed3-41fd-957d-b112e841286a",
"componentName": "@ms/sp-telemetry",
"componentVersion": "0.19.42",
"isDirectDependency": false
"componentId": "f9e737b7-f0df-4597-ba8c-3060f82380db",
"componentName": "@microsoft/sp-property-pane",
"componentVersion": "1.20.0",
"isDirectDependency": true
},
{
"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",
"componentId": "78359e4b-07c2-43c6-8d0b-d060b4d577e8",
"componentName": "@microsoft/sp-diagnostics",
"componentVersion": "1.20.0",
"isDirectDependency": false
},
{
"componentId": "7263c7d0-1d6a-45ec-8d85-d4d1d234171b",
"componentName": "@microsoft/sp-core-library",
"componentVersion": "1.13.1",
"componentVersion": "1.20.0",
"isDirectDependency": false
},
{
"componentId": "01c4df03-e775-48cb-aa14-171ee5199a15",
"componentName": "tslib",
"componentVersion": "1.10.0",
"componentVersion": "2.3.1",
"isDirectDependency": false
},
{
"componentId": "2e09fb9b-13bb-48f2-859f-97d6fff71176",
"componentName": "@ms/odsp-core-bundle",
"componentVersion": "1.1.192",
"componentVersion": "1.4.195",
"isDirectDependency": false
},
{
"componentId": "78359e4b-07c2-43c6-8d0b-d060b4d577e8",
"componentName": "@microsoft/sp-diagnostics",
"componentVersion": "1.13.1",
"componentId": "73e1dc6c-8441-42cc-ad47-4bd3659f8a3a",
"componentName": "@microsoft/sp-lodash-subset",
"componentVersion": "1.20.0",
"isDirectDependency": false
},
{
"componentId": "1c4541f7-5c31-41aa-9fa8-fbc9dc14c0a8",
"componentName": "@microsoft/sp-page-context",
"componentVersion": "1.13.1",
"componentId": "3173fefe-9995-49d1-a75d-a5caeaaba212",
"componentName": "@ms/sp-pages-content-panel-context",
"componentVersion": "0.1.0",
"isDirectDependency": false
},
{
@ -169,36 +254,133 @@
"isDirectDependency": false
},
{
"componentId": "c07208f0-ea3b-4c1a-9965-ac1b825211a6",
"componentName": "@microsoft/sp-http",
"componentVersion": "1.13.1",
"componentId": "63d75709-2785-4c91-97ad-489b171397d4",
"componentName": "@ms/sp-fluentui-migration-reactdom-render-bundle",
"componentVersion": "0.1.0",
"isDirectDependency": false
},
{
"componentId": "0d910c1c-13b9-4e1c-9aa4-b008c5e42d7d",
"componentName": "react",
"componentVersion": "16.13.1",
"componentId": "cc2cc925-b5be-41bb-880a-f0f8030c6aff",
"componentName": "@ms/odsp-utilities-bundle",
"componentVersion": "5.6.195",
"isDirectDependency": false
},
{
"componentId": "aa0a46ec-1505-43cd-a44a-93f3a5aa460a",
"componentName": "react-dom",
"componentVersion": "16.13.1",
"componentId": "8494e7d7-6b99-47b2-a741-59873e42f16f",
"componentName": "@ms/sp-component-utilities",
"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
},
{
"componentId": "974a7777-0990-4136-8fa6-95d80114c2e0",
"componentName": "@microsoft/sp-webpart-base",
"componentVersion": "1.13.1",
"componentVersion": "1.20.0",
"isDirectDependency": true
},
{
"componentId": "467dc675-7cc5-4709-8aac-78e3b71bd2f6",
"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
}
]
],
"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';
.listSearch {
@include ms-Grid;

View File

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

View File

@ -1,5 +1,5 @@
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 { IReadonlyTheme } from '@microsoft/sp-component-base';
import { SharePointType } from "../model/ISharePointFieldTypes";
@ -38,7 +38,7 @@ export interface IListSearchProps {
minutesToCache: number;
clickEnabled: boolean;
ModalType: IModalType;
completeModalFields: Array<ICompleteModalData>;
completeModalFields: Array<IBaseFieldData>;
redirectData: Array<IRedirectData>;
onRedirectIdQuery: string;
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 { SharePointType } from '../model/ISharePointFieldTypes';

View File

@ -13,30 +13,30 @@ import {
IGroup,
DetailsHeader,
DetailsListLayoutMode,
} from 'office-ui-fabric-react/lib/DetailsList';
} from '@fluentui/react';
import {
getTheme,
IconButton,
MessageBar,
MessageBarType,
ShimmeredDetailsList
} from 'office-ui-fabric-react';
import { SearchBox } from 'office-ui-fabric-react/lib/SearchBox';
} from '@fluentui/react';
import { SearchBox } from '@fluentui/react';
import Pagination from "react-js-pagination";
import { IReadonlyTheme } from '@microsoft/sp-component-base';
import { IIconProps } from 'office-ui-fabric-react/lib/Icon';
import { DefaultButton, PrimaryButton } from 'office-ui-fabric-react';
import { Icon, ITheme } from 'office-ui-fabric-react';
import { Shimmer } from 'office-ui-fabric-react/lib/Shimmer';
import { Modal } from 'office-ui-fabric-react/lib/Modal';
import { IIconProps } from '@fluentui/react';
import { DefaultButton, PrimaryButton } from '@fluentui/react';
import { Icon, ITheme } from '@fluentui/react';
import { Shimmer } from '@fluentui/react';
import { Modal } from '@fluentui/react';
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 { Persona, PersonaSize } from 'office-ui-fabric-react/lib/Persona';
import { Facepile, OverflowButtonType, IFacepilePersona } from 'office-ui-fabric-react/lib/Facepile';
import { Persona, PersonaSize } from '@fluentui/react';
import { Facepile, OverflowButtonType, IFacepilePersona } from '@fluentui/react';
import StringUtils from '../services/Utils';
import { Image, IImageProps, ImageFit } from 'office-ui-fabric-react/lib/Image';
import { Link } from 'office-ui-fabric-react';
import { Image, IImageProps, ImageFit } from '@fluentui/react';
import { Link } from '@fluentui/react';
import { FileTypeIcon, ApplicationType, IconType, ImageSize } from "@pnp/spfx-controls-react/lib/FileTypeIcon";
import IUserField from '../model/IUserField';
import IUrlField from '../model/IUrlField';
@ -47,6 +47,8 @@ import IResult from '../model/IResult';
import { IListSearchListQuery, IMapQuery } from '../model/IMapQuery';
import { WebPartTitle } from "@pnp/spfx-controls-react/lib/WebPartTitle";
import GraphService from '../services/GraphService';
import { List } from 'lodash';
import { getKeyValue } from '../utils/ObjectUtils';
const LOG_SOURCE = "IListdSearchWebPart";
@ -57,7 +59,7 @@ export default class IListdSearchWebPart extends React.Component<IListSearchProp
private keymapQuerys: IMapQuery = {};
private _graphService: GraphService;
constructor(props: IListSearchProps, state: IListSearchState) {
constructor(props: IListSearchProps) {
super(props);
this.state = {
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) {
this.setState({ items: null, filterItems: null, isLoading: true, columns: [] });
this.getData();
@ -92,12 +94,12 @@ export default class IListdSearchWebPart extends React.Component<IListSearchProp
this.getData();
}
public componentDidCatch(error, info) {
Log.warn(LOG_SOURCE, `Component throw exception ${info}`, this.props.Context.serviceScope);
componentDidCatch(error: Error, errorInfo: React.ErrorInfo): void {
Log.warn(LOG_SOURCE, `Component throw exception ${errorInfo}`, this.props.Context.serviceScope);
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.error(LOG_SOURCE, error, this.props.Context.serviceScope);
this.setState({
@ -109,13 +111,13 @@ export default class IListdSearchWebPart extends React.Component<IListSearchProp
private async getData() {
try {
let result: any[] = await this.readListsItems();
let result: Array<IResult> = await this.readListsItems();
if (this.props.ItemLimit) {
result = result.slice(0, this.props.ItemLimit);
}
let groupedItems = [];
let groupedItems: IGroupedItems[] = [];
if (this.props.groupByField) {
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();
let itemPromise: Array<Promise<Array<any>>> = [];
const itemPromise: Array<Promise<Array<IResult>>> = [];
Object.keys(this.keymapQuerys).map(site => {
let listService: ListService = new ListService(site, this.props.UseCache, this.props.minutesToCache, this.props.CacheType);
let siteProperties = this.props.Sites.filter(siteInformation => siteInformation.url === site);
const listService: ListService = new ListService(this.props.Context, site, this.props.UseCache, this.props.minutesToCache, this.props.CacheType);
const siteProperties = find(this.props.Sites, siteInformation => siteInformation.url === site);
Object.keys(this.keymapQuerys[site]).map(listQuery => {
itemPromise.push(listService.getListItems(
this.keymapQuerys[site][listQuery],
this.props.ListNameTitle,
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._graphService));
});
});
let items = await Promise.all(itemPromise);
let result = [];
const items = await Promise.all(itemPromise);
const result: IResult[] = [];
items.map(partialResult => {
result.push(...partialResult);
});
@ -159,18 +162,19 @@ export default class IListdSearchWebPart extends React.Component<IListSearchProp
}
private AddColumnsToDisplay(): IColumn[] {
let columns: IColumn[] = [];
const columns: IColumn[] = [];
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 });
});
return columns;
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
private setNewFilterState(items: any[], generalFilter: string, collapseAllGroups: boolean, columnFilters: IColumnFilter[]) {
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) {
this.groups.map(group => group.isCollapsed = true);
}
@ -182,9 +186,9 @@ export default class IListdSearchWebPart extends React.Component<IListSearchProp
}
private _getDetailListGroups(groupedItems: IGroupedItems[]) {
let groupedElements: number = 0;
let groupedElements = 0;
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;
return result;
});
@ -200,8 +204,8 @@ export default class IListdSearchWebPart extends React.Component<IListSearchProp
}
}
else {
let listQueryInfo = find(this.props.listsCollectionData, list => list.SiteCollectionSource == item.SiteCollectionSource && list.ListSourceField == item.ListSourceField);
let newQueryListItem: IListSearchListQuery = {
const listQueryInfo = find(this.props.listsCollectionData, list => list.SiteCollectionSource == item.SiteCollectionSource && list.ListSourceField == item.ListSourceField);
const newQueryListItem: IListSearchListQuery = {
list: { Id: item.ListSourceField, Title: item.ListSourceFieldName },
audienceEnabled: listQueryInfo.AudienceEnabled,
fields: [{ originalField: item.SourceField, newField: item.TargetField, fieldType: item.SPFieldType }],
@ -212,15 +216,15 @@ export default class IListdSearchWebPart extends React.Component<IListSearchProp
}
}
else {
let listQueryInfo = find(this.props.listsCollectionData, list => list.SiteCollectionSource == item.SiteCollectionSource && list.ListSourceField == item.ListSourceField);
let newQueryListItem: IListSearchListQuery = {
const listQueryInfo = find(this.props.listsCollectionData, list => list.SiteCollectionSource == item.SiteCollectionSource && list.ListSourceField == item.ListSourceField);
const newQueryListItem: IListSearchListQuery = {
list: { Id: item.ListSourceField, Title: item.ListSourceFieldName },
audienceEnabled: listQueryInfo.AudienceEnabled,
fields: [{ originalField: item.SourceField, newField: item.TargetField, fieldType: item.SPFieldType }],
camlQuery: listQueryInfo && listQueryInfo.Query,
viewName: listQueryInfo && listQueryInfo.ListView
};
this.keymapQuerys[item.SiteCollectionSource] = [];
this.keymapQuerys[item.SiteCollectionSource] = {};
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) {
try {
let isNewFilter: boolean = true;
let clearFilter: boolean = false;
let isMoreRestricted: boolean = false;
let newFitlers: IColumnFilter[] = this.state.columnFilters.filter(filter => {
let isNewFilter = true;
let clearFilter = false;
let isMoreRestricted = false;
const newFitlers: IColumnFilter[] = this.state.columnFilters.filter(filter => {
if (filter.columnName === propertyName) {
isMoreRestricted = filter.filterToApply.length < propertyValue.length;
filter.filterToApply = propertyValue;
@ -248,7 +252,7 @@ export default class IListdSearchWebPart extends React.Component<IListSearchProp
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);
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) {
if (this.props.IndividualColumnFilter) {
let newItems: Array<any> = [];
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const newItems: Array<any> = [];
itemsToRefine.map(item => {
let itemFounded: boolean = true;
let itemFounded = true;
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) {
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[]) {
if (valueToFilter && valueToFilter.length > 0) {
let filterItems: Array<any> = [];
let itemsToFilter = (isClearFilter || valueToFilter.length < this.state.generalFilter.length) ? allItems : filteredItems;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const filterItems: Array<any> = [];
const itemsToFilter = (isClearFilter || valueToFilter.length < this.state.generalFilter.length) ? allItems : filteredItems;
itemsToFilter.map(item => {
this.props.GeneralSearcheableFields.map(field => {
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);
return item;
}
@ -323,12 +331,12 @@ export default class IListdSearchWebPart extends React.Component<IListSearchProp
private _onRenderDetails(detailsFooterProps: IDetailsFooterProps, showSearchBox: boolean, isHeader: boolean): JSX.Element {
if (this.props.IndividualColumnFilter) {
let _renderDetailsFooterItemColumn: IDetailsRowBaseProps['onRenderItemColumn'] = (item, index, column) => {
let filter: IColumnFilter = this.state.columnFilters.find(colFilter => colFilter.columnName == column.name);
const _renderDetailsFooterItemColumn: IDetailsRowBaseProps['onRenderItemColumn'] = (item, index, column) => {
const filter: IColumnFilter = this.state.columnFilters.find(colFilter => colFilter.columnName == column.name);
if (this.props.IndividualColumnFilter && showSearchBox && column.data != SharePointType.FileIcon) {
return (
<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 {
@ -355,7 +363,7 @@ export default class IListdSearchWebPart extends React.Component<IListSearchProp
}
}
private handlePageChange(pageNumber) {
private handlePageChange(pageNumber: number) {
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;
}
// eslint-disable-next-line @typescript-eslint/no-explicit-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.props.groupByField) {
this.state.groupedItems.map(group => { result = [...result, ...group.Items]; });
}
else {
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);
}
else {
@ -399,16 +409,16 @@ export default class IListdSearchWebPart extends React.Component<IListSearchProp
}
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,
audienceEnabled: true,
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 }; })
};
let completeItem = await listService.getListItemById(completeItemQueryOptions, item.Id);
const completeItem = await listService.getListItemById(completeItemQueryOptions, item.Id);
if (completeItem) {
completeItem.SiteUrl = item.SiteUrl;
completeItem.ListName = item.ListName;
@ -428,10 +438,10 @@ export default class IListdSearchWebPart extends React.Component<IListSearchProp
}
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 (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());
window.location.replace(url.toString());
}
@ -569,6 +579,7 @@ export default class IListdSearchWebPart extends React.Component<IListSearchProp
return result;
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
private getOnRowClickRender(detailrow: any, defaultRender: any): JSX.Element {
return this.props.clickEnabled ?
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 {
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 {
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 {
let result;
let size = ImageSize.small;
let type = IconType.image;
const size = ImageSize.small;
const type = IconType.image;
switch (extesion) {
case "doc":
case "docm":
@ -679,10 +692,11 @@ export default class IListdSearchWebPart extends React.Component<IListSearchProp
return result;
}
private GetJSXElementByType(item: any, fieldName: string, fieldType: SharePointType, ommitCamlQuery: boolean = false): JSX.Element {
const value: any = this.GetItemValueFieldByFieldType(item, fieldName, fieldType, ommitCamlQuery);
// eslint-disable-next-line @typescript-eslint/no-explicit-any
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;
let result: JSX.Element = <span></span>;
let result: JSX.Element = <span/>;
switch (fieldType) {
case SharePointType.FileIcon:
{
@ -707,7 +721,7 @@ export default class IListdSearchWebPart extends React.Component<IListSearchProp
/>;
}
else {
result = <span></span>;
result = <span/>;
}
}
break;
@ -715,12 +729,13 @@ export default class IListdSearchWebPart extends React.Component<IListSearchProp
case SharePointType.UserMulti:
{
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) {
return <span style={{ color: semanticColors.bodyText }}>{val}</span>;
return <span key={index} style={{ color: semanticColors.bodyText }}>{val}</span>;
}
else {
return <span style={{ color: semanticColors.bodyText }}>{val}<br></br></span>;
return <span key={index} style={{ color: semanticColors.bodyText }}>{val}<br/></span>;
}
})}
</span>;
@ -740,7 +755,7 @@ export default class IListdSearchWebPart extends React.Component<IListSearchProp
/>;
}
else {
result = <span></span>;
result = <span/>;
}
}
break;
@ -748,18 +763,19 @@ export default class IListdSearchWebPart extends React.Component<IListSearchProp
case SharePointType.TaxonomyMulti:
{
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) {
return <span style={{ color: semanticColors.bodyText }}>{val}</span>;
return <span key={`${fieldType}-${index}`} style={{ color: semanticColors.bodyText }}>{val}</span>;
}
else {
return <span style={{ color: semanticColors.bodyText }}>{val}<br></br></span>;
return <span key={`${fieldType}-${index}`} style={{ color: semanticColors.bodyText }}>{val}<br/></span>;
}
})}
</span>;
}
else {
result = <span></span>;
result = <span/>;
}
break;
}
@ -768,39 +784,41 @@ export default class IListdSearchWebPart extends React.Component<IListSearchProp
result = <Link style={{ color: semanticColors.bodyText }} href="#">{value}</Link>;
}
else {
result = <span></span>;
result = <span/>;
}
break;
case SharePointType.ChoiceMulti:
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) {
return <span style={{ color: semanticColors.bodyText }}>{val}</span>;
return <span key={`${fieldType}-${index}`} style={{ color: semanticColors.bodyText }}>{val}</span>;
}
else {
return <span style={{ color: semanticColors.bodyText }}>{val}<br></br></span>;
return <span key={`${fieldType}-${index}`} style={{ color: semanticColors.bodyText }}>{val}<br/></span>;
}
})}
</span>;
}
else {
result = <span></span>;
result = <span/>;
}
break;
case SharePointType.LookupMulti:
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) {
return <Link style={{ color: semanticColors.bodyText }} href="#">{val}</Link>;
return <Link key={`${fieldType}-${index}`} style={{ color: semanticColors.bodyText }} href="#">{val}</Link>;
}
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>;
}
else {
result = <span></span>;
result = <span/>;
}
break;
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>;
}
else {
result = <span></span>;
result = <span/>;
}
break;
case SharePointType.Image:
@ -828,17 +846,17 @@ export default class IListdSearchWebPart extends React.Component<IListSearchProp
/>;
}
else {
result = <span></span>;
result = <span/>;
}
break;
}
case SharePointType.NoteFullHtml:
{
if (value) {
result = <span dangerouslySetInnerHTML={{ __html: value }}></span>;
result = <span dangerouslySetInnerHTML={{ __html: value }}/>;
}
else {
result = <span></span>;
result = <span/>;
}
break;
}
@ -850,9 +868,11 @@ export default class IListdSearchWebPart extends React.Component<IListSearchProp
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 value = item[field];
const value = item[field];
switch (type) {
case SharePointType.FileIcon:
{
@ -873,7 +893,7 @@ export default class IListdSearchWebPart extends React.Component<IListSearchProp
}
else {
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;
}
}
@ -883,7 +903,7 @@ export default class IListdSearchWebPart extends React.Component<IListSearchProp
case SharePointType.Image:
{
if (!isEmpty(value)) {
let url: IUrlField = { Url: value.Url, Description: value.Description };
const url: IUrlField = { Url: value.Url, Description: value.Description };
result = url;
}
break;
@ -915,8 +935,8 @@ export default class IListdSearchWebPart extends React.Component<IListSearchProp
}
else {
if (value && value.length > 0) {
let personas: IFacepilePersona[] = value.map(user => {
let email = StringUtils.GetUserEmail(user.Name);
const personas: IFacepilePersona[] = value.map((user: { Name: string; Title: string; }) => {
const email = StringUtils.GetUserEmail(user.Name);
return { imageUrl: email ? `/_layouts/15/userphoto.aspx?UserName=${email}` : undefined, personaName: user.Title, imageInitials: StringUtils.GetUserInitials(user.Title), };
});
result = personas;
@ -950,7 +970,7 @@ export default class IListdSearchWebPart extends React.Component<IListSearchProp
result = value ? value.split(';') : "";
}
else {
result = value && value.map(val => { return val.Title; });
result = value && value.map((val: { Title: string; }) => { return val.Title; });
}
break;
}
@ -994,7 +1014,7 @@ export default class IListdSearchWebPart extends React.Component<IListSearchProp
}
case SharePointType.TaxonomyMulti:
{
result = value && value.map(tax => { return tax.Label; });
result = value && value.map((tax: { Label: string; }) => { return tax.Label; });
break;
}
default:
@ -1007,10 +1027,11 @@ export default class IListdSearchWebPart extends React.Component<IListSearchProp
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[] = [];
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 => {
return { GroupName: group, Items: elementsInGroups[group] };
});
@ -1043,10 +1064,12 @@ export default class IListdSearchWebPart extends React.Component<IListSearchProp
});
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) }; });
this.setState({ columns: newColumns, groupedItems: newGroupedElements });
}
else {
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
const newItems = this._copyAndSort(this.state.filterItems, currColumn.fieldName!, currColumn.isSortedDescending);
this.setState({ columns: newColumns, filterItems: newItems });
}
@ -1056,13 +1079,13 @@ export default class IListdSearchWebPart extends React.Component<IListSearchProp
public render(): React.ReactElement<IListSearchProps> {
const { semanticColors }: IReadonlyTheme = this.props.themeVariant;
let clearAllButton = this.props.ClearAllFiltersBtnColor == "white" ? <DefaultButton text={this.props.ClearAllFiltersBtnText} className={styles.btn} onClick={(ev) => this._clearAllFilters()} /> :
<PrimaryButton 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={() => this._clearAllFilters()} />;
return (
<div className={styles.listSearch} style={{ backgroundColor: semanticColors.bodyBackground, color: semanticColors.bodyText }}>
<div className={styles.row}>
<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 ?
<MessageBar
messageBarType={MessageBarType.error}
@ -1089,7 +1112,7 @@ export default class IListdSearchWebPart extends React.Component<IListSearchProp
<div className={styles.rowData}>
<div className={styles.colData}>
{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
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 { 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 { TextField } from 'office-ui-fabric-react/lib/components/TextField';
import { IMappingFieldData, IListData, ICustomOption, SiteList, ListField, IBaseFieldData } from '../model/IListConfigProps';
import { TextField } from '@fluentui/react';
import { IListData, ICustomOption, SiteList, ListField } from '../model/IListConfigProps';
import { IPropertyPaneDropdownOption } from '@microsoft/sp-property-pane';
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 {
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}
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)}
onChange={(evt, option) => customOnchangeFunction ? customOnchangeFunction(row, field.id, option, updateFunction, errorFunction) : updateFunction(field.id, option.key)}
onRenderOption={field.onRenderOption}
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 {
let currentOptions = [];
public static getListPickerBySiteOptions(
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 => {
if (row.SiteCollectionSource && option.SiteCollectionSource == row.SiteCollectionSource) {
currentOptions.push({
@ -34,24 +53,54 @@ export default class CustomCollectionDataField {
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 {
let options = [];
public static getListPicker(
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) {
options = possibleOptions.map(option => { return { key: option.Id, text: option.Title }; });
}
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 {
let options = [];
public static getPickerByStringOptions(
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) {
options = possibleOptions.map(option => { return { key: option, text: option }; });
}
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 {
let options = [];
public static getFieldPickerByList(
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) {
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({
key: option.Key,
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 {
return <TextField placeholder={field.placeholder || field.title
}
@ -79,6 +128,7 @@ export default class CustomCollectionDataField {
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 {
return <Checkbox checked={item[field.id] ? item[field.id] : false}
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/
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 targetProperty: string;

View File

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

View File

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

View File

@ -2,11 +2,11 @@ import { SiteList } from "./IListConfigProps";
import { SharePointType } from "./ISharePointFieldTypes";
export interface IMapQuery {
[site: string]: Array<IMapQueryList>;
[site: string]: IMapQueryList;
}
export interface IMapQueryList {
[list: string]: Array<IListSearchListQuery>;
[list: string]: IListSearchListQuery;
}
export interface IListSearchListQuery {
@ -14,6 +14,12 @@ export interface IListSearchListQuery {
audienceEnabled: boolean;
camlQuery?: 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,17 +1,19 @@
import { SiteList } from "./IListConfigProps";
export default interface IResult {
FileExtension: string;
SiteUrl: string;
ListName: string; //Field to display list name in detail list
List: SiteList;
Id: number;
UniqueId: string;
ServerUrl: string;
FileLeafRef: string;
OData__ModernAudienceTargetUserField:Audience[];
// eslint-disable-next-line @typescript-eslint/no-explicit-any
[key: string]: any;
FileExtension: string;
SiteUrl: string;
ListName: string; //Field to display list name in detail list
List: SiteList;
Id: number;
UniqueId: string;
ServerUrl: string;
FileLeafRef: string;
OData__ModernAudienceTargetUserField: Audience[];
}
interface Audience{
interface Audience {
Name: string;
}

View File

@ -1,5 +1,6 @@
export interface ISessionStorageElement
{
hasExpired:boolean;
// eslint-disable-next-line @typescript-eslint/no-explicit-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/groups";
import { WebPartContext } from "@microsoft/sp-webpart-base";
import { PnPClientStorage } from "@pnp/common";
import IGraphService from "./IGraphService";
export default class GraphService implements IGraphService {
let _graph: GraphFI
export default class GraphService {
private _storage: PnPClientStorage;
private _localStorageKey: string = 'userGroups';
private _localStorageKey = 'userGroups';
// 1 day
private _expiredTimeMillisecons: number = 8.64e+7;
private _expiredTimeMillisecons = 8.64e+7;
public constructor(spfxContext: WebPartContext) {
graph.setup({
spfxContext
});
_graph = graphfi().using(SPFx(spfxContext));
this._storage = new PnPClientStorage();
}
@ -26,7 +23,7 @@ export default class GraphService implements IGraphService {
this._storage.local.deleteExpired();
let userGroups = this._storage.local.get(this._localStorageKey);
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));
}
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/lists";
import "@pnp/sp/items";
import "@pnp/sp/views";
import "@pnp/sp/fields";
import IListService from "./IListService";
import { ICamlQuery } from "@pnp/sp/lists";
import { ICamlQueryXml } from '../model/ICamlQueryXml';
import XMLParser from 'react-xml-parser';
import { IWeb, Web } from '@pnp/sp/webs';
import XMLParser, { XMLElement } from 'react-xml-parser';
import { SharePointType } from '../model/ISharePointFieldTypes';
import IResult from '../model/IResult';
import { intersection, isEmpty } from '@microsoft/sp-lodash-subset';
import { ListField, SiteList } from '../model/IListConfigProps';
import { IListSearchListQuery } from '../model/IMapQuery';
import { IListSearchListQuery, IListSearchListQueryItem } from '../model/IMapQuery';
import GraphService from './GraphService';
import { WebPartContext } from "@microsoft/sp-webpart-base";
import { getKeyValue, setKeyValue } from "../utils/ObjectUtils";
export interface QueryHelperEntity {
viewFields: string[];
expandFields: string[];
}
export default class ListService implements IListService {
private web: IWeb;
export default class ListService {
private static sourceSP: SPFI;
private baseUrl: string;
private _sp: SPFI;
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") {
sp.setup({
defaultCachingStore: useCache ? cacheType : undefined,
defaultCachingTimeoutSeconds: useCache ? (cacheTime * 60) : undefined,
sp: {
headers: {
private GetSourceSP(context: WebPartContext, useCache: boolean, cacheTime?: number, cacheType?: "session" | "local") {
if (!ListService.sourceSP) {
ListService.sourceSP = spfi().using(SPFx(context)).using(InjectHeaders(
{
Accept: 'application/json;odata=nometadata'
},
baseUrl: siteUrl
},
});
this.web = Web(siteUrl);
}
));
if (useCache) {
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._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>> {
try {
let camlQuery: boolean = false;
const camlQuery = false;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
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) {
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 = items.map(m => m.FieldValuesAsText);
// eslint-disable-next-line @typescript-eslint/no-explicit-any
items = items.map((m: { FieldValuesAsText: any; }) => m.FieldValuesAsText);
}
else {
if (listQueryOptions.viewName) {
let viewInfo: any = await this.web.lists.getById(listQueryOptions.list.Id).views.getByTitle(listQueryOptions.viewName).select("ViewQuery").get();
let query = this.getCamlQueryWithViewFieldsAndRowLimit(`<View><Query>${viewInfo.ViewQuery}</Query></View>`, queryConfig, rowLimit);
// eslint-disable-next-line @typescript-eslint/no-explicit-any
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 = items.map(m => m.FieldValuesAsText);
// eslint-disable-next-line @typescript-eslint/no-explicit-any
items = items.map((m: { FieldValuesAsText: any; }) => m.FieldValuesAsText);
}
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(','))
.top(rowLimit || ListService.MAX_TOP)
.expand(queryConfig.expandFields.join(',')).usingCaching().get();
.expand(queryConfig.expandFields.join(','))();
}
}
if (listQueryOptions.audienceEnabled && graphService) {
let userGroups: string[] = await graphService.getTransitiveMemberOf();
const userGroups: string[] = await graphService.getTransitiveMemberOf();
items = this.getAudienceItems(items, userGroups);
}
let mappedItems = items.map((i: IResult) => {
const mappedItems = items.map((i: IResult) => {
i.FileExtension = this.GetFileExtension(i.FileLeafRef);
i.SiteUrl = this.baseUrl;
i.ListName = listQueryOptions.list.Title;
@ -85,10 +97,12 @@ export default class ListService implements IListService {
});
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) {
i[sitePropertyName] = sitePropertyValue;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
setKeyValue(i, sitePropertyName as any, sitePropertyValue);
}
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> {
try {
let 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();
const queryConfig: QueryHelperEntity = this.GetViewFieldsWithId(listQueryOptions, false, true);
return this._sp.web.lists.getById(listQueryOptions.list.Id).items.getById(itemId).select(queryConfig.viewFields.join(',')).expand(queryConfig.expandFields.join(','))();
} catch (error) {
return Promise.reject(error);
}
@ -109,7 +124,7 @@ export default class ListService implements IListService {
public async getSiteListsTitle(): Promise<Array<SiteList>> {
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) {
return Promise.reject(error);
}
@ -117,33 +132,35 @@ export default class ListService implements IListService {
public async getListFields(listId: string): Promise<Array<ListField>> {
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) {
return Promise.reject(error);
}
}
private getAudienceItems(itemsToFilter: IResult[], userGroups: string[]) {
let results: IResult[] = [];
userGroups && itemsToFilter.map(item => {
let itemAudiencesIds: string[] = item.OData__ModernAudienceTargetUserField && item.OData__ModernAudienceTargetUserField.map(audience => { return audience.Name.split("|")[2]; });
if (itemAudiencesIds) {
let matches: string[] = intersection(itemAudiencesIds, userGroups);
if (matches && matches.length > 0) {
const results: IResult[] = [];
if (userGroups) {
itemsToFilter.map(item => {
const itemAudiencesIds: string[] = item.OData__ModernAudienceTargetUserField && item.OData__ModernAudienceTargetUserField.map(audience => { return audience.Name.split("|")[2]; });
if (itemAudiencesIds) {
const matches: string[] = intersection(itemAudiencesIds, userGroups);
if (matches && matches.length > 0) {
results.push(item);
}
}
else {
results.push(item);
}
}
else {
results.push(item);
}
});
});
}
return results;
}
private GetViewFieldsWithId(listQueryOptions: IListSearchListQuery, isCamlQuery: boolean, isItemId: boolean): QueryHelperEntity {
let result: QueryHelperEntity = { expandFields: [], viewFields: ['ServerUrl', 'FileLeafRef', 'Id', 'UniqueId'] };
let hasToAddFieldsAsText: boolean = false;
const result: QueryHelperEntity = { expandFields: [], viewFields: ['ServerUrl', 'FileLeafRef', 'Id', 'UniqueId'] };
let hasToAddFieldsAsText = false;
listQueryOptions.fields.map(field => {
switch (field.fieldType) {
case SharePointType.User:
@ -209,15 +226,17 @@ export default class ListService implements IListService {
return result;
}
private GetItemValue(item: any, field: any, fromCamlQuery: boolean): any {
private GetItemValue(item: IResult, field: IListSearchListQueryItem, fromCamlQuery: boolean): IResult {
switch (field.fieldType) {
case SharePointType.Lookup:
case SharePointType.LookupMulti:
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 {
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) {
delete item[field.originalField];
}
@ -257,8 +276,8 @@ export default class ListService implements IListService {
item[field.newField] = item['FieldValuesAsText'][field.originalField];
}
else {
let taxonomyValues = item["TaxCatchAll"];
let taxonomyTerm = taxonomyValues.find(t => t.ID === item[field.originalField].WssId);
const taxonomyValues = item["TaxCatchAll"];
const taxonomyTerm = taxonomyValues.find((t: { ID: number; }) => t.ID === item[field.originalField].WssId);
if (taxonomyTerm) {
item[field.newField] = taxonomyTerm;
}
@ -292,12 +311,13 @@ export default class ListService implements IListService {
return item;
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
private async getListItemsByCamlQuery(listId: string, camlQuery: string, queryConfig: QueryHelperEntity): Promise<Array<any>> {
try {
const caml: ICamlQuery = {
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) {
return Promise.reject(error);
}
@ -305,24 +325,24 @@ export default class ListService implements IListService {
private getCamlQueryWithViewFieldsAndRowLimit(camlQuery: string, queryConfig: QueryHelperEntity, rowLimit: number): string {
try {
let XmlParser = new XMLParser();
let xml: ICamlQueryXml = XmlParser.parseFromString(camlQuery);
const XmlParser = new XMLParser();
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: [] };
});
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 => {
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
rowLimitXml = child;
rowLimitXml.value = child.value;
}
});
@ -330,7 +350,7 @@ export default class ListService implements IListService {
xml.children = [viewFieldsXml, rowLimitXml, queryXml];
}
let result: string = XmlParser.toString(xml);
const result: string = XmlParser.toString(xml);
return result.replace("</RowLimit></RowLimit>", "</RowLimit>");
} catch (error) {
return `getCamlQueryWithViewFieldsAndRowLimit -> ${error.message}`;
@ -339,7 +359,7 @@ export default class ListService implements IListService {
}
private GetFileExtension(filename: string): string {
var re = /(?:\.([^.]+))?$/;
const re = /(?:\.([^.]+))?$/;
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 {
if (text) {
let initials = text.match(/\b\w/g) || [];
const initials = text.match(/\b\w/g) || [];
text = ((initials.shift() || '') + (initials.pop() || '')).toUpperCase();
}
return text;
}
public static GetUserEmail(text: string): string {
let result: string = "";
let result = "";
if (text && text.indexOf('|') > 0) {
let splited = text.split('|');
const splited = text.split('|');
if (splited && splited.length > 1) {
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';
.listSearchConsumerWebPart {

View File

@ -2,7 +2,7 @@ import * as React from 'react';
import styles from './ListSearchConsumerWebPart.module.scss';
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> {
return (
<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": {
"noImplicitAny": true,
"target": "es6",
"forceConsistentCasingInFileNames": true,
"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
}
}