From b573dca1def24c16dd648cde0c8491e1e2623f0e Mon Sep 17 00:00:00 2001 From: Franck Cornu Date: Tue, 12 Nov 2024 09:20:03 -0500 Subject: [PATCH] - Added missing postcss dependency for SPFx - removed unecessary SPFx project under packages (moved to apps) --- apps/spfx/package.json | 1 + .../searchBox/components/SearchBox.tsx | 2 +- .../components/SearchResults.tsx | 2 +- .../components/SearchVerticals.tsx | 2 +- packages/spfx/.eslintrc.js | 352 ------ packages/spfx/.gitignore | 35 - packages/spfx/.npmignore | 16 - packages/spfx/.vscode/launch.json | 23 - packages/spfx/.vscode/settings.json | 13 - packages/spfx/.yo-rc.json | 21 - packages/spfx/README.md | 9 - packages/spfx/babel.config.json | 12 - packages/spfx/config/config.json | 49 - .../spfx/config/deploy-azure-storage.json | 7 - packages/spfx/config/package-solution.json | 98 -- packages/spfx/config/sass.json | 3 - packages/spfx/config/serve.json | 6 - packages/spfx/config/write-manifests.json | 4 - packages/spfx/fast-serve/babel.config.json | 12 - packages/spfx/fast-serve/config.json | 6 - packages/spfx/fast-serve/webpack.extend.js | 81 -- packages/spfx/gulpfile.js | 222 ---- packages/spfx/package.json | 89 -- packages/spfx/src/common/BaseWebPart.tsx | 647 ---------- packages/spfx/src/common/ComponentType.ts | 11 - packages/spfx/src/common/Constants.ts | 7 - packages/spfx/src/common/declaration.d.ts | 9 - .../ConfigurationPanel/ConfigurationPanel.tsx | 147 --- .../IConfigurationPanelProps.ts | 36 - .../IConfigurationPanelState.ts | 32 - .../ConfigurationPanel/IConfigurationTab.ts | 21 - .../IConfigurationTabField.ts | 43 - .../src/controls/FormBuilder/FormBuilder.tsx | 229 ---- .../controls/FormBuilder/IFormBuilderProps.ts | 25 - .../controls/FormBuilder/IFormBuilderState.ts | 12 - .../FormDataCollection/FormDataCollection.tsx | 197 ---- .../IFormDataCollectionProps.ts | 68 -- .../IFormDataCollectionState.ts | 7 - .../ItemRepeater/IItemRepeaterProps.ts | 82 -- .../ItemRepeater/IItemRepeaterState.ts | 6 - .../ItemRepeater/IItemRepeaterValue.ts | 8 - .../controls/ItemRepeater/ItemRepeater.tsx | 258 ---- .../LayoutSlotField/ILayoutSlotFieldProps.ts | 7 - .../LayoutSlotField/ILayoutSlotFieldState.ts | 5 - .../LayoutSlotField/LayoutSlotField.tsx | 100 -- .../ILocalizedFieldProps.ts | 36 - .../ILocalizedFieldState.ts | 25 - .../LocalizedTextField/LocalizedField.tsx | 215 ---- .../components/ITranslation.ts | 12 - .../components/ITranslationFieldProps.ts | 26 - .../components/ITranslationFieldState.ts | 5 - .../components/TranslationField.tsx | 106 -- .../WebPartPlaceholder/WebPartPlaceholder.tsx | 20 - .../src/controls/WebPartPlaceholder/logo.svg | 1043 ----------------- .../datasources/MicrosoftSearchDataSource.tsx | 737 ------------ packages/spfx/src/datasources/loc/en-us.js | 57 - .../spfx/src/datasources/loc/strings.d.ts | 59 - .../spfx/src/helpers/DynamicPropertyHelper.ts | 43 - packages/spfx/src/helpers/LayoutHelper.ts | 193 --- .../spfx/src/helpers/ServiceScopeHelper.ts | 44 - packages/spfx/src/index.ts | 1 - packages/spfx/src/layouts/AvailableLayouts.ts | 85 -- .../filters/custom/FiltersCustomLayout.ts | 20 - .../filters/custom/filters-custom.html | 14 - .../filters/default/FiltersDefaultLayout.ts | 20 - .../src/layouts/filters/default/default.html | 22 - .../results/custom/ResultsCustomLayout.ts | 47 - .../results/custom/results-custom.html | 32 - .../simpleList/ResultsDefaultLayout.tsx | 61 - .../layouts/results/simpleList/default.html | 36 - .../results/tiles/ResultsTilesLayout.tsx | 162 --- .../layouts/results/tiles/results-tiles.html | 26 - .../verticals/custom/VerticalsCustomLayout.ts | 20 - .../verticals/custom/verticals-custom.html | 17 - .../default/VerticalsDefaultLayout.ts | 20 - .../layouts/verticals/default/default.html | 10 - packages/spfx/src/loc/commonStrings.d.ts | 160 --- packages/spfx/src/loc/en-us.js | 159 --- .../spfx/src/loc/propertyControlStrings.d.ts | 8 - .../spfx/src/models/common/BaseDataSource.ts | 66 -- .../spfx/src/models/common/BaseLayout.tsx | 142 --- .../models/common/IBaseWebComponentWrapper.ts | 27 - .../src/models/common/IBaseWebPartProps.ts | 77 -- .../spfx/src/models/common/ICustomPalette.ts | 5 - .../spfx/src/models/common/IDataSource.ts | 44 - packages/spfx/src/models/common/ILayout.ts | 42 - .../src/models/common/ILayoutDefinition.ts | 51 - .../spfx/src/models/common/ILayoutSlot.ts | 37 - .../src/models/common/ITemplateContext.ts | 10 - .../dynamicData/IDynamicDataSourceProperty.ts | 6 - .../dynamicData/ISearchVerticalSourceData.ts | 6 - .../IPropertyPaneCodeEditorInternalProps.ts | 5 - .../IPropertyPaneCodeEditorProps.ts | 8 - .../PropertyPaneCodeEditor.tsx | 55 - .../IPropertyPaneCodeEditorHostProps.ts | 9 - .../IPropertyPaneCodeEditorHostState.ts | 4 - .../components/PropertyPaneCodeEditorHost.tsx | 101 -- .../IPropertyPaneComboBoxInternalProps.ts | 5 - .../IPropertyPaneComboBoxProps.ts | 11 - .../PropertyPaneCombobox.ts | 82 -- .../IPropertyPaneFilePickerInternalProps.ts | 5 - .../IPropertyPaneFilePickerProps.ts | 8 - .../PropertyPaneFilePicker.tsx | 59 - .../IPropertyPaneFilePickerHostProps.ts | 9 - .../IPropertyPaneFilePickerHostState.ts | 6 - .../components/PropertyPaneFilePickerHost.tsx | 130 -- ...tyPaneFiltersConfigurationInternalProps.ts | 5 - .../IPropertyPaneFiltersConfigurationProps.ts | 9 - .../PropertyPaneFiltersConfiguration.tsx | 391 ------ ...ertyPaneFormDataCollectionInternalProps.ts | 5 - .../IPropertyPaneFormDataCollectionProps.ts | 4 - .../PropertyPaneFormDataCollection.tsx | 63 - .../IPropertyPaneNonReactiveTextFieldProps.ts | 47 - .../PropertyPaneNonReactiveTextField.ts | 78 -- .../components/INonReactiveTextFieldProps.ts | 52 - .../components/INonReactiveTextFieldState.ts | 12 - .../components/NonReactiveTextField.tsx | 75 -- .../dynamicDataService/DynamicDataService.ts | 55 - .../dynamicDataService/IDynamicDataService.ts | 8 - .../src/services/fileService/FileService.ts | 51 - .../src/services/fileService/IFileService.ts | 7 - .../ILocalizationService.ts | 12 - .../LocalizationService.ts | 155 --- .../tokenService/ISharePointTokenService.ts | 25 - .../tokenService/SharePointTokenService.ts | 633 ---------- packages/spfx/src/styles/postcss.config.js | 7 - packages/spfx/src/styles/tailwind.css | 8 - .../searchBox/ISearchBoxWebPartProps.ts | 35 - .../searchBox/SearchBoxWebPart.manifest.json | 37 - .../SearchBoxWebPart.manifest.template.json | 37 - .../webparts/searchBox/SearchBoxWebPart.ts | 197 ---- .../searchBox/components/ISearchBoxProps.ts | 5 - .../searchBox/components/SearchBox.tsx | 19 - .../spfx/src/webparts/searchBox/loc/en-us.js | 52 - .../src/webparts/searchBox/loc/mystrings.d.ts | 54 - .../ISearchFiltersWebPartProps.ts | 32 - .../SearchFiltersWebPart.manifest.json | 37 - ...earchFiltersWebPart.manifest.template.json | 37 - .../searchFilters/SearchFiltersWebPart.ts | 376 ------ .../components/ISearchFiltersProps.ts | 27 - .../components/SearchFilters.tsx | 53 - .../src/webparts/searchFilters/loc/en-us.js | 24 - .../webparts/searchFilters/loc/mystrings.d.ts | 28 - .../ISearchResultsWebPartProps.ts | 26 - .../SearchResultsWebPart.manifest.json | 37 - ...earchResultsWebPart.manifest.template.json | 37 - .../searchResults/SearchResultsWebPart.tsx | 610 ---------- .../components/ISearchResultComponentProps.ts | 23 - .../components/ISearchResultsProps.ts | 29 - .../components/ISearchResultsState.ts | 2 - .../components/SearchResults.tsx | 123 -- .../src/webparts/searchResults/loc/en-us.js | 23 - .../webparts/searchResults/loc/mystrings.d.ts | 25 - .../ISearchVerticalsWebPartProps.ts | 6 - .../SearchVerticalsWebPart.manifest.json | 37 - ...rchVerticalsWebPart.manifest.template.json | 37 - .../SearchVerticalsWebPart.tsx | 335 ------ .../components/ISearchVerticalsProps.ts | 16 - .../components/SearchVerticals.tsx | 71 -- .../src/webparts/searchVerticals/loc/en-us.js | 31 - .../searchVerticals/loc/mystrings.d.ts | 33 - packages/spfx/tailwind.config.js | 95 -- ...c8e4-0912-460b-a65c-7e0bbdb864cf_color.png | Bin 10248 -> 0 bytes ...e4-0912-460b-a65c-7e0bbdb864cf_outline.png | Bin 542 -> 0 bytes ...51b5-c1ea-4a68-8097-90edc9da61ce_color.png | Bin 10248 -> 0 bytes ...b5-c1ea-4a68-8097-90edc9da61ce_outline.png | Bin 542 -> 0 bytes ...f17d-c6f5-4853-8017-86ad27f396f1_color.png | Bin 10248 -> 0 bytes ...7d-c6f5-4853-8017-86ad27f396f1_outline.png | Bin 542 -> 0 bytes ...f315-4ce8-4386-88fa-897566e2a710_color.png | Bin 10248 -> 0 bytes ...15-4ce8-4386-88fa-897566e2a710_outline.png | Bin 542 -> 0 bytes packages/spfx/toolchain/gulp.js | 86 -- packages/spfx/tsconfig.json | 38 - pnpm-lock.yaml | 890 +------------- 173 files changed, 47 insertions(+), 12888 deletions(-) delete mode 100644 packages/spfx/.eslintrc.js delete mode 100644 packages/spfx/.gitignore delete mode 100644 packages/spfx/.npmignore delete mode 100644 packages/spfx/.vscode/launch.json delete mode 100644 packages/spfx/.vscode/settings.json delete mode 100644 packages/spfx/.yo-rc.json delete mode 100644 packages/spfx/README.md delete mode 100644 packages/spfx/babel.config.json delete mode 100644 packages/spfx/config/config.json delete mode 100644 packages/spfx/config/deploy-azure-storage.json delete mode 100644 packages/spfx/config/package-solution.json delete mode 100644 packages/spfx/config/sass.json delete mode 100644 packages/spfx/config/serve.json delete mode 100644 packages/spfx/config/write-manifests.json delete mode 100644 packages/spfx/fast-serve/babel.config.json delete mode 100644 packages/spfx/fast-serve/config.json delete mode 100644 packages/spfx/fast-serve/webpack.extend.js delete mode 100644 packages/spfx/gulpfile.js delete mode 100644 packages/spfx/package.json delete mode 100644 packages/spfx/src/common/BaseWebPart.tsx delete mode 100644 packages/spfx/src/common/ComponentType.ts delete mode 100644 packages/spfx/src/common/Constants.ts delete mode 100644 packages/spfx/src/common/declaration.d.ts delete mode 100644 packages/spfx/src/controls/ConfigurationPanel/ConfigurationPanel.tsx delete mode 100644 packages/spfx/src/controls/ConfigurationPanel/IConfigurationPanelProps.ts delete mode 100644 packages/spfx/src/controls/ConfigurationPanel/IConfigurationPanelState.ts delete mode 100644 packages/spfx/src/controls/ConfigurationPanel/IConfigurationTab.ts delete mode 100644 packages/spfx/src/controls/ConfigurationPanel/IConfigurationTabField.ts delete mode 100644 packages/spfx/src/controls/FormBuilder/FormBuilder.tsx delete mode 100644 packages/spfx/src/controls/FormBuilder/IFormBuilderProps.ts delete mode 100644 packages/spfx/src/controls/FormBuilder/IFormBuilderState.ts delete mode 100644 packages/spfx/src/controls/FormDataCollection/FormDataCollection.tsx delete mode 100644 packages/spfx/src/controls/FormDataCollection/IFormDataCollectionProps.ts delete mode 100644 packages/spfx/src/controls/FormDataCollection/IFormDataCollectionState.ts delete mode 100644 packages/spfx/src/controls/ItemRepeater/IItemRepeaterProps.ts delete mode 100644 packages/spfx/src/controls/ItemRepeater/IItemRepeaterState.ts delete mode 100644 packages/spfx/src/controls/ItemRepeater/IItemRepeaterValue.ts delete mode 100644 packages/spfx/src/controls/ItemRepeater/ItemRepeater.tsx delete mode 100644 packages/spfx/src/controls/LayoutSlotField/ILayoutSlotFieldProps.ts delete mode 100644 packages/spfx/src/controls/LayoutSlotField/ILayoutSlotFieldState.ts delete mode 100644 packages/spfx/src/controls/LayoutSlotField/LayoutSlotField.tsx delete mode 100644 packages/spfx/src/controls/LocalizedTextField/ILocalizedFieldProps.ts delete mode 100644 packages/spfx/src/controls/LocalizedTextField/ILocalizedFieldState.ts delete mode 100644 packages/spfx/src/controls/LocalizedTextField/LocalizedField.tsx delete mode 100644 packages/spfx/src/controls/LocalizedTextField/components/ITranslation.ts delete mode 100644 packages/spfx/src/controls/LocalizedTextField/components/ITranslationFieldProps.ts delete mode 100644 packages/spfx/src/controls/LocalizedTextField/components/ITranslationFieldState.ts delete mode 100644 packages/spfx/src/controls/LocalizedTextField/components/TranslationField.tsx delete mode 100644 packages/spfx/src/controls/WebPartPlaceholder/WebPartPlaceholder.tsx delete mode 100644 packages/spfx/src/controls/WebPartPlaceholder/logo.svg delete mode 100644 packages/spfx/src/datasources/MicrosoftSearchDataSource.tsx delete mode 100644 packages/spfx/src/datasources/loc/en-us.js delete mode 100644 packages/spfx/src/datasources/loc/strings.d.ts delete mode 100644 packages/spfx/src/helpers/DynamicPropertyHelper.ts delete mode 100644 packages/spfx/src/helpers/LayoutHelper.ts delete mode 100644 packages/spfx/src/helpers/ServiceScopeHelper.ts delete mode 100644 packages/spfx/src/index.ts delete mode 100644 packages/spfx/src/layouts/AvailableLayouts.ts delete mode 100644 packages/spfx/src/layouts/filters/custom/FiltersCustomLayout.ts delete mode 100644 packages/spfx/src/layouts/filters/custom/filters-custom.html delete mode 100644 packages/spfx/src/layouts/filters/default/FiltersDefaultLayout.ts delete mode 100644 packages/spfx/src/layouts/filters/default/default.html delete mode 100644 packages/spfx/src/layouts/results/custom/ResultsCustomLayout.ts delete mode 100644 packages/spfx/src/layouts/results/custom/results-custom.html delete mode 100644 packages/spfx/src/layouts/results/simpleList/ResultsDefaultLayout.tsx delete mode 100644 packages/spfx/src/layouts/results/simpleList/default.html delete mode 100644 packages/spfx/src/layouts/results/tiles/ResultsTilesLayout.tsx delete mode 100644 packages/spfx/src/layouts/results/tiles/results-tiles.html delete mode 100644 packages/spfx/src/layouts/verticals/custom/VerticalsCustomLayout.ts delete mode 100644 packages/spfx/src/layouts/verticals/custom/verticals-custom.html delete mode 100644 packages/spfx/src/layouts/verticals/default/VerticalsDefaultLayout.ts delete mode 100644 packages/spfx/src/layouts/verticals/default/default.html delete mode 100644 packages/spfx/src/loc/commonStrings.d.ts delete mode 100644 packages/spfx/src/loc/en-us.js delete mode 100644 packages/spfx/src/loc/propertyControlStrings.d.ts delete mode 100644 packages/spfx/src/models/common/BaseDataSource.ts delete mode 100644 packages/spfx/src/models/common/BaseLayout.tsx delete mode 100644 packages/spfx/src/models/common/IBaseWebComponentWrapper.ts delete mode 100644 packages/spfx/src/models/common/IBaseWebPartProps.ts delete mode 100644 packages/spfx/src/models/common/ICustomPalette.ts delete mode 100644 packages/spfx/src/models/common/IDataSource.ts delete mode 100644 packages/spfx/src/models/common/ILayout.ts delete mode 100644 packages/spfx/src/models/common/ILayoutDefinition.ts delete mode 100644 packages/spfx/src/models/common/ILayoutSlot.ts delete mode 100644 packages/spfx/src/models/common/ITemplateContext.ts delete mode 100644 packages/spfx/src/models/dynamicData/IDynamicDataSourceProperty.ts delete mode 100644 packages/spfx/src/models/dynamicData/ISearchVerticalSourceData.ts delete mode 100644 packages/spfx/src/propertyPane/PropertyPaneCodeEditor/IPropertyPaneCodeEditorInternalProps.ts delete mode 100644 packages/spfx/src/propertyPane/PropertyPaneCodeEditor/IPropertyPaneCodeEditorProps.ts delete mode 100644 packages/spfx/src/propertyPane/PropertyPaneCodeEditor/PropertyPaneCodeEditor.tsx delete mode 100644 packages/spfx/src/propertyPane/PropertyPaneCodeEditor/components/IPropertyPaneCodeEditorHostProps.ts delete mode 100644 packages/spfx/src/propertyPane/PropertyPaneCodeEditor/components/IPropertyPaneCodeEditorHostState.ts delete mode 100644 packages/spfx/src/propertyPane/PropertyPaneCodeEditor/components/PropertyPaneCodeEditorHost.tsx delete mode 100644 packages/spfx/src/propertyPane/PropertyPaneCombobox/IPropertyPaneComboBoxInternalProps.ts delete mode 100644 packages/spfx/src/propertyPane/PropertyPaneCombobox/IPropertyPaneComboBoxProps.ts delete mode 100644 packages/spfx/src/propertyPane/PropertyPaneCombobox/PropertyPaneCombobox.ts delete mode 100644 packages/spfx/src/propertyPane/PropertyPaneFilePicker/IPropertyPaneFilePickerInternalProps.ts delete mode 100644 packages/spfx/src/propertyPane/PropertyPaneFilePicker/IPropertyPaneFilePickerProps.ts delete mode 100644 packages/spfx/src/propertyPane/PropertyPaneFilePicker/PropertyPaneFilePicker.tsx delete mode 100644 packages/spfx/src/propertyPane/PropertyPaneFilePicker/components/IPropertyPaneFilePickerHostProps.ts delete mode 100644 packages/spfx/src/propertyPane/PropertyPaneFilePicker/components/IPropertyPaneFilePickerHostState.ts delete mode 100644 packages/spfx/src/propertyPane/PropertyPaneFilePicker/components/PropertyPaneFilePickerHost.tsx delete mode 100644 packages/spfx/src/propertyPane/PropertyPaneFiltersConfiguration/IPropertyPaneFiltersConfigurationInternalProps.ts delete mode 100644 packages/spfx/src/propertyPane/PropertyPaneFiltersConfiguration/IPropertyPaneFiltersConfigurationProps.ts delete mode 100644 packages/spfx/src/propertyPane/PropertyPaneFiltersConfiguration/PropertyPaneFiltersConfiguration.tsx delete mode 100644 packages/spfx/src/propertyPane/PropertyPaneFormDataCollection/IPropertyPaneFormDataCollectionInternalProps.ts delete mode 100644 packages/spfx/src/propertyPane/PropertyPaneFormDataCollection/IPropertyPaneFormDataCollectionProps.ts delete mode 100644 packages/spfx/src/propertyPane/PropertyPaneFormDataCollection/PropertyPaneFormDataCollection.tsx delete mode 100644 packages/spfx/src/propertyPane/PropertyPaneNonReactiveTextField/IPropertyPaneNonReactiveTextFieldProps.ts delete mode 100644 packages/spfx/src/propertyPane/PropertyPaneNonReactiveTextField/PropertyPaneNonReactiveTextField.ts delete mode 100644 packages/spfx/src/propertyPane/PropertyPaneNonReactiveTextField/components/INonReactiveTextFieldProps.ts delete mode 100644 packages/spfx/src/propertyPane/PropertyPaneNonReactiveTextField/components/INonReactiveTextFieldState.ts delete mode 100644 packages/spfx/src/propertyPane/PropertyPaneNonReactiveTextField/components/NonReactiveTextField.tsx delete mode 100644 packages/spfx/src/services/dynamicDataService/DynamicDataService.ts delete mode 100644 packages/spfx/src/services/dynamicDataService/IDynamicDataService.ts delete mode 100644 packages/spfx/src/services/fileService/FileService.ts delete mode 100644 packages/spfx/src/services/fileService/IFileService.ts delete mode 100644 packages/spfx/src/services/localizationService/ILocalizationService.ts delete mode 100644 packages/spfx/src/services/localizationService/LocalizationService.ts delete mode 100644 packages/spfx/src/services/tokenService/ISharePointTokenService.ts delete mode 100644 packages/spfx/src/services/tokenService/SharePointTokenService.ts delete mode 100644 packages/spfx/src/styles/postcss.config.js delete mode 100644 packages/spfx/src/styles/tailwind.css delete mode 100644 packages/spfx/src/webparts/searchBox/ISearchBoxWebPartProps.ts delete mode 100644 packages/spfx/src/webparts/searchBox/SearchBoxWebPart.manifest.json delete mode 100644 packages/spfx/src/webparts/searchBox/SearchBoxWebPart.manifest.template.json delete mode 100644 packages/spfx/src/webparts/searchBox/SearchBoxWebPart.ts delete mode 100644 packages/spfx/src/webparts/searchBox/components/ISearchBoxProps.ts delete mode 100644 packages/spfx/src/webparts/searchBox/components/SearchBox.tsx delete mode 100644 packages/spfx/src/webparts/searchBox/loc/en-us.js delete mode 100644 packages/spfx/src/webparts/searchBox/loc/mystrings.d.ts delete mode 100644 packages/spfx/src/webparts/searchFilters/ISearchFiltersWebPartProps.ts delete mode 100644 packages/spfx/src/webparts/searchFilters/SearchFiltersWebPart.manifest.json delete mode 100644 packages/spfx/src/webparts/searchFilters/SearchFiltersWebPart.manifest.template.json delete mode 100644 packages/spfx/src/webparts/searchFilters/SearchFiltersWebPart.ts delete mode 100644 packages/spfx/src/webparts/searchFilters/components/ISearchFiltersProps.ts delete mode 100644 packages/spfx/src/webparts/searchFilters/components/SearchFilters.tsx delete mode 100644 packages/spfx/src/webparts/searchFilters/loc/en-us.js delete mode 100644 packages/spfx/src/webparts/searchFilters/loc/mystrings.d.ts delete mode 100644 packages/spfx/src/webparts/searchResults/ISearchResultsWebPartProps.ts delete mode 100644 packages/spfx/src/webparts/searchResults/SearchResultsWebPart.manifest.json delete mode 100644 packages/spfx/src/webparts/searchResults/SearchResultsWebPart.manifest.template.json delete mode 100644 packages/spfx/src/webparts/searchResults/SearchResultsWebPart.tsx delete mode 100644 packages/spfx/src/webparts/searchResults/components/ISearchResultComponentProps.ts delete mode 100644 packages/spfx/src/webparts/searchResults/components/ISearchResultsProps.ts delete mode 100644 packages/spfx/src/webparts/searchResults/components/ISearchResultsState.ts delete mode 100644 packages/spfx/src/webparts/searchResults/components/SearchResults.tsx delete mode 100644 packages/spfx/src/webparts/searchResults/loc/en-us.js delete mode 100644 packages/spfx/src/webparts/searchResults/loc/mystrings.d.ts delete mode 100644 packages/spfx/src/webparts/searchVerticals/ISearchVerticalsWebPartProps.ts delete mode 100644 packages/spfx/src/webparts/searchVerticals/SearchVerticalsWebPart.manifest.json delete mode 100644 packages/spfx/src/webparts/searchVerticals/SearchVerticalsWebPart.manifest.template.json delete mode 100644 packages/spfx/src/webparts/searchVerticals/SearchVerticalsWebPart.tsx delete mode 100644 packages/spfx/src/webparts/searchVerticals/components/ISearchVerticalsProps.ts delete mode 100644 packages/spfx/src/webparts/searchVerticals/components/SearchVerticals.tsx delete mode 100644 packages/spfx/src/webparts/searchVerticals/loc/en-us.js delete mode 100644 packages/spfx/src/webparts/searchVerticals/loc/mystrings.d.ts delete mode 100644 packages/spfx/tailwind.config.js delete mode 100644 packages/spfx/teams/2ad6c8e4-0912-460b-a65c-7e0bbdb864cf_color.png delete mode 100644 packages/spfx/teams/2ad6c8e4-0912-460b-a65c-7e0bbdb864cf_outline.png delete mode 100644 packages/spfx/teams/4f2451b5-c1ea-4a68-8097-90edc9da61ce_color.png delete mode 100644 packages/spfx/teams/4f2451b5-c1ea-4a68-8097-90edc9da61ce_outline.png delete mode 100644 packages/spfx/teams/6aa5f17d-c6f5-4853-8017-86ad27f396f1_color.png delete mode 100644 packages/spfx/teams/6aa5f17d-c6f5-4853-8017-86ad27f396f1_outline.png delete mode 100644 packages/spfx/teams/aac5f315-4ce8-4386-88fa-897566e2a710_color.png delete mode 100644 packages/spfx/teams/aac5f315-4ce8-4386-88fa-897566e2a710_outline.png delete mode 100644 packages/spfx/toolchain/gulp.js delete mode 100644 packages/spfx/tsconfig.json diff --git a/apps/spfx/package.json b/apps/spfx/package.json index dca7691..dd332ab 100644 --- a/apps/spfx/package.json +++ b/apps/spfx/package.json @@ -72,6 +72,7 @@ "gulp-rename": "2.0.0", "gulp-replace": "1.1.4", "autoprefixer": "10.4.16", + "postcss": "8.4.31", "tailwindcss": "3.2.4", "@tailwindcss/forms": "0.5.3", "@tailwindcss/line-clamp": "0.4.4", diff --git a/apps/spfx/src/webparts/searchBox/components/SearchBox.tsx b/apps/spfx/src/webparts/searchBox/components/SearchBox.tsx index 4292960..63e15a5 100644 --- a/apps/spfx/src/webparts/searchBox/components/SearchBox.tsx +++ b/apps/spfx/src/webparts/searchBox/components/SearchBox.tsx @@ -3,7 +3,7 @@ import { ISearchBoxProps } from './ISearchBoxProps'; import { wrapWc } from 'wc-react'; import { SearchInputComponent } from '@pnp/modern-search-core'; -const SearchInputWebComponent = wrapWc('pnp-search-input'); +const SearchInputWebComponent = wrapWc>('pnp-search-input'); export class SearchBox extends React.Component { diff --git a/apps/spfx/src/webparts/searchResults/components/SearchResults.tsx b/apps/spfx/src/webparts/searchResults/components/SearchResults.tsx index d3364a3..da55d4c 100644 --- a/apps/spfx/src/webparts/searchResults/components/SearchResults.tsx +++ b/apps/spfx/src/webparts/searchResults/components/SearchResults.tsx @@ -10,7 +10,7 @@ import parse from 'html-react-parser'; import { SlotType } from '../../../models/common/ILayoutSlot'; import { EventConstants } from '@pnp/modern-search-core/dist/es6/common/Constants'; -const SearchResultsWebComponent = wrapWc('pnp-search-results'); +const SearchResultsWebComponent = wrapWc>('pnp-search-results'); export default class SearchResults extends React.Component { diff --git a/apps/spfx/src/webparts/searchVerticals/components/SearchVerticals.tsx b/apps/spfx/src/webparts/searchVerticals/components/SearchVerticals.tsx index 49af44e..2fdda3b 100644 --- a/apps/spfx/src/webparts/searchVerticals/components/SearchVerticals.tsx +++ b/apps/spfx/src/webparts/searchVerticals/components/SearchVerticals.tsx @@ -8,7 +8,7 @@ import parse, { } from 'html-react-parser'; import { isEqual } from '@microsoft/sp-lodash-subset'; import { Guid } from '@microsoft/sp-core-library'; -const SearchVerticalsWebComponent = wrapWc('pnp-search-verticals'); +const SearchVerticalsWebComponent = wrapWc>('pnp-search-verticals'); export default class SearchVerticals extends React.Component { diff --git a/packages/spfx/.eslintrc.js b/packages/spfx/.eslintrc.js deleted file mode 100644 index 473df80..0000000 --- a/packages/spfx/.eslintrc.js +++ /dev/null @@ -1,352 +0,0 @@ -require('@rushstack/eslint-config/patch/modern-module-resolution'); -module.exports = { - extends: ['@microsoft/eslint-config-spfx/lib/profiles/react'], - parserOptions: { tsconfigRootDir: __dirname }, - overrides: [ - { - files: ['*.ts', '*.tsx'], - parser: '@typescript-eslint/parser', - 'parserOptions': { - 'project': './tsconfig.json', - 'ecmaVersion': 2018, - 'sourceType': 'module' - }, - rules: { - // Prevent usage of the JavaScript null value, while allowing code to access existing APIs that may require null. https://www.npmjs.com/package/@rushstack/eslint-plugin - '@rushstack/no-new-null': 1, - // Require Jest module mocking APIs to be called before any other statements in their code block. https://www.npmjs.com/package/@rushstack/eslint-plugin - '@rushstack/hoist-jest-mock': 1, - // Require regular expressions to be constructed from string constants rather than dynamically building strings at runtime. https://www.npmjs.com/package/@rushstack/eslint-plugin-security - '@rushstack/security/no-unsafe-regexp': 1, - // STANDARDIZED BY: @typescript-eslint\eslint-plugin\dist\configs\recommended.json - '@typescript-eslint/adjacent-overload-signatures': 1, - // STANDARDIZED BY: @typescript-eslint\eslint-plugin\dist\configs\recommended.json - // - // CONFIGURATION: By default, these are banned: String, Boolean, Number, Object, Symbol - '@typescript-eslint/ban-types': [ - 1, - { - 'extendDefaults': false, - 'types': { - 'String': { - 'message': 'Use \'string\' instead', - 'fixWith': 'string' - }, - 'Boolean': { - 'message': 'Use \'boolean\' instead', - 'fixWith': 'boolean' - }, - 'Number': { - 'message': 'Use \'number\' instead', - 'fixWith': 'number' - }, - 'Object': { - 'message': 'Use \'object\' instead, or else define a proper TypeScript type:' - }, - 'Symbol': { - 'message': 'Use \'symbol\' instead', - 'fixWith': 'symbol' - }, - 'Function': { - 'message': 'The \'Function\' type accepts any function-like value.\nIt provides no type safety when calling the function, which can be a common source of bugs.\nIt also accepts things like class declarations, which will throw at runtime as they will not be called with \'new\'.\nIf you are expecting the function to accept certain arguments, you should explicitly define the function shape.' - } - } - } - ], - // RATIONALE: Code is more readable when the type of every variable is immediately obvious. - // Even if the compiler may be able to infer a type, this inference will be unavailable - // to a person who is reviewing a GitHub diff. This rule makes writing code harder, - // but writing code is a much less important activity than reading it. - // - // STANDARDIZED BY: @typescript-eslint\eslint-plugin\dist\configs\recommended.json - '@typescript-eslint/explicit-function-return-type': [ - 1, - { - 'allowExpressions': true, - 'allowTypedFunctionExpressions': true, - 'allowHigherOrderFunctions': false - } - ], - // STANDARDIZED BY: @typescript-eslint\eslint-plugin\dist\configs\recommended.json - // Rationale to disable: although this is a recommended rule, it is up to dev to select coding style. - // Set to 1 (warning) or 2 (error) to enable. - '@typescript-eslint/explicit-member-accessibility': 0, - // STANDARDIZED BY: @typescript-eslint\eslint-plugin\dist\configs\recommended.json - '@typescript-eslint/no-array-constructor': 1, - // STANDARDIZED BY: @typescript-eslint\eslint-plugin\dist\configs\recommended.json - // - // RATIONALE: The "any" keyword disables static type checking, the main benefit of using TypeScript. - // This rule should be suppressed only in very special cases such as JSON.stringify() - // where the type really can be anything. Even if the type is flexible, another type - // may be more appropriate such as "unknown", "{}", or "Record". - '@typescript-eslint/no-explicit-any': 1, - // RATIONALE: The #1 rule of promises is that every promise chain must be terminated by a catch() - // handler. Thus wherever a Promise arises, the code must either append a catch handler, - // or else return the object to a caller (who assumes this responsibility). Unterminated - // promise chains are a serious issue. Besides causing errors to be silently ignored, - // they can also cause a NodeJS process to terminate unexpectedly. - '@typescript-eslint/no-floating-promises': 2, - // RATIONALE: Catches a common coding mistake. - '@typescript-eslint/no-for-in-array': 2, - // STANDARDIZED BY: @typescript-eslint\eslint-plugin\dist\configs\recommended.json - '@typescript-eslint/no-misused-new': 2, - // RATIONALE: The "namespace" keyword is not recommended for organizing code because JavaScript lacks - // a "using" statement to traverse namespaces. Nested namespaces prevent certain bundler - // optimizations. If you are declaring loose functions/variables, it's better to make them - // static members of a class, since classes support property getters and their private - // members are accessible by unit tests. Also, the exercise of choosing a meaningful - // class name tends to produce more discoverable APIs: for example, search+replacing - // the function "reverse()" is likely to return many false matches, whereas if we always - // write "Text.reverse()" is more unique. For large scale organization, it's recommended - // to decompose your code into separate NPM packages, which ensures that component - // dependencies are tracked more conscientiously. - // - // STANDARDIZED BY: @typescript-eslint\eslint-plugin\dist\configs\recommended.json - '@typescript-eslint/no-namespace': [ - 1, - { - 'allowDeclarations': false, - 'allowDefinitionFiles': false - } - ], - // RATIONALE: Parameter properties provide a shorthand such as "constructor(public title: string)" - // that avoids the effort of declaring "title" as a field. This TypeScript feature makes - // code easier to write, but arguably sacrifices readability: In the notes for - // "@typescript-eslint/member-ordering" we pointed out that fields are central to - // a class's design, so we wouldn't want to bury them in a constructor signature - // just to save some typing. - // - // STANDARDIZED BY: @typescript-eslint\eslint-plugin\dist\configs\recommended.json - // Set to 1 (warning) or 2 (error) to enable the rule - '@typescript-eslint/parameter-properties': 0, - // RATIONALE: When left in shipping code, unused variables often indicate a mistake. Dead code - // may impact performance. - // - // STANDARDIZED BY: @typescript-eslint\eslint-plugin\dist\configs\recommended.json - '@typescript-eslint/no-unused-vars': [ - 1, - { - 'vars': 'all', - // Unused function arguments often indicate a mistake in JavaScript code. However in TypeScript code, - // the compiler catches most of those mistakes, and unused arguments are fairly common for type signatures - // that are overriding a base class method or implementing an interface. - 'args': 'none' - } - ], - // STANDARDIZED BY: @typescript-eslint\eslint-plugin\dist\configs\recommended.json - '@typescript-eslint/no-use-before-define': [ - 2, - { - 'functions': false, - 'classes': true, - 'variables': true, - 'enums': true, - 'typedefs': true - } - ], - // Disallows require statements except in import statements. - // In other words, the use of forms such as var foo = require("foo") are banned. Instead use ES6 style imports or import foo = require("foo") imports. - '@typescript-eslint/no-var-requires': 'error', - // RATIONALE: The "module" keyword is deprecated except when describing legacy libraries. - // - // STANDARDIZED BY: @typescript-eslint\eslint-plugin\dist\configs\recommended.json - '@typescript-eslint/prefer-namespace-keyword': 1, - // STANDARDIZED BY: @typescript-eslint\eslint-plugin\dist\configs\recommended.json - // Rationale to disable: it's up to developer to decide if he wants to add type annotations - // Set to 1 (warning) or 2 (error) to enable the rule - '@typescript-eslint/no-inferrable-types': 0, - // STANDARDIZED BY: @typescript-eslint\eslint-plugin\dist\configs\recommended.json - // Rationale to disable: declaration of empty interfaces may be helpful for generic types scenarios - '@typescript-eslint/no-empty-interface': 0, - // RATIONALE: This rule warns if setters are defined without getters, which is probably a mistake. - 'accessor-pairs': 1, - // RATIONALE: In TypeScript, if you write x["y"] instead of x.y, it disables type checking. - 'dot-notation': [ - 1, - { - 'allowPattern': '^_' - } - ], - // RATIONALE: Catches code that is likely to be incorrect - 'eqeqeq': 1, - // STANDARDIZED BY: eslint\conf\eslint-recommended.js - 'for-direction': 1, - // RATIONALE: Catches a common coding mistake. - 'guard-for-in': 2, - // RATIONALE: If you have more than 2,000 lines in a single source file, it's probably time - // to split up your code. - 'max-lines': ['warn', { max: 2000 }], - // STANDARDIZED BY: eslint\conf\eslint-recommended.js - 'no-async-promise-executor': 2, - // RATIONALE: Deprecated language feature. - 'no-caller': 2, - // STANDARDIZED BY: eslint\conf\eslint-recommended.js - 'no-compare-neg-zero': 2, - // STANDARDIZED BY: eslint\conf\eslint-recommended.js - 'no-cond-assign': 2, - // STANDARDIZED BY: eslint\conf\eslint-recommended.js - 'no-constant-condition': 1, - // STANDARDIZED BY: eslint\conf\eslint-recommended.js - 'no-control-regex': 2, - // STANDARDIZED BY: eslint\conf\eslint-recommended.js - 'no-debugger': 1, - // STANDARDIZED BY: eslint\conf\eslint-recommended.js - 'no-delete-var': 2, - // RATIONALE: Catches code that is likely to be incorrect - // STANDARDIZED BY: eslint\conf\eslint-recommended.js - 'no-duplicate-case': 2, - // STANDARDIZED BY: eslint\conf\eslint-recommended.js - 'no-empty': 1, - // STANDARDIZED BY: eslint\conf\eslint-recommended.js - 'no-empty-character-class': 2, - // STANDARDIZED BY: eslint\conf\eslint-recommended.js - 'no-empty-pattern': 1, - // RATIONALE: Eval is a security concern and a performance concern. - 'no-eval': 1, - // RATIONALE: Catches code that is likely to be incorrect - // STANDARDIZED BY: eslint\conf\eslint-recommended.js - 'no-ex-assign': 2, - // RATIONALE: System types are global and should not be tampered with in a scalable code base. - // If two different libraries (or two versions of the same library) both try to modify - // a type, only one of them can win. Polyfills are acceptable because they implement - // a standardized interoperable contract, but polyfills are generally coded in plain - // JavaScript. - 'no-extend-native': 1, - // Disallow unnecessary labels - 'no-extra-label': 1, - // STANDARDIZED BY: eslint\conf\eslint-recommended.js - 'no-fallthrough': 2, - // STANDARDIZED BY: eslint\conf\eslint-recommended.js - 'no-func-assign': 1, - // RATIONALE: Catches a common coding mistake. - 'no-implied-eval': 2, - // STANDARDIZED BY: eslint\conf\eslint-recommended.js - 'no-invalid-regexp': 2, - // RATIONALE: Catches a common coding mistake. - 'no-label-var': 2, - // RATIONALE: Eliminates redundant code. - 'no-lone-blocks': 1, - // STANDARDIZED BY: eslint\conf\eslint-recommended.js - 'no-misleading-character-class': 2, - // RATIONALE: Catches a common coding mistake. - 'no-multi-str': 2, - // RATIONALE: It's generally a bad practice to call "new Thing()" without assigning the result to - // a variable. Either it's part of an awkward expression like "(new Thing()).doSomething()", - // or else implies that the constructor is doing nontrivial computations, which is often - // a poor class design. - 'no-new': 1, - // RATIONALE: Obsolete language feature that is deprecated. - 'no-new-func': 2, - // RATIONALE: Obsolete language feature that is deprecated. - 'no-new-object': 2, - // RATIONALE: Obsolete notation. - 'no-new-wrappers': 1, - // RATIONALE: Catches code that is likely to be incorrect - // STANDARDIZED BY: eslint\conf\eslint-recommended.js - 'no-octal': 2, - // RATIONALE: Catches code that is likely to be incorrect - 'no-octal-escape': 2, - // RATIONALE: Catches code that is likely to be incorrect - // STANDARDIZED BY: eslint\conf\eslint-recommended.js - 'no-regex-spaces': 2, - // RATIONALE: Catches a common coding mistake. - 'no-return-assign': 2, - // RATIONALE: Security risk. - 'no-script-url': 1, - // STANDARDIZED BY: eslint\conf\eslint-recommended.js - 'no-self-assign': 2, - // RATIONALE: Catches a common coding mistake. - 'no-self-compare': 2, - // RATIONALE: This avoids statements such as "while (a = next(), a && a.length);" that use - // commas to create compound expressions. In general code is more readable if each - // step is split onto a separate line. This also makes it easier to set breakpoints - // in the debugger. - 'no-sequences': 1, - // RATIONALE: Catches code that is likely to be incorrect - // STANDARDIZED BY: eslint\conf\eslint-recommended.js - 'no-shadow-restricted-names': 2, - // RATIONALE: Obsolete language feature that is deprecated. - // STANDARDIZED BY: eslint\conf\eslint-recommended.js - 'no-sparse-arrays': 2, - // RATIONALE: Although in theory JavaScript allows any possible data type to be thrown as an exception, - // such flexibility adds pointless complexity, by requiring every catch block to test - // the type of the object that it receives. Whereas if catch blocks can always assume - // that their object implements the "Error" contract, then the code is simpler, and - // we generally get useful additional information like a call stack. - 'no-throw-literal': 2, - // RATIONALE: Catches a common coding mistake. - 'no-unmodified-loop-condition': 1, - // STANDARDIZED BY: eslint\conf\eslint-recommended.js - 'no-unsafe-finally': 2, - // RATIONALE: Catches a common coding mistake. - 'no-unused-expressions': 1, - // STANDARDIZED BY: eslint\conf\eslint-recommended.js - 'no-unused-labels': 1, - // STANDARDIZED BY: eslint\conf\eslint-recommended.js - 'no-useless-catch': 1, - // RATIONALE: Avoids a potential performance problem. - 'no-useless-concat': 1, - // RATIONALE: The "var" keyword is deprecated because of its confusing "hoisting" behavior. - // Always use "let" or "const" instead. - // - // STANDARDIZED BY: @typescript-eslint\eslint-plugin\dist\configs\recommended.json - 'no-var': 2, - // RATIONALE: Generally not needed in modern code. - 'no-void': 1, - // RATIONALE: Obsolete language feature that is deprecated. - // STANDARDIZED BY: eslint\conf\eslint-recommended.js - 'no-with': 2, - // RATIONALE: Makes logic easier to understand, since constants always have a known value - // @typescript-eslint\eslint-plugin\dist\configs\eslint-recommended.js - 'prefer-const': 1, - // RATIONALE: Catches a common coding mistake where "resolve" and "reject" are confused. - 'promise/param-names': 2, - // RATIONALE: Catches code that is likely to be incorrect - // STANDARDIZED BY: eslint\conf\eslint-recommended.js - 'require-atomic-updates': 2, - // STANDARDIZED BY: eslint\conf\eslint-recommended.js - 'require-yield': 1, - // "Use strict" is redundant when using the TypeScript compiler. - 'strict': [ - 2, - 'never' - ], - // RATIONALE: Catches code that is likely to be incorrect - // STANDARDIZED BY: eslint\conf\eslint-recommended.js - 'use-isnan': 2, - // STANDARDIZED BY: eslint\conf\eslint-recommended.js - // Set to 1 (warning) or 2 (error) to enable. - // Rationale to disable: !!{} - 'no-extra-boolean-cast': 0, - // ==================================================================== - // @microsoft/eslint-plugin-spfx - // ==================================================================== - '@microsoft/spfx/import-requires-chunk-name': 1, - '@microsoft/spfx/no-require-ensure': 2, - '@microsoft/spfx/pair-react-dom-render-unmount': 1 - } - }, - { - // For unit tests, we can be a little bit less strict. The settings below revise the - // defaults specified in the extended configurations, as well as above. - files: [ - // Test files - '*.test.ts', - '*.test.tsx', - '*.spec.ts', - '*.spec.tsx', - - // Facebook convention - '**/__mocks__/*.ts', - '**/__mocks__/*.tsx', - '**/__tests__/*.ts', - '**/__tests__/*.tsx', - - // Microsoft convention - '**/test/*.ts', - '**/test/*.tsx' - ], - rules: {} - } - ] -}; \ No newline at end of file diff --git a/packages/spfx/.gitignore b/packages/spfx/.gitignore deleted file mode 100644 index 572f0a3..0000000 --- a/packages/spfx/.gitignore +++ /dev/null @@ -1,35 +0,0 @@ -# Logs -logs -*.log -npm-debug.log* - -# Dependency directories -node_modules - -# Build generated files -dist -lib -release -solution -temp -*.sppkg -.heft - -# Coverage directory used by tools like istanbul -coverage - -# OSX -.DS_Store - -# Visual Studio files -.ntvs_analysis.dat -.vs -bin -obj - -# Resx Generated Code -*.resx.ts - -# Styles Generated Code -*.scss.ts -*.scss.d.ts \ No newline at end of file diff --git a/packages/spfx/.npmignore b/packages/spfx/.npmignore deleted file mode 100644 index ae0b487..0000000 --- a/packages/spfx/.npmignore +++ /dev/null @@ -1,16 +0,0 @@ -!dist -config - -gulpfile.js - -release -src -temp - -tsconfig.json -tslint.json - -*.log - -.yo-rc.json -.vscode diff --git a/packages/spfx/.vscode/launch.json b/packages/spfx/.vscode/launch.json deleted file mode 100644 index d622a59..0000000 --- a/packages/spfx/.vscode/launch.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "version": "0.2.0", - "configurations": [ - { - "name": "Hosted workbench", - "type": "msedge", - "request": "launch", - "url": "https://sonbaedev.sharepoint.com/sites/ThePerspective/_layouts/15/workbench.aspx", - "webRoot": "${workspaceRoot}", - "sourceMaps": true, - "sourceMapPathOverrides": { - "webpack:///.././src/*": "${webRoot}/src/*", - "webpack:///../../../src/*": "${webRoot}/src/*", - "webpack:///../../../../src/*": "${webRoot}/src/*", - "webpack:///../../../../../src/*": "${webRoot}/src/*" - }, - "runtimeArgs": [ - "--remote-debugging-port=9222", - "-incognito" - ] - } - ] -} \ No newline at end of file diff --git a/packages/spfx/.vscode/settings.json b/packages/spfx/.vscode/settings.json deleted file mode 100644 index a31a2c3..0000000 --- a/packages/spfx/.vscode/settings.json +++ /dev/null @@ -1,13 +0,0 @@ -// Place your settings in this file to overwrite default and user settings. -{ - // Configure glob patterns for excluding files and folders in the file explorer. - "files.exclude": { - "**/.git": true, - "**/.DS_Store": true, - "**/bower_components": true, - "**/coverage": true, - "**/lib-amd": true, - "src/**/*.scss.ts": true - }, - "typescript.tsdk": ".\\node_modules\\typescript\\lib" -} \ No newline at end of file diff --git a/packages/spfx/.yo-rc.json b/packages/spfx/.yo-rc.json deleted file mode 100644 index d8e5577..0000000 --- a/packages/spfx/.yo-rc.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "@microsoft/generator-sharepoint": { - "plusBeta": false, - "isCreatingSolution": false, - "nodeVersion": "16.20.1", - "sdksVersions": { - "@microsoft/microsoft-graph-client": "3.0.2", - "@microsoft/teams-js": "2.9.1" - }, - "version": "1.17.3", - "libraryName": "pnp-search-core--components", - "libraryId": "9aad2c6c-dd90-4fae-9e62-8aeae8969c9a", - "environment": "spo", - "packageManager": "npm", - "solutionName": "PnPModernSearchCoreComponents", - "solutionShortDescription": "PnP Modern Search - Web Components", - "skipFeatureDeployment": true, - "isDomainIsolated": false, - "componentType": "webpart" - } -} diff --git a/packages/spfx/README.md b/packages/spfx/README.md deleted file mode 100644 index b7005f4..0000000 --- a/packages/spfx/README.md +++ /dev/null @@ -1,9 +0,0 @@ -# PnP Modern Search Core Components - SPFx WebParts - -## Connection strategy - -The connection synchronization process is managed directly by web components, waiting for each other at page load (10 s delay). It means you can set the components ids as attributes and let component manage. - -Each component gets its corresponding dynamic data source reference in this format as the ID (`${this.manifest.componentType}.${this.manifest.id}.${this.instanceId}:${componentType}`;) - -Ex: WebPart.6aa5f17d-c6f5-4853-8017-86ad27f396f1.8f28620f-75b7-453d-b96a-fcf85872634a:pnpModernSearchCoreResultsWebPar \ No newline at end of file diff --git a/packages/spfx/babel.config.json b/packages/spfx/babel.config.json deleted file mode 100644 index 442789b..0000000 --- a/packages/spfx/babel.config.json +++ /dev/null @@ -1,12 +0,0 @@ - -{ - "presets": [ - "@babel/preset-typescript", - [ - "@babel/preset-env", - { - "modules": "auto" - } - ] - ] -} \ No newline at end of file diff --git a/packages/spfx/config/config.json b/packages/spfx/config/config.json deleted file mode 100644 index f8b99d2..0000000 --- a/packages/spfx/config/config.json +++ /dev/null @@ -1,49 +0,0 @@ -{ - "$schema": "https://developer.microsoft.com/json-schemas/spfx-build/config.2.0.schema.json", - "version": "2.0", - "bundles": { - "pnp-core-search-results-web-part": { - "components": [ - { - "entrypoint": "./lib/webparts/searchResults/SearchResultsWebPart.js", - "manifest": "./src/webparts/searchResults/SearchResultsWebPart.manifest.json" - } - ] - }, - "pnp-core-search-box-web-part": { - "components": [ - { - "entrypoint": "./lib/webparts/searchBox/SearchBoxWebPart.js", - "manifest": "./src/webparts/searchBox/SearchBoxWebPart.manifest.json" - } - ] - }, - "pnp-core-search-filters-web-part": { - "components": [ - { - "entrypoint": "./lib/webparts/searchFilters/SearchFiltersWebPart.js", - "manifest": "./src/webparts/searchFilters/SearchFiltersWebPart.manifest.json" - } - ] - }, - "pnp-core-search-verticals-web-part": { - "components": [ - { - "entrypoint": "./lib/webparts/searchVerticals/SearchVerticalsWebPart.js", - "manifest": "./src/webparts/searchVerticals/SearchVerticalsWebPart.manifest.json" - } - ] - } - }, - "externals": {}, - "localizedResources": { - "SearchResultsWebPartStrings": "lib/webparts/searchResults/loc/{locale}.js", - "SearchBoxWebPartStrings": "lib/webparts/searchBox/loc/{locale}.js", - "PropertyControlStrings": "node_modules/@pnp/spfx-property-controls/lib/loc/{locale}.js", - "ControlStrings": "node_modules/@pnp/spfx-controls-react/lib/loc/{locale}.js", - "CommonStrings": "lib/loc/{locale}.js", - "SearchFiltersWebPartStrings": "lib/webparts/searchFilters/loc/{locale}.js", - "MicrosoftSearchDataSourceStrings": "lib/datasources/loc/{locale}.js", - "SearchVerticalsWebPartStrings": "lib/webparts/searchVerticals/loc/{locale}.js" - } -} diff --git a/packages/spfx/config/deploy-azure-storage.json b/packages/spfx/config/deploy-azure-storage.json deleted file mode 100644 index 7347f13..0000000 --- a/packages/spfx/config/deploy-azure-storage.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "$schema": "https://developer.microsoft.com/json-schemas/spfx-build/deploy-azure-storage.schema.json", - "workingDir": "./release/assets/", - "account": "", - "container": "", - "accessKey": "" -} \ No newline at end of file diff --git a/packages/spfx/config/package-solution.json b/packages/spfx/config/package-solution.json deleted file mode 100644 index 88a768f..0000000 --- a/packages/spfx/config/package-solution.json +++ /dev/null @@ -1,98 +0,0 @@ -{ - "$schema": "https://developer.microsoft.com/json-schemas/spfx-build/package-solution.schema.json", - "solution": { - "name": "PnP Modern Search Core - Search Web Parts", - "id": "9aad2c6c-dd90-4fae-9e62-8aeae8969c9a", - "version": "1.0.0.0", - "includeClientSideAssets": true, - "skipFeatureDeployment": true, - "isDomainIsolated": false, - "webApiPermissionRequests": [ - { - "resource": "Microsoft Graph", - "scope": "Presence.Read.All" - }, - { - "resource": "Microsoft Graph", - "scope": "User.Read" - }, - { - "resource": "Microsoft Graph", - "scope": "Files.Read.All" - }, - { - "resource": "Microsoft Graph", - "scope": "People.Read" - }, - { - "resource": "Microsoft Graph", - "scope": "Contacts.Read" - }, - { - "resource": "Microsoft Graph", - "scope": "User.Read.All" - }, - { - "resource": "Microsoft Graph", - "scope": "Mail.Read" - }, - { - "resource": "Microsoft Graph", - "scope": "Calendars.Read" - }, - { - "resource": "Microsoft Graph", - "scope": "Sites.Read.All" - }, - { - "resource": "Microsoft Graph", - "scope": "ExternalItem.Read.All" - }, - { - "resource": "Microsoft Graph", - "scope": "Chat.Read" - }, - { - "resource": "Microsoft Graph", - "scope": "ChannelMessage.Read.All" - }, - { - "resource": "Microsoft Graph", - "scope": "Bookmark.Read.All" - }, - { - "resource": "Microsoft Graph", - "scope": "Acronym.Read.All" - } - ], - "developer": { - "name": "Franck Cornu", - "websiteUrl": "", - "privacyUrl": "", - "termsOfUseUrl": "", - "mpnId": "" - }, - "metadata": { - "shortDescription": { - "default": "PnP Modern Search Core Web Parts" - }, - "longDescription": { - "default": "PnP Modern Search Core Web Parts" - }, - "screenshotPaths": [], - "videoUrl": "", - "categories": [] - }, - "features": [ - { - "title": "PnP Modern Search Core - Search Web Parts", - "description": "The feature that activates elements of the pnp-core-search-components solution.", - "id": "88bafa4c-d368-4945-91f5-c573b6aa19ba", - "version": "1.0.0.0" - } - ] - }, - "paths": { - "zippedPackage": "solution/pnp.webparts.search.core.sppkg" - } -} \ No newline at end of file diff --git a/packages/spfx/config/sass.json b/packages/spfx/config/sass.json deleted file mode 100644 index 5e78c98..0000000 --- a/packages/spfx/config/sass.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "$schema": "https://developer.microsoft.com/json-schemas/core-build/sass.schema.json" -} \ No newline at end of file diff --git a/packages/spfx/config/serve.json b/packages/spfx/config/serve.json deleted file mode 100644 index a4c03e2..0000000 --- a/packages/spfx/config/serve.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "$schema": "https://developer.microsoft.com/json-schemas/spfx-build/spfx-serve.schema.json", - "port": 4321, - "https": true, - "initialPage": "https://{tenantDomain}/_layouts/workbench.aspx" -} diff --git a/packages/spfx/config/write-manifests.json b/packages/spfx/config/write-manifests.json deleted file mode 100644 index bad3526..0000000 --- a/packages/spfx/config/write-manifests.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "$schema": "https://developer.microsoft.com/json-schemas/spfx-build/write-manifests.schema.json", - "cdnBasePath": "" -} \ No newline at end of file diff --git a/packages/spfx/fast-serve/babel.config.json b/packages/spfx/fast-serve/babel.config.json deleted file mode 100644 index 5119eb5..0000000 --- a/packages/spfx/fast-serve/babel.config.json +++ /dev/null @@ -1,12 +0,0 @@ - -{ - "presets": [ - [ - "@babel/preset-env", - { - "modules": "auto", - "debug": false - } - ] - ] -} \ No newline at end of file diff --git a/packages/spfx/fast-serve/config.json b/packages/spfx/fast-serve/config.json deleted file mode 100644 index fbb6384..0000000 --- a/packages/spfx/fast-serve/config.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "$schema": "https://raw.githubusercontent.com/s-KaiNet/spfx-fast-serve/master/schema/config.latest.schema.json", - "cli": { - "isLibraryComponent": false - } -} \ No newline at end of file diff --git a/packages/spfx/fast-serve/webpack.extend.js b/packages/spfx/fast-serve/webpack.extend.js deleted file mode 100644 index c332b7c..0000000 --- a/packages/spfx/fast-serve/webpack.extend.js +++ /dev/null @@ -1,81 +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. -*/ - -const path = require('path'); - -// 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 = { - module: { - rules: [ - { - test: /\.js$/, - exclude: (_) => { - return /node_modules/.test(_) && !/(@microsoft|@monaco-editor|@pnp\/modern-search-core)/.test(_) - }, - use: { - loader: 'babel-loader' - } - }, - { - test: /\.js$/, - // only run on lit packages in the root node_module folder - include: /node_modules\/(\@lit)|(lit)/, - exclude: [ - { - // Exclude this rule from everything. - test: __dirname, - // Add back the ES2021 Lit dependencies. Add anything else here that uses modern - // JavaScript that Webpack 4 doesn't understand. - exclude: ['@lit', 'lit-element', 'lit-html'].map((p) => - path.resolve(__dirname, 'node_modules/' + p) - ), - }, - ], - use: { - loader: 'babel-loader', - options: { - plugins: [ - "@babel/plugin-transform-optional-chaining", - "@babel/plugin-transform-nullish-coalescing-operator", - "@babel/plugin-transform-logical-assignment-operators" - ] - } - } - }, - { - test: /strings\..+\.d\.ts$/, - use: - { - loader: 'null-loader', - } - - }, - { - test: /\.js$/, - exclude: (_) => { - return /node_modules/.test(_) && !/(@pnp)/.test(_) && /strings\..+\.js$/.test(_); - }, - enforce: 'pre', - use: ['source-map-loader'], - } - ] - - }, -} - -// 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 -} diff --git a/packages/spfx/gulpfile.js b/packages/spfx/gulpfile.js deleted file mode 100644 index df28be1..0000000 --- a/packages/spfx/gulpfile.js +++ /dev/null @@ -1,222 +0,0 @@ -/* eslint-disable @typescript-eslint/no-empty-function */ -'use strict'; - -const gulp = require('gulp') -const path = require('path'); -const fs = require("fs"); -const log = require('fancy-log'); -const replace = require("gulp-replace"); -const { src, dest } = require("gulp"); -const rename = require("gulp-rename"); -const build = require('@microsoft/sp-build-web'); -build.addSuppression(`Warning - [sass] The local CSS class 'ms-Grid' is not camelCase and will not be type-safe.`); - -const envCheck = build.subTask('environmentCheck', (gulp, config, done) => { - - build.configureWebpack.mergeConfig({ - additionalConfiguration: (generatedConfiguration) => { - - generatedConfiguration.module.rules.push( - { - test: /\.js$/, - exclude: (_) => { - return /node_modules/.test(_) && !/(@microsoft|@monaco-editor|@pnp\/modern-search-core)/.test(_) - }, - use: { - loader: 'babel-loader' - } - }, - { - test: /\.js$/, - // only run on lit packages in the root node_module folder - include: /node_modules\/(\@lit)|(lit)/, - exclude: [ - { - // Exclude this rule from everything. - test: __dirname, - // Add back the ES2021 Lit dependencies. Add anything else here that uses modern - // JavaScript that Webpack 4 doesn't understand. - exclude: ['@lit', 'lit-element', 'lit-html'].map((p) => - path.resolve(__dirname, 'node_modules/' + p) - ), - }, - ], - use: { - loader: 'babel-loader', - options: { - plugins: [ - "@babel/plugin-transform-optional-chaining", - "@babel/plugin-transform-nullish-coalescing-operator", - "@babel/plugin-transform-logical-assignment-operators" - ] - } - } - } - ); - - if (!config.production) { - generatedConfiguration.module.rules.push( - { - test: /strings\..+\.d\.ts$/, - use: - { - loader: 'null-loader', - } - - }, - { - test: /\.js$/, - exclude: (_) => { - return /node_modules/.test(_) && !/(@pnp)/.test(_) && /strings\..+\.js$/.test(_); - }, - enforce: 'pre', - use: ['source-map-loader'], - } - ); - } else { - - generatedConfiguration.module.rules.push( - { - test: /strings\..+(\.d\.ts|\.map)$/, - use: - { - loader: 'null-loader', - } - - } - ); - } - - return generatedConfiguration; - } - }); - - done(); -}); - -build.rig.addPreBuildTask(envCheck); - - -var getTasks = build.rig.getTasks; -build.rig.getTasks = function () { - var result = getTasks.call(build.rig); - - result.set('serve', result.get('serve-deprecated')); - - return result; -}; - -/* fast-serve */ -const { addFastServe } = require("spfx-fast-serve-helpers"); -addFastServe(build); -/* end of fast-serve */ - -const readJson = (path, cb) => { - fs.readFile(require.resolve(path), (err, data) => { - if (err) - log.error(err) - else - cb(null, JSON.parse(data)) - }); -} - -const findFilesByExt = (base, ext, files, result) => { - files = files || fs.readdirSync(base) - result = result || [] - - files.forEach( - function (file) { - var newbase = path.join(base, file) - if (fs.statSync(newbase).isDirectory()) { - result = findFilesByExt(newbase, ext, fs.readdirSync(newbase), result) - } else { - if (file.substr(-1 * (ext.length + 1)) == '.' + ext) { - result.push(newbase) - } - } - } - ); - return result -} - -gulp.task('update-version', async () => { - - // List all manifest files - const manifestFiles = findFilesByExt('./src','manifest.json'); - - const semver = require('semver'); - const versionArgIdx = process.argv.indexOf('--value'); - const newVersionNumber = semver.valid(process.argv[versionArgIdx+1]); - - if (versionArgIdx !== -1 && newVersionNumber) { - - // Update version in the package-solution - const pkgSolutionFilePath = path.resolve('./config/package-solution.json'); - - readJson(pkgSolutionFilePath, (err, pkgSolution) => { - log.info('Old package-solution.json version:\t' + pkgSolution.solution.version); - const pkgVersion = `${semver.major(newVersionNumber)}.${semver.minor(newVersionNumber)}.${semver.patch(newVersionNumber)}.0`; - pkgSolution.solution.version = pkgVersion; - log.info('New package-solution.json version:\t' + pkgVersion); - fs.writeFileSync(pkgSolutionFilePath, JSON.stringify(pkgSolution, null, 4), (error) => {}); - }); - - // Updated version in Web Part manifests - manifestFiles.forEach((manifestFile) => { - readJson(path.resolve(`./${manifestFile}`), (err, manifest) => { - - log.info(`Updating manifest file: "./${manifestFile}"`); - - log.info('Old manifestFile version:\t' + manifest.version); - const wpVersion = `${semver.major(newVersionNumber)}.${semver.minor(newVersionNumber)}.${semver.patch(newVersionNumber)}`; - manifest.version = wpVersion; - log.info('New manifestFile version:\t' + wpVersion); - fs.writeFileSync(manifestFile, JSON.stringify(manifest, null, 4), (error) => { }); - }); - }); - } else { - log.error(`The provided version ${process.argv[versionArgIdx+1]} is not a valid SemVer version`); - } - -}); - -gulp.task('update-package-name', async () => { - - const pkgSolutionFilePath = './config/package-solution.json'; - - const fileNameArg = process.argv.indexOf('--name'); - const fileName = process.argv[fileNameArg + 1]; - - if (fileNameArg !== -1 && fileName) { - readJson(pkgSolutionFilePath, (err, pkgSolution) => { - const currentPackageName = path.basename(pkgSolution.paths.zippedPackage, '.sppkg'); - log.info(`Rename ${currentPackageName}.sppkg to ${fileName}.sppkg`); - pkgSolution.paths.zippedPackage = pkgSolution.paths.zippedPackage.replace(path.basename(pkgSolution.paths.zippedPackage, '.sppkg'), fileName); - fs.writeFile(pkgSolutionFilePath, JSON.stringify(pkgSolution, null, 4), (error) => { }); - }); - } else { - log.error(`Error: wrong parameters`); - } -}); - -// Local project tasks -gulp.task('update-docs-url', async () => { - - const hostUrlArg = process.argv.indexOf("--hosturl"); - const hostUrl = process.argv[hostUrlArg+1]; - - return src("src/webparts/**/*.template.json") - .pipe(replace("{{DOCUMENTATION_HOST_URL}}", hostUrl)) - .pipe(rename((path) => { - - return { - dirname: "src/webparts/" + path.dirname, - basename: path.basename.replace(".template",""), - extname: ".json" - }; - })) - .pipe(dest("./")) -}); - -build.initialize(require('gulp')); - diff --git a/packages/spfx/package.json b/packages/spfx/package.json deleted file mode 100644 index dca7691..0000000 --- a/packages/spfx/package.json +++ /dev/null @@ -1,89 +0,0 @@ -{ - "name": "@pnp/modern-search-core-spfx", - "version": "0.0.1", - "private": true, - "engines": { - "node": ">=16.13.0 <17.0.0" - }, - "main": "lib/index.js", - "scripts": { - "build": "gulp bundle", - "clean": "gulp clean", - "test": "gulp test", - "webpack:serve": "gulp bundle --custom-serve --max_old_space_size=4096 && fast-serve", - "serve": "npm-run-all -p tailwindcss:watch webpack:serve", - "tailwindcss": "tailwindcss -i ./src/styles/tailwind.css -o ./src/styles/dist/tailwind.css --minify --postcss ./src/styles/postcss.config.js", - "tailwindcss:watch": "tailwindcss -i ./src/styles/tailwind.css -o ./src/styles/dist/tailwind.css --watch --minify --postcss ./src/styles/postcss.config.js" - }, - "dependencies": { - "@fluentui/react": "^7.199.1", - "@microsoft/microsoft-graph-client": "3.0.2", - "@microsoft/sp-component-base": "1.18.2", - "@microsoft/sp-core-library": "1.18.2", - "@microsoft/sp-diagnostics": "1.18.2", - "@microsoft/sp-dynamic-data": "1.18.2", - "@microsoft/sp-http": "1.18.2", - "@microsoft/sp-http-base": "1.18.2", - "@microsoft/sp-http-msgraph": "1.18.2", - "@microsoft/sp-loader": "1.18.2", - "@microsoft/sp-lodash-subset": "1.18.2", - "@microsoft/sp-office-ui-fabric-core": "1.18.2", - "@microsoft/sp-page-context": "1.18.2", - "@microsoft/sp-property-pane": "1.18.2", - "@microsoft/sp-webpart-base": "1.18.2", - "@monaco-editor/react": "^4.5.1", - "@pnp/spfx-controls-react": "3.15.0", - "@pnp/spfx-property-controls": "3.1.0", - "@pnp/modern-search-core": "workspace:*", - "@pnp/telemetry-js": "2.0.0", - "dompurify": "3.0.5", - "html-react-parser": "4.2.1", - "office-ui-fabric-react": "^7.199.1", - "react": "17.0.1", - "react-dom": "17.0.1", - "tslib": "2.5.0", - "wc-react": "0.5.1", - "@webcomponents/scoped-custom-element-registry": "0.0.9" - }, - "devDependencies": { - "@babel/preset-env": "7.22.5", - "@babel/preset-typescript": "7.22.15", - "@babel/plugin-transform-optional-chaining": "7.23.4", - "@babel/plugin-transform-nullish-coalescing-operator": "7.23.4", - "@babel/plugin-transform-logical-assignment-operators": "7.23.4", - "@microsoft/eslint-config-spfx": "1.18.2", - "@microsoft/eslint-plugin-spfx": "1.18.2", - "@microsoft/rush-stack-compiler-4.5": "0.5.0", - "@microsoft/sp-build-web": "1.18.2", - "@microsoft/sp-module-interfaces": "1.18.2", - "@rushstack/eslint-config": "2.5.1", - "@types/dompurify": "3.0.2", - "@types/react": "17.0.45", - "@types/react-dom": "17.0.17", - "@types/webpack-env": "~1.15.2", - "ajv": "8.12.0", - "undertaker-registry": "2.0.0", - "fancy-log": "^2.0.0", - "babel-loader": "^8.3.0", - "babel-plugin-module-resolver": "5.0.0", - "eslint": "^8.33.0", - "eslint-plugin-react-hooks": "4.3.0", - "gulp": "^4.0.2", - "gulp-rename": "2.0.0", - "gulp-replace": "1.1.4", - "autoprefixer": "10.4.16", - "tailwindcss": "3.2.4", - "@tailwindcss/forms": "0.5.3", - "@tailwindcss/line-clamp": "0.4.4", - "@tailwindcss/container-queries": "0.1.1", - "html-loader": "^1.1.0", - "monaco-editor": "^0.41.0", - "source-map-loader": "1.1.3", - "null-loader": "4.0.1", - "spfx-fast-serve-helpers": "~1.18.0", - "typescript": "4.9.5", - "webpack": "~4.44.2", - "semver": "7.5.4", - "npm-run-all": "^4.1.5" - } -} diff --git a/packages/spfx/src/common/BaseWebPart.tsx b/packages/spfx/src/common/BaseWebPart.tsx deleted file mode 100644 index 2b4f60c..0000000 --- a/packages/spfx/src/common/BaseWebPart.tsx +++ /dev/null @@ -1,647 +0,0 @@ -import { BaseClientSideWebPart } from '@microsoft/sp-webpart-base'; -import { IBaseWebPartProps } from "../models/common/IBaseWebPartProps"; -import { ThemeProvider, IReadonlyTheme, ThemeChangedEventArgs } from '@microsoft/sp-component-base'; -import { isEqual } from '@microsoft/sp-lodash-subset'; -import { IPropertyPaneGroup, PropertyPaneLabel, PropertyPaneLink, PropertyPaneToggle } from '@microsoft/sp-property-pane'; -import * as commonStrings from "CommonStrings"; -import { - SearchFiltersComponent, - SearchInputComponent, - SearchResultsComponent, - SearchVerticalsComponent, - LanguageProvider, - Providers, - SharePointProvider, - LocalizationHelper, - AdaptiveCardComponent, - VideoPlayerComponent -} from '@pnp/modern-search-core'; -import { - IPropertyPaneField, - PropertyPaneChoiceGroup, -} from '@microsoft/sp-property-pane'; -import { DisplayMode, Log, ServiceScope } from '@microsoft/sp-core-library'; -import { ILocalizationService } from '../services/localizationService/ILocalizationService'; -import { LocalizationService } from '../services/localizationService/LocalizationService'; -import PnPTelemetry from '@pnp/telemetry-js'; -import { ComponentType } from './ComponentType'; -import { ComponentElements, ThemePublicCSSVariables } from '@pnp/modern-search-core/dist/es6/common/Constants'; -import { ConfigurationFieldType, IConfigurationTabField } from '../controls/ConfigurationPanel/IConfigurationTabField'; -import { IConfigurationTab } from '../controls/ConfigurationPanel/IConfigurationTab'; -import { ColorPicker, IColor, getColorFromString } from '@fluentui/react'; -import * as React from 'react'; -import { ICustomColorField } from '../models/common/ICustomPalette'; -import { ConfigurationPanel } from '../controls/ConfigurationPanel/ConfigurationPanel'; -import { PropertyPaneFormDataCollection } from '../propertyPane/PropertyPaneFormDataCollection/PropertyPaneFormDataCollection'; -import { ItemRepeater } from '../controls/ItemRepeater/ItemRepeater'; -import { PropertyPaneFilePicker } from '../propertyPane/PropertyPaneFilePicker/PropertyPaneFilePicker'; -import { LayoutHelper } from '../helpers/LayoutHelper'; -import { BuiltinLayoutsKeys } from '../layouts/AvailableLayouts'; -import { PropertyPaneCodeEditor } from '../propertyPane/PropertyPaneCodeEditor/PropertyPaneCodeEditor'; -import { ILayoutDefinition, LayoutType } from '../models/common/ILayoutDefinition'; -import { FileService } from '../services/fileService/FileService'; -import { ILayout } from '../models/common/ILayout'; -import IDynamicDataService from '../services/dynamicDataService/IDynamicDataService'; -import { DynamicDataService } from '../services/dynamicDataService/DynamicDataService'; -import IFileService from '../services/fileService/IFileService'; -import '../styles/dist/tailwind.css'; -import { PropertyPaneWebPartInformation } from '@pnp/spfx-property-controls'; - -//#region Default colors - -const defaultLightColorOverrides = [ - { - colorName: commonStrings.PropertyPane.PrimaryColorFieldName, - colorValue: "", - colorVariable: ThemePublicCSSVariables.colorPrimary - }, - { - colorName: commonStrings.PropertyPane.BackgroundColorFieldName, - colorValue: "", - colorVariable: ThemePublicCSSVariables.primaryBackgroundColor - }, - { - colorName: commonStrings.PropertyPane.TextColorFieldName, - colorValue: "", - colorVariable: ThemePublicCSSVariables.textColor - } -]; - -const defaultDarkColorOverrides = [ - { - colorName: commonStrings.PropertyPane.PrimaryColorFieldName, - colorValue: "", - colorVariable: ThemePublicCSSVariables.colorPrimary - }, - { - colorName: commonStrings.PropertyPane.BackgroundColorFieldName, - colorValue: "", - colorVariable: ThemePublicCSSVariables.primaryBackgroundColorDark - }, - { - colorName: commonStrings.PropertyPane.TextColorFieldName, - colorValue: "", - colorVariable: ThemePublicCSSVariables.textColorDark - } -]; - -//#endregion - -/** - * Generic abstract class for all Web Parts in the solution - */ -export abstract class BaseWebPart extends BaseClientSideWebPart { - - /** - * Theme variables - */ - protected _themeProvider: ThemeProvider; - protected _themeVariant: IReadonlyTheme; - - /** - * Placeholder component loaded dynamically - */ - // eslint-disable-next-line @typescript-eslint/no-explicit-any - protected _placeholderComponent: any = null; - - // eslint-disable-next-line @typescript-eslint/no-explicit-any - protected _propertyPanePropertyEditor: any = null; - - /** - * The Web Part properties - */ - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-ignore: redefinition - protected properties: T; - - private languageProvider: LanguageProvider; - - private _colorsItemRepeaterRef = React.createRef>(); - - private _domPurify: DOMPurify.DOMPurifyI; - - /** - * All availabel layout for the current WebPart - */ - protected abstract availableLayoutDefinitions: ILayoutDefinition[]; - - /** - * The template content to display - */ - protected templateContentToDisplay: string; - - /** - * External template content already fetched - */ - protected externalTemplateContent: string; - - /** - * The file service for external templates - */ - protected fileService: FileService; - - /** - * The dynamic data service instance - */ - protected dynamicDataService: IDynamicDataService; - - /** - * The service scope for this specific Web Part instance - */ - protected webPartInstanceServiceScope: ServiceScope; - - /** - * The selected layout instance for the Web Part - */ - protected layout: ILayout; - - constructor() { - super(); - - this.languageProvider = new LanguageProvider(); - } - - protected async onInit(): Promise { - - try { - // Disable PnP Telemetry - const telemetry = PnPTelemetry.getInstance(); - telemetry.optOut(); - } catch (error) { - Log.warn(this.manifest.alias, `Opt out for PnP Telemetry failed. Details: ${error}`, this.context.serviceScope); - } - - const localizationService = this.context.serviceScope.consume(LocalizationService.ServiceKey); - const currentLocale = await localizationService.getCurrentPageUILanguage(); - - // Define all needed components - if (!customElements.get(ComponentElements.SearchResultsComponent)) { - customElements.define([ComponentElements.SearchResultsComponent].toString(), SearchResultsComponent); - } - - if (!customElements.get(ComponentElements.SearchFiltersComponent)) { - customElements.define([ComponentElements.SearchFiltersComponent].toString(), SearchFiltersComponent); - } - - if (!customElements.get(ComponentElements.SearchInputComponent)) { - customElements.define([ComponentElements.SearchInputComponent].toString(), SearchInputComponent); - } - - if (!customElements.get(ComponentElements.SearchVerticalsComponent)) { - customElements.define([ComponentElements.SearchVerticalsComponent].toString(), SearchVerticalsComponent); - } - - if (!customElements.get(ComponentElements.AdaptiveCardComponent)) { - customElements.define([ComponentElements.AdaptiveCardComponent].toString(), AdaptiveCardComponent); - } - - if (!customElements.get(ComponentElements.VideoPlayerComponent)) { - customElements.define([ComponentElements.VideoPlayerComponent].toString(), VideoPlayerComponent); - } - - if (!Providers.globalProvider) { - Providers.globalProvider = new SharePointProvider(this.context); - } - - // Set current language according to cuirrent page translation language or UI locale if not translated - if (LocalizationHelper.strings?.language !== currentLocale) { - await this.languageProvider.setLanguage(currentLocale); - } - - // Initializes shared services - await this.initializeBaseWebPart(); - - // Initialize layout instance - if (!this.layout) { - this.layout = await LayoutHelper.getLayoutInstance(this.webPartInstanceServiceScope, this.context, this.properties, this.properties.selectedLayoutKey, this.availableLayoutDefinitions); - } - - await this.loadResources(); - - return; - } - - /** - * Initializes shared services and properties used by all Web Parts - */ - protected async initializeBaseWebPart(): Promise { - - // Initialize services - - this.context.serviceScope.whenFinished(() => { - this.dynamicDataService = this.context.serviceScope.consume(DynamicDataService.ServiceKey); - this.dynamicDataService.dynamicDataProvider = this.context.dynamicDataProvider; - this.fileService = this.context.serviceScope.consume(FileService.ServiceKey); - }); - - // Create a specific Web Part service scope - this.webPartInstanceServiceScope = this.context.serviceScope.startNewChild(); - this.webPartInstanceServiceScope.finish(); - - // Initializes theme variant - this.initThemeVariant(); - - this.properties.followSiteTheme = this.properties.followSiteTheme !== undefined ? this.properties.followSiteTheme : true; - this.properties.colorOverrides = this.properties.colorOverrides ? this.properties.colorOverrides : (this._themeVariant.isInverted ? defaultDarkColorOverrides : defaultLightColorOverrides); - this.properties.layoutProperties = this.properties.layoutProperties ? this.properties.layoutProperties : {}; - - this.setThemeVariables(); - } - - protected async loadPropertyPaneResources(): Promise { - - - const { PropertyPanePropertyEditor } = await import( - /* webpackChunkName: 'pnp-modern-search-property-pane' */ - '@pnp/spfx-property-controls/lib/PropertyPanePropertyEditor' - ); - this._propertyPanePropertyEditor = PropertyPanePropertyEditor; - } - - protected async onPropertyPaneConfigurationStart(): Promise { - await this.loadPropertyPaneResources(); - } - - /** - * Returns common information groups for the property pane - */ - protected getPropertyPaneWebPartInfoGroups(): IPropertyPaneGroup[] { - - return [ - { - groupName: commonStrings.PropertyPane.InformationPage.About, - groupFields: [ - PropertyPaneWebPartInformation({ - description: `
${commonStrings.PropertyPane.InformationPage.Authors}:PnP logo
`, - key: 'authors' - }), - PropertyPaneLabel('', { - text: `${commonStrings.PropertyPane.InformationPage.Version}: ${this && this.manifest.version ? this.manifest.version : ''}` - }), - PropertyPaneLabel('', { - text: `${commonStrings.PropertyPane.InformationPage.InstanceId}: ${this.instanceId}` - }), - ] - }, - { - groupName: commonStrings.PropertyPane.InformationPage.Resources.GroupName, - groupFields: [ - PropertyPaneLink('',{ - target: '_blank', - href: this.properties.documentationLink, - text: commonStrings.PropertyPane.InformationPage.Resources.Documentation - }), - PropertyPaneLink('',{ - target: '_blank', - href: this.properties.issueLink, - text: commonStrings.PropertyPane.InformationPage.Resources.IssueLink - }) - ] - }, - { - groupName: commonStrings.PropertyPane.InformationPage.ImportExport, - groupFields: [ - PropertyPaneWebPartInformation({ - description: `${commonStrings.PropertyPane.InformationPage.DeveloperSettingsWarning}`, - key: 'warning' - }), - this._propertyPanePropertyEditor({ - webpart: this, - key: 'propertyEditor' - }), - ], - isCollapsed: false - } - ]; - } - - protected async onPropertyPaneFieldChanged(propertyPath: string, oldValue: unknown, newValue: unknown): Promise { - - if (propertyPath.localeCompare("colorOverrides") === 0 || propertyPath.localeCompare("followSiteTheme") === 0) { - - if (this.properties.followSiteTheme) { - this.properties.colorOverrides = this._themeVariant.isInverted ? defaultDarkColorOverrides : defaultLightColorOverrides; - } - - this.setThemeVariables(); - } - - //#region Layout related properties - - // Notify layout a property has been updated (only if the layout is already selected) - if ((propertyPath.localeCompare('selectedLayoutKey') !== 0) && this.layout) { - this.layout.onPropertyUpdate(propertyPath, oldValue, newValue); - } - - // Reset layout properties - if (propertyPath.localeCompare('selectedLayoutKey') === 0 && !isEqual(oldValue, newValue)) { - - this.properties.layoutProperties = {}; - this.layout = await LayoutHelper.getLayoutInstance(this.webPartInstanceServiceScope, this.context, this.properties, this.properties.selectedLayoutKey, this.availableLayoutDefinitions); - } - - // Detect if the layout has been changed to custom - if (propertyPath.localeCompare('inlineTemplateContent') === 0) { - - // Reset the external template file pointer and already fetched content if the inline tempalte is modified - this.properties.externalTemplateFilePickerResult = null; - this.externalTemplateContent = null; - - // Automatically switch the option to 'Custom' if a default template has been edited - // (meaning the user started from a default template) - if (this.properties.inlineTemplateContent) { - - const layoutDefinition = this.availableLayoutDefinitions.filter(layoutDef => - layoutDef.key === this.properties.selectedLayoutKey - )[0]; - - switch (layoutDefinition.type) { - case LayoutType.Results: - this.properties.selectedLayoutKey = BuiltinLayoutsKeys.ResultsCustom; - break; - case LayoutType.Filters: - this.properties.selectedLayoutKey = BuiltinLayoutsKeys.FiltersCustom; - break; - } - } - } - - if (propertyPath.localeCompare("externalTemplateFilePickerResult") === 0) { - this.templateContentToDisplay = await this.fileService.downloadFileContent(this.properties.externalTemplateFilePickerResult); - this.externalTemplateContent = this.templateContentToDisplay - } - - - } - - protected getThemePageGroup(): IPropertyPaneGroup { - - const colorFieldConfiguration: IConfigurationTab[] = [ - { - name: commonStrings.PropertyPane.ColorSettingsTabLabel, - fields: [ - { - type: ConfigurationFieldType.Custom, - props: { - }, - onCustomRender: (field: IConfigurationTabField, defaultValue: string, onFieldValueUpdate: (field: IConfigurationTabField, value: string) => void) => { - const color = getColorFromString(defaultValue); - return { - onFieldValueUpdate(field, colorObj.str); - }} - /> - }, - targetProperty: "colorValue", - } - ] - }, - ]; - - const mainFormFields: IConfigurationTabField[] = [ - { - type: ConfigurationFieldType.Custom, - targetProperty: null, - onCustomRender: (field, defaultValue, onUpdate) => { - - return - configurationTabs={colorFieldConfiguration} - renderRowTitle={(field: ICustomColorField) => { return field.colorName }} - onFormSave={(formData: ICustomColorField) => { - onUpdate(field, formData) - }} - dataObject={defaultValue} - renderPanelTitle={(propsDataObject: ICustomColorField) => { - return propsDataObject.colorName; - }} - />; - } - } - ]; - - const themeFields = [ - PropertyPaneToggle('followSiteTheme', { - label: commonStrings.PropertyPane.FollowSiteTheme, - checked: this.properties.followSiteTheme - }) - ]; - - if (!this.properties.followSiteTheme) { - themeFields.push( - new PropertyPaneFormDataCollection('colorOverrides', { - label: commonStrings.PropertyPane.CustomColorsFieldName, - itemRepeaterProps: { - innerRef: this._colorsItemRepeaterRef, - addButtonLabel: commonStrings.PropertyPane.CustomColorsAddButtonLabel, - enableDragDrop: false, - disabled: true, - isItemLocked: (item: ICustomColorField) => { - return true; - } - }, - items: this.properties.colorOverrides, - formConfiguration: mainFormFields - }) - ); - } - - return { - groupName: commonStrings.PropertyPane.ThemeSettingsGroupName, - groupFields: themeFields - }; - } - - protected getTemplateOptionsGroup(): IPropertyPaneGroup { - - const stylingFields: IPropertyPaneField[] = [ - PropertyPaneChoiceGroup('selectedLayoutKey', { - options: LayoutHelper.getLayoutOptions(this.availableLayoutDefinitions) - }) - ]; - - // We can customize the template for any layout - stylingFields.push( - new PropertyPaneCodeEditor('inlineTemplateContent', { - label: commonStrings.PropertyPane.EditComponentTemplates, - defaultValue: this.templateContentToDisplay, - theme: this._themeVariant, - isReadOnly: !!this.properties.externalTemplateFilePickerResult && this.properties.selectedLayoutKey === BuiltinLayoutsKeys.ResultsCustom - }), - PropertyPaneToggle('enableDebugMode', { - label: commonStrings.PropertyPane.EnableDebugMode - }), - PropertyPaneToggle('useMicrosoftGraphToolkit', { - label: commonStrings.PropertyPane.UseMicrosoftGraphToolkit - }) - ); - - // Only show the template external URL for 'Custom' option - if (this.properties.selectedLayoutKey === BuiltinLayoutsKeys.ResultsCustom || this.properties.selectedLayoutKey === BuiltinLayoutsKeys.FiltersCustom) { - stylingFields.splice(2,0, - new PropertyPaneFilePicker('externalTemplateFilePickerResult', { - label: commonStrings.PropertyPane.UseExternalTemplateFile, - componentContext: this.context, - filePickerResult: this.properties?.externalTemplateFilePickerResult - }) - ); - } - - return { - groupName: commonStrings.PropertyPane.TemplateSettingsGroupName, - groupFields: stylingFields - }; - } - - - protected async loadResources(): Promise { - - if (this.displayMode === DisplayMode.Edit) { - - const { Placeholder } = await import( - /* webpackChunkName: '-modern-search-core-property-pane' */ - '@pnp/spfx-controls-react/lib/Placeholder' - ); - this._placeholderComponent = Placeholder; - } - } - - /** - * Initializes theme variant properties - */ - private initThemeVariant(): void { - - // Consume the new ThemeProvider service - this._themeProvider = this.context.serviceScope.consume(ThemeProvider.serviceKey); - - // If it exists, get the theme variant - this._themeVariant = this._themeProvider.tryGetTheme(); - - // Register a handler to be notified if the theme variant changes - this._themeProvider.themeChangedEvent.add(this, this._handleThemeChangedEvent.bind(this)); - } - - /** - * Update the current theme variant reference and re-render. - * @param args The new theme - */ - private _handleThemeChangedEvent(args: ThemeChangedEventArgs): void { - - if (!isEqual(this._themeVariant, args.theme)) { - this._themeVariant = args.theme; - this.setThemeVariables(); - this.render(); - } - } - - private setThemeVariables(): void { - - const setCommonStyles = (): void => { - this.domElement.style.setProperty(ThemePublicCSSVariables.colorPrimary, this._themeVariant.palette.themePrimary); - this.domElement.style.setProperty(ThemePublicCSSVariables.fontFamilyPrimary, this._themeVariant.fonts.medium.fontFamily); - this.domElement.style.setProperty(ThemePublicCSSVariables.fontFamilySecondary, this._themeVariant.fonts.medium.fontFamily); - } - - const setDarkMode = (): void => { - this.domElement.style.setProperty(ThemePublicCSSVariables.primaryBackgroundColorDark, this._themeVariant.semanticColors.bodyBackground); - this.domElement.style.setProperty(ThemePublicCSSVariables.textColorDark, this._themeVariant.semanticColors.bodyText); - - this.domElement.style.removeProperty(ThemePublicCSSVariables.primaryBackgroundColor); - this.domElement.style.removeProperty(ThemePublicCSSVariables.textColor); - }; - - const setLightMode = (): void => { - this.domElement.style.setProperty(ThemePublicCSSVariables.primaryBackgroundColor, this._themeVariant.semanticColors.bodyBackground); - this.domElement.style.setProperty(ThemePublicCSSVariables.textColor, this._themeVariant.semanticColors.bodyText); - - this.domElement.style.removeProperty(ThemePublicCSSVariables.primaryBackgroundColorDark); - this.domElement.style.removeProperty(ThemePublicCSSVariables.textColorDark); - }; - - if (this.properties.followSiteTheme) { - - setCommonStyles(); - - if (this._themeVariant.isInverted) { - setDarkMode(); - } else { - setLightMode(); - } - - } else { - - // Set custom colors values - this.properties.colorOverrides.forEach(color => { - this.domElement.style.setProperty(color.colorVariable, color.colorValue); - }); - } - - } - - protected getComponentId(componentType: ComponentType): string { - return `${this.manifest.componentType}.${this.manifest.id}.${this.instanceId}:${componentType}`; - } - - protected async initDomPurify(): Promise { - - if (this.properties.selectedLayoutKey === BuiltinLayoutsKeys.ResultsCustom || - this.properties.selectedLayoutKey === BuiltinLayoutsKeys.FiltersCustom || - this.properties.selectedLayoutKey === BuiltinLayoutsKeys.VerticalsCustom ) { - - const DOMPurify = await import( - /* webpackChunkName: 'pnp-modern-search-core-dompurify' */ - 'dompurify' - ); - - this._domPurify = DOMPurify; - - this._domPurify.setConfig({ - CUSTOM_ELEMENT_HANDLING: { - tagNameCheck: /^pnp|mgt-/, - attributeNameCheck: () => true, - allowCustomizedBuiltInElements: true, - }, - ADD_TAGS: ['style'], - ALLOW_DATA_ATTR: true, - ALLOWED_URI_REGEXP: /^(?:(?:(?:f|ht)tps?|mailto|file|tel|callto|cid|xmpp|xxx|ms-\w+):|[^a-z]|[a-z+.-]+(?:[^a-z+.\-:]|$))/i - }); - } - } - - protected async initTemplate(): Promise { - - // Gets the template content according to the selected key - const selectedLayoutTemplateContent = this.availableLayoutDefinitions.filter(layout => { return layout.key === this.properties.selectedLayoutKey; })[0].templateContent; - let externalTemplateContent; - - if (this.properties.selectedLayoutKey === BuiltinLayoutsKeys.ResultsCustom || - this.properties.selectedLayoutKey === BuiltinLayoutsKeys.FiltersCustom || - this.properties.selectedLayoutKey === BuiltinLayoutsKeys.VerticalsCustom) { - - if (!this._domPurify) { - await this.initDomPurify(); - } - - if (this.properties.externalTemplateFilePickerResult) { - - if (!this.externalTemplateContent) { - externalTemplateContent = await this.fileService.downloadFileContent(this.properties.externalTemplateFilePickerResult); - } else { - externalTemplateContent = this.externalTemplateContent; - } - - this.templateContentToDisplay = this.sanitizeTemplate(externalTemplateContent) - - } else { - this.templateContentToDisplay = this.properties.inlineTemplateContent ? this.sanitizeTemplate(this.properties.inlineTemplateContent) : selectedLayoutTemplateContent; - } - - } else { - this.templateContentToDisplay = selectedLayoutTemplateContent; - } - } - - private sanitizeTemplate(templateContent: string): string { - return this._domPurify.sanitize(`
${templateContent}
`).replace(/^
/,"").replace(/<\/div>$/,""); - } -} \ No newline at end of file diff --git a/packages/spfx/src/common/ComponentType.ts b/packages/spfx/src/common/ComponentType.ts deleted file mode 100644 index ce77b7e..0000000 --- a/packages/spfx/src/common/ComponentType.ts +++ /dev/null @@ -1,11 +0,0 @@ - -/** - * List of all available components for data dynamic data connections filtering - */ -export enum ComponentType { - SearchResults = 'pnpModernSearchCoreResultsWebPart', - SearchFilters = 'pnpModernSearchCoreFiltersWebPart', - SearchBox = 'pnpModernSearchCoreSearchBoxWebPart', - SearchVerticals = 'pnpModernSearchCoreVerticalsWebPart', - PageEnvironment = 'PageContext' -} \ No newline at end of file diff --git a/packages/spfx/src/common/Constants.ts b/packages/spfx/src/common/Constants.ts deleted file mode 100644 index 4c08822..0000000 --- a/packages/spfx/src/common/Constants.ts +++ /dev/null @@ -1,7 +0,0 @@ -export class Constants { - - /** - * The client tag to append to all REST calls to SharePoint - */ - public static readonly X_CLIENTSERVICE_CLIENTTAG = 'NonISV|PnP|ModernSearchCore'; -} \ No newline at end of file diff --git a/packages/spfx/src/common/declaration.d.ts b/packages/spfx/src/common/declaration.d.ts deleted file mode 100644 index fa27af9..0000000 --- a/packages/spfx/src/common/declaration.d.ts +++ /dev/null @@ -1,9 +0,0 @@ -declare namespace JSX { - interface IntrinsicElements { - "pnp-search-input": any; - "pnp-search-results": any; - "pnp-search-verticals": any; - "pnp-search-filters": any; - "pnp-language-provider": any; - } -} diff --git a/packages/spfx/src/controls/ConfigurationPanel/ConfigurationPanel.tsx b/packages/spfx/src/controls/ConfigurationPanel/ConfigurationPanel.tsx deleted file mode 100644 index 177f561..0000000 --- a/packages/spfx/src/controls/ConfigurationPanel/ConfigurationPanel.tsx +++ /dev/null @@ -1,147 +0,0 @@ -import * as React from "react"; -import { IConfigurationPanelProps } from "./IConfigurationPanelProps"; -import { IConfigurationPanelState } from "./IConfigurationPanelState"; -import { DefaultButton, IconButton, Label, Panel, Pivot, PivotItem, PrimaryButton } from "office-ui-fabric-react"; -import { FormBuilder } from "../FormBuilder/FormBuilder"; -import { cloneDeep, isEqual } from "@microsoft/sp-lodash-subset"; -import { IConfigurationTab } from "./IConfigurationTab"; - -export class ConfigurationPanel extends React.Component,IConfigurationPanelState> { - - constructor(props: IConfigurationPanelProps) { - super(props); - - this.state = { - isOpen: false, - currentformData: null, - savedformData: null, - title: null, - canSave: false, - errors: new Map>() - }; - - this.togglePanel = this.togglePanel.bind(this); - this.onFormValuesUpdated = this.onFormValuesUpdated.bind(this); - this.onFormDismissed = this.onFormDismissed.bind(this); - } - - public componentDidMount(): void { - - this.setState({ - savedformData: {...this.props.dataObject}, - currentformData: {...this.props.dataObject}, - title: this.props.renderRowTitle(this.props.dataObject) - }); - } - - public render(): React.ReactNode { - - const renderFooter =
-
- { - this.setState({ - canSave: false, - savedformData: {...this.state.currentformData} - }); - - this.props.onFormSave(this.state.currentformData); - this.togglePanel(); - }} - disabled={!this.state.canSave} - >Save - Cancel -
-
; - - - const renderTabs = this.props.configurationTabs.filter(tab => !tab.isVisible || (tab.isVisible && this.state.currentformData && tab.isVisible(this.state.currentformData))).map((tab, i) => { - - return -
- ) => { - this.onFormValuesUpdated(tab, formData, errors); - this.forceUpdate(); - }} - /> -
-
- }); - - return <> -
- - -
- { - return renderFooter; - }} - > - - {renderTabs} - - - - } - - public togglePanel(): void { - - this.setState({ - isOpen: !this.state.isOpen - }); - } - - private onFormDismissed(): void { - - // Revert back to original form values - this.setState({ - currentformData: {...this.state.savedformData}, - canSave: false - }); - - if (this.props.onFormDismissed) { - this.props.onFormDismissed(this.state.savedformData); - } - - this.togglePanel(); - } - - private onFormValuesUpdated(tab: IConfigurationTab, formData: T, errors: Map): void { - - const title = this.props.renderRowTitle(formData); - - // Update errors list from all tabs - const tabErrors = cloneDeep(this.state.errors); - if (errors.size === 0) { - if (tabErrors.get(tab.name)) - tabErrors.delete(tab.name); - } else { - tabErrors.set(tab.name, errors); - } - - // Merge form data from all tabs - const mergedFormDataFromTabs = {...this.state.currentformData,...formData}; - - // Compare updates from saved input data - const canSave = !isEqual(this.state.savedformData, mergedFormDataFromTabs) && !(tabErrors.size > 0); - - this.setState({ - currentformData: mergedFormDataFromTabs, - title: title, - canSave: canSave, - errors: tabErrors - }); - } -} diff --git a/packages/spfx/src/controls/ConfigurationPanel/IConfigurationPanelProps.ts b/packages/spfx/src/controls/ConfigurationPanel/IConfigurationPanelProps.ts deleted file mode 100644 index 045185d..0000000 --- a/packages/spfx/src/controls/ConfigurationPanel/IConfigurationPanelProps.ts +++ /dev/null @@ -1,36 +0,0 @@ -import { IConfigurationTab } from "./IConfigurationTab"; - -export interface IConfigurationPanelProps { - - /** - * The panel title - */ - renderPanelTitle?: ((propsDataObject: T) => string); - - /** - * Property in the object used as item title - */ - renderRowTitle: (formData: T) => string; - - /** - * The input data object to render - */ - dataObject?: T; - - /** - * Tabs configuration for the panel - */ - configurationTabs: IConfigurationTab[]; - - /** - * Callback handler when the form is saved - * @param formData the current form data of type T - */ - onFormSave: (formData: T) => void; - - /** - * Callback handler when the form is dismissed without saving - * @param formData the current form data of type T - */ - onFormDismissed?: (formData: T) => void; -} \ No newline at end of file diff --git a/packages/spfx/src/controls/ConfigurationPanel/IConfigurationPanelState.ts b/packages/spfx/src/controls/ConfigurationPanel/IConfigurationPanelState.ts deleted file mode 100644 index c68eb05..0000000 --- a/packages/spfx/src/controls/ConfigurationPanel/IConfigurationPanelState.ts +++ /dev/null @@ -1,32 +0,0 @@ -export interface IConfigurationPanelState { - - /** - * Flag indicating is the panel is open - */ - isOpen: boolean; - - /** - * The current form data being edited (not save yet) - */ - currentformData: T; - - /** - * The form data saved. Used as reference data to determine if updates have been made since last modification - */ - savedformData: T; - - /** - * The panel title - */ - title: string; - - /** - * Flag indicating if the form data can be saved (no errors and data updated) - */ - canSave: boolean; - - /** - * List of errors by tab name - */ - errors: Map> -} \ No newline at end of file diff --git a/packages/spfx/src/controls/ConfigurationPanel/IConfigurationTab.ts b/packages/spfx/src/controls/ConfigurationPanel/IConfigurationTab.ts deleted file mode 100644 index 6295cd6..0000000 --- a/packages/spfx/src/controls/ConfigurationPanel/IConfigurationTab.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { IConfigurationTabField } from "./IConfigurationTabField"; - -export interface IConfigurationTab { - - /** - * Name of the tab - */ - name: string; - - /** - * Fields contained in this tab - */ - fields: IConfigurationTabField[]; - - /** - * Handler to determine the visibility of the tab based on the current data - * @param dataObject the current for data object - * @returns 'true' if the field should be visible, 'false' otherwise - */ - isVisible?: (dataObject: unknown) => boolean; -} \ No newline at end of file diff --git a/packages/spfx/src/controls/ConfigurationPanel/IConfigurationTabField.ts b/packages/spfx/src/controls/ConfigurationPanel/IConfigurationTabField.ts deleted file mode 100644 index 20ae48f..0000000 --- a/packages/spfx/src/controls/ConfigurationPanel/IConfigurationTabField.ts +++ /dev/null @@ -1,43 +0,0 @@ -export enum ConfigurationFieldType { - Dropdown, - TextField, - Toggle, - ChoiceGroup, - Slider, - LocalizedField, - FilterAggregationsField, - RepeatedItem, - Custom -} - -export interface IConfigurationTabField { - - /** - * Type of the field to be instanciated - */ - type: ConfigurationFieldType; - - /** - * properties to pass to components - */ - // eslint-disable-next-line @typescript-eslint/no-explicit-any - props?: any; - - /** - * The target property path for setting default value/save. If set to 'null', the value for that fille will the one passed to the form - */ - targetProperty?: string; - - /** - * Custom render function if the type is set to "Custom" - */ - // eslint-disable-next-line @typescript-eslint/no-explicit-any - onCustomRender?: (field: IConfigurationTabField, defaultValue: any, onFieldValueUpdate: (field: IConfigurationTabField, value: any) => void) => React.ReactNode; - - /** - * Handler to determine the visibility of the field based on the current handler - * @param dataObject the current for data object - * @returns 'true' if the field should be visible, 'false' otherwise - */ - isVisible?: (dataObject: unknown) => boolean; -} \ No newline at end of file diff --git a/packages/spfx/src/controls/FormBuilder/FormBuilder.tsx b/packages/spfx/src/controls/FormBuilder/FormBuilder.tsx deleted file mode 100644 index 28f1972..0000000 --- a/packages/spfx/src/controls/FormBuilder/FormBuilder.tsx +++ /dev/null @@ -1,229 +0,0 @@ -import * as React from "react"; -import { IFormBuilderProps } from "./IFormBuilderProps"; -import { IFormBuilderState } from "./IFormBuilderState"; -import { ObjectHelper } from "@pnp/modern-search-core/dist/es6/helpers/ObjectHelper"; -import { ILocalizedString } from "@pnp/modern-search-core/dist/es6/models/common/ILocalizedString"; -import { TextField, Dropdown, Toggle, ChoiceGroup, Slider, Stack, IDropdown } from "office-ui-fabric-react"; -import { ConfigurationFieldType, IConfigurationTabField } from "../ConfigurationPanel/IConfigurationTabField"; -import { LocalizedField } from "../LocalizedTextField/LocalizedField"; -import { cloneDeep, isEmpty } from "@microsoft/sp-lodash-subset"; -import { FormDataCollection } from "../FormDataCollection/FormDataCollection"; - -export class FormBuilder extends React.Component, IFormBuilderState> { - - constructor(props: IFormBuilderProps) { - - super(props); - - // Important to initialize formData here to get default values working and avoid an unecessary render - this.state = { - formData: cloneDeep(this.props.dataObject), // Will work with primitive types or objects - errors: new Map() - }; - - this.onFieldValueUpdate = this.onFieldValueUpdate.bind(this); - } - - public componentDidMount(): void { - - const errors = this.validateFormFields(this.state.formData); - - // Initializer errors state at form load - this.setState({ - errors: errors - }); - - if (this.props.validateOnLoad) { - this.props.onFormValuesUpdated(this.state.formData, errors) - } - } - - public render(): React.ReactNode { - - const renderFields = this.props.fields.map((field, i) => { - - let renderField = null; - let defaultFieldValue = null; - const isVisible = field.isVisible ? field.isVisible(this.state.formData) : true; - - // No target property means primitive type (ex; 'string') - if (field.targetProperty) { - // This method should return the original property type - defaultFieldValue = ObjectHelper.getPropertyByPath(this.state.formData, field.targetProperty); - } else { - defaultFieldValue = this.state.formData; - } - - switch (field.type) { - - case ConfigurationFieldType.TextField: - renderField = { - this.onFieldValueUpdate(field, newValue); - }} - defaultValue={defaultFieldValue} - />; - break - - case ConfigurationFieldType.Dropdown: { - - const dropDownRef = React.createRef(); - - renderField = { - - // eslint-disable-next-line @typescript-eslint/no-explicit-any - let value: any = option.key; - if (field.props?.multiSelect) { - value = dropDownRef.current.selectedOptions.map(o => o.key); - } - - this.onFieldValueUpdate(field, value); - - }} - /> - } - break; - - case ConfigurationFieldType.Toggle: - - renderField = { - this.onFieldValueUpdate(field, checked); - }} - />; - break; - - case ConfigurationFieldType.ChoiceGroup: - - renderField = { - this.onFieldValueUpdate(field, option.key); - }} - />; - break; - - case ConfigurationFieldType.Slider: - - renderField = { - this.onFieldValueUpdate(field, value); - }} - />; - break; - - case ConfigurationFieldType.LocalizedField: - - renderField = { - this.onFieldValueUpdate(field, value); - }} - />; - break; - - - case ConfigurationFieldType.RepeatedItem: - - renderField = - {...field.props} - items={isEmpty(defaultFieldValue) ? [] : defaultFieldValue} - onChange={(value: T[]) => { - this.onFieldValueUpdate(field, value); - }} - />; - break; - - case ConfigurationFieldType.Custom: - renderField = field.onCustomRender(field, defaultFieldValue, this.onFieldValueUpdate); - - break; - - default: - break - } - - return isVisible ? renderField : null; - }); - - return {renderFields}; - } - - // eslint-disable-next-line @typescript-eslint/no-explicit-any - private onFieldValueUpdate(field: IConfigurationTabField, value: any): void { - - // Value can be a primitive type or an object - let formData = value; - - if (field.targetProperty) { - formData = ObjectHelper.setPropertyByPath(this.state.formData, field.targetProperty, value); - } - const errors = this.validateFormFields(formData); - - this.setState({ - formData: cloneDeep(formData), // Will work with primitive types or objects - errors: errors - }, () => { - this.props.onFormValuesUpdated(formData, errors); - }); - } - - /** - * Validate all fields if they have any errors - * @param formData the current form data - * @returns - */ - private validateFormFields(formData: T): Map { - - const errors = cloneDeep(this.state.errors); - - this.props.fields.forEach(field => { - - const clearFieldError = (targetProperty: string): void => { - if (errors.get(targetProperty)) { - errors.delete(targetProperty); - } - }; - - const isFieldVisible = field.isVisible ? field.isVisible(formData) : true; - - if (field?.props?.onGetErrorMessage) { - - if (isFieldVisible) { - - let value = formData; - if (field.targetProperty) { - value = ObjectHelper.getPropertyByPath(formData, field.targetProperty); - } - - const errorMessage = field.props.onGetErrorMessage(value); - if (errorMessage !== '') { - - // Add the error for that field in the errors list - if (!errors.get(field.targetProperty)) { - errors.set(field.targetProperty, errorMessage); - } - } else { - clearFieldError(field.targetProperty); - } - } else { - clearFieldError(field.targetProperty); - } - } - }); - - return errors; - } -} \ No newline at end of file diff --git a/packages/spfx/src/controls/FormBuilder/IFormBuilderProps.ts b/packages/spfx/src/controls/FormBuilder/IFormBuilderProps.ts deleted file mode 100644 index bda0a24..0000000 --- a/packages/spfx/src/controls/FormBuilder/IFormBuilderProps.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { IConfigurationTabField } from "../ConfigurationPanel/IConfigurationTabField"; - -export interface IFormBuilderProps { - - /** - * Flag indicating if errors should be validated on load and the caller notified - */ - validateOnLoad?: boolean; - - /** - * The default form data to render - */ - dataObject: T; - - /** - * Fields contained in this tab - */ - fields: IConfigurationTabField[]; - - /** - * Callback handler when values are updated in the form - * @param value the form data - */ - onFormValuesUpdated: (value: T, errors: Map) => void; -} \ No newline at end of file diff --git a/packages/spfx/src/controls/FormBuilder/IFormBuilderState.ts b/packages/spfx/src/controls/FormBuilder/IFormBuilderState.ts deleted file mode 100644 index 50b558e..0000000 --- a/packages/spfx/src/controls/FormBuilder/IFormBuilderState.ts +++ /dev/null @@ -1,12 +0,0 @@ -export interface IFormBuilderState { - - /** - * Current form data - */ - formData: T; - - /** - * List of errors currently in the form - */ - errors: Map; -} \ No newline at end of file diff --git a/packages/spfx/src/controls/FormDataCollection/FormDataCollection.tsx b/packages/spfx/src/controls/FormDataCollection/FormDataCollection.tsx deleted file mode 100644 index a79c604..0000000 --- a/packages/spfx/src/controls/FormDataCollection/FormDataCollection.tsx +++ /dev/null @@ -1,197 +0,0 @@ -import * as React from "react"; -import { IFormDataCollectionProps } from "./IFormDataCollectionProps"; -import { IFormDataCollectionState } from "./IFormDataCollectionState"; -import { Guid } from "@microsoft/sp-core-library"; -import { isEqual } from "@microsoft/sp-lodash-subset"; -import { Label } from "office-ui-fabric-react"; -import { IRow, ItemRepeater } from "../ItemRepeater/ItemRepeater"; -import { FormBuilder } from "../FormBuilder/FormBuilder"; -import { IItemRepeaterValue } from "../ItemRepeater/IItemRepeaterValue"; - -export class FormDataCollection extends React.Component, IFormDataCollectionState> { - - constructor(props: IFormDataCollectionProps) { - - super(props); - this.state = { - defaultRows: [], - values: [] - }; - - this.onRenderNewRow = this.onRenderNewRow.bind(this); - this.onRowDeleted = this.onRowDeleted.bind(this); - this.onRowAdded = this.onRowAdded.bind(this); - this.onRowsOrderChanged = this.onRowsOrderChanged.bind(this); - } - - public render(): React.ReactNode { - - - return <> - {this.props.label ? : null } - - ; - } - - public componentDidMount(): void { - this.initializeState(); - } - - public componentDidUpdate(prevProps: Readonly>): void { - - // Important to not recreate rows every time when items update - // If parent initializes items from the componentDidMount method, items will be likely empty on the first render. The stateKey ensure the default rows initialized is controlled by the parent knowing when the items are "ready" - if (!isEqual(prevProps.stateKey, this.props.stateKey)) { - this.initializeState(); - } - } - - private initializeState(): void { - - if (this.props.items) { - - const repeatedItems = this.fromOriginalValue(this.props.items); - const defaultRows: IRow[] = repeatedItems.map(repeatedItem => { - - return { - id: repeatedItem.id, - renderItem: () => { - return this.renderRow(repeatedItem.id, repeatedItem.value); - }, - locked: this.props.itemRepeaterProps.isItemLocked ? this.props.itemRepeaterProps.isItemLocked(repeatedItem.value) : false - } - }); - - this.setState({ - defaultRows: defaultRows, - values: repeatedItems - }); - } - } - - private onRenderNewRow(id: string): IRow { - - const newRow = { - id: id, - renderItem: (didMount: boolean) => { - return this.renderRow(id, this.props.newRowDefaultObject(), didMount); - }, - locked: false // If we can create a row, it makes no sens to lock it - } as IRow; - - return newRow; - } - - private onRowDeleted(id: string): void { - - const fieldValues = this.state.values.filter(value => value.id !== id); - - this.setState({ - values: fieldValues - }); - - this.props.onChange(this.toOriginalValue(fieldValues)); - } - - public onRowAdded(id: string): void { - - if (this.props.onRowAdded) { - this.props.onRowAdded(id); - } - - } - - public onRowsOrderChanged(rows: IRow[]): void { - - // Updte the sort idx corresponding to that row - let fieldValues: IItemRepeaterValue[] = []; - - // Get the field values in the same order as rows - fieldValues = rows.map((row, i) => { - const filterConfiguration = this.state.values.filter(f => f.id === row.id)[0]; - return filterConfiguration; - }); - - this.setState( { - values: fieldValues - }); - - this.props.onRowsOrderChanged(this.toOriginalValue(fieldValues)); - } - - private onValueUpdated(fieldId: string, newValue?: T, errors?: Map): void { - - let fieldValues: IItemRepeaterValue[] = []; - - if (this.state.values.some(t => t.id === fieldId)) { - - fieldValues = this.state.values.map(value => { - if (value.id === fieldId) { - return { - id: value.id, - value: newValue - }; - } else { - return value; - } - }); - } else { - - fieldValues = [ - ...this.state.values, - { - id: fieldId, - value: newValue - } - ]; - } - - this.setState( { - values: fieldValues - }); - - this.props.onChange(this.toOriginalValue(fieldValues), errors); - } - - private fromOriginalValue(items: T[]) : IItemRepeaterValue[] { - - return items.map(item => { - return { - id: Guid.newGuid().toString(), - value: item - } - }); - } - - private toOriginalValue(items: IItemRepeaterValue[]): T[] { - return items.map(item => item.value); - } - - private renderRow(rowId: string, value: T, didMount?: boolean): React.ReactNode { - - // Determine if an existing value with this id already exists if the row already mounted - let dataObject; - const existingValue = this.state.values.filter(c => c.id === rowId); - if (existingValue.length > 0) { - dataObject = existingValue[0].value; - } - - return this.onValueUpdated(rowId, value,errors)} - />; - } - - -} \ No newline at end of file diff --git a/packages/spfx/src/controls/FormDataCollection/IFormDataCollectionProps.ts b/packages/spfx/src/controls/FormDataCollection/IFormDataCollectionProps.ts deleted file mode 100644 index 9ea3d23..0000000 --- a/packages/spfx/src/controls/FormDataCollection/IFormDataCollectionProps.ts +++ /dev/null @@ -1,68 +0,0 @@ -import { IConfigurationTabField } from "../ConfigurationPanel/IConfigurationTabField"; -import { IItemRepeaterSharedProps } from "../ItemRepeater/IItemRepeaterProps"; - -export interface IFormDataCollectionSharedProps { - - /** - * The item repeater props - */ - itemRepeaterProps?: Partial>; - - /** - * The field label to display - */ - label?: string - - /** - * Key to force a re render of the component and recreate rows from items. Useful if your default items are initialized in the parent componentDidMount method - */ - stateKey?: string; - - /** - * The form confirugration to display items - */ - formConfiguration: IConfigurationTabField[]; - - /** - * Flag indicating if form errors should be validated on load and the caller notified - */ - validateOnLoad?: boolean; - - /** - * Function returning a new instance of item of type T when a new row is added. New row fields will be initialized this this data. - * @returns the new object instance of type T - */ - newRowDefaultObject?: () => T; - - /** - * Default items to render - */ - items: T[]; - - /** - * Validates errors on the whole form related according ot the current data of type T - * @param value the object value - * @returns an empty string if no error, a relevant error message otherwise - */ - onGetErrorMessage?: (value: T[]) => string; - - /** - * Callback handler when a new row is added - * @param rowId the new row id - */ - onRowAdded?: (rowId: string) => void; - - - /*** - * Callback handler when the values are reorded - */ - onRowsOrderChanged?: (value: T[]) => void; -} - -export interface IFormDataCollectionProps extends IFormDataCollectionSharedProps { - - /*** - * Callback handler when the values are updated - */ - onChange: (value: T[], errors?: Map) => void; -} \ No newline at end of file diff --git a/packages/spfx/src/controls/FormDataCollection/IFormDataCollectionState.ts b/packages/spfx/src/controls/FormDataCollection/IFormDataCollectionState.ts deleted file mode 100644 index 8113d6e..0000000 --- a/packages/spfx/src/controls/FormDataCollection/IFormDataCollectionState.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { IItemRepeaterValue } from "../ItemRepeater/IItemRepeaterValue"; -import { IRow } from "../ItemRepeater/ItemRepeater"; - -export interface IFormDataCollectionState { - values: IItemRepeaterValue[]; - defaultRows: IRow[]; -} \ No newline at end of file diff --git a/packages/spfx/src/controls/ItemRepeater/IItemRepeaterProps.ts b/packages/spfx/src/controls/ItemRepeater/IItemRepeaterProps.ts deleted file mode 100644 index 197c53b..0000000 --- a/packages/spfx/src/controls/ItemRepeater/IItemRepeaterProps.ts +++ /dev/null @@ -1,82 +0,0 @@ -import { IRow, ItemRepeater } from "./ItemRepeater"; - -export enum IconPlacement { - Right, - Bottom -} - -export interface IItemRepeaterSharedProps { - - /** - * The label to display for the the add new row button - */ - addButtonLabel?: string; - - /** - * The label to display on the remove button - */ - removeButtonLabel?: string; - - /** - * Indicating if adding new rows is disabled - */ - disabled?: boolean; - - /** - * Add a separator between items. Only when removeButtonPlacement is "Bottom" - */ - separator?: boolean; - - /** - * Enable drag and drop on the repeater - */ - enableDragDrop?: boolean; - - /** - * The plcaement of the remove icon for the row (bottom or right) - */ - removeButtonPlacement?: IconPlacement; - - /** - * The inner ref to be abel to add/remove rows manually - */ - innerRef?: React.LegacyRef>; - - /** - * Callback function to determine if the current item should be locked when the row is created (no deletion). By default, the item can be deleted - * @param item the current item to process - * @returns true if locked, false otherwise - */ - isItemLocked?: (item: T) => boolean; -} - -export interface IItemRepeaterProps extends IItemRepeaterSharedProps { - - /** - * The default rows to display - */ - defaultRows?: IRow[]; - - /** - * Element to render when a new row is added - */ - onRenderNewRow?(rowId: string): IRow; - - /** - * Callback when a row is added - * @param row the row id added - */ - onRowAdded?(id: string): void; - - /** - * Callback when a row is deleted - * @param row the row id to delete - */ - onRowDeleted?(id: string): void; - - /** - * Callback handler when the rows order is updated. Index in the array represenst the new order - * @param rows - */ - onRowsOrderChanged?(rows: IRow[]): void; -} \ No newline at end of file diff --git a/packages/spfx/src/controls/ItemRepeater/IItemRepeaterState.ts b/packages/spfx/src/controls/ItemRepeater/IItemRepeaterState.ts deleted file mode 100644 index 97e677c..0000000 --- a/packages/spfx/src/controls/ItemRepeater/IItemRepeaterState.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { IRow } from "./ItemRepeater"; - -export interface IItemRepeaterState { - rows: IRow[]; - mountedRowIds: string[]; -} \ No newline at end of file diff --git a/packages/spfx/src/controls/ItemRepeater/IItemRepeaterValue.ts b/packages/spfx/src/controls/ItemRepeater/IItemRepeaterValue.ts deleted file mode 100644 index ea19c37..0000000 --- a/packages/spfx/src/controls/ItemRepeater/IItemRepeaterValue.ts +++ /dev/null @@ -1,8 +0,0 @@ -/** - * Represents an item with value of type T to repeat. - * Use this interface to track changes on data when rows are added or deleted - */ -export interface IItemRepeaterValue { - id: string; - value: T; -} \ No newline at end of file diff --git a/packages/spfx/src/controls/ItemRepeater/ItemRepeater.tsx b/packages/spfx/src/controls/ItemRepeater/ItemRepeater.tsx deleted file mode 100644 index 7b467aa..0000000 --- a/packages/spfx/src/controls/ItemRepeater/ItemRepeater.tsx +++ /dev/null @@ -1,258 +0,0 @@ -import * as React from "react"; -import { ActionButton, IconButton } from '@fluentui/react/lib/Button'; -import { isEqual } from "@microsoft/sp-lodash-subset"; -import { IItemRepeaterProps, IconPlacement } from "./IItemRepeaterProps"; -import { IItemRepeaterState } from "./IItemRepeaterState"; -import { DetailsList, Selection, IDragDropContext, IDragDropEvents, IStackTokens, MarqueeSelection, Separator, Stack, IColumn, CheckboxVisibility, SelectionMode, IStackItemStyles, Label } from "office-ui-fabric-react"; -import { Guid } from "@microsoft/sp-core-library"; - -export interface IRow { - /** - * Unique ID of the row - */ - id: string; - - /** - * Render function for a row. - * @param didMount Flag indicating if the row has already been mounted once. Useful to determine first usage scenario (ex: popup) - */ - renderItem(didMount?: boolean): React.ReactNode; - - - locked?: boolean; -} - -const stackTokens: IStackTokens = { childrenGap: 12 }; -const stackItemStyles: IStackItemStyles = { - root: { - display: 'flex', - alignItems: "center", - justifyContent: "space-between" - } -} - -export class ItemRepeater extends React.Component, IItemRepeaterState> { - - private _selection: Selection; - private _dragDropEvents: IDragDropEvents; - private _draggedItem: IRow | undefined; - private _draggedIndex: number; - - constructor(props: IItemRepeaterProps) { - super(props); - - this.state = { - rows: [], - mountedRowIds: [] - }; - - this._selection = new Selection(); - this._dragDropEvents = this._getDragDropEvents(); - this._draggedIndex = -1; - - this.addItemRow = this.addItemRow.bind(this); - this.deleteItemRow = this.deleteItemRow.bind(this); - } - - public componentDidMount(): void { - - if (this.props.defaultRows) { - this.setState({ - rows: [...this.props.defaultRows] - }); - } - } - - public componentDidUpdate(prevProps: Readonly>): void { - - if (!isEqual(prevProps.defaultRows, this.props.defaultRows)) { - this.setState({ - rows: [...this.props.defaultRows] - }); - } - } - - public render(): JSX.Element { - - const renderAddButton: JSX.Element = - {this.props.addButtonLabel ? this.props.addButtonLabel : "Add new item"} - ; - - let renderContent = - {this.state.rows.map(row => { - return this.renderRow(row); - })} - ; - - if (this.props.enableDragDrop) { - - const columns: IColumn[] = [ - { - key: "id", - name: '', - minWidth: 100, - styles: { - root: { - width: "100%" - } - } - } - ]; - - renderContent = - { - this.setState({ - mountedRowIds: [...this.state.mountedRowIds,row.id] - }); - }} - isHeaderVisible={false} - onRenderItemColumn={(row: IRow, index: number) => { - return {this.props.enableDragDrop ? : null}{this.renderRow(row)} - }} - /> - ; - } - - return <> - {renderContent} - {this.props.onRenderNewRow ? renderAddButton : null} - ; - } - - private renderRow(row: IRow): JSX.Element { - - const removeBtnIconProps = { iconName: 'Delete' }; - let renderRemoveBtn = this.deleteItemRow(row.id)} - />; - let isHorizontal = true; - if (this.props.removeButtonPlacement === IconPlacement.Bottom) { - isHorizontal = false; - renderRemoveBtn = this.deleteItemRow(row.id)} - > - {this.props.removeButtonLabel} - ; - } - - if (row.locked) { - renderRemoveBtn = ; - } - - return
- - - {row.renderItem(this.state.mountedRowIds.indexOf(row.id) !== -1)} - - - {renderRemoveBtn} - - - {this.props.separator && !isHorizontal ? - - : null - } -
; - } - - public addItemRow(): void { - - const id = Guid.newGuid().toString(); - - this.setState({ - rows: [ - ...this.state.rows, - this.props.onRenderNewRow(id) // Give an unique ID for that row - ] - }, () => { - if (this.props.onRowAdded) { - this.props.onRowAdded(id); - } - }); - } - - public deleteItemRow(id: string): void { - - this.setState({ - rows: this.state.rows.filter(i => i.id !== id) - }, () => { - if (this.props.onRowDeleted) { - this.props.onRowDeleted(id); - } - }); - } - - private _getDragDropEvents(): IDragDropEvents { - return { - canDrop: (dropContext?: IDragDropContext, dragContext?: IDragDropContext) => { - return true; - }, - canDrag: (item?: IRow) => { - return true; - }, - onDrop: (item?: IRow, event?: DragEvent) => { - if (this._draggedItem) { - this._insertBeforeItem(item); - } - }, - onDragStart: (item?: IRow, itemIndex?: number) => { - this._draggedItem = item; - this._draggedIndex = itemIndex; - }, - onDragEnd: (item?: IRow, event?: DragEvent) => { - this._draggedItem = undefined; - this._draggedIndex = -1; - }, - }; - } - - private _insertBeforeItem(item: IRow): void { - - const draggedItems = this._selection.isIndexSelected(this._draggedIndex) - ? (this._selection.getSelection() as IRow[]) - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - : [this._draggedItem!]; - - const insertIndex = this.state.rows.indexOf(item); - const items = this.state.rows.filter(itm => draggedItems.indexOf(itm) === -1); - - items.splice(insertIndex, 0, ...draggedItems); - - this.setState({ - rows: items - }, () => { - if (this.props.onRowsOrderChanged) { - this.props.onRowsOrderChanged(items); - } - }); - } -} \ No newline at end of file diff --git a/packages/spfx/src/controls/LayoutSlotField/ILayoutSlotFieldProps.ts b/packages/spfx/src/controls/LayoutSlotField/ILayoutSlotFieldProps.ts deleted file mode 100644 index d889ec1..0000000 --- a/packages/spfx/src/controls/LayoutSlotField/ILayoutSlotFieldProps.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { ILayoutSlot } from "../../models/common/ILayoutSlot"; - -export interface ILayoutSlotFieldProps { - defaultValue: ILayoutSlot; - onChange: (slot: ILayoutSlot) => void - dynamicValues: string[]; -} \ No newline at end of file diff --git a/packages/spfx/src/controls/LayoutSlotField/ILayoutSlotFieldState.ts b/packages/spfx/src/controls/LayoutSlotField/ILayoutSlotFieldState.ts deleted file mode 100644 index 3cc873b..0000000 --- a/packages/spfx/src/controls/LayoutSlotField/ILayoutSlotFieldState.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { ILayoutSlot } from "../../models/common/ILayoutSlot"; - -export interface ILayoutSlotFieldState { - slot: ILayoutSlot; -} \ No newline at end of file diff --git a/packages/spfx/src/controls/LayoutSlotField/LayoutSlotField.tsx b/packages/spfx/src/controls/LayoutSlotField/LayoutSlotField.tsx deleted file mode 100644 index 8649dcd..0000000 --- a/packages/spfx/src/controls/LayoutSlotField/LayoutSlotField.tsx +++ /dev/null @@ -1,100 +0,0 @@ -import * as React from "react"; -import { ILayoutSlotFieldProps } from "./ILayoutSlotFieldProps"; -import { ILayoutSlotFieldState } from "./ILayoutSlotFieldState"; -import { Dropdown, IDropdownOption, Stack, TextField, Toggle } from "office-ui-fabric-react"; -import { SlotType } from "../../models/common/ILayoutSlot"; -import { sortBy, uniqBy } from "@microsoft/sp-lodash-subset"; - -export class LayoutSlotField extends React.Component { - - constructor(props: ILayoutSlotFieldProps) { - super(props); - - this.state = { - slot: props.defaultValue - }; - } - - public render(): React.ReactNode { - const fieldsOptions = this.props.dynamicValues?.map(value => { - return { key: value, text: value} - }); - - const options = sortBy(uniqBy([ - { - key: this.state.slot.slotValue, - text: this.state.slot.slotValue - }, - ...fieldsOptions - ], 'key'), 'key'); - - return <> - - { - const slot = {...this.state.slot}; - slot.slotName = newValue; - this.setState({ - slot:slot - }, () => { - this.props.onChange(slot); - }); - }} - /> - {this.state.slot.slotType === SlotType.DynamicField ? - { - const slot = {...this.state.slot}; - slot.slotValue = option.key as SlotType; - this.setState({ - slot:slot - }, () => { - this.props.onChange(slot); - }); - - }} - /> - : - { - const slot = {...this.state.slot}; - slot.slotValue = newValue; - this.setState({ - slot:slot - }, () => { - this.props.onChange(slot); - }); - }} - /> - } - { - const slot = {...this.state.slot}; - slot.slotType = checked ? SlotType.DynamicField : SlotType.RawValue - this.setState({ - slot:slot - }, () => { - this.props.onChange(slot); - }); - - }} - /> - - ; - - } -} \ No newline at end of file diff --git a/packages/spfx/src/controls/LocalizedTextField/ILocalizedFieldProps.ts b/packages/spfx/src/controls/LocalizedTextField/ILocalizedFieldProps.ts deleted file mode 100644 index c94e51a..0000000 --- a/packages/spfx/src/controls/LocalizedTextField/ILocalizedFieldProps.ts +++ /dev/null @@ -1,36 +0,0 @@ -import { ServiceScope } from "@microsoft/sp-core-library"; -import { ILocalizedString } from "@pnp/modern-search-core/dist/es6/models/common/ILocalizedString"; - -export interface ILocalizedFieldProps { - - /** - * SPFx service scope to resolve services - */ - serviceScope: ServiceScope; - - /** - * Label of the field - */ - label?: string; - - /** - * The default value for this field - */ - defaultValue?: string | ILocalizedString; - - /** - * Callback handler when the field value is updated - * @param value The new value - */ - onChange: (value: string | ILocalizedString) => void; - - /** - * Error - */ - onGetErrorMessage?: (value: string) => string; - - /** - * If the field is required - */ - required?: boolean; -} \ No newline at end of file diff --git a/packages/spfx/src/controls/LocalizedTextField/ILocalizedFieldState.ts b/packages/spfx/src/controls/LocalizedTextField/ILocalizedFieldState.ts deleted file mode 100644 index 65d0a89..0000000 --- a/packages/spfx/src/controls/LocalizedTextField/ILocalizedFieldState.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { ILocalizedString } from "@pnp/modern-search-core/dist/es6/models/common/ILocalizedString"; -import { ITranslation } from "./components/ITranslation"; - -export interface ILocalizedFieldState { - - /** - * State key to force a re-render and recreation of all rows - */ - stateKey: string; - - /** - * Current field value - */ - fieldValue: string | ILocalizedString; - - /** - * The default translation for currnet locale - */ - defaultTranslation: string; - - /** - * List of additional translations if any - */ - additionalTranslations: ITranslation[]; -} \ No newline at end of file diff --git a/packages/spfx/src/controls/LocalizedTextField/LocalizedField.tsx b/packages/spfx/src/controls/LocalizedTextField/LocalizedField.tsx deleted file mode 100644 index d9e7766..0000000 --- a/packages/spfx/src/controls/LocalizedTextField/LocalizedField.tsx +++ /dev/null @@ -1,215 +0,0 @@ -import * as React from "react"; -import { ILocalizedFieldProps } from "./ILocalizedFieldProps"; -import { ILocalizedFieldState } from "./ILocalizedFieldState"; -import { IDropdownOption, TextField } from "office-ui-fabric-react"; -import { Guid } from "@microsoft/sp-core-library"; -import { TranslationField } from "./components/TranslationField"; -import { ILocalizedString } from "@pnp/modern-search-core/dist/es6/models/common/ILocalizedString"; -import { LocalizedStringHelper } from "@pnp/modern-search-core/dist/es6/helpers/LocalizedStringHelper"; -import { ILocalizationService } from "../../services/localizationService/ILocalizationService"; -import { LocalizationService } from "../../services/localizationService/LocalizationService"; -import { PageContext } from "@microsoft/sp-page-context"; -import { ITranslation } from "./components/ITranslation"; - -import { ConfigurationFieldType } from "../ConfigurationPanel/IConfigurationTabField"; -import { FormDataCollection } from "../FormDataCollection/FormDataCollection"; - -export class LocalizedField extends React.Component { - - private localizationService: ILocalizationService; - private pageContext: PageContext; - - /** - * The list of all available locales in the site - */ - private availableLocales: IDropdownOption[] = []; - - constructor(props: ILocalizedFieldProps) { - - super(props); - - this.state = { - defaultTranslation: null, - fieldValue: null, - additionalTranslations: [], - stateKey: null - }; - - this.onDefaultTranslationUpdated = this.onDefaultTranslationUpdated.bind(this); - this.onAdditionalTranslationsUpdated = this.onAdditionalTranslationsUpdated.bind(this); - - this.props.serviceScope.whenFinished(() => { - this.localizationService = this.props.serviceScope.consume(LocalizationService.ServiceKey); - this.pageContext = this.props.serviceScope.consume(PageContext.serviceKey); - }); - } - - public async componentDidMount(): Promise { - - await this.initSupportedLanguages(); - this.initializeState(); - } - - private initializeState(): void { - - if (LocalizedStringHelper.isLocalizedString(this.props.defaultValue)) { - - const translationFieldValues: ITranslation[] = this.getTranslations(this.props.defaultValue as ILocalizedString); - - this.setState({ - defaultTranslation: (this.props.defaultValue as ILocalizedString).default, - additionalTranslations: translationFieldValues, - stateKey: Guid.newGuid().toString() // Used to force recreating item repeater rows from initialized items - }); - - } else { - - this.setState({ - defaultTranslation: this.props.defaultValue as string - }); - } - } - - public render(): React.ReactNode { - - let defaultTranslationValue: string; - const disabled: boolean = this.availableLocales && !this.availableLocales.some(locale => !this.state.additionalTranslations.some(t => t.locale === locale.key)); - - if (LocalizedStringHelper.isLocalizedString(this.props.defaultValue)) { - defaultTranslationValue = (this.props.defaultValue as ILocalizedString).default; - } else { - defaultTranslationValue = this.props.defaultValue as string; - } - - const disabledLocales = this.state.additionalTranslations.map(t => t.locale); - const renderLanguages = - stateKey={this.state.stateKey} - items={this.state.additionalTranslations} - itemRepeaterProps={{ - disabled: disabled, - addButtonLabel: "Add new translation" - }} - formConfiguration={[ - { - type: ConfigurationFieldType.Custom, - targetProperty: null, - onCustomRender: (field, defaultValue, onUpdate) => { - return { - onUpdate(field, value); - }} - />; - } - } - ]} - newRowDefaultObject={() => { - return { - locale: "", - value: "" - } - }} - onChange={this.onAdditionalTranslationsUpdated} - />; - - const renderControl =
-
- -
-
- {renderLanguages} -
-
; - - return renderControl; - - } - - private onDefaultTranslationUpdated(event: React.FormEvent, newValue?: string): void { - - let fieldValue: string | ILocalizedString = newValue; - - if (this.state.additionalTranslations.length > 0) { - fieldValue = this.toLocalizedString(newValue, this.state.additionalTranslations); - } - - this.setState({ - defaultTranslation: newValue, - fieldValue: fieldValue - }); - - this.props.onChange(fieldValue); - } - - private onAdditionalTranslationsUpdated(translations: ITranslation[]): void { - - let fieldValue: string | ILocalizedString = this.state.defaultTranslation; - - if (translations.length > 0) { - fieldValue = this.toLocalizedString(this.state.defaultTranslation, translations); - } - - this.setState({ - additionalTranslations: translations, - fieldValue: fieldValue - }); - - this.props.onChange(fieldValue); - } - - private async initSupportedLanguages(): Promise { - const supportedLocales = await this.localizationService.getSiteSupportedLocales(); - this.availableLocales = supportedLocales.map(locale => { - return { - key: locale, - text: locale, - disabled: false - }; - }); - } - - private toLocalizedString(defaultTranslation: string, otherTranslations: ITranslation[]): ILocalizedString { - - let localizedStrings = {}; - [...otherTranslations].forEach(translation => { - localizedStrings = Object.assign(localizedStrings, { [translation.locale]: translation.value }) - }); - - return { - default: defaultTranslation, - ...localizedStrings - } - } - - private getTranslations(localizedString: ILocalizedString): ITranslation[] { - - return Object.keys(localizedString).filter(k => k !== 'default').map(key => { - - return { - locale: key, - value: localizedString[key] - }; - }); - - } -} \ No newline at end of file diff --git a/packages/spfx/src/controls/LocalizedTextField/components/ITranslation.ts b/packages/spfx/src/controls/LocalizedTextField/components/ITranslation.ts deleted file mode 100644 index 0760c89..0000000 --- a/packages/spfx/src/controls/LocalizedTextField/components/ITranslation.ts +++ /dev/null @@ -1,12 +0,0 @@ -export interface ITranslation { - - /** - * The translation locale - */ - locale: string; - - /** - * The translation value - */ - value: string; -} \ No newline at end of file diff --git a/packages/spfx/src/controls/LocalizedTextField/components/ITranslationFieldProps.ts b/packages/spfx/src/controls/LocalizedTextField/components/ITranslationFieldProps.ts deleted file mode 100644 index c0a0278..0000000 --- a/packages/spfx/src/controls/LocalizedTextField/components/ITranslationFieldProps.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { IDropdownOption } from "office-ui-fabric-react"; -import { ITranslation } from "./ITranslation"; - -export interface ITranslationFieldProps { - - /** - * The list of supported locales to display - */ - supportedLocales: IDropdownOption[]; - - /** - * Disabled option keys if nay - */ - disabledLocales?: string[]; - - /** - * The default value - */ - defaultValue?: ITranslation; - - /** - * Callback handler when the translation is updated - * @param value the new value - */ - onChange: (value: ITranslation) => void; -} \ No newline at end of file diff --git a/packages/spfx/src/controls/LocalizedTextField/components/ITranslationFieldState.ts b/packages/spfx/src/controls/LocalizedTextField/components/ITranslationFieldState.ts deleted file mode 100644 index ac1ef44..0000000 --- a/packages/spfx/src/controls/LocalizedTextField/components/ITranslationFieldState.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { ITranslation } from "./ITranslation"; - -export interface ITranslationFieldState { - translation: ITranslation; -} \ No newline at end of file diff --git a/packages/spfx/src/controls/LocalizedTextField/components/TranslationField.tsx b/packages/spfx/src/controls/LocalizedTextField/components/TranslationField.tsx deleted file mode 100644 index 2653d9b..0000000 --- a/packages/spfx/src/controls/LocalizedTextField/components/TranslationField.tsx +++ /dev/null @@ -1,106 +0,0 @@ -import * as React from "react"; -import { ITranslationFieldState } from "./ITranslationFieldState"; -import { ComboBox, IComboBox, IComboBoxOption, TextField } from "office-ui-fabric-react"; -import { ITranslationFieldProps } from "./ITranslationFieldProps"; - -//#region Fluent UI styles -const comboBoxStyles = { - container: { - maxWidth: 80, - } -}; - -const textFieldStyles = { - wrapper: { - borderLeft: "none" - } -}; -//#endregion - -export class TranslationField extends React.Component { - - constructor(props: ITranslationFieldProps) { - - super(props); - - this.state = { - translation: { - locale: null, - value: null - } - }; - - this.onResolveOptions = this.onResolveOptions.bind(this); - this.onLocaleChange = this.onLocaleChange.bind(this); - this.onTranslationValueChange = this.onTranslationValueChange.bind(this); - } - - public componentDidMount(): void { - - if (this.props.defaultValue) { - this.setState({ - translation: this.props.defaultValue - }); - } - } - - public render(): React.ReactNode { - - return
- - -
; - } - - private onResolveOptions(options: IComboBoxOption[]): IComboBoxOption[] { - - if (this.props.disabledLocales && this.props.disabledLocales.length > 0) { - return options.map(option => { - option.disabled = this.props.disabledLocales.indexOf(option.key as string) !== -1; - return option; - }); - } - - return options; - } - - private onLocaleChange(event: React.FormEvent, option?: IComboBoxOption, index?: number, value?: string): void { - - this.setState({ - translation: { - locale: option.key as string, - value: this.state.translation.value - } - }); - - if (option.key && this.state.translation.value) { - this.props.onChange(this.state.translation); - } - } - - private onTranslationValueChange(event: React.FormEvent, newValue?: string): void { - - const updatedTranslation = { - locale: this.state.translation.locale, - value: newValue - }; - - this.setState({ - translation: updatedTranslation - }); - - if (this.state.translation.locale && newValue) { - this.props.onChange(updatedTranslation); - } - } -} \ No newline at end of file diff --git a/packages/spfx/src/controls/WebPartPlaceholder/WebPartPlaceholder.tsx b/packages/spfx/src/controls/WebPartPlaceholder/WebPartPlaceholder.tsx deleted file mode 100644 index 46114f3..0000000 --- a/packages/spfx/src/controls/WebPartPlaceholder/WebPartPlaceholder.tsx +++ /dev/null @@ -1,20 +0,0 @@ -import * as React from "react"; -import * as commonStrings from "CommonStrings"; - -export interface IWebPartPlaceholderProps { - description: string; - documentationLink: string; -} - -export default class WebPartPlaceholder extends React.Component { - - public render(): React.ReactElement { - - return ; - } - -} \ No newline at end of file diff --git a/packages/spfx/src/controls/WebPartPlaceholder/logo.svg b/packages/spfx/src/controls/WebPartPlaceholder/logo.svg deleted file mode 100644 index 85da0c2..0000000 --- a/packages/spfx/src/controls/WebPartPlaceholder/logo.svg +++ /dev/null @@ -1,1043 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/packages/spfx/src/datasources/MicrosoftSearchDataSource.tsx b/packages/spfx/src/datasources/MicrosoftSearchDataSource.tsx deleted file mode 100644 index 5d3dba4..0000000 --- a/packages/spfx/src/datasources/MicrosoftSearchDataSource.tsx +++ /dev/null @@ -1,737 +0,0 @@ -import { IPropertyPaneField, IPropertyPaneGroup, PropertyPaneCheckbox, PropertyPaneSlider, PropertyPaneChoiceGroup, PropertyPaneDynamicField, PropertyPaneHorizontalRule, PropertyPaneLabel, PropertyPaneTextField, PropertyPaneToggle, PropertyPaneDropdown, IPropertyPaneDropdownProps } from "@microsoft/sp-property-pane"; -import { BaseDataSource } from "../models/common/BaseDataSource"; -import { IChoiceGroupProps, IComboBoxOption, ITextFieldProps, IToggleProps } from "@fluentui/react"; -import * as sourceStrings from 'MicrosoftSearchDataSourceStrings'; -import { DynamicProperty } from "@microsoft/sp-component-base"; -import { intersection, isEmpty, isEqual } from "@microsoft/sp-lodash-subset"; -import { ServiceScope } from "@microsoft/sp-core-library"; -import { EntityType, IQueryAlterationOptions } from "@pnp/modern-search-core/dist/es6/models/search/IMicrosoftSearchRequest"; -import IDynamicDataService from "../services/dynamicDataService/IDynamicDataService"; -import { DynamicDataService } from "../services/dynamicDataService/DynamicDataService"; -import { ComponentType } from "../common/ComponentType"; -import { ConfigurationFieldType, IConfigurationTabField } from "../controls/ConfigurationPanel/IConfigurationTabField"; -import { PropertyPaneCombobox } from "../propertyPane/PropertyPaneCombobox/PropertyPaneCombobox"; -import { PropertyPaneFormDataCollection } from "../propertyPane/PropertyPaneFormDataCollection/PropertyPaneFormDataCollection"; -import { PropertyPaneNonReactiveTextField } from "../propertyPane/PropertyPaneNonReactiveTextField/PropertyPaneNonReactiveTextField"; -import { ISortFieldConfiguration, SortFieldDirection } from "@pnp/modern-search-core/dist/es6/models/common/ISortFieldConfiguration"; -import * as React from "react"; -import { ConfigurationPanel } from "../controls/ConfigurationPanel/ConfigurationPanel"; -import { IConfigurationTab } from "../controls/ConfigurationPanel/IConfigurationTab"; -import { ILocalizedFieldProps } from "../controls/LocalizedTextField/ILocalizedFieldProps"; -import { ItemRepeater } from "../controls/ItemRepeater/ItemRepeater"; - -export enum QueryTextSource { - StaticValue, - DynamicValue -} - -export enum QueryMode { - Basic, - Advanced -} - -export interface IPagingSettings { - - /** - * Flag indicating if the pagniation control should be displayed - */ - showPaging: boolean; - - /** - * The number of pages to display in the pagination control - */ - numberOfPagesToDisplay: number; - - /** - * The number of results to show per results page - */ - pageSize: number; -} - -export interface IExternalContentSource { - id: string; -} - -export interface IMicrosoftSearchDataSourceProperties { - - /** - * Flag indicating if a default query text should be applied - */ - useDefaultQueryText: boolean; - - /** - * The input query text to pass to the data source - */ - queryText: DynamicProperty; - - /** - * The default query text to apply - */ - defaultQueryText: string; - - /** - * Indicates ifthe query text comes from a static or dynamic value - */ - queryTextSource: QueryTextSource; - - /** - * The search query template - */ - queryTemplate: string; - - /** - * The entity types to search - */ - entityTypes: EntityType[]; - - /** - * If "entityTypes" contains "externalItem", specify the connection ids of the external sources - */ - contentSources: string[]; - - /** - * Search managed properties to retrieve for results and usable in the results template. - * Comma separated. Refer to the [Microsoft Search API documentation](https://learn.microsoft.com/en-us/graph/api/resources/search-api-overview?view=graph-rest-1.0&preserve-view=true#scope-search-based-on-entity-types) to know what properties can be used according to entity types. - */ - selectedFields: string[]; - - /** - * The query building mode - */ - queryMode: QueryMode; - - /** - * Paging settings - */ - paging: IPagingSettings; - - /** - * Flag indicating if the beta endpoint for Microsoft Graph API should be used - */ - useBetaEndpoint: boolean; - - /** - * Flag indicating if Micrsoft Search result types should be applied in results - */ - enableResultTypes: boolean; - - /** - * The query alteration options for spelling corrections - */ - queryAlterationOptions: IQueryAlterationOptions; - - /** - * Determines if the Web Part should use filters component connection - */ - useFilters: boolean; - - /** - * Dynamic data connection references for filters - */ - filtersDataSourceReference: string; - - /** - * Sort properties for the request - */ - sortFieldsConfiguration?: ISortFieldConfiguration[]; -} - -export class MicrosoftSearchDataSource extends BaseDataSource { - - private _entityTypeOptions: IComboBoxOption[] = [ - { - key: EntityType.Message, - text: "Messages", - disabled: false - }, - { - key: EntityType.Event, - text: "Events", - disabled: false - }, - { - key: EntityType.Drive, - text: "Drive", - disabled: false - }, - { - key: EntityType.DriveItem, - text: "Drive Items", - disabled: false - }, - { - key: EntityType.ExternalItem, - text: "External Items", - disabled: false - }, - { - key: EntityType.ListItem, - text: "List Items", - disabled: false - }, - { - key: EntityType.List, - text: "List", - disabled: false - }, - { - key: EntityType.Site, - text: "Sites", - disabled: false - }, - { - key: EntityType.Person, - text: "People" - }, - { - key: EntityType.TeamsMessage, - text: "Teams messages" - }, - { - key: EntityType.Bookmark, - text: "Bookmarks" - }, - { - key: EntityType.Acronym, - text: "Acronyms" - } - ]; - - // https://learn.microsoft.com/en-us/graph/api/resources/search-api-overview?view=graph-rest-1.0#known-limitations - private _entityTypesExclusions: Map = new Map( - [ - [EntityType.Bookmark, [EntityType.Bookmark]], - [EntityType.Acronym, [EntityType.Acronym]], - [EntityType.Person, [EntityType.Person]], - [EntityType.Message, [EntityType.Message]], - [EntityType.TeamsMessage, [EntityType.TeamsMessage]], - [EntityType.Event, [EntityType.Event]], - [EntityType.Drive, [EntityType.Drive,EntityType.DriveItem,EntityType.ExternalItem,EntityType.ListItem,EntityType.List,EntityType.Site]], - [EntityType.DriveItem, [EntityType.Drive,EntityType.DriveItem,EntityType.ExternalItem,EntityType.ListItem,EntityType.List,EntityType.Site]], - [EntityType.ExternalItem, [EntityType.Drive,EntityType.DriveItem,EntityType.ExternalItem,EntityType.ListItem,EntityType.List,EntityType.Site]], - [EntityType.List, [EntityType.Drive,EntityType.DriveItem,EntityType.ExternalItem,EntityType.ListItem,EntityType.List,EntityType.Site]], - [EntityType.ListItem, [EntityType.Drive,EntityType.DriveItem,EntityType.ExternalItem,EntityType.ListItem,EntityType.List,EntityType.Site]], - [EntityType.Site, [EntityType.Drive,EntityType.DriveItem,EntityType.ExternalItem,EntityType.ListItem,EntityType.List,EntityType.Site]], - ] - ); - - private _selectedFieldsOptions : IComboBoxOption[] = []; - - /** - * The dynamic data service instance - */ - private dynamicDataService: IDynamicDataService; - - /** - * Property pane fields - */ - // eslint-disable-next-line @typescript-eslint/no-explicit-any - private _propertyFieldNumber: any = null; - private propertyPaneFiltersConnectionField: IPropertyPaneField; - - private _itemRepeaterRef = React.createRef>(); - private _lastCreatedConfigurationPanelRef: React.RefObject> = null; - private _lastRowId: string; - - public constructor(serviceScope: ServiceScope) { - super(serviceScope); - - serviceScope.whenFinished(() => { - this.dynamicDataService = serviceScope.consume(DynamicDataService.ServiceKey); - }); - } - - public async onInit(): Promise { - - this.initializeProperties(); - - await this.loadPropertyPaneResources(); - } - - public async onPropertyPaneFieldChanged(propertyPath: string, oldValue: unknown, newValue: unknown) : Promise { - - // Remove the connection when static query text or unused - if ((propertyPath.localeCompare('queryTextSource') === 0 && this.properties.queryTextSource === QueryTextSource.StaticValue) || - (propertyPath.localeCompare('queryTextSource') === 0 && oldValue === QueryTextSource.StaticValue && newValue === QueryTextSource.DynamicValue)) { - - this.properties.queryText.setValue(''); - this.render(); - } - - if (this.properties.queryTextSource === QueryTextSource.StaticValue - || !this.properties.useDefaultQueryText) { - // Reset the default query text - this.properties.defaultQueryText = undefined; - } - - if (propertyPath.localeCompare('contentSources') === 0) { - this.properties.contentSources = this.properties.contentSources.map(v => `/external/connections/${v}`); - } - - // Refresh list of available connections - this.propertyPaneFiltersConnectionField = await this.getFiltersConnectionField(); - this.context.propertyPane.refresh(); - } - - public getPropertyPaneGroupsConfiguration(): IPropertyPaneGroup[] { - - return [ - this.getQuerySettingsGroup(), - this.getAdvancedSettings(), - this.getPagingSettings() - ] - } - - private getQuerySettingsGroup(): IPropertyPaneGroup { - - const groupFields: IPropertyPaneField[] = [ - - PropertyPaneChoiceGroup('queryMode', { - options: [ - { - key: QueryMode.Basic, - text: sourceStrings.PropertyPane.QuerySettingsGroup.QueryMode.BasicMode, - disabled: true - }, - { - key: QueryMode.Advanced, - text: sourceStrings.PropertyPane.QuerySettingsGroup.QueryMode.AdvancedMode, - } - ] - }) - ]; - - switch (this.properties.queryMode) { - - case QueryMode.Basic: - // Show query builder - groupFields.push( - PropertyPaneHorizontalRule() - ); - break; - - case QueryMode.Advanced: - groupFields.push( - PropertyPaneHorizontalRule(), - new PropertyPaneCombobox('entityTypes', { - label: sourceStrings.PropertyPane.QuerySettingsGroup.SearchEntityTypeFieldLabel, - options: this._entityTypeOptions, - onResolveOptions: (options: IComboBoxOption[]) => { - - // Determine what entity types are allowed according to exclusions list and current selected values - const allowedFromExclusions = this.properties.entityTypes.length > 0 ? intersection(this.properties.entityTypes.map(entity => this._entityTypesExclusions.get(entity))[0]) : this._entityTypeOptions.map(e => e.key); - return options.map(option => { - option.disabled = allowedFromExclusions.indexOf(option.key as EntityType) === -1 - return option; - }); - }, - defaultSelectedKey: this.properties.entityTypes, - useComboBoxAsMenuWidth: true, - multiSelect: true - }), - ...this.getSearchQueryTextFields(), - new PropertyPaneNonReactiveTextField('queryTemplate', { - componentKey: "microsoftSearch-queryTemplate", - defaultValue: this.properties.queryTemplate, - label: sourceStrings.PropertyPane.QuerySettingsGroup.SearchQueryTemplateFieldLabel, - placeholderText: sourceStrings.PropertyPane.QuerySettingsGroup.SearchQueryTemplatePlaceHolderText, - multiline: true, - description: sourceStrings.PropertyPane.QuerySettingsGroup.SearchQueryTemplateFieldDescription, - applyBtnText: sourceStrings.PropertyPane.QuerySettingsGroup.SearchQueryQueryTemplateApplyBtnText, - allowEmptyValue: false, - rows: 8 - }) - ); - break; - - default: - break; - } - - const getErrorMessage = (value: string): string => { - return !isEmpty(value) ? '' : sourceStrings.PropertyPane.QuerySettingsGroup.FieldTextErrorMessage ; - }; - - - if (this.properties.entityTypes.indexOf(EntityType.ExternalItem) !== -1) { - groupFields.splice(3, 0, new PropertyPaneFormDataCollection('contentSources', { - label: sourceStrings.PropertyPane.QuerySettingsGroup.SearchContentSourcesFieldLabel, - itemRepeaterProps: { - addButtonLabel: sourceStrings.PropertyPane.QuerySettingsGroup.SearchContentSourcesAddNewBtnLabel, - }, - items: this.properties.contentSources, - newRowDefaultObject: () => "", - formConfiguration: [ - { - type: ConfigurationFieldType.TextField, - targetProperty: null, - props: { - onGetErrorMessage: getErrorMessage - } as ITextFieldProps - } - ], - })); - } - - return { - - groupName: sourceStrings.PropertyPane.QuerySettingsGroup.GroupName, - groupFields: groupFields - }; - } - - private getAdvancedSettings(): IPropertyPaneGroup { - - const advancedGroupFields = [ - new PropertyPaneCombobox('selectedFields', { - label: sourceStrings.PropertyPane.AdvancedSettingsGroup.SearchSelectedFieldsFieldLabel, - options: this._selectedFieldsOptions, - onValueChange: (options: IComboBoxOption[]) => { - this._selectedFieldsOptions = options; - }, - useComboBoxAsMenuWidth: true, - allowFreeform: true, - autoComplete: 'on', - placeholder: sourceStrings.PropertyPane.AdvancedSettingsGroup.SearchSelectedFieldsPlaceholderLabel, - multiSelect: true, - }), - PropertyPaneToggle('useFilters', { - label: sourceStrings.PropertyPane.AdvancedSettingsGroup.SearchFiltersUseFiltersFieldLabel, - checked: this.properties.useFilters - }), - this.getSearchSortConfigurationField(), - PropertyPaneToggle('enableResultTypes', { - label: sourceStrings.PropertyPane.AdvancedSettingsGroup.SearchEnableResultTypesFieldLabel, - checked: this.properties.enableResultTypes - }), - PropertyPaneToggle('useBetaEndpoint', { - label: sourceStrings.PropertyPane.AdvancedSettingsGroup.SearchUseBetaEndpointFieldLabel - }), - /*PropertyPaneToggle('queryAlterationOptions.enableSuggestion', { - label: sourceStrings.PropertyPane.AdvancedSettingsGroup.SearchEnableSuggestionFieldLabel, - checked: this.properties.queryAlterationOptions.enableSuggestion - }),*/ - PropertyPaneToggle('queryAlterationOptions.enableModification', { - label: sourceStrings.PropertyPane.AdvancedSettingsGroup.SearchEnableModificationFieldLabel, - checked: this.properties.queryAlterationOptions.enableModification - }) - ]; - - if (this.properties.useFilters) { - advancedGroupFields.splice(2, 0, this.propertyPaneFiltersConnectionField); - } - - return { - groupName: sourceStrings.PropertyPane.AdvancedSettingsGroup.GroupName, - groupFields: advancedGroupFields, - isCollapsed: false - } - } - - private getPagingSettings(): IPropertyPaneGroup { - - return { - groupName: sourceStrings.PropertyPane.PagingSettingsGroup.GroupName, - groupFields: [ - PropertyPaneToggle('paging.showPaging', { - label: sourceStrings.PropertyPane.PagingSettingsGroup.SearchShowPagingFieldLabel, - }), - this._propertyFieldNumber('paging.pageSize', { - label: sourceStrings.PropertyPane.PagingSettingsGroup.SearchPageSizeFieldLabel, - maxValue: 500, - minValue: 1, - deferredValidationTime: 500, - value: this.properties.paging.pageSize, - disabled: !this.properties.paging.showPaging, - key: 'paging.pageSize' - }), - PropertyPaneSlider('paging.numberOfPagesToDisplay', { - label: sourceStrings.PropertyPane.PagingSettingsGroup.SearchPagesNumberFieldLabel, - max: 20, - min: 1, // 0 = no page numbers displayed - step: 1, - showValue: true, - value: this.properties.paging.numberOfPagesToDisplay, - disabled: !this.properties.paging.showPaging - }) - ], - isCollapsed: false - } - } - - private getSearchQueryTextFields(): IPropertyPaneField[] { - - const searchQueryTextFields: IPropertyPaneField[] = [ - - PropertyPaneLabel('', { - text: sourceStrings.PropertyPane.QuerySettingsGroup.SearchQueryTextFieldLabel - }) - ]; - - searchQueryTextFields.push( - - PropertyPaneChoiceGroup('queryTextSource', { - options: [ - { - key: QueryTextSource.StaticValue, - text: sourceStrings.PropertyPane.QuerySettingsGroup.SearchQueryTextStaticValue - }, - { - key: QueryTextSource.DynamicValue, - text: sourceStrings.PropertyPane.QuerySettingsGroup.SearchQueryTextDynamicValue - } - ] - }) - ); - - switch (this.properties.queryTextSource) { - - case QueryTextSource.StaticValue: - searchQueryTextFields.push( - PropertyPaneTextField('queryText', { - label: '', - description: sourceStrings.PropertyPane.QuerySettingsGroup.SearchQueryTextFieldDescription, - multiline: true, - resizable: true, - placeholder: sourceStrings.PropertyPane.QuerySettingsGroup.SearchQueryPlaceHolderText, - onGetErrorMessage: this._validateEmptyField.bind(this), - deferredValidationTime: 500 - }) - ); - break; - - case QueryTextSource.DynamicValue: - searchQueryTextFields.push( - - // Workaround: save the value in the root dynamic property of the Web Part (the default value won't be saved otherwise after a page refresh) - PropertyPaneDynamicField('queryText', { - label: '', - }), - PropertyPaneCheckbox('useDefaultQueryText', { - text: sourceStrings.PropertyPane.QuerySettingsGroup.SearchQueryTextUseDefaultQuery, - disabled: this.properties.queryText.reference === undefined - }) - ); - - if (this.properties.useDefaultQueryText && this.properties.queryText.reference !== undefined) { - searchQueryTextFields.push( - PropertyPaneTextField('defaultQueryText', { - label: sourceStrings.PropertyPane.QuerySettingsGroup.SearchQueryTextDefaultValue, - multiline: true - }) - ); - } - - break; - - default: - break; - } - - return searchQueryTextFields; - } - - private getSearchSortConfigurationField(): IPropertyPaneField { - - const getErrorMessage = (value: string): string => { - return !isEmpty(value) ? '' : sourceStrings.PropertyPane.QuerySettingsGroup.FieldTextErrorMessage; - }; - - const newSortFieldConfiguration: ISortFieldConfiguration = { - isDefaultSort: false, - isUserSort: false, - sortDirection: SortFieldDirection.Ascending, - sortField: "", - sortFieldDisplayName: "" - }; - - const sortFieldTabConfiguration: IConfigurationTab[] = [ - { - name: "General", - fields: [ - { - type: ConfigurationFieldType.TextField, - props: { - label: sourceStrings.PropertyPane.AdvancedSettingsGroup.SortFieldLabel, - required: true, - onGetErrorMessage: getErrorMessage, - } as Partial, - targetProperty: "sortField", - }, - { - type: ConfigurationFieldType.ChoiceGroup, - props: { - label: sourceStrings.PropertyPane.AdvancedSettingsGroup.SortDirectionLabel, - options: [{key: SortFieldDirection.Ascending, text: "Ascending"},{key: SortFieldDirection.Descending, text: "Descending"}] - } as Partial, - targetProperty: "sortDirection" - }, - { - type: ConfigurationFieldType.Toggle, - props: { - label: sourceStrings.PropertyPane.AdvancedSettingsGroup.IsDefaultSort, - } as Partial, - targetProperty: "isDefaultSort" - }, - { - type: ConfigurationFieldType.Toggle, - props: { - label: sourceStrings.PropertyPane.AdvancedSettingsGroup.IsUserSort, - } as Partial, - targetProperty: "isUserSort" - }, - { - type: ConfigurationFieldType.LocalizedField, - props: { - serviceScope: this.context.serviceScope, - label: sourceStrings.PropertyPane.AdvancedSettingsGroup.SortDisplayName, - onGetErrorMessage: getErrorMessage, - required: true, - } as Partial, - targetProperty: "sortFieldDisplayName", - isVisible: (dataObject: ISortFieldConfiguration) => { - return dataObject.isUserSort; - } - }, - ] - }, - ]; - - const mainFormFields: IConfigurationTabField[] = [ - { - type: ConfigurationFieldType.Custom, - targetProperty: null, - onCustomRender: (field, defaultValue, onUpdate) => { - - this._lastCreatedConfigurationPanelRef = React.createRef>(); - - return - ref={this._lastCreatedConfigurationPanelRef} - configurationTabs={sortFieldTabConfiguration} - renderRowTitle={(sortField: ISortFieldConfiguration) => { return sortField.sortField }} - onFormSave={(formData) => { onUpdate(field, formData)}} - dataObject={defaultValue} - renderPanelTitle={() => sourceStrings.PropertyPane.AdvancedSettingsGroup.AddNewSortPropertyLabel} - onFormDismissed={(configuration: ISortFieldConfiguration) => { - if (isEqual(configuration, newSortFieldConfiguration)) { - // Remove row as no item has been saved - this._itemRepeaterRef.current.deleteItemRow(this._lastRowId) - } - }} - />; - } - } - ]; - - return new PropertyPaneFormDataCollection('sortFieldsConfiguration', { - label: sourceStrings.PropertyPane.AdvancedSettingsGroup.SortPropertiesCategory, - itemRepeaterProps: { - innerRef: this._itemRepeaterRef, - addButtonLabel: sourceStrings.PropertyPane.AdvancedSettingsGroup.AddNewSortPropertyLabel, - enableDragDrop: true - }, - items: this.properties.sortFieldsConfiguration, - newRowDefaultObject: () => newSortFieldConfiguration, - formConfiguration: mainFormFields, - onRowAdded: (rowId: string) => { - // Save the row id to be able to delete it afterwards - this._lastRowId = rowId; - // Get the last created row (empty at this point) and open the panel - this._lastCreatedConfigurationPanelRef.current.togglePanel(); - }, - onRowsOrderChanged: (value: ISortFieldConfiguration[]) => { - this.properties.sortFieldsConfiguration = value; - this.render() - } - }); - } - - private initializeProperties(): void { - - // Initialize dynamic properties - if (!this.properties.queryText) { - this.properties.queryText = new DynamicProperty(this.context.dynamicDataProvider); - this.properties.queryText.setValue(''); - } - - this.properties.queryTextSource = this.properties.queryTextSource ? this.properties.queryTextSource : QueryTextSource.StaticValue; - this.properties.queryTemplate = this.properties.queryTemplate ? this.properties.queryTemplate : "{searchTerms}"; - - this.properties.queryMode = this.properties.queryMode !== undefined ? this.properties.queryMode : QueryMode.Advanced; - - this.properties.entityTypes = this.properties.entityTypes !== undefined ? this.properties.entityTypes : [EntityType.ListItem]; - this.properties.contentSources = this.properties.contentSources !== undefined ? this.properties.contentSources : []; - - this.properties.selectedFields = this.properties.selectedFields !== undefined ? this.properties.selectedFields : [ - "name", - "webUrl", - "title", - "summary", - "created", - "createdBy", - "filetype", - "defaultEncodingURL", - "lastModifiedTime", - "lastModifiedDateTime", - "modifiedBy", - "path", - "hitHighlightedSummary", - "SPSiteURL", - "SiteTitle", - "thumbnailUrl", - "normSiteID", - "normUniqueID", - "normListID", - "lastModifiedBy", - "displayName", - "description" - ]; - this._selectedFieldsOptions = this.properties.selectedFields.map(field => { return {key: field, text: field, selected: true}}); - - this.properties.useBetaEndpoint = this.properties.useBetaEndpoint !== undefined ? this.properties.useBetaEndpoint : false; - this.properties.queryAlterationOptions = this.properties.queryAlterationOptions ?? { enableModification: false, enableSuggestion: false }; - - if (!this.properties.paging) { - - this.properties.paging = { - pageSize: 10, - numberOfPagesToDisplay: 5, - showPaging: true, - }; - } - - this.properties.sortFieldsConfiguration = this.properties.sortFieldsConfiguration !== undefined ? this.properties.sortFieldsConfiguration: []; - } - - public async loadPropertyPaneResources(): Promise { - - const { PropertyFieldNumber } = await import( - /* webpackChunkName: 'pnp-modern-search-core-property-pane' */ - '@pnp/spfx-property-controls/lib/PropertyFieldNumber' - ); - - this._propertyFieldNumber = PropertyFieldNumber; - this.propertyPaneFiltersConnectionField = await this.getFiltersConnectionField(); - } - - /** - * Checks if a field if empty or not - * @param value the value to check - */ - private _validateEmptyField(value: string): string { - - if (!value) { - return sourceStrings.General.EmptyFieldErrorMessage; - } - - return ''; - } - - private async getFiltersConnectionField(): Promise> { - - return PropertyPaneDropdown('filtersDataSourceReference', { - options: await this.dynamicDataService.getAvailableDataSourcesByType(ComponentType.SearchFilters), - label: sourceStrings.PropertyPane.AdvancedSettingsGroup.SearchFiltersFieldsFieldLabel - }); - } -} \ No newline at end of file diff --git a/packages/spfx/src/datasources/loc/en-us.js b/packages/spfx/src/datasources/loc/en-us.js deleted file mode 100644 index 1c8edee..0000000 --- a/packages/spfx/src/datasources/loc/en-us.js +++ /dev/null @@ -1,57 +0,0 @@ -/* eslint-disable no-undef */ -define([], function() { - return { - General: { - EmptyFieldErrorMessage: "This field cannot be empty", - }, - PropertyPane: { - QuerySettingsGroup: { - GroupName: "Query settings", - QueryMode: { - BasicMode: "Basic mode (coming soon...)", - AdvancedMode: "Advanced mode" - }, - SearchQueryTextStaticValue: "Static value", - SearchQueryTextDynamicValue: "Dynamic value", - SearchQueryTextFieldLabel: "Query text", - SearchQueryTextFieldDescription: "", - SearchQueryPlaceHolderText: "Enter query text...", - SearchQueryTextUseDefaultQuery: "Use a default value", - SearchQueryTextDefaultValue: "Default value", - SearchEntityTypeFieldLabel: "Entity types", - SearchQueryTemplateFieldLabel: "Query template", - SearchQueryTemplatePlaceHolderText: "ex: Path:{Site}", - SearchQueryTemplateFieldDescription: "The search query template. You can also use {} to build a dynamic query.", - SearchQueryQueryTemplateApplyBtnText: "Apply", - SearchContentSourcesFieldLabel: "Content sources", - SearchContentSourcesAddNewBtnLabel: "Add new connection id", - SearchContentSourcesPlaceholderLabel: "Enter connection(s) id(s)...", - FieldTextErrorMessage: "Field must have a value" - }, - AdvancedSettingsGroup: { - GroupName: "AdvancedSettings", - SearchSelectedFieldsFieldLabel: "Fields", - SearchSelectedFieldsPlaceholderLabel: "Enter field(s) name...", - SearchEnableResultTypesFieldLabel: "Enable result types", - SearchUseBetaEndpointFieldLabel: "Use beta endpoint", - SearchEnableSuggestionFieldLabel: "Enable suggestions", - SearchEnableModificationFieldLabel: "Enable modifications", - SearchFiltersFieldsFieldLabel: "Get filters configuration from this Web Part", - SearchFiltersUseFiltersFieldLabel: "Use filters/sort", - SortFieldLabel: "Sort field", - SortDirectionLabel: "Sort direction", - IsDefaultSort: "Is default sort", - IsUserSort: "Is user sort", - SortDisplayName: "Display name", - SortPropertiesCategory: "Sort properties", - AddNewSortPropertyLabel: "Add new sort property" - }, - PagingSettingsGroup: { - GroupName: "Paging settings", - SearchPageSizeFieldLabel: "Page size", - SearchPagesNumberFieldLabel: "Number of pages to show", - SearchShowPagingFieldLabel: "Show paging" - } - } - } -}) \ No newline at end of file diff --git a/packages/spfx/src/datasources/loc/strings.d.ts b/packages/spfx/src/datasources/loc/strings.d.ts deleted file mode 100644 index 40bd689..0000000 --- a/packages/spfx/src/datasources/loc/strings.d.ts +++ /dev/null @@ -1,59 +0,0 @@ -declare interface IMicrosoftSearchDataSourceStrings { - General: { - EmptyFieldErrorMessage: string; - }, - PropertyPane: { - QuerySettingsGroup: { - GroupName: string; - QueryMode: { - BasicMode: string; - AdvancedMode: string; - }, - SearchQueryTextStaticValue: string; - SearchQueryTextDynamicValue: string; - SearchQueryTextFieldLabel: string; - SearchQueryTextFieldDescription: string; - SearchQueryPlaceHolderText: string; - SearchQueryTextUseDefaultQuery: string; - SearchQueryTextDefaultValue: string; - SearchEntityTypeFieldLabel: string; - SearchQueryTemplateFieldLabel: string; - SearchQueryTemplatePlaceHolderText: string; - SearchQueryTemplateFieldDescription: string; - SearchQueryQueryTemplateApplyBtnText: string; - SearchContentSourcesFieldLabel: string; - SearchContentSourcesAddNewBtnLabel: string; - SearchContentSourcesPlaceholderLabel: string; - FieldTextErrorMessage: string; - }, - AdvancedSettingsGroup: { - GroupName: string; - SearchSelectedFieldsFieldLabel: string; - SearchSelectedFieldsPlaceholderLabel: string; - SearchEnableResultTypesFieldLabel: string; - SearchUseBetaEndpointFieldLabel: string; - SearchEnableSuggestionFieldLabel: string; - SearchEnableModificationFieldLabel: string; - SearchFiltersFieldsFieldLabel: string; - SearchFiltersUseFiltersFieldLabel: string; - SortFieldLabel: string; - SortDirectionLabel: string; - IsDefaultSort: string; - IsUserSort: string; - SortDisplayName: string; - SortPropertiesCategory: string; - AddNewSortPropertyLabel: string; - } - PagingSettingsGroup: { - GroupName: string; - SearchPageSizeFieldLabel: string; - SearchPagesNumberFieldLabel: string; - SearchShowPagingFieldLabel: string; - } - } -} - -declare module 'MicrosoftSearchDataSourceStrings' { - const strings: IMicrosoftSearchDataSourceStrings; - export = strings; -} diff --git a/packages/spfx/src/helpers/DynamicPropertyHelper.ts b/packages/spfx/src/helpers/DynamicPropertyHelper.ts deleted file mode 100644 index 82a41b0..0000000 --- a/packages/spfx/src/helpers/DynamicPropertyHelper.ts +++ /dev/null @@ -1,43 +0,0 @@ -import { DynamicProperty } from '@microsoft/sp-component-base'; - -export class DynamicPropertyHelper { - /** - * Returns the value of the property or undefined - * @param property the property - */ - // eslint-disable-next-line @typescript-eslint/no-explicit-any - public static tryGetValueSafe(property: DynamicProperty): any { - if (!property) return undefined; - if (property.isDisposed) return undefined; - try { - return property.tryGetValue(); - } catch (error) { - return undefined; - } - } - - /** - * Returns the values of the property or undefined - * @param property the property - */ - // eslint-disable-next-line @typescript-eslint/no-explicit-any - public static tryGetValuesSafe(property: DynamicProperty): any[] { - if (!property) return undefined; - if (property.isDisposed) return undefined; - try { - return property.tryGetValues(); - } catch (error) { - return undefined; - } - } - - public static tryGetSourceSafe(property: DynamicProperty): unknown { - if (!property) return undefined; - if (property.isDisposed) return undefined; - try { - return property.tryGetSource(); - } catch (error) { - return undefined; - } - } -} \ No newline at end of file diff --git a/packages/spfx/src/helpers/LayoutHelper.ts b/packages/spfx/src/helpers/LayoutHelper.ts deleted file mode 100644 index 8b141c4..0000000 --- a/packages/spfx/src/helpers/LayoutHelper.ts +++ /dev/null @@ -1,193 +0,0 @@ - -import { ServiceKey, ServiceScope } from '@microsoft/sp-core-library'; -import { ServiceScopeHelper } from './ServiceScopeHelper'; -import { IPropertyPaneChoiceGroupOption, IPropertyPaneField, PropertyPaneToggle } from '@microsoft/sp-property-pane'; -import { WebPartContext } from '@microsoft/sp-webpart-base'; -import { BuiltinLayoutsKeys } from '../layouts/AvailableLayouts'; -import { ILayout } from '../models/common/ILayout'; -import { ILayoutDefinition } from '../models/common/ILayoutDefinition'; -import { ILayoutSlot } from '../models/common/ILayoutSlot'; -import { IBaseWebPartProps } from '../models/common/IBaseWebPartProps'; - -export class LayoutHelper { - - /** - * Gets the layout instance according to the current selected one - * @param rootScope the root service scope - * @param context the Web Part context - * @param properties the web part properties (only supported Web Parts) - * @param layoutKey the selected layout key - * @param layoutDefinitions the available layout definitions - * @returns the data source provider instance - */ - public static async getLayoutInstance(rootScope: ServiceScope, context: WebPartContext, properties: IBaseWebPartProps, layoutKey: string, layoutDefinitions: ILayoutDefinition[]): Promise { - - let layout: ILayout = undefined; - let serviceKey: ServiceKey = undefined; - - if (layoutKey) { - - // If it is a builtin layout, we load the corresponding known class file asynchronously for performance purpose - // We also create the service key at the same time to be able to get an instance - switch (layoutKey) { - - // Results Default - case BuiltinLayoutsKeys.ResultsDefault: { - - const { ResultsDefaultLayout } = await import( - /* webpackChunkName: 'pnp-modern-search-core-results-list-layout' */ - '../layouts/results/simpleList/ResultsDefaultLayout' - ); - - serviceKey = ServiceKey.create('ModernSearchCoreResultsDefaultLayout', ResultsDefaultLayout); - break; - } - - // Results Custom - case BuiltinLayoutsKeys.ResultsCustom: { - - const { ResultsCustomLayout } = await import( - /* webpackChunkName: 'pnp-modern-search-core-results-custom-layout' */ - '../layouts/results/custom/ResultsCustomLayout' - ); - - serviceKey = ServiceKey.create('ModernSearchCoreResultsCustomLayout', ResultsCustomLayout); - break; - } - - - // Results Tiles - case BuiltinLayoutsKeys.ResultsTiles: { - - const { ResultsTilesLayout } = await import( - /* webpackChunkName: 'pnp-modern-search-core-results-tiles-layout' */ - '../layouts/results/tiles/ResultsTilesLayout' - ); - - serviceKey = ServiceKey.create('ModernSearchCoreResultsTilesLayout', ResultsTilesLayout); - break; - } - - // Filters Default - case BuiltinLayoutsKeys.FiltersDefault: { - - const { FiltersDefaultLayout } = await import( - /* webpackChunkName: 'pnp-modern-search-core-filters-default-layout' */ - '../layouts/filters/default/FiltersDefaultLayout' - ); - - serviceKey = ServiceKey.create('ModernSearchCoreFiltersDefaultLayout', FiltersDefaultLayout); - break; - } - - // Filters Custom - case BuiltinLayoutsKeys.FiltersCustom: { - - const { FiltersCustomLayout } = await import( - /* webpackChunkName: 'pnp-modern-search-core-filters-custom-layout' */ - '../layouts/filters/custom/FiltersCustomLayout' - ); - - serviceKey = ServiceKey.create('ModernSearchCoreFiltersCustomLayout', FiltersCustomLayout); - break; - } - - // Verticals Default - case BuiltinLayoutsKeys.VerticalsDefault: { - - const { VerticalsDefaultLayout } = await import( - /* webpackChunkName: 'pnp-modern-search-core-verticals-default-layout' */ - '../layouts/verticals/default/VerticalsDefaultLayout' - ); - - serviceKey = ServiceKey.create('ModernSearchCoreVerticalsDefaultLayout', VerticalsDefaultLayout); - break; - } - - // Verticals Custom - case BuiltinLayoutsKeys.VerticalsCustom: { - - const { VerticalsCustomLayout } = await import( - /* webpackChunkName: 'pnp-modern-search-core-verticals-custom-layout' */ - '../layouts/verticals/custom/VerticalsCustomLayout' - ); - - serviceKey = ServiceKey.create('ModernSearchCoreVerticalsCustomLayout', VerticalsCustomLayout); - break; - } - } - - return new Promise((resolve, reject) => { - - // Register the layout service in the Web Part scope only (child scope of the current scope) - const childServiceScope = ServiceScopeHelper.registerChildServices(rootScope, [serviceKey]); - - childServiceScope.whenFinished(async () => { - - layout = childServiceScope.consume(serviceKey); - - // Initialize the layout with current Web Part properties - if (layout) { - layout.properties = properties.layoutProperties; // Web Parts using layouts must define this sub property - layout.context = context; - await layout.onInit(); - resolve(layout); - } - }); - }); - } - } - - /** - * Builds the layout options list from available layouts - */ - public static getLayoutOptions(availableLayoutDefinitions: ILayoutDefinition[]): IPropertyPaneChoiceGroupOption[] { - - const layoutOptions: IPropertyPaneChoiceGroupOption[] = []; - - availableLayoutDefinitions.forEach((layout) => { - layoutOptions.push({ - iconProps: { - officeFabricIconFontName: layout.iconName - }, - imageSize: { - width: 200, - height: 100 - }, - key: layout.key, - text: layout.name, - }); - }); - - return layoutOptions; - } - - /** - * Converts the configured template slots to an hashtable to be used in the Handlebars templates - * @param templateSlots the configured template slots - */ - public static convertTemplateSlotsToHashtable(layoutSlots: ILayoutSlot[]): { [key: string]: string } { - - // Transform the slots as an hashtable for the HB templates (easier to manipulate rather than a full object) - const slots: { [key: string]: string } = {}; - - if (layoutSlots) { - layoutSlots.forEach(layoutSlot => { - slots[layoutSlot.slotName] = layoutSlot.slotValue; - }); - } - - return slots; - } - - public static getCommonLayoutsOptionFields(properties: T): IPropertyPaneField[] { - - const commonFields: IPropertyPaneField[] = [ - PropertyPaneToggle('showResultsCount', { - label: "Show result count", - }) - ]; - - return commonFields; - } -} \ No newline at end of file diff --git a/packages/spfx/src/helpers/ServiceScopeHelper.ts b/packages/spfx/src/helpers/ServiceScopeHelper.ts deleted file mode 100644 index f86956e..0000000 --- a/packages/spfx/src/helpers/ServiceScopeHelper.ts +++ /dev/null @@ -1,44 +0,0 @@ -import { ServiceScope, ServiceKey } from '@microsoft/sp-core-library'; - -export class ServiceScopeHelper { - - /** - * Registers new services within a child scope of the specified root scope - * @param serviceKey the service keys of services to register in that scope - */ - public static registerChildServices(rootScope: ServiceScope, serviceKeys: ServiceKey[]): ServiceScope { - - let childScope: ServiceScope = null; - - if (rootScope) { - - childScope = rootScope.startNewChild(); - serviceKeys.forEach(serviceKey => { - childScope.createDefaultAndProvide(serviceKey); - }); - - childScope.finish(); - } - - return childScope; - } - - /** - * Gets the top root service scope from a child scope - * @param scope a child service scope - * @returns - */ - public static getRootServiceScope(scope: ServiceScope): ServiceScope { - - let rootServiceScope; - - let parentScope = scope.getParent(); - - while (parentScope !== undefined) { - rootServiceScope = parentScope; - parentScope = parentScope.getParent(); - } - - return rootServiceScope; - } -} \ No newline at end of file diff --git a/packages/spfx/src/index.ts b/packages/spfx/src/index.ts deleted file mode 100644 index fb81db1..0000000 --- a/packages/spfx/src/index.ts +++ /dev/null @@ -1 +0,0 @@ -// A file is required to be in the root of the /src directory by the TypeScript compiler diff --git a/packages/spfx/src/layouts/AvailableLayouts.ts b/packages/spfx/src/layouts/AvailableLayouts.ts deleted file mode 100644 index 2704562..0000000 --- a/packages/spfx/src/layouts/AvailableLayouts.ts +++ /dev/null @@ -1,85 +0,0 @@ -/* eslint-disable @typescript-eslint/no-var-requires */ -import { ILayoutDefinition, LayoutRenderType, LayoutType } from "../models/common/ILayoutDefinition"; -import * as strings from 'CommonStrings'; - -export enum BuiltinLayoutsKeys { - ResultsDefault = 'ResultsDefault', - ResultsCustom = 'ResultsCustom', - ResultsTiles = 'ResultsTiles', - FiltersDefault = 'FiltersDefault', - FiltersCustom = 'FiltersCustom', - VerticalsDefault = 'VerticalsDefault', - VerticalsCustom = 'VerticalsCustom' -} - -export class AvailableLayouts { - - /** - * Returns the list of builtin layouts for the Search Results - */ - public static BuiltinLayouts: ILayoutDefinition[] = [ - { - name: strings.Layouts.Default.Name, - key: BuiltinLayoutsKeys.ResultsDefault.toString(), - iconName: 'AppIconDefault', - type: LayoutType.Results, - templateContent: require('./results/simpleList/default.html'), - renderType: LayoutRenderType.Html, - serviceKey: null // ServiceKey will be created dynamically for builtin layout - }, - { - name: "Tiles", - key: BuiltinLayoutsKeys.ResultsTiles.toString(), - iconName: 'Tiles', - type: LayoutType.Results, - templateContent: require('./results/tiles/results-tiles.html'), - renderType: LayoutRenderType.Html, - serviceKey: null // ServiceKey will be created dynamically for builtin layout - }, - { - name: strings.Layouts.Custom.Name, - key: BuiltinLayoutsKeys.ResultsCustom.toString(), - iconName: 'CodeEdit', - type: LayoutType.Results, - templateContent: require('./results/custom/results-custom.html'), - renderType: LayoutRenderType.Html, - serviceKey: null // ServiceKey will be created dynamically for builtin layout - }, - { - name: strings.Layouts.Default.Name, - key: BuiltinLayoutsKeys.FiltersDefault.toString(), - iconName: 'AppIconDefault', - type: LayoutType.Filters, - templateContent: require('./filters/default/default.html'), - renderType: LayoutRenderType.Html, - serviceKey: null // ServiceKey will be created dynamically for builtin layout - }, - { - name: strings.Layouts.Custom.Name, - key: BuiltinLayoutsKeys.FiltersCustom.toString(), - iconName: 'CodeEdit', - type: LayoutType.Filters, - templateContent: require('./filters/custom/filters-custom.html'), - renderType: LayoutRenderType.Html, - serviceKey: null // ServiceKey will be created dynamically for builtin layout - }, - { - name: strings.Layouts.Default.Name, - key: BuiltinLayoutsKeys.VerticalsDefault.toString(), - iconName: 'AppIconDefault', - type: LayoutType.Verticals, - templateContent: require('./verticals/default/default.html'), - renderType: LayoutRenderType.Html, - serviceKey: null // ServiceKey will be created dynamically for builtin layout - }, - { - name: strings.Layouts.Custom.Name, - key: BuiltinLayoutsKeys.VerticalsCustom.toString(), - iconName: 'CodeEdit', - type: LayoutType.Verticals, - templateContent: require('./verticals/custom/verticals-custom.html'), - renderType: LayoutRenderType.Html, - serviceKey: null // ServiceKey will be created dynamically for builtin layout - } - ]; -} \ No newline at end of file diff --git a/packages/spfx/src/layouts/filters/custom/FiltersCustomLayout.ts b/packages/spfx/src/layouts/filters/custom/FiltersCustomLayout.ts deleted file mode 100644 index 959bf3e..0000000 --- a/packages/spfx/src/layouts/filters/custom/FiltersCustomLayout.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { IPropertyPaneField } from "@microsoft/sp-property-pane"; -import { BaseLayout } from "../../../models/common/BaseLayout"; -import { ServiceScope } from "@microsoft/sp-core-library"; -import { ILayoutProps } from "../../../models/common/ILayout"; - -export interface IFiltersCustomLayoutProperties extends ILayoutProps { -} - -export class FiltersCustomLayout extends BaseLayout { - - constructor(serviceScope: ServiceScope) { - super(serviceScope); - } - - public getPropertyPaneFieldsConfiguration(availableFields: string[]): IPropertyPaneField[] { - - return [ - ] - } -} \ No newline at end of file diff --git a/packages/spfx/src/layouts/filters/custom/filters-custom.html b/packages/spfx/src/layouts/filters/custom/filters-custom.html deleted file mode 100644 index dc284d4..0000000 --- a/packages/spfx/src/layouts/filters/custom/filters-custom.html +++ /dev/null @@ -1,14 +0,0 @@ - - - \ No newline at end of file diff --git a/packages/spfx/src/layouts/filters/default/FiltersDefaultLayout.ts b/packages/spfx/src/layouts/filters/default/FiltersDefaultLayout.ts deleted file mode 100644 index e58e499..0000000 --- a/packages/spfx/src/layouts/filters/default/FiltersDefaultLayout.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { IPropertyPaneField } from "@microsoft/sp-property-pane"; -import { BaseLayout } from "../../../models/common/BaseLayout"; -import { ServiceScope } from "@microsoft/sp-core-library"; -import { ILayoutProps } from "../../../models/common/ILayout"; - -export interface IFiltersDefaultLayoutProperties extends ILayoutProps { -} - -export class FiltersDefaultLayout extends BaseLayout { - - constructor(serviceScope: ServiceScope) { - super(serviceScope); - } - - public getPropertyPaneFieldsConfiguration(availableFields: string[]): IPropertyPaneField[] { - - return [ - ] - } -} \ No newline at end of file diff --git a/packages/spfx/src/layouts/filters/default/default.html b/packages/spfx/src/layouts/filters/default/default.html deleted file mode 100644 index af0621c..0000000 --- a/packages/spfx/src/layouts/filters/default/default.html +++ /dev/null @@ -1,22 +0,0 @@ - \ No newline at end of file diff --git a/packages/spfx/src/layouts/results/custom/ResultsCustomLayout.ts b/packages/spfx/src/layouts/results/custom/ResultsCustomLayout.ts deleted file mode 100644 index 29d33dd..0000000 --- a/packages/spfx/src/layouts/results/custom/ResultsCustomLayout.ts +++ /dev/null @@ -1,47 +0,0 @@ -import { IPropertyPaneField } from "@microsoft/sp-property-pane"; -import { BaseLayout } from "../../../models/common/BaseLayout"; -import { BuiltinTemplateSlots, ILayoutSlot, SlotType } from "../../../models/common/ILayoutSlot"; -import { ServiceScope } from "@microsoft/sp-core-library"; -import { ILayoutProps } from "../../../models/common/ILayout"; - -export interface IResultsCustomLayoutProperties extends ILayoutProps { -} - -export class ResultsCustomLayout extends BaseLayout { - - constructor(serviceScope: ServiceScope) { - super(serviceScope); - - this._defaultSlots = [ - { - slotName: BuiltinTemplateSlots.Title, - slotValue: 'resource.fields.title', - slotType: SlotType.DynamicField, - }, - { - slotName: BuiltinTemplateSlots.Path, - slotValue: 'resource.webUrl', - slotType: SlotType.DynamicField, - }, - { - slotName: BuiltinTemplateSlots.Summary, - slotValue: 'summary', - slotType: SlotType.DynamicField - }, - { - slotName: BuiltinTemplateSlots.FileType, - slotValue: 'resource.fields.filetype', - slotType: SlotType.DynamicField - } - ]; - } - - public getPropertyPaneFieldsConfiguration(availableFields: string[]): IPropertyPaneField[] { - - return [ - this.getPropertyPaneSlotField(availableFields, false, (item: ILayoutSlot) => { - return false; - }) - ] - } -} \ No newline at end of file diff --git a/packages/spfx/src/layouts/results/custom/results-custom.html b/packages/spfx/src/layouts/results/custom/results-custom.html deleted file mode 100644 index d328f57..0000000 --- a/packages/spfx/src/layouts/results/custom/results-custom.html +++ /dev/null @@ -1,32 +0,0 @@ - - - \ No newline at end of file diff --git a/packages/spfx/src/layouts/results/simpleList/ResultsDefaultLayout.tsx b/packages/spfx/src/layouts/results/simpleList/ResultsDefaultLayout.tsx deleted file mode 100644 index 8546a1c..0000000 --- a/packages/spfx/src/layouts/results/simpleList/ResultsDefaultLayout.tsx +++ /dev/null @@ -1,61 +0,0 @@ -import { IPropertyPaneField } from "@microsoft/sp-property-pane"; -import { BaseLayout } from "../../../models/common/BaseLayout"; -import { BuiltinTemplateSlots, ILayoutSlot, SlotType } from "../../../models/common/ILayoutSlot"; -import { ServiceScope } from "@microsoft/sp-core-library"; -import { ILayoutProps } from "../../../models/common/ILayout"; - -export interface IResultsDefaultLayoutProperties extends ILayoutProps{ -} - -export class ResultsDefaultLayout extends BaseLayout { - - - constructor(serviceScope: ServiceScope) { - super(serviceScope); - - this._defaultSlots = [ - { - slotName: BuiltinTemplateSlots.Title, - slotValue: 'resource.fields.title', - slotType: SlotType.DynamicField, - disabled: true - }, - { - slotName: BuiltinTemplateSlots.Path, - slotValue: 'resource.webUrl', - slotType: SlotType.DynamicField, - disabled: true - }, - { - slotName: BuiltinTemplateSlots.Summary, - slotValue: 'summary', - slotType: SlotType.DynamicField, - disabled: true - }, - { - slotName: BuiltinTemplateSlots.FileType, - slotValue: 'resource.fields.filetype', - slotType: SlotType.DynamicField, - disabled: true - }, - { - slotName: "ACVideoUrl", - slotValue: "", - slotType: SlotType.RawValue, - disabled: true - } - ]; - } - - - public getPropertyPaneFieldsConfiguration(availableFields: string[]): IPropertyPaneField[] { - - const isItemLocked = (item: ILayoutSlot): boolean => { - return this._defaultSlots.map(s => s.slotName).indexOf(item.slotName) !== -1; - }; - - return [ - this.getPropertyPaneSlotField(availableFields, true, isItemLocked) - ] - } -} \ No newline at end of file diff --git a/packages/spfx/src/layouts/results/simpleList/default.html b/packages/spfx/src/layouts/results/simpleList/default.html deleted file mode 100644 index 0460523..0000000 --- a/packages/spfx/src/layouts/results/simpleList/default.html +++ /dev/null @@ -1,36 +0,0 @@ - - - \ No newline at end of file diff --git a/packages/spfx/src/layouts/results/tiles/ResultsTilesLayout.tsx b/packages/spfx/src/layouts/results/tiles/ResultsTilesLayout.tsx deleted file mode 100644 index 46e127d..0000000 --- a/packages/spfx/src/layouts/results/tiles/ResultsTilesLayout.tsx +++ /dev/null @@ -1,162 +0,0 @@ -import { IPropertyPaneDropdownOption, IPropertyPaneField, PropertyPaneDropdown, PropertyPaneDropdownOptionType, PropertyPaneSlider } from "@microsoft/sp-property-pane"; -import { BaseLayout } from "../../../models/common/BaseLayout"; -import { BuiltinTemplateSlots, ILayoutSlot, SlotType } from "../../../models/common/ILayoutSlot"; -import { ServiceScope } from "@microsoft/sp-core-library"; -import { ILayoutProps } from "../../../models/common/ILayout"; -import * as commonStrings from "CommonStrings"; - -export interface IResultsTilesLayoutProperties extends ILayoutProps { - - /** - * The prefered number of cards per row per sizes (Small, Medium, Large, Extra Large, Extra Extra Large) - * Corresponds to TailwindCSS container queries breakpoints https://github.com/tailwindlabs/tailwindcss-container-queries?tab=readme-ov-file#configuration - */ - mdCardNumberPerRow: number; - smCardNumberPerRow: number; - lgCardNumberPerRow: number; - xlCardNumberPerRow: number; - xxlCardNumberPerRow: number; - - /** - * The container width - */ - containerWidth: string; -} - -export class ResultsTilesLayout extends BaseLayout { - - - constructor(serviceScope: ServiceScope) { - super(serviceScope); - - this._defaultSlots = [ - { - slotName: BuiltinTemplateSlots.Title, - slotValue: 'title', - slotType: SlotType.DynamicField, - disabled: true - }, - { - slotName: "Subtitle", - slotValue: "", - slotType: SlotType.DynamicField, - disabled: true - }, - { - slotName: BuiltinTemplateSlots.Path, - slotValue: 'resource.webUrl', - slotType: SlotType.DynamicField, - disabled: true - }, - { - slotName: BuiltinTemplateSlots.Summary, - slotValue: 'summary', - slotType: SlotType.DynamicField, - disabled: true - }, - { - slotName: BuiltinTemplateSlots.FileType, - slotValue: 'filetype', - slotType: SlotType.DynamicField, - disabled: true - }, - { - slotName: "Thumbnail_Url", - slotValue: 'thumbnailUrl', - slotType: SlotType.DynamicField, - disabled: true - }, - { - slotName: "Main_Category", - slotValue: "", - slotType: SlotType.RawValue, - disabled: true - }, - { - slotName: "Secondary_Category", - slotValue: "", - slotType: SlotType.RawValue, - disabled: true - }, - { - slotName: "Tags", - slotValue: "", - slotType: SlotType.RawValue, - disabled: true - }, - { - slotName: "Image_Tag", - slotValue: "", - slotType: SlotType.RawValue, - disabled: true - } - ]; - } - - public async onInit(): Promise { - - this.properties.smCardNumberPerRow = this.properties.smCardNumberPerRow ? this.properties.smCardNumberPerRow : 1; - this.properties.mdCardNumberPerRow = this.properties.mdCardNumberPerRow ? this.properties.mdCardNumberPerRow : 2; - this.properties.lgCardNumberPerRow = this.properties.lgCardNumberPerRow ? this.properties.lgCardNumberPerRow : 3; - this.properties.xlCardNumberPerRow = this.properties.xlCardNumberPerRow ? this.properties.xlCardNumberPerRow : 4; - this.properties.xxlCardNumberPerRow = this.properties.xxlCardNumberPerRow ? this.properties.xxlCardNumberPerRow : 5; - - this.properties.containerWidth = this.properties.containerWidth ? this.properties.containerWidth : "md"; - - return super.onInit(); - } - - public getPropertyPaneFieldsConfiguration(availableFields: string[]): IPropertyPaneField[] { - - const isItemLocked = (item: ILayoutSlot): boolean => { - return this._defaultSlots.map(s => s.slotName).indexOf(item.slotName) !== -1; - }; - - const propertyName = `${this.properties.containerWidth}CardNumberPerRow`; - const containerWidthOptions: IPropertyPaneDropdownOption[] = [ - { - key: "", - text: commonStrings.Layouts.ResultsTiles.ContainerWidthOptionsFieldLabel, - type: PropertyPaneDropdownOptionType.Header - }, - { - key: "sm", - text: commonStrings.Layouts.ResultsTiles.SmallWidth - }, - { - key: "md", - text: commonStrings.Layouts.ResultsTiles.MediumWidth, - }, - { - key: "lg", - text: commonStrings.Layouts.ResultsTiles.LargeWidth, - }, - { - key: "xl", - text: commonStrings.Layouts.ResultsTiles.ExtraLargeWidth, - }, - { - key: "xxl", - text: commonStrings.Layouts.ResultsTiles.ExtraExtraLargeWidth - } - ]; - - return [ - PropertyPaneDropdown('layoutProperties.containerWidth', { - label: commonStrings.Layouts.ResultsTiles.ContainerWidthFieldLabel, - options: containerWidthOptions, - selectedKey: this.properties.containerWidth - }), - PropertyPaneSlider(`layoutProperties.${propertyName}`, { - label: `${containerWidthOptions.filter(f => f.key === this.properties.containerWidth)[0]?.text} - Number of cards to show`, - min: 1, - max: 5, - step: 1, - showValue: true, - // eslint-disable-next-line @typescript-eslint/no-explicit-any - value: (this.properties as any)[propertyName] - }), - this.getPropertyPaneSlotField(availableFields, true, isItemLocked) - ] - } -} \ No newline at end of file diff --git a/packages/spfx/src/layouts/results/tiles/results-tiles.html b/packages/spfx/src/layouts/results/tiles/results-tiles.html deleted file mode 100644 index 41ff65d..0000000 --- a/packages/spfx/src/layouts/results/tiles/results-tiles.html +++ /dev/null @@ -1,26 +0,0 @@ - \ No newline at end of file diff --git a/packages/spfx/src/layouts/verticals/custom/VerticalsCustomLayout.ts b/packages/spfx/src/layouts/verticals/custom/VerticalsCustomLayout.ts deleted file mode 100644 index 7e8072d..0000000 --- a/packages/spfx/src/layouts/verticals/custom/VerticalsCustomLayout.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { IPropertyPaneField } from "@microsoft/sp-property-pane"; -import { BaseLayout } from "../../../models/common/BaseLayout"; -import { ServiceScope } from "@microsoft/sp-core-library"; -import { ILayoutProps } from "../../../models/common/ILayout"; - -export interface IVerticalsCustomLayoutProperties extends ILayoutProps { -} - -export class VerticalsCustomLayout extends BaseLayout { - - constructor(serviceScope: ServiceScope) { - super(serviceScope); - } - - public getPropertyPaneFieldsConfiguration(availableFields: string[]): IPropertyPaneField[] { - - return [ - ] - } -} \ No newline at end of file diff --git a/packages/spfx/src/layouts/verticals/custom/verticals-custom.html b/packages/spfx/src/layouts/verticals/custom/verticals-custom.html deleted file mode 100644 index 8edb479..0000000 --- a/packages/spfx/src/layouts/verticals/custom/verticals-custom.html +++ /dev/null @@ -1,17 +0,0 @@ - \ No newline at end of file diff --git a/packages/spfx/src/layouts/verticals/default/VerticalsDefaultLayout.ts b/packages/spfx/src/layouts/verticals/default/VerticalsDefaultLayout.ts deleted file mode 100644 index d203ce0..0000000 --- a/packages/spfx/src/layouts/verticals/default/VerticalsDefaultLayout.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { IPropertyPaneField } from "@microsoft/sp-property-pane"; -import { BaseLayout } from "../../../models/common/BaseLayout"; -import { ServiceScope } from "@microsoft/sp-core-library"; -import { ILayoutProps } from "../../../models/common/ILayout"; - -export interface IVerticalsDefaultLayoutProperties extends ILayoutProps { -} - -export class VerticalsDefaultLayout extends BaseLayout { - - constructor(serviceScope: ServiceScope) { - super(serviceScope); - } - - public getPropertyPaneFieldsConfiguration(availableFields: string[]): IPropertyPaneField[] { - - return [ - ] - } -} \ No newline at end of file diff --git a/packages/spfx/src/layouts/verticals/default/default.html b/packages/spfx/src/layouts/verticals/default/default.html deleted file mode 100644 index b5002ba..0000000 --- a/packages/spfx/src/layouts/verticals/default/default.html +++ /dev/null @@ -1,10 +0,0 @@ - \ No newline at end of file diff --git a/packages/spfx/src/loc/commonStrings.d.ts b/packages/spfx/src/loc/commonStrings.d.ts deleted file mode 100644 index 5e22398..0000000 --- a/packages/spfx/src/loc/commonStrings.d.ts +++ /dev/null @@ -1,160 +0,0 @@ -declare interface ICommonStrings { - Tokens: { - SelectTokenLabel: string; - Context: { - ContextTokensGroupName: string; - SiteAbsoluteUrl: string; - SiteRelativeUrl: string; - WebAbsoluteUrl: string; - WebRelativeUrl: string; - WebTitle: string; - InputQueryText: string; - }, - Custom: { - CustomTokensGroupName: string; - CustomValuePlaceholder: string; - InvalidtokenFormatErrorMessage: string; - }, - Date: { - DateTokensGroupName: string; - Today: string; - Yesterday: string; - Tomorrow: string; - OneWeekAgo: string; - OneMonthAgo: string; - OneYearAgo: string; - }, - Page: { - PageTokensGroupName: string; - PageId: string; - PageTitle: string; - PageCustom: string; - }, - User: { - UserTokensGroupName: string; - UserName: string; - Me: string; - UserDepartment: string; - UserCustom: string; - } - }, - General: { - SameTabOpenBehavior: string; - NewTabOpenBehavior: string; - PageOpenBehaviorLabel: string; - }, - PropertyPane: { - ThemeSettingsGroupName: string; - ColorSettingsTabLabel: string; - FollowSiteTheme: string; - CustomColorsFieldName: string; - CustomColorsAddButtonLabel: string; - PrimaryColorFieldName: string; - BackgroundColorFieldName: string; - TextColorFieldName: string; - EditComponentTemplates: string; - EnableDebugMode: string; - UseMicrosoftGraphToolkit: string; - UseExternalTemplateFile: string; - TemplateSettingsGroupName: string; - InformationPage: { - ImportExport: string; - Version: string; - InstanceId: string; - About: string; - Authors: string; - Resources: { - GroupName: string; - Documentation: string; - IssueLink: string; - PleaseReferToDocumentationMessage: string; - }, - DeveloperSettingsWarning: string; - }, - PropertyPaneFiltersConfiguration: { - TextFieldErrorMessage: string; - AggregationsErrorMessage: string; - FilterNameLabel: string; - DisplayNameLabel: string; - TemplateLabel: string; - CheckboxLabel: string; - DateLabel: string; - SliderLabel: string; - ShowCountLabel: string; - OperatorLabel: string; - IsMultiValue: string; - SortByLabel: string; - ByCountLabel: string; - ByNameLabel: string; - SortDirectionLabel: string; - AscendingLabel: string; - DescendingLabel: string; - NumberOfValuesLabel: string; - Aggregations: { - TabTitle: string; - AddBtnLabel: string; - RemoveBtnLabel: string; - MatchingValuesLabel: string; - RegularExpressionLabel: string; - AddNewValueBtnLabel: string; - AggregationValueLabel: string; - IconUrlLabel: string; - }, - SliderSettings: { - TabTitle: string; - MinValueLabel: string; - MinValueDescription: string; - MaxValueLabel: string; - MaxValueDescription: string; - DefaultMinLabel: string; - DefaultMinDescription: string; - DefaultMaxLabel: string; - DefaultMaxDescription: string; - Markers: { - MarkersTitle: string; - AddBtnLabel: string; - RemoveBtnLabel: string; - MarkerLabelLabel: string; - MarkerLabelDescription: string; - MarkerValueLabel: string; - MarkerValueDescription: string; - SizeLabel: string; - SizeDescription: string; - } - }, - DisplaySettings: { - TabTitle: string; - SelectTabLabel: string; - PlaceholderLabel: string; - }, - AddNewFilterBtnLabel: string; - } - }, - Controls: { - }, - Layouts: { - Debug: { - Name: string; - }, - Default: { - Name: string; - }, - Custom: { - Name: string; - }, - ResultsTiles: { - ContainerWidthOptionsFieldLabel: string; - ContainerWidthFieldLabel: string; - SmallWidth: string; - MediumWidth: string; - LargeWidth: string; - ExtraLargeWidth: string; - ExtraExtraLargeWidth: string; - } - } -} - -declare module 'CommonStrings' { - const strings: ICommonStrings; - export = strings; -} diff --git a/packages/spfx/src/loc/en-us.js b/packages/spfx/src/loc/en-us.js deleted file mode 100644 index d569d89..0000000 --- a/packages/spfx/src/loc/en-us.js +++ /dev/null @@ -1,159 +0,0 @@ -define([], function() { - return { - Tokens: { - SelectTokenLabel: "Select a token...", - Context: { - ContextTokensGroupName: "Context tokens", - SiteAbsoluteUrl: "Site absolute URL", - SiteRelativeUrl: "Site server relative URL", - WebAbsoluteUrl: "Web absolute URL", - WebRelativeUrl: "Web server relative URL", - WebTitle: "Web title", - InputQueryText: "Input query text" - }, - Custom: { - CustomTokensGroupName: "Custom value", - CustomValuePlaceholder: "Enter a value...", - InvalidtokenFormatErrorMessage: "Please enter a supported token format using '{' and '}'. (ex: {Today})" - }, - Date: { - DateTokensGroupName: "Date tokens", - Today: "Today", - Yesterday: "Yesterday", - Tomorrow: "Tomorrow", - OneWeekAgo: "One week ago", - OneMonthAgo: "One month ago", - OneYearAgo: "One year ago" - }, - Page: { - PageTokensGroupName: "Page tokens", - PageId: "Page ID", - PageTitle: "Page Title", - PageCustom: "Other page column", - }, - User: { - UserTokensGroupName: "User tokens", - UserName: "User Name", - Me: "Me", - UserDepartment: "User Department", - UserCustom: "User custom property" - } - }, - General: { - SameTabOpenBehavior: "Use the current tab", - NewTabOpenBehavior: "Open in a new tab", - PageOpenBehaviorLabel: "Opening behavior", - }, - PropertyPane: { - ThemeSettingsGroupName: "Theme settings", - ColorSettingsTabLabel: "Choose color", - FollowSiteTheme: "Follow site theme", - CustomColorsFieldName: "Custom colors", - CustomColorsAddButtonLabel: "Add new custom color", - BackgroundColorFieldName: "Background color", - PrimaryColorFieldName: "Primary color", - TextColorFieldName: "Text color", - EditComponentTemplates: "Edit component template(s)", - EnableDebugMode: "Debug mode", - UseMicrosoftGraphToolkit: "Enable Microsoft Graph Toolkit", - UseExternalTemplateFile: "Use external template file", - TemplateSettingsGroupName: "Template(s) customization", - InformationPage: { - ImportExport: "Import/Export WebPart settings", - About: "About", - Authors: "Author(s)", - Version: "Version", - InstanceId: "Web Part instance ID", - Resources: { - GroupName: "Resources", - Documentation: "📖 Read the documentation", - IssueLink: "🐞 Raise an issue", - PleaseReferToDocumentationMessage: "Please refer to the official documentation." - }, - DeveloperSettingsWarning: "❗️❗️ This is a developer feature, make sure you know what are you doing ❗️❗️" - }, - PropertyPaneFiltersConfiguration: { - TextFieldErrorMessage: "Field must have a value", - AggregationsErrorMessage: "All aggregations must have a name", - FilterNameLabel: "Filter name", - DisplayNameLabel: "Display name", - TemplateLabel: "Template", - CheckboxLabel: "Checkbox", - DateLabel: "Date", - SliderLabel: "Label", - ShowCountLabel: "Show count", - OperatorLabel: "Operator", - IsMultiValue: "Is multi value", - SortByLabel: "Sort by", - ByCountLabel: "By count", - ByNameLabel: "By name", - SortDirectionLabel: "Sort direction", - AscendingLabel: "Ascending", - DescendingLabel: "Descending", - NumberOfValuesLabel: "Number of values", - Aggregations: { - TabTitle: "Aggregations", - AddBtnLabel: "Add new aggreagation", - RemoveBtnLabel: "Remove aggregation", - MatchingValuesLabel: "Matching values", - RegularExpressionLabel: "Regular expression", - AddNewValueBtnLabel: "Add new value", - AggregationValueLabel: "Aggregation value", - IconUrlLabel: "Icon URL" - }, - SliderSettings: { - TabTitle: "Settings", - MinValueLabel: "Minimum value", - MinValueDescription: "The mininum value that can be selected on the slider", - MaxValueLabel: "Maximum value", - MaxValueDescription: "The maximum value that can be selected on the slider", - DefaultMinLabel: "Default minimum value", - DefaultMinDescription: "The default mininum value selected on the slider", - DefaultMaxLabel: "Default maximum value", - DefaultMaxDescription: "The default maximum value selected on the slider", - Markers: { - MarkersTitle: "Markers", - AddBtnLabel: "Add new marker", - RemoveBtnLabel: "Remove marker", - MarkerLabelLabel: "Label", - MarkerLabelDescription: "Label to display on the marker. Can be null.", - MarkerValueLabel: "Value", - MarkerValueDescription: "Value of the marker. Should falls between min and max values", - SizeLabel: "Size", - SizeDescription: "Label size in px" - } - }, - DisplaySettings: { - TabTitle: "Display", - SelectTabLabel: "Show this filter on selected tabs", - PlaceholderLabel: "Select a tab..." - }, - AddNewFilterBtnLabel: "Add new filter" - - - } - }, - Controls: { - }, - Layouts: { - Debug: { - Name: "Debug" - }, - Default: { - Name: "Default" - }, - Custom: { - Name: "Custom" - }, - ResultsTiles: { - ContainerWidthOptionsFieldLabel: "WebPart widths", - ContainerWidthFieldLabel: "WebPart container width", - SmallWidth: "Small (Less than 384px)", - MediumWidth: "Medium (from 384px to 448px)", - LargeWidth: "Large (from 448px to 512px)", - ExtraLargeWidth: "Extra Large (from 512px to 576px)", - ExtraExtraLargeWidth: "Extra Extra Large (more than 576px)", - } - } - } -}) diff --git a/packages/spfx/src/loc/propertyControlStrings.d.ts b/packages/spfx/src/loc/propertyControlStrings.d.ts deleted file mode 100644 index 657f39f..0000000 --- a/packages/spfx/src/loc/propertyControlStrings.d.ts +++ /dev/null @@ -1,8 +0,0 @@ -declare interface IPropertyControlStrings { - CollectionDataItemFieldRequiredLabel: string; -} - -declare module 'PropertyControlStrings' { - const strings: IPropertyControlStrings; - export = strings; -} diff --git a/packages/spfx/src/models/common/BaseDataSource.ts b/packages/spfx/src/models/common/BaseDataSource.ts deleted file mode 100644 index 9a2b397..0000000 --- a/packages/spfx/src/models/common/BaseDataSource.ts +++ /dev/null @@ -1,66 +0,0 @@ -import { IPropertyPaneConditionalGroup, IPropertyPaneGroup } from "@microsoft/sp-property-pane"; -import { ServiceScope } from '@microsoft/sp-core-library'; -import { WebPartContext } from "@microsoft/sp-webpart-base"; -import IDataSource from "./IDataSource"; -import { DynamicProperty } from "@microsoft/sp-component-base"; - -export abstract class BaseDataSource implements IDataSource { - - protected serviceScope: ServiceScope; - - protected _properties: T; - private _context: WebPartContext; - private _render: () => void | Promise; - - get properties(): T { - return this._properties; - } - - set properties(properties: T) { - this._properties = properties; - } - - get context(): WebPartContext { - return this._context; - } - - set context(context: WebPartContext) { - this._context = context; - } - - get render(): () => void { - return this._render; - } - - set render(renderFunc: () => void | Promise) { - this._render = renderFunc; - } - - public constructor(serviceScope: ServiceScope) { - this.serviceScope = serviceScope; - } - - protected _dynamicProperties: Map>; - - get dynamicProperties(): Map> { - return this._dynamicProperties; - } - - set dynamicProperties(value: Map>) { - this._dynamicProperties = value; - } - - public onInit(): void | Promise { - return; - } - - public getPropertyPaneGroupsConfiguration(): IPropertyPaneGroup[] | IPropertyPaneConditionalGroup[] { - - // Returns an empty configuration by default - return []; - } - - public onPropertyPaneFieldChanged(propertyPath: string, oldValue: unknown, newValue: unknown): void { - // Do nothing by default - } -} \ No newline at end of file diff --git a/packages/spfx/src/models/common/BaseLayout.tsx b/packages/spfx/src/models/common/BaseLayout.tsx deleted file mode 100644 index 15cf618..0000000 --- a/packages/spfx/src/models/common/BaseLayout.tsx +++ /dev/null @@ -1,142 +0,0 @@ -import { IPropertyPaneField } from "@microsoft/sp-property-pane"; -import { ServiceScope } from '@microsoft/sp-core-library'; -import { WebPartContext } from '@microsoft/sp-webpart-base'; -import { ILayout, ILayoutProps } from "./ILayout"; -import { ILayoutSlot, SlotType } from "./ILayoutSlot"; -import { isEqual } from "@microsoft/sp-lodash-subset"; -import * as React from "react"; -import { ConfigurationPanel } from "../../controls/ConfigurationPanel/ConfigurationPanel"; -import { IConfigurationTab } from "../../controls/ConfigurationPanel/IConfigurationTab"; -import { ConfigurationFieldType, IConfigurationTabField } from "../../controls/ConfigurationPanel/IConfigurationTabField"; -import { LayoutSlotField } from "../../controls/LayoutSlotField/LayoutSlotField"; -import { ItemRepeater } from "../../controls/ItemRepeater/ItemRepeater"; -import { PropertyPaneFormDataCollection } from "../../propertyPane/PropertyPaneFormDataCollection/PropertyPaneFormDataCollection"; - -export abstract class BaseLayout implements ILayout { - - private _properties!: T; - private _context: WebPartContext; - protected serviceScope: ServiceScope; - protected _defaultSlots: ILayoutSlot[]; - - private _itemRepeaterRef = React.createRef>(); - private _lastCreatedConfigurationPanelRef: React.RefObject> = null; - private _lastRowId: string; - - get properties(): T { - return this._properties; - } - - set properties(properties: T) { - this._properties = properties; - } - - get context(): WebPartContext { - return this._context; - } - - set context(context: WebPartContext) { - this._context = context; - } - - public constructor(serviceScope: ServiceScope) { - this.serviceScope = serviceScope; - } - - public async onInit(): Promise { - this.properties.slots = this.properties.slots ? this.properties.slots : this._defaultSlots; - return; - } - - public getPropertyPaneFieldsConfiguration(availableFields: string[]): IPropertyPaneField[] { - return []; - } - - /** - * Gets the property pane slots field - * @param availableFields the list of available fields from results - * @param disabled if the 'Add new slot' button should be disabled - * @param isItemLocked function determining if the slot should be locked - */ - protected getPropertyPaneSlotField(availableFields: string[], disabled: boolean, isItemLocked: (item: ILayoutSlot) => boolean): PropertyPaneFormDataCollection { - - const newSlot = { - slotName: "", - slotType: SlotType.RawValue, - slotValue: "" - }; - - const slotTabsConfiguration: IConfigurationTab[] = [ - { - name: "Settings", - fields: [ - { - type: ConfigurationFieldType.Custom, - targetProperty: null, - onCustomRender: (field, defaultValue, onUpdate) => { - return { - onUpdate(field, value); - }} - dynamicValues={availableFields} - />; - } - } - ] - } - ]; - - const mainFormFields: IConfigurationTabField[] = [ - { - type: ConfigurationFieldType.Custom, - targetProperty: null, - onCustomRender: (field, defaultValue, onUpdate) => { - - this._lastCreatedConfigurationPanelRef = React.createRef>(); - - return - ref={this._lastCreatedConfigurationPanelRef} - configurationTabs={slotTabsConfiguration} - renderRowTitle={(slot: ILayoutSlot) => { return slot.slotName }} - onFormSave={(formData) => { onUpdate(field, formData)}} - dataObject={defaultValue} - renderPanelTitle={() =>"Add new slot"} - onFormDismissed={(configuration: ILayoutSlot) => { - - if (isEqual(configuration, newSlot)) { - // Remove row as no item has been saved - this._itemRepeaterRef.current.deleteItemRow(this._lastRowId) - } - }} - />; - } - } - ]; - - return new PropertyPaneFormDataCollection('layoutProperties.slots', { - items: this.properties.slots, - label: "Available slots", - stateKey: JSON.stringify(this.properties.slots), - itemRepeaterProps: { - innerRef: this._itemRepeaterRef, - addButtonLabel: "Add new slot", - disabled: disabled, - isItemLocked: isItemLocked - }, - formConfiguration: mainFormFields, - newRowDefaultObject: () => newSlot, - onRowAdded: (rowId: string) => { - // Save the row id to be able to delete it afterwards - this._lastRowId = rowId; - // Get the last created row (empty at this point) and open the panel - this._lastCreatedConfigurationPanelRef.current.togglePanel(); - } - }); - } - - public onPropertyUpdate(propertyPath: string, oldValue: unknown, newValue: unknown): void { - // Do nothing by default - } - -} \ No newline at end of file diff --git a/packages/spfx/src/models/common/IBaseWebComponentWrapper.ts b/packages/spfx/src/models/common/IBaseWebComponentWrapper.ts deleted file mode 100644 index 7157c73..0000000 --- a/packages/spfx/src/models/common/IBaseWebComponentWrapper.ts +++ /dev/null @@ -1,27 +0,0 @@ -export interface IBaseWebComponentWrapperProps { - - /** - * Unique id of the component (same as dynamic data source referemce) - */ - id: string; - - /** - * Theme to use for the component - */ - theme: string; - - /** - * Enables the debug mode on component - */ - enableDebugMode: boolean; - - /** - * Enable the Microsoft Graph Toolkit for templates - */ - useMicrosoftGraphToolkit: boolean; - - /** - * The web HTML template content - */ - templateContent?: string; -} \ No newline at end of file diff --git a/packages/spfx/src/models/common/IBaseWebPartProps.ts b/packages/spfx/src/models/common/IBaseWebPartProps.ts deleted file mode 100644 index bd69776..0000000 --- a/packages/spfx/src/models/common/IBaseWebPartProps.ts +++ /dev/null @@ -1,77 +0,0 @@ -import { ICustomColorField } from "./ICustomPalette"; -import { IFilePickerResult } from "@pnp/spfx-controls-react"; -import { LayoutRenderType } from "./ILayoutDefinition"; -import { ILayoutSlot } from "./ILayoutSlot"; - -export interface IBaseWebPartProps { - - /** - * The selected layout key - */ - selectedLayoutKey: string; - - /** - * Content of the template if customized inline (i.e. without external file of custom layout) - */ - inlineTemplateContent: string; - - /** - * External template URL - */ - externalTemplateFilePickerResult: IFilePickerResult; - - /** - * Enables the debug mode on component - */ - enableDebugMode: boolean; - - /** - * Enable Microsoft Graph Toolkit components for templates - */ - useMicrosoftGraphToolkit: boolean; - - /** - * The layout properties - */ - layoutProperties: { - - - slots?: ILayoutSlot[]; - - /** - * Any other property from layouts (builtin + custom) - */ - // eslint-disable-next-line @typescript-eslint/no-explicit-any - [key: string]: any; - }; - - /** - * The layout type - */ - layoutRenderType: LayoutRenderType; - - /** - * The link URL to the solution documenation - */ - documentationLink: string; - - /** - * The GitLab issue link - */ - issueLink: string; - - /** - * The Web Part title - */ - title: string; - - /** - * If the component should follow the site theme automatically - */ - followSiteTheme: boolean; - - /** - * The primary color of the component - */ - colorOverrides: ICustomColorField[]; -} \ No newline at end of file diff --git a/packages/spfx/src/models/common/ICustomPalette.ts b/packages/spfx/src/models/common/ICustomPalette.ts deleted file mode 100644 index 5b0dba6..0000000 --- a/packages/spfx/src/models/common/ICustomPalette.ts +++ /dev/null @@ -1,5 +0,0 @@ -export interface ICustomColorField { - colorName: string; - colorVariable: string; - colorValue: string; -} \ No newline at end of file diff --git a/packages/spfx/src/models/common/IDataSource.ts b/packages/spfx/src/models/common/IDataSource.ts deleted file mode 100644 index b9c9746..0000000 --- a/packages/spfx/src/models/common/IDataSource.ts +++ /dev/null @@ -1,44 +0,0 @@ -import { DynamicProperty } from "@microsoft/sp-component-base"; -import { IPropertyPaneConditionalGroup, IPropertyPaneGroup } from "@microsoft/sp-property-pane"; -import { WebPartContext } from "@microsoft/sp-webpart-base"; - -export default interface IDataSource { - - /** - * The Web Part properties in the property bag. Corresponds to the isolated 'dataSourceProperties' property in the global property bag. - */ - properties: unknown; - - /** - * Dynamic properties to set <'name of the property',instance> - */ - dynamicProperties: Map>; - - /** - * Context of the main Web Part - */ - context: WebPartContext; - - /** - * This API is called to render the web part. - */ - render: () => void | Promise; - - /** - * Method called during the Web Part initialization. - */ - onInit(): void | Promise; - - /** - * Returns the data source property pane option fields if any. - */ - getPropertyPaneGroupsConfiguration(): IPropertyPaneGroup[] | IPropertyPaneConditionalGroup[]; - - /** - * Method called when a property pane field in changed in the Web Part. - * @param propertyPath the property path. - * @param oldValue the old value. - * @param newValue the new value. - */ - onPropertyPaneFieldChanged(propertyPath: string, oldValue: unknown, newValue: unknown): void; -} \ No newline at end of file diff --git a/packages/spfx/src/models/common/ILayout.ts b/packages/spfx/src/models/common/ILayout.ts deleted file mode 100644 index 84dc6b0..0000000 --- a/packages/spfx/src/models/common/ILayout.ts +++ /dev/null @@ -1,42 +0,0 @@ -import { IPropertyPaneField } from "@microsoft/sp-property-pane"; -import { WebPartContext } from '@microsoft/sp-webpart-base'; -import { ILayoutSlot } from "./ILayoutSlot"; - -export interface ILayoutProps { - slots: ILayoutSlot[]; -} - -export interface ILayout { - - /** - * The Web Part properties in the property bag. Corresponds to the isolated 'layoutProperties' property in the global property bag. - */ - // eslint-disable-next-line @typescript-eslint/no-explicit-any - properties: any; - - /** - * Context of the main Web Part - */ - context: WebPartContext; - - /** - * Method called during the Web Part initialization. - */ - onInit(): void | Promise; - - /** - * Returns the layout property pane option fields if any - * A good practice is to prefix property pane properties by the layout name like PropertyPaneTextField('customLayout.myTextProperty', {...})} - * @param availableFields the available fields coming from results - * @param dataContext the current data source data context - */ - getPropertyPaneFieldsConfiguration(availableFields: string[]): IPropertyPaneField[]; - - /** - * Method called when a property pane field in changed in the Web Part - * @param propertyPath the property path - * @param oldValue the old value - * @param newValue the new value - */ - onPropertyUpdate(propertyPath: string, oldValue: unknown, newValue: unknown): void; -} diff --git a/packages/spfx/src/models/common/ILayoutDefinition.ts b/packages/spfx/src/models/common/ILayoutDefinition.ts deleted file mode 100644 index 8aeff92..0000000 --- a/packages/spfx/src/models/common/ILayoutDefinition.ts +++ /dev/null @@ -1,51 +0,0 @@ -import { ServiceKey } from '@microsoft/sp-core-library'; -import { ILayout } from './ILayout'; - -export interface ILayoutDefinition { - - /** - * The layout friendly name - */ - name: string; - - /** - * The layout unique key - */ - key: string; - - /** - * The layout type (Results, Filter) - */ - type: LayoutType; - - /** - * The Office UI Fabric icon name - * See https://developer.microsoft.com/en-us/fabric#/styles/web/icons - */ - iconName: string; - - /** - * The template HTML content. You can use the require('; -} - -export enum LayoutType { - Results = "ResultsLayout", - Filters = "FiltersLayout", - Verticals = "VerticalsLayout" -} - -export enum LayoutRenderType { - Html = "Html" -} \ No newline at end of file diff --git a/packages/spfx/src/models/common/ILayoutSlot.ts b/packages/spfx/src/models/common/ILayoutSlot.ts deleted file mode 100644 index e1bc59f..0000000 --- a/packages/spfx/src/models/common/ILayoutSlot.ts +++ /dev/null @@ -1,37 +0,0 @@ -/** - * List of available slot values for Handlebars templates - */ -export enum BuiltinTemplateSlots { - Title = "Title", - Path = "Path", - Summary = "Summary", - FileType = "FileType" -} - -export enum SlotType { - DynamicField = 'dynamicfield', - RawValue = 'rawvalue' -} - -export interface ILayoutSlot { - - /** - * Name of the slot to be used in the Handlebars templates (ex: 'Title'). This will be accessible using \{{@slots.}} in templates - */ - slotName: BuiltinTemplateSlots | string; - - /** - * The source field associated with that slot - */ - slotValue: string; - - /** - * The slot type (dynamic field vs static value) - */ - slotType: SlotType; - - /** - * If the slot name can be edited - */ - disabled?: boolean; -} diff --git a/packages/spfx/src/models/common/ITemplateContext.ts b/packages/spfx/src/models/common/ITemplateContext.ts deleted file mode 100644 index 3ce3689..0000000 --- a/packages/spfx/src/models/common/ITemplateContext.ts +++ /dev/null @@ -1,10 +0,0 @@ -export interface ITemplateContext { - - // eslint-disable-next-line @typescript-eslint/no-explicit-any - layoutProperties: { [key: string]: any; } - - /** - * Hashtable of configured slots for the current data source. - */ - slots: { [key: string]: string }; -} \ No newline at end of file diff --git a/packages/spfx/src/models/dynamicData/IDynamicDataSourceProperty.ts b/packages/spfx/src/models/dynamicData/IDynamicDataSourceProperty.ts deleted file mode 100644 index 803094a..0000000 --- a/packages/spfx/src/models/dynamicData/IDynamicDataSourceProperty.ts +++ /dev/null @@ -1,6 +0,0 @@ -interface IDynamicDataSourceProperty { - key: string; - text: string; -} - -export default IDynamicDataSourceProperty; \ No newline at end of file diff --git a/packages/spfx/src/models/dynamicData/ISearchVerticalSourceData.ts b/packages/spfx/src/models/dynamicData/ISearchVerticalSourceData.ts deleted file mode 100644 index 652721d..0000000 --- a/packages/spfx/src/models/dynamicData/ISearchVerticalSourceData.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { IDataVerticalConfiguration } from "@pnp/modern-search-core/dist/es6/models/common/IDataVerticalConfiguration"; - -export interface ISearchVerticalSourceData { - verticalsConfiguration: IDataVerticalConfiguration[]; - selectedVerticalKey: string; -} \ No newline at end of file diff --git a/packages/spfx/src/propertyPane/PropertyPaneCodeEditor/IPropertyPaneCodeEditorInternalProps.ts b/packages/spfx/src/propertyPane/PropertyPaneCodeEditor/IPropertyPaneCodeEditorInternalProps.ts deleted file mode 100644 index 5948122..0000000 --- a/packages/spfx/src/propertyPane/PropertyPaneCodeEditor/IPropertyPaneCodeEditorInternalProps.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { IPropertyPaneCustomFieldProps } from "@microsoft/sp-property-pane"; -import { IPropertyPaneCodeEditorProps } from "./IPropertyPaneCodeEditorProps"; - -export interface IPropertyPaneCodeEditorInternalProps extends IPropertyPaneCodeEditorProps, IPropertyPaneCustomFieldProps { -} \ No newline at end of file diff --git a/packages/spfx/src/propertyPane/PropertyPaneCodeEditor/IPropertyPaneCodeEditorProps.ts b/packages/spfx/src/propertyPane/PropertyPaneCodeEditor/IPropertyPaneCodeEditorProps.ts deleted file mode 100644 index 143c0af..0000000 --- a/packages/spfx/src/propertyPane/PropertyPaneCodeEditor/IPropertyPaneCodeEditorProps.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { IReadonlyTheme } from "@microsoft/sp-component-base"; - -export interface IPropertyPaneCodeEditorProps { - label?: string - defaultValue: string; - isReadOnly?: boolean; - theme?: IReadonlyTheme -} \ No newline at end of file diff --git a/packages/spfx/src/propertyPane/PropertyPaneCodeEditor/PropertyPaneCodeEditor.tsx b/packages/spfx/src/propertyPane/PropertyPaneCodeEditor/PropertyPaneCodeEditor.tsx deleted file mode 100644 index 972d83a..0000000 --- a/packages/spfx/src/propertyPane/PropertyPaneCodeEditor/PropertyPaneCodeEditor.tsx +++ /dev/null @@ -1,55 +0,0 @@ -import { IPropertyPaneField, PropertyPaneFieldType } from "@microsoft/sp-property-pane"; -import { IPropertyPaneCodeEditorProps } from "./IPropertyPaneCodeEditorProps"; -import { IPropertyPaneCodeEditorInternalProps } from "./IPropertyPaneCodeEditorInternalProps"; -import * as ReactDom from 'react-dom'; -import * as React from 'react'; -import { PropertyPaneCodeEditorHost } from "./components/PropertyPaneCodeEditorHost"; - -export class PropertyPaneCodeEditor implements IPropertyPaneField { - - public type: PropertyPaneFieldType = PropertyPaneFieldType.Custom; - public targetProperty: string; - public properties: IPropertyPaneCodeEditorInternalProps; - private elem: HTMLElement; - - constructor(targetProperty: string, properties: IPropertyPaneCodeEditorProps) { - - this.targetProperty = targetProperty; - this.properties = { - key: targetProperty, - label: properties.label, - onRender: this.onRender.bind(this), - onDispose: this.onDispose.bind(this), - ...properties, - }; - } - - public render(): void { - if (!this.elem) { - return; - } - - this.onRender(this.elem); - } - - private onDispose(element: HTMLElement): void { - ReactDom.unmountComponentAtNode(element); - } - - private onRender(elem: HTMLElement, ctx?: unknown, changeCallback?: (targetProperty?: string, newValue?: string) => void): void { - - if (!this.elem) { - this.elem = elem; - } - - const element = { - changeCallback(this.targetProperty, value) - }} - />; - - ReactDom.render(element, elem); - } - -} diff --git a/packages/spfx/src/propertyPane/PropertyPaneCodeEditor/components/IPropertyPaneCodeEditorHostProps.ts b/packages/spfx/src/propertyPane/PropertyPaneCodeEditor/components/IPropertyPaneCodeEditorHostProps.ts deleted file mode 100644 index 4d5c45c..0000000 --- a/packages/spfx/src/propertyPane/PropertyPaneCodeEditor/components/IPropertyPaneCodeEditorHostProps.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { IReadonlyTheme } from "@microsoft/sp-component-base"; - -export interface IPropertyPaneCodeEditorHostProps { - label?: string - defaultValue: string; - onValueChange: (value: string) => void; - isReadOnly?: boolean; - theme?: IReadonlyTheme; -} \ No newline at end of file diff --git a/packages/spfx/src/propertyPane/PropertyPaneCodeEditor/components/IPropertyPaneCodeEditorHostState.ts b/packages/spfx/src/propertyPane/PropertyPaneCodeEditor/components/IPropertyPaneCodeEditorHostState.ts deleted file mode 100644 index c36851b..0000000 --- a/packages/spfx/src/propertyPane/PropertyPaneCodeEditor/components/IPropertyPaneCodeEditorHostState.ts +++ /dev/null @@ -1,4 +0,0 @@ -export interface IPropertyPaneCodeEditorHostState { - isOpen: boolean; - value: string; -} \ No newline at end of file diff --git a/packages/spfx/src/propertyPane/PropertyPaneCodeEditor/components/PropertyPaneCodeEditorHost.tsx b/packages/spfx/src/propertyPane/PropertyPaneCodeEditor/components/PropertyPaneCodeEditorHost.tsx deleted file mode 100644 index 6aac6a8..0000000 --- a/packages/spfx/src/propertyPane/PropertyPaneCodeEditor/components/PropertyPaneCodeEditorHost.tsx +++ /dev/null @@ -1,101 +0,0 @@ -import * as React from "react"; -import { IPropertyPaneCodeEditorHostProps } from "./IPropertyPaneCodeEditorHostProps"; -import { Editor, loader } from "@monaco-editor/react/dist/index.js"; -import { DefaultButton, IconButton, Label, Panel, PanelType, PrimaryButton, Stack, TextField } from "office-ui-fabric-react"; -import { IPropertyPaneCodeEditorHostState } from "./IPropertyPaneCodeEditorHostState"; -import { isEqual } from "@microsoft/sp-lodash-subset"; - -export class PropertyPaneCodeEditorHost extends React.Component { - - constructor(props: IPropertyPaneCodeEditorHostProps) { - super(props); - - this.state = { - isOpen: false, - value: props.defaultValue - }; - - loader.config({ paths: { - vs: "https://cdn.jsdelivr.net/npm/monaco-editor@0.41.0/min/vs" // Use the same version as the web component to benefit from the cache - }}); - - this.togglePanel = this.togglePanel.bind(this); - - } - - public render(): React.ReactNode { - - const renderFooter =
-
- { - this.props.onValueChange(this.state.value); - this.togglePanel(); - }} - disabled={isEqual(this.props.defaultValue, this.state.value)} - >Save - Cancel -
-
; - - return <> - - - - - - {return renderFooter}} - > - { - this.setState({ - value: value - }) - }} - theme={this.props.theme?.isInverted ? "vs-dark" : "vs"} - /> - - - - } - - public componentDidUpdate(prevProps: Readonly): void { - if (!isEqual(prevProps.defaultValue, this.props.defaultValue)) { - this.setState({ - value: this.props.defaultValue - }); - } - } - - public togglePanel(): void { - - this.setState({ - isOpen: !this.state.isOpen - }); - } -} \ No newline at end of file diff --git a/packages/spfx/src/propertyPane/PropertyPaneCombobox/IPropertyPaneComboBoxInternalProps.ts b/packages/spfx/src/propertyPane/PropertyPaneCombobox/IPropertyPaneComboBoxInternalProps.ts deleted file mode 100644 index dd300a9..0000000 --- a/packages/spfx/src/propertyPane/PropertyPaneCombobox/IPropertyPaneComboBoxInternalProps.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { IPropertyPaneCustomFieldProps } from "@microsoft/sp-property-pane"; -import { IPropertyPaneComboboxProps } from "./IPropertyPaneComboBoxProps"; - -export interface IPropertyPaneComboBoxInternalProps extends IPropertyPaneComboboxProps, IPropertyPaneCustomFieldProps { -} \ No newline at end of file diff --git a/packages/spfx/src/propertyPane/PropertyPaneCombobox/IPropertyPaneComboBoxProps.ts b/packages/spfx/src/propertyPane/PropertyPaneCombobox/IPropertyPaneComboBoxProps.ts deleted file mode 100644 index 50616c7..0000000 --- a/packages/spfx/src/propertyPane/PropertyPaneCombobox/IPropertyPaneComboBoxProps.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { IComboBoxOption, IComboBoxProps } from "office-ui-fabric-react"; - -export interface IPropertyPaneComboboxProps extends IComboBoxProps { - - /** - * Callback when a new manual value is added - * @param options the new options - * @returns the new available options - */ - onValueChange?: (options: IComboBoxOption[]) => void; -} \ No newline at end of file diff --git a/packages/spfx/src/propertyPane/PropertyPaneCombobox/PropertyPaneCombobox.ts b/packages/spfx/src/propertyPane/PropertyPaneCombobox/PropertyPaneCombobox.ts deleted file mode 100644 index 4de54a8..0000000 --- a/packages/spfx/src/propertyPane/PropertyPaneCombobox/PropertyPaneCombobox.ts +++ /dev/null @@ -1,82 +0,0 @@ -import { - IPropertyPaneField, - PropertyPaneFieldType - } from '@microsoft/sp-property-pane'; -import * as ReactDom from 'react-dom'; -import * as React from 'react'; -import { ComboBox, IComboBox, IComboBoxOption, IComboBoxProps } from 'office-ui-fabric-react'; -import { IPropertyPaneComboBoxInternalProps } from './IPropertyPaneComboBoxInternalProps'; -import { IPropertyPaneComboboxProps } from './IPropertyPaneComboBoxProps'; - -export class PropertyPaneCombobox implements IPropertyPaneField { - - public type: PropertyPaneFieldType = PropertyPaneFieldType.Custom; - public targetProperty: string; - public properties: IPropertyPaneComboBoxInternalProps; - private elem: HTMLElement; - private comboBoxRef = React.createRef(); - - constructor(targetProperty: string, properties: IPropertyPaneComboboxProps) { - - this.targetProperty = targetProperty; - this.properties = { - key: targetProperty, - label: properties.label, - onRender: this.onRender.bind(this), - onDispose: this.onDispose.bind(this), - onValueChange: properties.onValueChange, - ...properties, - componentRef: this.comboBoxRef - }; - } - - public render(): void { - if (!this.elem) { - return; - } - - this.onRender(this.elem); - } - - private onDispose(element: HTMLElement): void { - ReactDom.unmountComponentAtNode(element); - } - - private onRender(elem: HTMLElement, ctx?: unknown, changeCallback?: (targetProperty?: string, newValue?: string[]) => void): void { - - if (!this.elem) { - this.elem = elem; - } - - const element: React.ReactElement = React.createElement(ComboBox, - { - ...this.properties, - onChange: (event: React.FormEvent, option?: IComboBoxOption, index?: number, value?: string) => { - - // Add the value to the existing available options but keep their current selected state - let currentOptions = this.properties.options.map(option => { - option.selected = this.comboBoxRef.current.selectedOptions.some(o => o.key === option.key); - return option; - }); - - if (option) { - const selectedOptions = this.comboBoxRef.current.selectedOptions.map(o => o.key as string); - changeCallback(this.targetProperty, selectedOptions); - } - - if (this.properties.allowFreeform && !option && value) { - - currentOptions = [...currentOptions, {key: value, text: value, selected: true}]; - changeCallback(this.targetProperty, currentOptions.filter(o => o.selected).map(o => o.key as string)); - } - - // Optional callback to allow parent to update the available options - if (this.properties.onValueChange) { - this.properties.onValueChange(currentOptions); - } - } - } - ); - ReactDom.render(element, elem); - } -} \ No newline at end of file diff --git a/packages/spfx/src/propertyPane/PropertyPaneFilePicker/IPropertyPaneFilePickerInternalProps.ts b/packages/spfx/src/propertyPane/PropertyPaneFilePicker/IPropertyPaneFilePickerInternalProps.ts deleted file mode 100644 index 64b2c48..0000000 --- a/packages/spfx/src/propertyPane/PropertyPaneFilePicker/IPropertyPaneFilePickerInternalProps.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { IPropertyPaneCustomFieldProps } from "@microsoft/sp-property-pane"; -import { IPropertyPaneFilePickerProps } from "./IPropertyPaneFilePickerProps"; - -export interface IPropertyPaneFilePickerInternalProps extends IPropertyPaneFilePickerProps, IPropertyPaneCustomFieldProps { -} \ No newline at end of file diff --git a/packages/spfx/src/propertyPane/PropertyPaneFilePicker/IPropertyPaneFilePickerProps.ts b/packages/spfx/src/propertyPane/PropertyPaneFilePicker/IPropertyPaneFilePickerProps.ts deleted file mode 100644 index 5ca35a5..0000000 --- a/packages/spfx/src/propertyPane/PropertyPaneFilePicker/IPropertyPaneFilePickerProps.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { BaseComponentContext } from "@microsoft/sp-component-base"; -import { IFilePickerResult } from "@pnp/spfx-controls-react"; - -export interface IPropertyPaneFilePickerProps { - label?: string; - componentContext: BaseComponentContext; - filePickerResult?: IFilePickerResult; -} \ No newline at end of file diff --git a/packages/spfx/src/propertyPane/PropertyPaneFilePicker/PropertyPaneFilePicker.tsx b/packages/spfx/src/propertyPane/PropertyPaneFilePicker/PropertyPaneFilePicker.tsx deleted file mode 100644 index 5500d3d..0000000 --- a/packages/spfx/src/propertyPane/PropertyPaneFilePicker/PropertyPaneFilePicker.tsx +++ /dev/null @@ -1,59 +0,0 @@ -import { IPropertyPaneField, PropertyPaneFieldType } from "@microsoft/sp-property-pane"; -import * as ReactDom from 'react-dom'; -import * as React from 'react'; -import { IPropertyPaneFilePickerProps } from "./IPropertyPaneFilePickerProps"; -import { IPropertyPaneFilePickerInternalProps } from "./IPropertyPaneFilePickerInternalProps"; -import { PropertyPaneFilePickerHost } from "./components/PropertyPaneFilePickerHost"; -import { IFilePickerResult } from '@pnp/spfx-controls-react/lib/FilePicker'; - -export class PropertyPaneFilePicker implements IPropertyPaneField { - - public type: PropertyPaneFieldType = PropertyPaneFieldType.Custom; - public targetProperty: string; - public properties: IPropertyPaneFilePickerInternalProps; - private elem: HTMLElement; - - constructor(targetProperty: string, properties: IPropertyPaneFilePickerProps) { - - this.targetProperty = targetProperty; - this.properties = { - key: targetProperty, - label: properties.label, - onRender: this.onRender.bind(this), - onDispose: this.onDispose.bind(this), - ...properties, - }; - } - - public render(): void { - if (!this.elem) { - return; - } - - this.onRender(this.elem); - } - - private onDispose(element: HTMLElement): void { - ReactDom.unmountComponentAtNode(element); - } - - private onRender(elem: HTMLElement, ctx?: unknown, changeCallback?: (targetProperty?: string, newValue?: IFilePickerResult) => void): void { - - if (!this.elem) { - this.elem = elem; - } - - const element = { - changeCallback(this.targetProperty, filePickerResult) - }} - />; - - ReactDom.render(element, elem); - } - -} diff --git a/packages/spfx/src/propertyPane/PropertyPaneFilePicker/components/IPropertyPaneFilePickerHostProps.ts b/packages/spfx/src/propertyPane/PropertyPaneFilePicker/components/IPropertyPaneFilePickerHostProps.ts deleted file mode 100644 index 6a82be3..0000000 --- a/packages/spfx/src/propertyPane/PropertyPaneFilePicker/components/IPropertyPaneFilePickerHostProps.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { BaseComponentContext } from "@microsoft/sp-component-base"; -import { IFilePickerResult } from "@pnp/spfx-controls-react"; - -export interface IPropertyPaneFilePickerHostProps { - label?: string; - componentContext: BaseComponentContext; - filePickerResult?: IFilePickerResult; - onFileSelected: (filePickerResult: IFilePickerResult) => void; -} \ No newline at end of file diff --git a/packages/spfx/src/propertyPane/PropertyPaneFilePicker/components/IPropertyPaneFilePickerHostState.ts b/packages/spfx/src/propertyPane/PropertyPaneFilePicker/components/IPropertyPaneFilePickerHostState.ts deleted file mode 100644 index aa903ab..0000000 --- a/packages/spfx/src/propertyPane/PropertyPaneFilePicker/components/IPropertyPaneFilePickerHostState.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { IFilePickerResult } from "@pnp/spfx-controls-react"; - -export interface IPropertyPaneFilePickerHostState { - filePickerResult: IFilePickerResult; - isPanelOpen: boolean; -} \ No newline at end of file diff --git a/packages/spfx/src/propertyPane/PropertyPaneFilePicker/components/PropertyPaneFilePickerHost.tsx b/packages/spfx/src/propertyPane/PropertyPaneFilePicker/components/PropertyPaneFilePickerHost.tsx deleted file mode 100644 index 61ec2ff..0000000 --- a/packages/spfx/src/propertyPane/PropertyPaneFilePicker/components/PropertyPaneFilePickerHost.tsx +++ /dev/null @@ -1,130 +0,0 @@ -import * as React from "react"; -import { IPropertyPaneFilePickerHostProps } from "./IPropertyPaneFilePickerHostProps"; -import { IPropertyPaneFilePickerHostState } from "./IPropertyPaneFilePickerHostState"; -import { FilePicker, IFilePickerResult } from '@pnp/spfx-controls-react/lib/FilePicker'; -import { IconButton, Label, Stack, TextField, TooltipHost } from "office-ui-fabric-react"; -import { isEqual } from "@microsoft/sp-lodash-subset"; - -const textFieldStyles = { - root: { - width: "100%", - }, - fieldGroup: { - selectors: { - "input:hover": { - cursor: "pointer" - } - } - } -}; - -const toolTipStyles = { - root: { - display: 'inline-block', - width: "100%" - } -} - -export class PropertyPaneFilePickerHost extends React.Component { - - constructor(props: IPropertyPaneFilePickerHostProps) { - super(props); - - this.state = { - filePickerResult: props.filePickerResult, - isPanelOpen: false - }; - } - - public componentDidUpdate(prevProps: Readonly): void { - if (!isEqual(prevProps.filePickerResult, this.props.filePickerResult)) { - this.setState({ - filePickerResult: this.props.filePickerResult - }); - } - } - - public render(): React.ReactNode { - - let renderTextField = { - this.setState({isPanelOpen: true}) - }} - />; - - if (this.props.filePickerResult) { - - renderTextField = - { - this.setState({isPanelOpen: true}) - }} - styles={textFieldStyles} - value={this.state.filePickerResult?.fileName} - iconProps={{iconName: "Info"}} - /> - ; - } - - return <> - - - {renderTextField} - - - } -} \ No newline at end of file diff --git a/packages/spfx/src/propertyPane/PropertyPaneFiltersConfiguration/IPropertyPaneFiltersConfigurationInternalProps.ts b/packages/spfx/src/propertyPane/PropertyPaneFiltersConfiguration/IPropertyPaneFiltersConfigurationInternalProps.ts deleted file mode 100644 index f5fa6fb..0000000 --- a/packages/spfx/src/propertyPane/PropertyPaneFiltersConfiguration/IPropertyPaneFiltersConfigurationInternalProps.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { IPropertyPaneCustomFieldProps } from "@microsoft/sp-property-pane"; -import { IPropertyPaneFiltersConfigurationProps } from "./IPropertyPaneFiltersConfigurationProps"; - -export interface IPropertyPaneFiltersConfigurationInternalProps extends IPropertyPaneFiltersConfigurationProps, IPropertyPaneCustomFieldProps { -} \ No newline at end of file diff --git a/packages/spfx/src/propertyPane/PropertyPaneFiltersConfiguration/IPropertyPaneFiltersConfigurationProps.ts b/packages/spfx/src/propertyPane/PropertyPaneFiltersConfiguration/IPropertyPaneFiltersConfigurationProps.ts deleted file mode 100644 index 9e84c49..0000000 --- a/packages/spfx/src/propertyPane/PropertyPaneFiltersConfiguration/IPropertyPaneFiltersConfigurationProps.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { ServiceScope } from "@microsoft/sp-core-library"; -import { IDataFilterConfiguration } from "@pnp/modern-search-core/dist/es6/models/common/IDataFilterConfiguration"; -import { IDataVerticalConfiguration } from "@pnp/modern-search-core/dist/es6/models/common/IDataVerticalConfiguration"; - -export interface IPropertyPaneFiltersConfigurationProps { - serviceScope: ServiceScope; - defaultValue: IDataFilterConfiguration[]; - verticalsConfiguration?: IDataVerticalConfiguration[] -} \ No newline at end of file diff --git a/packages/spfx/src/propertyPane/PropertyPaneFiltersConfiguration/PropertyPaneFiltersConfiguration.tsx b/packages/spfx/src/propertyPane/PropertyPaneFiltersConfiguration/PropertyPaneFiltersConfiguration.tsx deleted file mode 100644 index 2cd9ce8..0000000 --- a/packages/spfx/src/propertyPane/PropertyPaneFiltersConfiguration/PropertyPaneFiltersConfiguration.tsx +++ /dev/null @@ -1,391 +0,0 @@ -import { - IPropertyPaneField, - PropertyPaneFieldType - } from '@microsoft/sp-property-pane'; -import * as ReactDom from 'react-dom'; -import * as React from 'react'; -import { IPropertyPaneFiltersConfigurationProps } from './IPropertyPaneFiltersConfigurationProps'; -import { IPropertyPaneFiltersConfigurationInternalProps } from './IPropertyPaneFiltersConfigurationInternalProps'; -import { FilterSortDirection, FilterSortType, IDataFilterAggregation, IDataFilterConfiguration } from '@pnp/modern-search-core/dist/es6/models/common/IDataFilterConfiguration'; -import { BuiltinFilterTemplates } from '@pnp/modern-search-core/dist/es6/models/common/BuiltinTemplate'; -import { FilterConditionOperator } from '@pnp/modern-search-core/dist/es6/models/common/IDataFilter'; -import { ITextFieldProps, IChoiceGroupOptionProps, IToggleProps, ISliderProps, IDropdownProps, MessageBar, MessageBarType } from 'office-ui-fabric-react'; -import { isEmpty, isEqual } from '@microsoft/sp-lodash-subset'; -import { LocalizedStringHelper } from '@pnp/modern-search-core/dist/es6/helpers/LocalizedStringHelper'; -import { ILocalizedString } from '@pnp/modern-search-core/dist/es6/models/common/ILocalizedString'; -import { ConfigurationPanel } from '../../controls/ConfigurationPanel/ConfigurationPanel'; -import { IConfigurationTab } from '../../controls/ConfigurationPanel/IConfigurationTab'; -import { IConfigurationTabField, ConfigurationFieldType } from '../../controls/ConfigurationPanel/IConfigurationTabField'; -import { FormDataCollection } from '../../controls/FormDataCollection/FormDataCollection'; -import { IFormDataCollectionProps } from '../../controls/FormDataCollection/IFormDataCollectionProps'; -import { IconPlacement, IItemRepeaterSharedProps } from '../../controls/ItemRepeater/IItemRepeaterProps'; -import { ItemRepeater } from '../../controls/ItemRepeater/ItemRepeater'; -import { ILocalizedFieldProps } from '../../controls/LocalizedTextField/ILocalizedFieldProps'; -import { BaseComponentContext } from '@microsoft/sp-component-base'; -import * as commonStrings from "CommonStrings"; - -//#region Fields validation - -const getErrorMessage = (value: string): string => { - return !isEmpty(value) ? '' : commonStrings.PropertyPane.PropertyPaneFiltersConfiguration.TextFieldErrorMessage; -}; - -// Check if translation has a default value -const localizedStringGetErrorMessage = (value: string | ILocalizedString): string => { - return !isEmpty(LocalizedStringHelper.isLocalizedString(value) ? (value as ILocalizedString).default : value) ? '' : `Field must have a value`; -}; - -// Check if all aggregations have a name -const aggregationsGetErrorMessage = (values: IDataFilterAggregation[]): string => { - return values.some(value => isEmpty(value.aggregationName)) ? commonStrings.PropertyPane.PropertyPaneFiltersConfiguration.AggregationsErrorMessage : ''; -}; - -//#endregion - -export class PropertyPaneFiltersConfiguration implements IPropertyPaneField { - - public type: PropertyPaneFieldType = PropertyPaneFieldType.Custom; - public targetProperty: string; - public shouldFocus?: boolean; - public properties: IPropertyPaneFiltersConfigurationInternalProps; - private elem: HTMLElement; - - private _itemRepeaterRef = React.createRef>(); - private _lastCreatedConfigurationPanelRef: React.RefObject> = null; - private _lastRowId: string; - - private newFilterBaseConfiguration: IDataFilterConfiguration; - private filterTabsConfiguration: IConfigurationTab[]; - private mainFormFields: IConfigurationTabField[]; - - constructor(targetProperty: string, properties: IPropertyPaneFiltersConfigurationProps) { - - this.targetProperty = targetProperty; - this.properties = { - key: targetProperty, - onRender: this.onRender.bind(this), - onDispose: this.onDispose.bind(this), - ...properties - }; - - - this.newFilterBaseConfiguration = { - filterName: "", - displayName: "", - isMulti: false, - maxBuckets: 100, - operator: FilterConditionOperator.AND, - showCount: false, - sortBy: FilterSortType.ByCount, - sortDirection: FilterSortDirection.Ascending, - sortIdx: this.properties.defaultValue.length, - template: BuiltinFilterTemplates.CheckBox, - aggregations: [], - }; - - this.filterTabsConfiguration = [ - { - name: "Basic", - fields: [ - { - type: ConfigurationFieldType.TextField, - props: { - label: commonStrings.PropertyPane.PropertyPaneFiltersConfiguration.FilterNameLabel, - required: true, - onGetErrorMessage: getErrorMessage, - validateOnLoad: true - } as Partial, - targetProperty: "filterName" - }, - { - type: ConfigurationFieldType.LocalizedField, - props: { - label: commonStrings.PropertyPane.PropertyPaneFiltersConfiguration.DisplayNameLabel, - onGetErrorMessage: localizedStringGetErrorMessage, - required: true, - serviceScope: this.properties.serviceScope - } as Partial, - targetProperty: "displayName" - }, - { - type: ConfigurationFieldType.ChoiceGroup, - props: { - label: commonStrings.PropertyPane.PropertyPaneFiltersConfiguration.TemplateLabel, - options: [ - { - key: BuiltinFilterTemplates.CheckBox, - text: commonStrings.PropertyPane.PropertyPaneFiltersConfiguration.CheckboxLabel, - iconProps: { iconName: 'CheckboxComposite' } - }, - { - key: BuiltinFilterTemplates.Date, - text: commonStrings.PropertyPane.PropertyPaneFiltersConfiguration.DateLabel, - iconProps: { iconName: 'DateTime' } - } - ] - } as Partial, - targetProperty: "template" - }, - { - type: ConfigurationFieldType.Toggle, - props: { - label: commonStrings.PropertyPane.PropertyPaneFiltersConfiguration.ShowCountLabel, - } as Partial, - targetProperty: "showCount" - }, - { - type: ConfigurationFieldType.ChoiceGroup, - props: { - label: commonStrings.PropertyPane.PropertyPaneFiltersConfiguration.OperatorLabel, - options: [ - { - key: FilterConditionOperator.AND, - text: "AND" - }, - { - key: FilterConditionOperator.OR, - text: "OR" - } - ] - } as Partial, - targetProperty: "operator" - }, - { - type: ConfigurationFieldType.Toggle, - props: { - label: commonStrings.PropertyPane.PropertyPaneFiltersConfiguration.IsMultiValue, - } as Partial, - targetProperty: "isMulti" - }, - { - type: ConfigurationFieldType.ChoiceGroup, - props: { - label: commonStrings.PropertyPane.PropertyPaneFiltersConfiguration.SortByLabel, - options: [ - { - key: FilterSortType.ByCount, - text: commonStrings.PropertyPane.PropertyPaneFiltersConfiguration.ByCountLabel - }, - { - key: FilterSortType.ByName, - text: commonStrings.PropertyPane.PropertyPaneFiltersConfiguration.ByNameLabel - } - ] - } as Partial, - targetProperty: "sortBy" - }, - { - type: ConfigurationFieldType.ChoiceGroup, - props: { - label: commonStrings.PropertyPane.PropertyPaneFiltersConfiguration.SortDirectionLabel, - options: [ - { - key: FilterSortDirection.Ascending, - text: commonStrings.PropertyPane.PropertyPaneFiltersConfiguration.AscendingLabel - }, - { - key: FilterSortDirection.Descending, - text: commonStrings.PropertyPane.PropertyPaneFiltersConfiguration.DescendingLabel - } - ] - } as Partial, - targetProperty: "sortDirection" - }, - { - type: ConfigurationFieldType.Slider, - props: { - label: commonStrings.PropertyPane.PropertyPaneFiltersConfiguration.NumberOfValuesLabel, - max: 500, - min: 10 - } as Partial, - targetProperty: "maxBuckets" - } - ] - }, - { - name: commonStrings.PropertyPane.PropertyPaneFiltersConfiguration.Aggregations.TabTitle, - fields: [ - { - type: ConfigurationFieldType.RepeatedItem, - targetProperty: "aggregations", - props: { - validateOnLoad: true, - label: commonStrings.PropertyPane.PropertyPaneFiltersConfiguration.Aggregations.TabTitle, - onGetErrorMessage: aggregationsGetErrorMessage, - itemRepeaterProps: { - addButtonLabel: commonStrings.PropertyPane.PropertyPaneFiltersConfiguration.Aggregations.AddBtnLabel, - removeButtonLabel: commonStrings.PropertyPane.PropertyPaneFiltersConfiguration.Aggregations.RemoveBtnLabel, - removeButtonPlacement: IconPlacement.Bottom, - separator: true - } as IItemRepeaterSharedProps, - formConfiguration: [ - { - type: ConfigurationFieldType.LocalizedField, - targetProperty: "aggregationName", - props: { - serviceScope: this.properties.serviceScope, - onGetErrorMessage: localizedStringGetErrorMessage, - required: true - } as Partial - }, - { - type: ConfigurationFieldType.RepeatedItem, - targetProperty: "matchingValues", - props: { - label: commonStrings.PropertyPane.PropertyPaneFiltersConfiguration.Aggregations.MatchingValuesLabel, - formConfiguration: [ - { - type: ConfigurationFieldType.TextField, - targetProperty: null, - props: { - onRenderDescription: (props: ITextFieldProps): JSX.Element => { - if (/^\/.+\/$/gi.test(props.defaultValue)) { - return - {commonStrings.PropertyPane.PropertyPaneFiltersConfiguration.Aggregations.RegularExpressionLabel} - - } - - return null; - } - } as ITextFieldProps - } - ], - newRowDefaultObject: () => "", - itemRepeaterProps: { - addButtonLabel: commonStrings.PropertyPane.PropertyPaneFiltersConfiguration.Aggregations.AddNewValueBtnLabel - } - } as Partial> - }, - { - type: ConfigurationFieldType.TextField, - targetProperty: "aggregationValue", - props: { - label: commonStrings.PropertyPane.PropertyPaneFiltersConfiguration.Aggregations.AggregationValueLabel - } as Partial - }, - { - type: ConfigurationFieldType.TextField, - targetProperty: "aggregationValueIconUrl", - props: { - label: commonStrings.PropertyPane.PropertyPaneFiltersConfiguration.Aggregations.IconUrlLabel - } as Partial - } - ], - newRowDefaultObject: () => { return { - aggregationName: "", - aggregationValue: "", - matchingValues: [], - aggregationValueIconUrl: "" - }} - } as Partial> - } - ] - } - ]; - - // Add visibility section if connected to a vertical - if (this.properties.verticalsConfiguration) { - this.filterTabsConfiguration.push( - { - name: commonStrings.PropertyPane.PropertyPaneFiltersConfiguration.DisplaySettings.TabTitle, - fields: [ - { - type: ConfigurationFieldType.Dropdown, - targetProperty: "verticalKeys", - props: { - multiSelect: true, - placeholder: commonStrings.PropertyPane.PropertyPaneFiltersConfiguration.DisplaySettings.PlaceholderLabel, - label: commonStrings.PropertyPane.PropertyPaneFiltersConfiguration.DisplaySettings.SelectTabLabel, - options: this.properties.verticalsConfiguration.map((v) => { - return { - key: v.key, - text: v.tabName - } - }) - } as IDropdownProps - } - ] - } - ) - } - - this.mainFormFields = [ - { - type: ConfigurationFieldType.Custom, - targetProperty: null, - onCustomRender: (field, defaultValue, onUpdate) => { - - this._lastCreatedConfigurationPanelRef = React.createRef>(); - - return - ref={this._lastCreatedConfigurationPanelRef} - configurationTabs={this.filterTabsConfiguration} - renderRowTitle={(filter: IDataFilterConfiguration) => { return LocalizedStringHelper.getDefaultValue(filter.displayName) }} - onFormSave={(formData) => { onUpdate(field, formData)}} - dataObject={defaultValue} - renderPanelTitle={() => commonStrings.PropertyPane.PropertyPaneFiltersConfiguration.AddNewFilterBtnLabel } - onFormDismissed={(configuration: IDataFilterConfiguration) => { - - if (isEqual(configuration, this.newFilterBaseConfiguration)) { - // Remove row as no item has been saved - this._itemRepeaterRef.current.deleteItemRow(this._lastRowId) - } - }} - />; - } - } - ]; - } - - public render(): void { - if (!this.elem) { - return; - } - - this.onRender(this.elem); - } - - private onDispose(element: HTMLElement): void { - ReactDom.unmountComponentAtNode(element); - } - private onRender(elem: HTMLElement, ctx?: BaseComponentContext, changeCallback?: (targetProperty?: string, newValue?: IDataFilterConfiguration[]) => void): void { - - if (!this.elem) { - this.elem = elem; - } - - const element = - formConfiguration={this.mainFormFields} - itemRepeaterProps={{ - addButtonLabel: commonStrings.PropertyPane.PropertyPaneFiltersConfiguration.AddNewFilterBtnLabel, - enableDragDrop: true, - innerRef: this._itemRepeaterRef - }} - newRowDefaultObject={(): IDataFilterConfiguration => { - return this.newFilterBaseConfiguration; - }} - items={this.properties.defaultValue} - onChange={(value: IDataFilterConfiguration[], errors?: Map) => { - changeCallback(this.targetProperty, value); - }} - onRowAdded={(rowId) => { - // Save the row id to be able to delete it afterwards - this._lastRowId = rowId; - // Get the last created row (empty at this point) and open the panel - this._lastCreatedConfigurationPanelRef.current.togglePanel(); - }} - onRowsOrderChanged={(value: IDataFilterConfiguration[]) => { - - // Update the sortIdx proeprty according to the array sort order - const filterConfiguration = value.map((configuration, i) => { - configuration.sortIdx = i; - return configuration; - }); - - changeCallback(this.targetProperty, filterConfiguration); - }} - />; - - ReactDom.render(element, elem); - } -} \ No newline at end of file diff --git a/packages/spfx/src/propertyPane/PropertyPaneFormDataCollection/IPropertyPaneFormDataCollectionInternalProps.ts b/packages/spfx/src/propertyPane/PropertyPaneFormDataCollection/IPropertyPaneFormDataCollectionInternalProps.ts deleted file mode 100644 index f0f1d0a..0000000 --- a/packages/spfx/src/propertyPane/PropertyPaneFormDataCollection/IPropertyPaneFormDataCollectionInternalProps.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { IPropertyPaneCustomFieldProps } from "@microsoft/sp-property-pane"; -import { IPropertyPaneFormDataCollectionProps } from "./IPropertyPaneFormDataCollectionProps"; - -export interface IPropertyPaneFormDataCollectionInternalProps extends IPropertyPaneFormDataCollectionProps, IPropertyPaneCustomFieldProps { -} \ No newline at end of file diff --git a/packages/spfx/src/propertyPane/PropertyPaneFormDataCollection/IPropertyPaneFormDataCollectionProps.ts b/packages/spfx/src/propertyPane/PropertyPaneFormDataCollection/IPropertyPaneFormDataCollectionProps.ts deleted file mode 100644 index 07b64cf..0000000 --- a/packages/spfx/src/propertyPane/PropertyPaneFormDataCollection/IPropertyPaneFormDataCollectionProps.ts +++ /dev/null @@ -1,4 +0,0 @@ -import { IFormDataCollectionSharedProps } from "../../controls/FormDataCollection/IFormDataCollectionProps"; - -export interface IPropertyPaneFormDataCollectionProps extends IFormDataCollectionSharedProps { -} \ No newline at end of file diff --git a/packages/spfx/src/propertyPane/PropertyPaneFormDataCollection/PropertyPaneFormDataCollection.tsx b/packages/spfx/src/propertyPane/PropertyPaneFormDataCollection/PropertyPaneFormDataCollection.tsx deleted file mode 100644 index 6fe93a6..0000000 --- a/packages/spfx/src/propertyPane/PropertyPaneFormDataCollection/PropertyPaneFormDataCollection.tsx +++ /dev/null @@ -1,63 +0,0 @@ -import { - IPropertyPaneField, - PropertyPaneFieldType - } from '@microsoft/sp-property-pane'; -import * as ReactDom from 'react-dom'; -import * as React from 'react'; -import { IPropertyPaneFormDataCollectionProps } from './IPropertyPaneFormDataCollectionProps'; -import { IPropertyPaneFormDataCollectionInternalProps } from './IPropertyPaneFormDataCollectionInternalProps'; -import { FormDataCollection } from '../../controls/FormDataCollection/FormDataCollection'; -import { IFormDataCollectionProps } from '../../controls/FormDataCollection/IFormDataCollectionProps'; -import { BaseComponentContext } from '@microsoft/sp-component-base'; - -export class PropertyPaneFormDataCollection implements IPropertyPaneField> { - - public type: PropertyPaneFieldType = PropertyPaneFieldType.Custom; - public targetProperty: string; - public shouldFocus?: boolean; - public properties: IPropertyPaneFormDataCollectionInternalProps; - private elem: HTMLElement; - - constructor(targetProperty: string, properties: IPropertyPaneFormDataCollectionProps) { - - this.targetProperty = targetProperty; - this.properties = { - key: targetProperty, - onRender: this.onRender.bind(this), - onDispose: this.onDispose.bind(this), - ...properties - }; - } - - public render(): void { - if (!this.elem) { - return; - } - - this.onRender(this.elem); - } - - private onDispose(element: HTMLElement): void { - ReactDom.unmountComponentAtNode(element); - } - private onRender(elem: HTMLElement, ctx?: BaseComponentContext, changeCallback?: (targetProperty?: string, newValue?: T[]) => void): void { - - if (!this.elem) { - this.elem = elem; - } - - const props = { - ...this.properties, - onChange: (newValues: T[], errors: Map) => { - // Don't save the field if there is an error - if (!errors || errors?.size === 0) { - changeCallback(this.targetProperty, newValues) - } - - } - } as IFormDataCollectionProps; - - const renderElement = {...props}/>; - ReactDom.render(renderElement, elem); - } -} \ No newline at end of file diff --git a/packages/spfx/src/propertyPane/PropertyPaneNonReactiveTextField/IPropertyPaneNonReactiveTextFieldProps.ts b/packages/spfx/src/propertyPane/PropertyPaneNonReactiveTextField/IPropertyPaneNonReactiveTextFieldProps.ts deleted file mode 100644 index 63a2cd0..0000000 --- a/packages/spfx/src/propertyPane/PropertyPaneNonReactiveTextField/IPropertyPaneNonReactiveTextFieldProps.ts +++ /dev/null @@ -1,47 +0,0 @@ -export interface IPropertyPaneNonReactiveTextFieldProps { - - /** - * The unique key for the component - */ - componentKey: string; - - /** - * The default value to display - */ - defaultValue?: string; - - /** - * The placeholder to display in the text field - */ - placeholderText?: string; - - /** - * If the text field should be multiline - */ - multiline?: boolean; - - /** - * The text field label - */ - label?: string; - - /** - * The text field description - */ - description?: string; - - /** - * The text to display in the 'apply' button - */ - applyBtnText?: string; - - /** - * The number of rows to display - */ - rows?: number; - - /** - * Flag indicating if the user can save an empty value - */ - allowEmptyValue?: boolean; -} \ No newline at end of file diff --git a/packages/spfx/src/propertyPane/PropertyPaneNonReactiveTextField/PropertyPaneNonReactiveTextField.ts b/packages/spfx/src/propertyPane/PropertyPaneNonReactiveTextField/PropertyPaneNonReactiveTextField.ts deleted file mode 100644 index 2092c32..0000000 --- a/packages/spfx/src/propertyPane/PropertyPaneNonReactiveTextField/PropertyPaneNonReactiveTextField.ts +++ /dev/null @@ -1,78 +0,0 @@ -import * as React from 'react'; -import * as ReactDom from 'react-dom'; -import { IPropertyPaneCustomFieldProps, IPropertyPaneField, PropertyPaneFieldType } from '@microsoft/sp-property-pane'; -import { IPropertyPaneNonReactiveTextFieldProps } from './IPropertyPaneNonReactiveTextFieldProps'; -import { NonReactiveTextField } from "./components/NonReactiveTextField"; -import { INonReactiveTextFieldProps } from "./components/INonReactiveTextFieldProps"; -import { BaseComponentContext } from '@microsoft/sp-component-base'; - -export interface IPropertyPaneNonReactiveTextFieldInternalProps extends IPropertyPaneNonReactiveTextFieldProps, IPropertyPaneCustomFieldProps { -} - -export class PropertyPaneNonReactiveTextField implements IPropertyPaneField { - - public type: PropertyPaneFieldType = PropertyPaneFieldType.Custom; - public targetProperty: string; - public shouldFocus?: boolean; - public properties: IPropertyPaneNonReactiveTextFieldInternalProps; - private elem: HTMLElement; - - constructor(targetProperty: string, properties: IPropertyPaneNonReactiveTextFieldProps) { - this.targetProperty = targetProperty; - - this.properties = { - componentKey: properties.componentKey, - key: properties.componentKey, - description: properties.description, - label: properties.label, - placeholderText: properties.placeholderText, - multiline: properties.multiline, - onRender: this.onRender.bind(this), - onDispose: this.onDispose.bind(this), - applyBtnText: properties.applyBtnText, - defaultValue: properties.defaultValue, - rows: properties.rows, - allowEmptyValue: properties.allowEmptyValue - }; - } - - public render(): void { - if (!this.elem) { - return; - } - - this.onRender(this.elem); - } - - private onDispose(element: HTMLElement): void { - ReactDom.unmountComponentAtNode(element); - } - - private onRender(elem: HTMLElement, ctx?: BaseComponentContext, changeCallback?: (targetProperty?: string, newValue?: unknown) => void): void { - - if (!this.elem) { - this.elem = elem; - } - - // eslint-disable-next-line @typescript-eslint/no-explicit-any - const element: React.ReactElement = React.createElement("div", { key: this.properties.key }, - React.createElement(NonReactiveTextField, { - key: this.properties.componentKey, - onUpdate: ((value: string) => { - changeCallback(this.targetProperty, value); - }).bind(this), - description: this.properties.description, - label: this.properties.label, - multiline: this.properties.multiline, - placeholderText: this.properties.placeholderText, - applyBtnText: this.properties.applyBtnText, - defaultValue: this.properties.defaultValue, - rows: this.properties.rows, - allowEmptyValue: this.properties.allowEmptyValue - } as INonReactiveTextFieldProps) - ); - - ReactDom.render(element, elem); - } - -} \ No newline at end of file diff --git a/packages/spfx/src/propertyPane/PropertyPaneNonReactiveTextField/components/INonReactiveTextFieldProps.ts b/packages/spfx/src/propertyPane/PropertyPaneNonReactiveTextField/components/INonReactiveTextFieldProps.ts deleted file mode 100644 index c592758..0000000 --- a/packages/spfx/src/propertyPane/PropertyPaneNonReactiveTextField/components/INonReactiveTextFieldProps.ts +++ /dev/null @@ -1,52 +0,0 @@ -export interface INonReactiveTextFieldProps { - - /** - * Unique key for the component - */ - key?: string; - - /** - * The default value to display - */ - defaultValue?: string; - - /** - * Handler when a field value is updated - */ - onUpdate: (value: string) => void; - - /** - * The placeholder to display in the text field - */ - placeholderText?: string; - - /** - * If the text field should be multiline - */ - multiline?: boolean; - - /** - * The text field lable - */ - label?: string; - - /** - * The text field description - */ - description?: string; - - /** - * The text to display in the 'apply' button - */ - applyBtnText?: string; - - /** - * The number of rows to display - */ - rows?: number; - - /** - * Flag indicating if the user can save an empty value - */ - allowEmptyValue?: boolean; -} \ No newline at end of file diff --git a/packages/spfx/src/propertyPane/PropertyPaneNonReactiveTextField/components/INonReactiveTextFieldState.ts b/packages/spfx/src/propertyPane/PropertyPaneNonReactiveTextField/components/INonReactiveTextFieldState.ts deleted file mode 100644 index 3b902f3..0000000 --- a/packages/spfx/src/propertyPane/PropertyPaneNonReactiveTextField/components/INonReactiveTextFieldState.ts +++ /dev/null @@ -1,12 +0,0 @@ -export interface INonReactiveTextFieldState { - - /** - * Content of the text field - */ - value: string; - - /** - * The icon to display in the button - */ - iconName: string; -} \ No newline at end of file diff --git a/packages/spfx/src/propertyPane/PropertyPaneNonReactiveTextField/components/NonReactiveTextField.tsx b/packages/spfx/src/propertyPane/PropertyPaneNonReactiveTextField/components/NonReactiveTextField.tsx deleted file mode 100644 index 3ac6bf0..0000000 --- a/packages/spfx/src/propertyPane/PropertyPaneNonReactiveTextField/components/NonReactiveTextField.tsx +++ /dev/null @@ -1,75 +0,0 @@ -import * as React from 'react'; -import { INonReactiveTextFieldProps } from './INonReactiveTextFieldProps'; -import { INonReactiveTextFieldState } from './INonReactiveTextFieldState'; -import { TextField, PrimaryButton, IButtonProps } from "office-ui-fabric-react"; -import { isEqual } from '@microsoft/sp-lodash-subset'; - -export class NonReactiveTextField extends React.Component { - - public constructor(props: INonReactiveTextFieldProps) { - super(props); - - this.state = { - value: props.defaultValue, - iconName: null - }; - - this._onChange = this._onChange.bind(this); - this._onApply = this._onApply.bind(this); - } - - public render(): React.ReactNode { - - const iconProps: IButtonProps = this.state.iconName ? {iconProps:{iconName: this.state.iconName}} : null; - const isDisabled = (!this.state.value && !this.props.allowEmptyValue) || isEqual(this.state.value, this.props.defaultValue); - - return <> - - - ; - } - - - public componentDidUpdate(prevProps: INonReactiveTextFieldProps): void { - if (!isEqual(prevProps.defaultValue, this.props.defaultValue)) { - this.setState({ - value: this.props.defaultValue - }); - } - } - - public _onChange(event: React.FormEvent, newValue?: string): void { - - this.setState({ - value: newValue, - iconName: newValue !== this.props.defaultValue ? 'Save' : null - }); - } - - public _onApply(): void { - this.props.onUpdate(this.state.value); - - this.setState({ - iconName: 'Accept' - }); - } -} \ No newline at end of file diff --git a/packages/spfx/src/services/dynamicDataService/DynamicDataService.ts b/packages/spfx/src/services/dynamicDataService/DynamicDataService.ts deleted file mode 100644 index 7818b34..0000000 --- a/packages/spfx/src/services/dynamicDataService/DynamicDataService.ts +++ /dev/null @@ -1,55 +0,0 @@ -import IDynamicDataService from "./IDynamicDataService"; -import { DynamicDataProvider } from "@microsoft/sp-component-base"; -import { IDynamicDataSource } from "@microsoft/sp-dynamic-data"; -import { ServiceScope, ServiceKey } from "@microsoft/sp-core-library"; -import IDynamicDataSourceProperty from "../../models/dynamicData/IDynamicDataSourceProperty"; - -const DynamicDataService_ServiceKey = 'PnPModernSearchDynamicDataService'; - -export class DynamicDataService implements IDynamicDataService { - - public static ServiceKey: ServiceKey = ServiceKey.create(DynamicDataService_ServiceKey, DynamicDataService); - - private _dynamicDataProvider: DynamicDataProvider; - - get dynamicDataProvider(): DynamicDataProvider { - return this._dynamicDataProvider; - } - - set dynamicDataProvider(value: DynamicDataProvider) { - this._dynamicDataProvider = value; - } - - // eslint-disable-next-line @typescript-eslint/no-empty-function - constructor(serviceScope: ServiceScope) { - } - - /** - * Get available data sources on the page with specific property Id (i.e. corresponding to the underlying component type) - * @param propertyId The property id to look for to determine sources - */ - public async getAvailableDataSourcesByType(propertyId: string): Promise { - - const propertyOptions: IDynamicDataSourceProperty[] = []; - - if (!this.dynamicDataProvider.isDisposed) { - this._dynamicDataProvider.getAvailableSources().forEach(async (sourceInfo) => { - const source: IDynamicDataSource = this._dynamicDataProvider.tryGetSource(sourceInfo.id); - if (source) { - const properties = await source.getPropertyDefinitionsAsync(); - properties.forEach(prop => { - if (prop.id === propertyId) { - propertyOptions.push({ - key: `${source.id}:${prop.id}`, - text: prop.title - }); - } - }); - } - }); - } - - return propertyOptions; - } - -} \ No newline at end of file diff --git a/packages/spfx/src/services/dynamicDataService/IDynamicDataService.ts b/packages/spfx/src/services/dynamicDataService/IDynamicDataService.ts deleted file mode 100644 index a9d43a2..0000000 --- a/packages/spfx/src/services/dynamicDataService/IDynamicDataService.ts +++ /dev/null @@ -1,8 +0,0 @@ - -import { DynamicDataProvider } from "@microsoft/sp-component-base"; -import IDynamicDataSourceProperty from "../../models/dynamicData/IDynamicDataSourceProperty"; - -export default interface IDynamicDataService { - dynamicDataProvider: DynamicDataProvider; - getAvailableDataSourcesByType(propertyId: string): Promise; -} \ No newline at end of file diff --git a/packages/spfx/src/services/fileService/FileService.ts b/packages/spfx/src/services/fileService/FileService.ts deleted file mode 100644 index cc68115..0000000 --- a/packages/spfx/src/services/fileService/FileService.ts +++ /dev/null @@ -1,51 +0,0 @@ -import { IFilePickerResult } from "@pnp/spfx-controls-react"; -import IFileService from "./IFileService"; -import { ServiceKey, ServiceScope } from "@microsoft/sp-core-library"; -import { FilesSearchService } from "@pnp/spfx-controls-react/lib/services/FilesSearchService"; -import { BaseComponentContext } from "@microsoft/sp-component-base"; -import { PageContext } from "@microsoft/sp-page-context"; -import { HttpClient, SPHttpClient } from "@microsoft/sp-http"; - -const FileService_ServiceKey = 'ModernSearchCoreFileService'; - -export class FileService implements IFileService { - - public _fileSearchService: FilesSearchService; - public static ServiceKey: ServiceKey = ServiceKey.create(FileService_ServiceKey, FileService); - - constructor(serviceScope: ServiceScope) { - - serviceScope.whenFinished(() => { - - const pageContext = serviceScope.consume(PageContext.serviceKey); - const spHttpClient = serviceScope.consume(SPHttpClient.serviceKey); - const httpClient = serviceScope.consume(HttpClient.serviceKey); - - const context: Partial = { - pageContext: pageContext, - spHttpClient: spHttpClient, - httpClient: httpClient - }; - - this._fileSearchService = new FilesSearchService(context as BaseComponentContext, null); - - }) - } - - public async downloadFileContent(filePickerResult: IFilePickerResult): Promise { - - let file = null; - let fileContent = null; - if (filePickerResult.spItemUrl) { - file = await this._fileSearchService.downloadSPFileContent(filePickerResult.fileAbsoluteUrl, filePickerResult.fileName); - } else { - file = await this._fileSearchService.downloadBingContent(filePickerResult.fileAbsoluteUrl, filePickerResult.fileName); - } - - if (file) { - fileContent = await file.text(); - } - - return fileContent; - } -} \ No newline at end of file diff --git a/packages/spfx/src/services/fileService/IFileService.ts b/packages/spfx/src/services/fileService/IFileService.ts deleted file mode 100644 index 5bef3d6..0000000 --- a/packages/spfx/src/services/fileService/IFileService.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { IFilePickerResult } from "@pnp/spfx-controls-react"; -import { FilesSearchService } from "@pnp/spfx-controls-react/lib/services/FilesSearchService"; - -export default interface IFileService { - _fileSearchService: FilesSearchService; - downloadFileContent(filePickerResult: IFilePickerResult): Promise; -} \ No newline at end of file diff --git a/packages/spfx/src/services/localizationService/ILocalizationService.ts b/packages/spfx/src/services/localizationService/ILocalizationService.ts deleted file mode 100644 index a841a80..0000000 --- a/packages/spfx/src/services/localizationService/ILocalizationService.ts +++ /dev/null @@ -1,12 +0,0 @@ -export interface ILocalizationService { - - /** - * Gets all supported locales (available translations) according to site settings - */ - getSiteSupportedLocales(): Promise; - - /** - * Returns the current page locale (ex: fr-fr) regarding if it is a translation or not. In the latter, the current UI locale is returned. - */ - getCurrentPageUILanguage(): Promise; -} \ No newline at end of file diff --git a/packages/spfx/src/services/localizationService/LocalizationService.ts b/packages/spfx/src/services/localizationService/LocalizationService.ts deleted file mode 100644 index 88a1fd9..0000000 --- a/packages/spfx/src/services/localizationService/LocalizationService.ts +++ /dev/null @@ -1,155 +0,0 @@ -import { ServiceKey, ServiceScope } from "@microsoft/sp-core-library"; -import { ILocalizationService } from "./ILocalizationService"; -import { SPHttpClient } from "@microsoft/sp-http"; -import { PageContext } from "@microsoft/sp-page-context"; - -const LocalizationService_ServiceKey = "ModernSearchCoreLocalizationService"; - -export class LocalizationService implements ILocalizationService { - - /** - * The current page context - */ - private pageContext: PageContext; - - /** - * The SPHttpClient instance - */ - private spHttpClient: SPHttpClient; - - private _supportedLocales: string[]; - - // Locales to match with this.context.pageContext.cultureInfo.currentUICultureName for SPFx - public static locales = new Map([ - [1025,"ar-SA"], - [1026, "bg-BG"], - [1027, "ca-ES"], - [1028, "zh-TW"], - [1029, "cs-CZ"], - [1030, "da-DK"], - [1031, "de-DE"], - [1032, "el-GR"], - [1033, "en-US"], - [1035, "fi-FI"], - [1036, "fr-FR"], - [1037, "he-IL"], - [1038, "hu-HU"], - [1040, "it-IT"], - [1041, "ja-JP"], - [1042, "ko-KR"], - [1043, "nl-NL"], - [1044, "nb-NO"], - [1045, "pl-PL"], - [1046, "pt-BR"], - [1048, "ro-RO"], - [1049, "ru-RU"], - [1050, "hr-HR"], - [1051, "sk-SK"], - [1053, "sv-SE"], - [1054, "th-TH"], - [1055, "tr-TR"], - [1057, "id-ID"], - [1058, "uk-UA"], - [1060, "sl-SI"], - [1061, "et-EE"], - [1062, "lv-LV"], - [1063, "lt-LT"], - [1066, "vi-VN"], - [1068, "az-Latn-AZ"], - [1069, "eu-ES"], - [1071, "mk-MK"], - [1081, "hi-IN"], - [1086, "ms-MY"], - [1087, "kk-KZ"], - [1106, "cy-GB"], - [1110, "gl-ES"], - [1164, "prs-AF"], - [2052, "zh-CN"], - [2070, "pt-PT"], - [2074, "sr-Latn-CS"], - [2108, "ga-IE"], - [3082, "es-ES"], - [5146, "bs-Latn-BA"], - [9242, "sr-Latn-RS"], - [10266, "sr-Cyrl-RS"], - ]); - - public constructor(serviceScope: ServiceScope) { - - serviceScope.whenFinished(() => { - - this.pageContext = serviceScope.consume(PageContext.serviceKey); - this.spHttpClient = serviceScope.consume(SPHttpClient.serviceKey); - }); - } - - public static ServiceKey: ServiceKey = ServiceKey.create(LocalizationService_ServiceKey, LocalizationService); - - public async getSiteSupportedLocales(): Promise { - - if (this._supportedLocales) { - return this._supportedLocales; - } - - // Look at missing translations on the home page of the site - // If translations are not enabled in the site settings, supported locales array will be empty - const response = await this.spHttpClient.get(`${this.pageContext.site.absoluteUrl}/_api/sitepages/pages?$select=Translations&$expand=Translations&$filter=IsWebWelcomePage eq true`, SPHttpClient.configurations.v1); - - if (response.ok) { - const localesJson = await response.json(); - this._supportedLocales = localesJson.value[0].Translations.UntranslatedLanguages; - return this._supportedLocales; - } - - return []; - } - - public async getCurrentPageUILanguage(): Promise { - - try { - - const listId = this.pageContext.list.id; - const itemId = this.pageContext.listItem.id; - - const response = await this.spHttpClient.post( `${this.pageContext.web.absoluteUrl}/_api/web/Lists(guid'${listId}')/RenderListDataAsStream`, SPHttpClient.configurations.v1, { - body: JSON.stringify({ - parameters: { - RenderOptions: 2, - ViewXml:` - - - - - - - - - - - - ${itemId} - - - - - - ` - } - }) - }); - - if (response.ok) { - const page = await response.json(); - const pageLocale = page?.Row[0]?._SPTranslationLanguage; - if (pageLocale) { - return pageLocale; - } - - return this.pageContext.cultureInfo.currentUICultureName.toLocaleLowerCase(); - } - - } catch(error) { - return this.pageContext.cultureInfo.currentUICultureName.toLocaleLowerCase(); - } - } -} \ No newline at end of file diff --git a/packages/spfx/src/services/tokenService/ISharePointTokenService.ts b/packages/spfx/src/services/tokenService/ISharePointTokenService.ts deleted file mode 100644 index 0ad41f1..0000000 --- a/packages/spfx/src/services/tokenService/ISharePointTokenService.ts +++ /dev/null @@ -1,25 +0,0 @@ -export interface ISharePointTokenService { - - /** - * Retrieves available current page properties - * @internal this method is not intended to be used directly in your code. - */ - getPageProperties(): Promise; - - /** - * Retrieve all current user profile properties - * @internal this method is not intended to be used directly in your code. - */ - getUserProfileProperties(): Promise; - - /** - * Resolve tokens from input string - * @param inputString the string to resolve - */ - resolveTokens(inputString: string): Promise; - -} - -export interface IProfileProperties { - [propertyName: string]: string; -} diff --git a/packages/spfx/src/services/tokenService/SharePointTokenService.ts b/packages/spfx/src/services/tokenService/SharePointTokenService.ts deleted file mode 100644 index a66387e..0000000 --- a/packages/spfx/src/services/tokenService/SharePointTokenService.ts +++ /dev/null @@ -1,633 +0,0 @@ -/* eslint-disable @typescript-eslint/no-explicit-any */ -/* eslint-disable @rushstack/security/no-unsafe-regexp */ -/* eslint-disable require-atomic-updates */ -import { ServiceKey, ServiceScope, Log } from "@microsoft/sp-core-library"; -import { PageContext } from '@microsoft/sp-page-context'; -import { SPHttpClient } from '@microsoft/sp-http'; -import { DateHelper } from '@pnp/modern-search-core/dist/es6/helpers/DateHelper'; -import { Constants } from "../../common/Constants"; -import { ObjectHelper } from '@pnp/modern-search-core/dist/es6/helpers/ObjectHelper'; -import { isEmpty, uniq } from "@microsoft/sp-lodash-subset"; -import { IProfileProperties, ISharePointTokenService } from "./ISharePointTokenService"; - -const TokenService_ServiceKey = 'ModernSearchCoreSharePointTokenService'; - -export class SharePointTokenService implements ISharePointTokenService { - - /** - * The list of user properties. Used to avoid refetching it every time. - */ - private userProperties: IProfileProperties = null; - - /** - * The current page item. Used to avoid refetching it every time. - */ - private currentPageItem: { [key:string] : unknown } = null; - - /** - * The current service scope - */ - private serviceScope: ServiceScope; - - /** - * The current page context - */ - private pageContext: PageContext; - - /** - * The SPHttpClient instance - */ - private spHttpClient: SPHttpClient; - - /** - * A date helper instance - */ - private dateHelper: DateHelper; - - /** - * The moment.js library reference - */ - private dayJs: any; - - public static ServiceKey: ServiceKey = ServiceKey.create(TokenService_ServiceKey, SharePointTokenService); - - public constructor(serviceScope: ServiceScope) { - - this.serviceScope = serviceScope; - - serviceScope.whenFinished(() => { - - this.pageContext = serviceScope.consume(PageContext.serviceKey); - this.spHttpClient = serviceScope.consume(SPHttpClient.serviceKey); - - this.dateHelper = new DateHelper(); - }); - } - - public async resolveTokens(inputString: string): Promise { - - if (inputString) { - - this.dayJs = await this.dateHelper.dayJs(this.pageContext.cultureInfo.currentUICultureName); - - // Resolves dynamic tokens (i.e. tokens resolved asynchronously versus static ones set by the Web Part context) - inputString = await this.replacePageTokens(inputString); - inputString = await this.replaceUserTokens(inputString); - inputString = this.replaceDateTokens(inputString); - inputString = this.replaceQueryStringTokens(inputString); - inputString = this.replaceWebTokens(inputString); - inputString = this.replacePageContextTokens(inputString); - inputString = this.replaceSiteTokens(inputString); - inputString = this.replaceListTokens(inputString); - inputString = this.replaceGroupTokens(inputString); - inputString = this.replaceLegacyPageContextTokens(inputString); - inputString = await this.replaceHubTokens(inputString); - inputString = inputString.replace(/\{TenantUrl\}/gi, `https://` + window.location.host); - - // The 'OR/AND' operator should be called after all tokens are processed (works with comma delimited values potentially coming from resolved) - inputString = this.replaceAndOrOperator(inputString); - } - - return inputString; - } - - /** - * Retrieves available current page item properties - */ - public async getPageProperties(): Promise<{}> { - - let item = null; - - // Do this check to ensure we are not in the workbench - if (this.pageContext.listItem) { - - const url = this.pageContext.web.absoluteUrl + `/_api/web/GetList(@v1)/RenderExtendedListFormData(itemId=${this.pageContext.listItem.id},formId='viewform',mode='2',options=7)?@v1='${this.pageContext.list.serverRelativeUrl}'`; - - try { - const response = await this.spHttpClient.post(url, SPHttpClient.configurations.v1, { - headers: { - 'X-ClientService-ClientTag': Constants.X_CLIENTSERVICE_CLIENTTAG, - 'UserAgent': Constants.X_CLIENTSERVICE_CLIENTTAG - } - }); - - if (response.ok) { - const result = await response.json(); - const itemRow = JSON.parse(result.value); - // Lower case all properties - // https://codereview.stackexchange.com/questions/162416/object-keys-to-lowercase - // eslint-disable-next-line no-sequences - item = Object.keys(itemRow.Data.Row[0]) - .reduce((c: {[key: string]: any}, k: string) => { - c[k] = itemRow.Data.Row[0][k]; - return c; - },{}); - } - else { - throw response.statusText; - } - - } catch (error) { - const errorMessage = error ? error.message : `Failed to resolve page tokens`; - Log.error(TokenService_ServiceKey, new Error(`Error: '${error}'`), this.serviceScope); - throw new Error(errorMessage); - } - } - - return item; - } - - /** - * Retrieve all current user profile properties - */ - public async getUserProfileProperties(): Promise { - - let responseJson = null; - const userProperties: IProfileProperties = {}; - const endpoint = `${this.pageContext.web.absoluteUrl}/_api/SP.UserProfiles.PeopleManager/GetMyProperties`; - const response = await this.spHttpClient.get(endpoint, SPHttpClient.configurations.v1, { - headers: { - 'X-ClientService-ClientTag': Constants.X_CLIENTSERVICE_CLIENTTAG, - 'UserAgent': Constants.X_CLIENTSERVICE_CLIENTTAG - } - }); - - if (response.ok) { - responseJson = await response.json(); - - if (responseJson.UserProfileProperties) { - - responseJson.UserProfileProperties.forEach((property: any) => { - userProperties[property.Key.toLowerCase()] = property.Value; - }); - } - - return userProperties; - - } else { - - const errorMessage = `${TokenService_ServiceKey}: Error retrieving user profiel properties. Details: ${(response as any).statusMessage ? (response as any).statusMessage : response.status}`; - const error = new Error(errorMessage); - - Log.error(TokenService_ServiceKey, error, this.serviceScope); - throw error; - } - } - - /** - * Resolve current page values from tokens - * @param inputString the input string containing tokens - */ - private async replacePageTokens(inputString: string): Promise { - - const pageTokenRegExp: RegExp = /\{(?:Page)\.(.*?)\}/gi; - let matches = pageTokenRegExp.exec(inputString); - let item: { [key: string] : any } = {}; - - // Make a check to the listItem property in the case we are in the hosted workbench - if (matches !== null && this.pageContext.listItem) { - - let pageItem = this.currentPageItem; - - if (!pageItem) { - // Get page properties dymamically - pageItem = await this.getPageProperties(); - } - - const properties = Object.keys(pageItem); - properties.forEach(property => { - item[property] = pageItem[property]; - }); - - item = this.recursivelyLowercaseJSONKeys(item); - - // eslint-disable-next-line no-unmodified-loop-condition - while (matches !== null && item !== null) { - - const pageProperty = matches[1]; - let itemProp: string = ''; // Return an empty string when not found instead of undefined since this value will be translated as text - - if (/\.Label|\.TermID/gi.test(pageProperty)) { - - const term = pageProperty.split("."); - const columnName = term[0].toLowerCase(); - const labelOrTermId = term[1].toLowerCase(); - - // Handle multi or single taxonomy values - if (Array.isArray(item[columnName]) && item[columnName].length > 0) { - - // By convention, multi values should be separated by a comma, which is the default array delimiter for the array toString() method - // This value could be processed in the replaceAndOrOperator() method so we need to keep the same delimiter convention - itemProp = item[columnName].map((taxonomyValue: any) => { - return taxonomyValue[labelOrTermId]; // Use the 'TermId' or 'Label' properties - }).join(','); - } - else if (!Array.isArray(item[columnName]) && item[columnName] !== undefined && item[columnName] !== "") { - itemProp = item[columnName][labelOrTermId]; - } - - } else { - - // Return the property as is - itemProp = ObjectHelper.getPropertyByPath(item, pageProperty.toLowerCase()); - } - - inputString = inputString.replace(matches[0], itemProp); - matches = pageTokenRegExp.exec(inputString); - } - } - - return inputString; - } - - /** - * Resolve current page context related tokens - * @param inputString the input string containing tokens - */ - private replacePageContextTokens(inputString: string): string { - - const siteRegExp = /\{(?:PageContext)\.(.*?)\}/gi; - let matches = siteRegExp.exec(inputString); - - if (matches !== null) { - - while (matches !== null) { - const prop = matches[1]; - inputString = inputString.replace(new RegExp(matches[0], "gi"), this.pageContext ? ObjectHelper.getPropertyByPath(this.pageContext, prop) : ''); - matches = siteRegExp.exec(inputString); - } - } - - return inputString; - } - - /** - * Resolve current user property values from tokens - * @param inputString the input string containing tokens - */ - private async replaceUserTokens(inputString: string): Promise { - - const userTokenRegExp: RegExp = /\{(?:User)\.(.*?)\}/gi; - let matches = userTokenRegExp.exec(inputString.toLowerCase()); - - // Browse matched tokens - while (matches !== null) { - - const userProperty = matches[1].toLowerCase(); - let propertyValue = null; - - // Check if other user profile properties have to be retrieved - if (!/^(name|email)$/gi.test(userProperty)) { - - // Check if the user profile api was already called - if (!this.userProperties) { - this.userProperties = await this.getUserProfileProperties(); - } - - // Need to enclose with quotes because of dash separated values (ex: "sps-interests") - propertyValue = ObjectHelper.getPropertyByPath(this.userProperties, `"${userProperty}"`); - - } else { - - switch (userProperty) { - - case "email": - propertyValue = this.pageContext.user.email; - break; - - case "name": - propertyValue = this.pageContext.user.displayName; - break; - default: - propertyValue = this.pageContext.user.displayName; - break; - } - } - - // If value not found in the fetched properties, let the value untouched to be resolved server side by a query variable - // Ex: {User.Audiences} or {User.PreferredDisplayLanguage} - if (propertyValue !== undefined) { - - const tokenExprToReplace = new RegExp(matches[0], 'gi'); - - // Replace the match with the property value - inputString = inputString.replace(tokenExprToReplace, propertyValue); - } - - // Look for other tokens - matches = userTokenRegExp.exec(inputString); - } - - inputString = inputString.replace(/\{Me\}/gi, this.pageContext.user.displayName); - - return inputString; - } - - /** - * Resolve date related tokens - * @param inputString the input string containing tokens - */ - private replaceDateTokens(inputString: string): string { - - const currentDate = /\{CurrentDate\}/gi; - const currentMonth = /\{CurrentMonth\}/gi; - const currentYear = /\{CurrentYear\}/gi; - - // Replaces any "{Today} +/- [digit]" expression - const results = /\{Today\s*[+-]\s*\[{0,1}\d{1,}\]{0,1}\}/gi; - let match: any; - while ((match = results.exec(inputString)) !== null) { - for (const result of match) { - const operator = result.indexOf('+') !== -1 ? '+' : '-'; - const addOrRemove = operator === '+' ? 1 : -1; - const operatorSplit = result.split(operator); - const digit = parseInt(operatorSplit[operatorSplit.length - 1].replace("{", "").replace("}", "").trim()) * addOrRemove; - const dt = new Date(); - dt.setDate(dt.getDate() + digit); - const formatDate = this.dayJs(dt).utc().format("YYYY-MM-DDTHH:mm:ss\\Z"); - inputString = inputString.replace(result, formatDate); - } - } - - // Replaces any "{Today}" expression by it's actual value - const formattedDate = this.dayJs(new Date()).utc().format("YYYY-MM-DDTHH:mm:ss\\Z"); - inputString = inputString.replace(new RegExp("{Today}", 'gi'), formattedDate); - - const d = new Date(); - inputString = inputString.replace(currentDate, d.getDate().toString()); - inputString = inputString.replace(currentMonth, (d.getMonth() + 1).toString()); - inputString = inputString.replace(currentYear, d.getFullYear().toString()); - - return inputString; - } - - /** - * Resolve query string related tokens - * @param inputString the input string containing tokens - */ - private replaceQueryStringTokens(inputString: string): string { - - const webRegExp = /\{(?:\?){0,1}(?:QueryString)\.(.*?)\}/gi; - let modifiedString = inputString; - let matches = webRegExp.exec(inputString); - - if (matches !== null) { - const url = new URL(window.location.href); - const queryParameters = new URLSearchParams(url.search); - - while (matches !== null) { - const qsProp = matches[1]; - const itemProp = decodeURIComponent(queryParameters.get(qsProp) || ""); - if (itemProp) { - modifiedString = modifiedString.replace(matches[0], itemProp); - } - else if (matches[0].indexOf("?") !== -1) { - // If QueryString Token is specified like this, {?QueryString.Parameter}, it is removed if the QueryString doesn't exist - modifiedString = modifiedString.replace(matches[0], ""); - } - - matches = webRegExp.exec(inputString); - } - } - return modifiedString; - } - - /** - * Resolve current web related tokens - * @param inputString the input string containing tokens - */ - private replaceWebTokens(inputString: string): string { - - const queryStringVariables = /\{(?:Web)\.(.*?)\}/gi; - let matches = queryStringVariables.exec(inputString); - - if (matches !== null) { - - while (matches !== null) { - const webProp = matches[1]; - inputString = inputString.replace(new RegExp(matches[0], "gi"), this.pageContext.web ? (this.pageContext.web as {[key:string]: any})[webProp] : ''); - matches = queryStringVariables.exec(inputString); - } - } - - return inputString; - } - - /** - * Resolve current site related tokens - * @param inputString the input string containing tokens - */ - private replaceSiteTokens(inputString: string): string { - - const siteRegExp = /\{(?:Site)\.(.*?)\}/gi; - let matches = siteRegExp.exec(inputString); - - if (matches !== null) { - - while (matches !== null) { - const siteProp = matches[1]; - - // Ensure the property is in the page context first. - // If not, let the value untouched as it could be a query variable instead processed server side (ex: {Site.URL} - const sitePropertyValue = ObjectHelper.getPropertyByPath(this.pageContext.site, siteProp); - - if (sitePropertyValue) { - inputString = inputString.replace(new RegExp(matches[0], "gi"), this.pageContext.site ? sitePropertyValue : ''); - } - - matches = siteRegExp.exec(inputString); - } - } - - return inputString; - } - - /** - * Resolve current hub site related tokens - * @param inputString the input string containing tokens - */ - private async replaceHubTokens(inputString: string): Promise { - - const hubRegExp = /\{(?:Hub)\.(.*?)\}/gi; - let matches = hubRegExp.exec(inputString); - - // Get hub info - const hubInfos = await this.getHubInfo(); - - if (matches !== null && hubInfos) { - - while (matches !== null) { - const hubProp = matches[1]; - inputString = inputString.replace(new RegExp(matches[0], "gi"), hubInfos[hubProp]); - matches = hubRegExp.exec(inputString); - } - } - - return inputString; - } - - /** - * Resolve current Office 365 group related tokens - * @param inputString the input string containing tokens - */ - private replaceGroupTokens(inputString: string): string { - - const groupRegExp = /\{(?:Group)\.(.*?)\}/gi; - let matches = groupRegExp.exec(inputString); - - if (matches !== null) { - - while (matches !== null) { - const groupProp = matches[1]; - inputString = inputString.replace(new RegExp(matches[0], "gi"), this.pageContext.site.group ? ObjectHelper.getPropertyByPath(this.pageContext.site.group, groupProp) : ''); - matches = groupRegExp.exec(inputString); - } - } - - return inputString; - } - - /** - * Resolve current list related tokens - * @param inputString the input string containing tokens - */ - private replaceListTokens(inputString: string): string { - const listRegExp = /\{(?:List)\.(.*?)\}/gi; - let matches = listRegExp.exec(inputString); - - if (matches !== null) { - - while (matches !== null) { - const listProp = matches[1]; - inputString = inputString.replace(new RegExp(matches[0], "gi"), this.pageContext.list ? ObjectHelper.getPropertyByPath(this.pageContext.list, listProp) : ''); - matches = listRegExp.exec(inputString); - } - } - - return inputString; - } - - /** - * Resolve legacy page tokens - * @param inputString the input string containing tokens - */ - private replaceLegacyPageContextTokens(inputString: string): string { - - const legacyPageContextRegExp = /\{(?:LegacyPageContext)\.(.*?)\}/gi; - let matches = legacyPageContextRegExp.exec(inputString); - - if (matches !== null) { - - while (matches !== null) { - const legacyProp = matches[1]; - inputString = inputString.replace(new RegExp(matches[0], "gi"), this.pageContext.legacyPageContext ? ObjectHelper.getPropertyByPath(this.pageContext.legacyPageContext, legacyProp) : ''); - matches = legacyPageContextRegExp.exec(inputString); - } - } - - return inputString; - } - - private replaceAndOrOperator(inputString: string): string { - - // Example match: {|owstaxidmetadataalltagsinfo:{Page..TermID}} - const orAndConditionTokens = /\{(?:(\||&)(.+?)(>=|=|<=|:|<>|<|>))(\{?.*?\}?\s*)\}/gi; - const reQueryTemplate = inputString; - let match = orAndConditionTokens.exec(inputString); - - if (match !== null) { - while (match !== null) { - - const conditions = []; - const conditionOperator = match[1]; - const property = match[2]; - const operator = match[3]; - const tokenValue = match[4]; - - const quotes = '"'; - const orAndOperator = conditionOperator === '|' ? 'OR' : 'AND'; - - // {User} tokens are resolved server-side by SharePoint so we exclude them - if (!/\{(?:User)\.(.*?)\}/gi.test(tokenValue)) { - const allValues = tokenValue.split(/[,|]/gi); // Works with taxonomy multi values (TermID, Label) + multi choices fields + {filters..valueAsText} token. By convention, all multi values for this operator should be sparated by a comma - - if (allValues.length > 0) { - // Remove duplicates before processing - uniq(allValues).forEach(value => { - - if (!isEmpty(value)) { - // If the token value contains a whitespace, we enclose the value with quotes - conditions.push(`(${property}${operator}${/\s/g.test(value) ? `${quotes}${value}${quotes}` : value})`); - } - }); - } else { - - if (!isEmpty(tokenValue)) { - conditions.push(`(${property}${operator}${/\s/g.test(tokenValue) ? `${quotes}${tokenValue}${quotes}` : tokenValue})`); - } - } - - const condition = `${conditions.join(` ${orAndOperator} `)}`; - - inputString = inputString.replace(match[0], condition); - } - - match = orAndConditionTokens.exec(reQueryTemplate); - } - } - - return inputString; - } - - /** - * Get hub site data - */ - public async getHubInfo(): Promise<{[key:string]: any}> { - - try { - - const restUrl = `${this.pageContext.site.absoluteUrl}/_api/site?$select=IsHubSite,HubSiteId,Id`; - const data = await this.spHttpClient.get(restUrl, SPHttpClient.configurations.v1, { - headers: { - 'X-ClientService-ClientTag': Constants.X_CLIENTSERVICE_CLIENTTAG, - 'UserAgent': Constants.X_CLIENTSERVICE_CLIENTTAG - } - }); - - if (data && data.ok) { - const jsonData = await data.json(); - if (jsonData) { - return jsonData; - } - } - - return null; - } catch (error) { - - Log.error(TokenService_ServiceKey, new Error(`Error while fetching Hub site data. Details: ${error}`), this.serviceScope); - return null; - } - } - - /** - * Recursively lower case object keys - * https://github.com/Vin65/recursive-lowercase-json/blob/master/src/index.js - * @param obj the JSON object - */ - private recursivelyLowercaseJSONKeys(obj: {[key:string]: any}): {} { - - const copyOfObj = obj; - if (typeof copyOfObj !== 'object' || copyOfObj === null) { - return copyOfObj; - } - - if (Array.isArray(copyOfObj)) { - return copyOfObj.map(o => this.recursivelyLowercaseJSONKeys(o)); - } - - return Object.keys(copyOfObj).reduce((prev: {[key:string]: any}, curr: string) => { - prev[curr.toLowerCase()] = this.recursivelyLowercaseJSONKeys(copyOfObj[curr]); - return prev; - }, {}); - } -} diff --git a/packages/spfx/src/styles/postcss.config.js b/packages/spfx/src/styles/postcss.config.js deleted file mode 100644 index 449fd58..0000000 --- a/packages/spfx/src/styles/postcss.config.js +++ /dev/null @@ -1,7 +0,0 @@ -module.exports = { - plugins: { - 'postcss-import': {}, - tailwindcss: {}, - autoprefixer: {}, - } -} \ No newline at end of file diff --git a/packages/spfx/src/styles/tailwind.css b/packages/spfx/src/styles/tailwind.css deleted file mode 100644 index 2236834..0000000 --- a/packages/spfx/src/styles/tailwind.css +++ /dev/null @@ -1,8 +0,0 @@ -@tailwind base; -@tailwind components; -@tailwind utilities; - -/* Issue https://stackoverflow.com/questions/72207205/incomplete-css-grid-leaving-first-item-blank-instead-of-last */ -.CanvasComponent.LCS .grid:after, .CanvasComponent.LCS .grid:before { - @apply content-none !important; -} \ No newline at end of file diff --git a/packages/spfx/src/webparts/searchBox/ISearchBoxWebPartProps.ts b/packages/spfx/src/webparts/searchBox/ISearchBoxWebPartProps.ts deleted file mode 100644 index 3aaa400..0000000 --- a/packages/spfx/src/webparts/searchBox/ISearchBoxWebPartProps.ts +++ /dev/null @@ -1,35 +0,0 @@ -import { QueryPathBehavior, PageOpenBehavior } from "@pnp/modern-search-core/dist/es6/helpers/UrlHelper"; -import { IBaseWebPartProps } from "../../models/common/IBaseWebPartProps"; - -export interface ISearchBoxWebPartProps extends IBaseWebPartProps { - - /** - * Flag indicating in the search query text should be sent to an other page - */ - searchInNewPage: boolean; - - /** - * The page URL to send the query text - */ - pageUrl: string; - - /** - * Whether to use an URL fragment (#) or query string parameter to pass the query text - */ - queryPathBehavior: QueryPathBehavior; - - /** - * The query string parameter to use to send the query text - */ - queryStringParameter: string; - - /** - * Flag indicating if the search box should open a new tab or use the current page - */ - openBehavior: PageOpenBehavior; - - /** - * Placeholder text to display in the search box - */ - inputPlaceholder: string; -} \ No newline at end of file diff --git a/packages/spfx/src/webparts/searchBox/SearchBoxWebPart.manifest.json b/packages/spfx/src/webparts/searchBox/SearchBoxWebPart.manifest.json deleted file mode 100644 index 4edfc50..0000000 --- a/packages/spfx/src/webparts/searchBox/SearchBoxWebPart.manifest.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "$schema": "https://developer.microsoft.com/json-schemas/spfx/client-side-web-part-manifest.schema.json", - "id": "2ad6c8e4-0912-460b-a65c-7e0bbdb864cf", - "alias": "PnPModernSearchCoreSearchBoxWebPart", - "componentType": "WebPart", - "version": "1.0.0", - "manifestVersion": 2, - "requiresCustomScript": false, - "supportedHosts": [ - "SharePointWebPart", - "TeamsPersonalApp", - "TeamsTab", - "SharePointFullPage" - ], - "supportsThemeVariants": true, - "preconfiguredEntries": [ - { - "groupId": "5c03119e-3074-46fd-976b-c60198311f70", - "group": { - "default": "Advanced" - }, - "title": { - "default": "PnP Modern Search Core Components - Search Box", - "dfr-frfault": "PnP Modern Search Core Components - Boîte de recherche" - }, - "description": { - "default": "Allows users to search data source results using query text", - "fr-fr": "Permet aux utilisateurs de rechercher sur la base d'une requête textuelle" - }, - "iconImageUrl": "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0nNDAnIGhlaWdodD0nMjgnIHZpZXdCb3g9JzAgMCA0MCAyOCcgZmlsbD0nbm9uZScgeG1sbnM9J2h0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnJz48cGF0aCBmaWxsLXJ1bGU9J2V2ZW5vZGQnIGNsaXAtcnVsZT0nZXZlbm9kZCcgZD0nTTE3LjkgMi4yQzEyLjMgMi4yIDcuNyA2LjggNy43IDEyLjRDNy43IDE4IDEyLjMgMjIuNiAxNy45IDIyLjZDMjMuNSAyMi42IDI4LjEgMTggMjguMSAxMi40QzI4LjEgNi43IDIzLjYgMi4yIDE3LjkgMi4yWk01LjUgMTIuNEM1LjUgNS42IDExLjEgMCAxNy45IDBDMjQuNyAwIDMwLjMgNS41IDMwLjMgMTIuNEMzMC4zIDE5LjIgMjQuOCAyNC44IDE3LjkgMjQuOEMxMS4xIDI0LjggNS41IDE5LjIgNS41IDEyLjRaJyBmaWxsPScjMDA3OGQ0Jy8+PHBhdGggZmlsbC1ydWxlPSdldmVub2RkJyBjbGlwLXJ1bGU9J2V2ZW5vZGQnIGQ9J00yNS4wOTk4IDE5LjZDMjUuNDk5OCAxOS4yIDI2LjE5OTggMTkuMiAyNi41OTk4IDE5LjZMMzMuMDk5OCAyNi4xQzMzLjQ5OTggMjYuNSAzMy40OTk4IDI3LjIgMzMuMDk5OCAyNy42QzMyLjY5OTggMjggMzEuOTk5OCAyOCAzMS41OTk4IDI3LjZMMjUuMDk5OCAyMS4xQzI0LjY5OTggMjAuNyAyNC42OTk4IDIwIDI1LjA5OTggMTkuNlonIGZpbGw9JyMwMDc4ZDQnLz48L3N2Zz4=", - "properties": { - "issueLink": "https://github.com/microsoft-search/pnp-modern-search-core-components/issues/new", - "documentationLink": "https://microsoft-search.github.io/pnp-modern-search-core-components/docs/sharepoint-webparts/available-webparts/search-box" - } - } - ] -} \ No newline at end of file diff --git a/packages/spfx/src/webparts/searchBox/SearchBoxWebPart.manifest.template.json b/packages/spfx/src/webparts/searchBox/SearchBoxWebPart.manifest.template.json deleted file mode 100644 index ec4505d..0000000 --- a/packages/spfx/src/webparts/searchBox/SearchBoxWebPart.manifest.template.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "$schema": "https://developer.microsoft.com/json-schemas/spfx/client-side-web-part-manifest.schema.json", - "id": "2ad6c8e4-0912-460b-a65c-7e0bbdb864cf", - "alias": "PnPModernSearchCoreSearchBoxWebPart", - "componentType": "WebPart", - "version": "1.0.0", - "manifestVersion": 2, - "requiresCustomScript": false, - "supportedHosts": [ - "SharePointWebPart", - "TeamsPersonalApp", - "TeamsTab", - "SharePointFullPage" - ], - "supportsThemeVariants": true, - "preconfiguredEntries": [ - { - "groupId": "5c03119e-3074-46fd-976b-c60198311f70", - "group": { - "default": "Advanced" - }, - "title": { - "default": "PnP Modern Search Core Components - Search Box", - "dfr-frfault": "PnP Modern Search Core Components - Boîte de recherche" - }, - "description": { - "default": "Allows users to search data source results using query text", - "fr-fr": "Permet aux utilisateurs de rechercher sur la base d'une requête textuelle" - }, - "iconImageUrl": "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0nNDAnIGhlaWdodD0nMjgnIHZpZXdCb3g9JzAgMCA0MCAyOCcgZmlsbD0nbm9uZScgeG1sbnM9J2h0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnJz48cGF0aCBmaWxsLXJ1bGU9J2V2ZW5vZGQnIGNsaXAtcnVsZT0nZXZlbm9kZCcgZD0nTTE3LjkgMi4yQzEyLjMgMi4yIDcuNyA2LjggNy43IDEyLjRDNy43IDE4IDEyLjMgMjIuNiAxNy45IDIyLjZDMjMuNSAyMi42IDI4LjEgMTggMjguMSAxMi40QzI4LjEgNi43IDIzLjYgMi4yIDE3LjkgMi4yWk01LjUgMTIuNEM1LjUgNS42IDExLjEgMCAxNy45IDBDMjQuNyAwIDMwLjMgNS41IDMwLjMgMTIuNEMzMC4zIDE5LjIgMjQuOCAyNC44IDE3LjkgMjQuOEMxMS4xIDI0LjggNS41IDE5LjIgNS41IDEyLjRaJyBmaWxsPScjMDA3OGQ0Jy8+PHBhdGggZmlsbC1ydWxlPSdldmVub2RkJyBjbGlwLXJ1bGU9J2V2ZW5vZGQnIGQ9J00yNS4wOTk4IDE5LjZDMjUuNDk5OCAxOS4yIDI2LjE5OTggMTkuMiAyNi41OTk4IDE5LjZMMzMuMDk5OCAyNi4xQzMzLjQ5OTggMjYuNSAzMy40OTk4IDI3LjIgMzMuMDk5OCAyNy42QzMyLjY5OTggMjggMzEuOTk5OCAyOCAzMS41OTk4IDI3LjZMMjUuMDk5OCAyMS4xQzI0LjY5OTggMjAuNyAyNC42OTk4IDIwIDI1LjA5OTggMTkuNlonIGZpbGw9JyMwMDc4ZDQnLz48L3N2Zz4=", - "properties": { - "issueLink": "https://github.com/microsoft-search/pnp-modern-search-core-components/issues/new", - "documentationLink": "{{DOCUMENTATION_HOST_URL}}/docs/sharepoint-webparts/available-webparts/search-box" - } - } - ] -} \ No newline at end of file diff --git a/packages/spfx/src/webparts/searchBox/SearchBoxWebPart.ts b/packages/spfx/src/webparts/searchBox/SearchBoxWebPart.ts deleted file mode 100644 index ec54446..0000000 --- a/packages/spfx/src/webparts/searchBox/SearchBoxWebPart.ts +++ /dev/null @@ -1,197 +0,0 @@ -//#region Imports -import * as React from 'react'; -import * as ReactDom from 'react-dom'; -import { - IPropertyPaneConfiguration, - IPropertyPaneField, - IPropertyPanePage, - PropertyPaneDropdown, - PropertyPaneTextField, - PropertyPaneToggle -} from '@microsoft/sp-property-pane'; -import * as commonStrings from "CommonStrings"; -import * as webPartStrings from 'SearchBoxWebPartStrings'; -import { SearchBox } from './components/SearchBox'; -import { ISearchBoxProps } from './components/ISearchBoxProps'; -import { IDynamicDataCallables, IDynamicDataPropertyDefinition } from '@microsoft/sp-dynamic-data'; -import { BaseWebPart } from '../../common/BaseWebPart'; -import { ComponentType } from '../../common/ComponentType'; -import { PageOpenBehavior, QueryPathBehavior } from '@pnp/modern-search-core/dist/es6/helpers/UrlHelper'; -import { ISearchBoxWebPartProps } from './ISearchBoxWebPartProps'; -import { ILayoutDefinition } from '../../models/common/ILayoutDefinition'; -//#endregion - -export default class SearchBoxWebPart extends BaseWebPart implements IDynamicDataCallables { - - protected availableLayoutDefinitions: ILayoutDefinition[] = []; - - //#region Class methods - - //#region WebPart lifecycle methods - - protected async onInit(): Promise { - - await super.onInit(); - - this.context.dynamicDataSourceManager.initializeSource(this); - } - - public render(): void { - - const element: React.ReactElement = React.createElement( - SearchBox, - { - ...this.properties, - id: this.getComponentId(ComponentType.SearchBox), - theme: this._themeVariant.isInverted ? "dark" : "" - } as ISearchBoxProps - ); - - ReactDom.render(element, this.domElement); - } - - protected onDispose(): void { - ReactDom.unmountComponentAtNode(this.domElement); - } - - //#endregion - - //#region Dynamic Data methods - - public getPropertyDefinitions(): IDynamicDataPropertyDefinition[] { - - // Use the Web Part title as property title since we don't expose sub properties - const propertyDefinitions: IDynamicDataPropertyDefinition[] = []; - - propertyDefinitions.push( - { - id: ComponentType.SearchBox, - title: this.properties.title ? `${this.properties.title} - ${this.instanceId}` : `${webPartStrings.General.WebPartDefaultTitle} - ${this.instanceId}`, - } - ); - - return propertyDefinitions; - } - - public getPropertyValue(propertyId: string): string { - return; - } - - //#endregion - - //#region Property Pane methods - protected getPropertyPaneConfiguration(): IPropertyPaneConfiguration { - - const propertyPanePages: IPropertyPanePage[] = [ - { - groups: [ - { - groupName: webPartStrings.PropertyPane.SearchBoxSettingsGroup.GroupName, - groupFields: this._getSearchBoxSettingsFields() - } - ], - displayGroupsAsAccordion: true - }, - // Common page - { - displayGroupsAsAccordion: true, - groups: [this.getThemePageGroup()] - }, - // 'About' infos - { - displayGroupsAsAccordion: true, - groups: [ - ...this.getPropertyPaneWebPartInfoGroups(), - ] - } - ]; - - return { - pages: propertyPanePages - }; - } - - /** - * Determines the group fields for the search options inside the property pane - */ - private _getSearchBoxSettingsFields(): IPropertyPaneField[] { - - let searchBehaviorOptionsFields: IPropertyPaneField[] = [ - PropertyPaneTextField('inputPlaceholder', { - label: webPartStrings.PropertyPane.SearchBoxSettingsGroup.PlaceholderTextLabel - }), - PropertyPaneToggle("searchInNewPage", { - label: webPartStrings.PropertyPane.SearchBoxSettingsGroup.SearchInNewPageLabel - }), - ]; - - - if (this.properties.searchInNewPage) { - searchBehaviorOptionsFields = searchBehaviorOptionsFields.concat([ - PropertyPaneTextField('pageUrl', { - disabled: !this.properties.searchInNewPage, - label: webPartStrings.PropertyPane.SearchBoxSettingsGroup.PageUrlLabel, - onGetErrorMessage: this._validatePageUrl.bind(this), - validateOnFocusOut: true, - validateOnFocusIn: true, - placeholder: 'https://...' - }), - PropertyPaneDropdown('openBehavior', { - label: commonStrings.General.PageOpenBehaviorLabel, - options: [ - { key: PageOpenBehavior.Self, text: commonStrings.General.SameTabOpenBehavior }, - { key: PageOpenBehavior.NewTab, text: commonStrings.General.NewTabOpenBehavior } - ], - disabled: !this.properties.searchInNewPage, - selectedKey: this.properties.openBehavior - }), - PropertyPaneDropdown('queryPathBehavior', { - label: webPartStrings.PropertyPane.SearchBoxSettingsGroup.QueryPathBehaviorLabel, - options: [ - { key: QueryPathBehavior.URLFragment, text: webPartStrings.PropertyPane.SearchBoxSettingsGroup.UrlFragmentQueryPathBehavior }, - { key: QueryPathBehavior.QueryParameter, text: webPartStrings.PropertyPane.SearchBoxSettingsGroup.QueryStringQueryPathBehavior } - ], - disabled: !this.properties.searchInNewPage, - selectedKey: this.properties.queryPathBehavior - }) - ]); - } - - if (this.properties.searchInNewPage && this.properties.queryPathBehavior === QueryPathBehavior.QueryParameter) { - searchBehaviorOptionsFields = searchBehaviorOptionsFields.concat([ - PropertyPaneTextField('queryStringParameter', { - disabled: !this.properties.searchInNewPage || this.properties.searchInNewPage && this.properties.queryPathBehavior !== QueryPathBehavior.QueryParameter, - label: webPartStrings.PropertyPane.SearchBoxSettingsGroup.QueryStringParameterName, - onGetErrorMessage: (value) => { - if (this.properties.queryPathBehavior === QueryPathBehavior.QueryParameter) { - if (value === null || - value.trim().length === 0) { - return webPartStrings.PropertyPane.SearchBoxSettingsGroup.QueryParameterNotEmpty; - } - } - return ''; - } - }) - ]); - } - - return searchBehaviorOptionsFields; - } - - /** - * Verifies if the string is a correct URL - * @param value the URL to verify - */ - private _validatePageUrl(value: string): string { - - if ((!(/^(https?):\/\/[^\s/$.?#].[^\s]*/).test(value) || !value) && this.properties.searchInNewPage) { - return webPartStrings.PropertyPane.SearchBoxSettingsGroup.UrlErrorMessage; - } - - return ''; - } - - //#endregion - - //#endregion -} diff --git a/packages/spfx/src/webparts/searchBox/components/ISearchBoxProps.ts b/packages/spfx/src/webparts/searchBox/components/ISearchBoxProps.ts deleted file mode 100644 index 182da42..0000000 --- a/packages/spfx/src/webparts/searchBox/components/ISearchBoxProps.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { IBaseWebComponentWrapperProps } from "../../../models/common/IBaseWebComponentWrapper"; -import { ISearchBoxWebPartProps } from "../ISearchBoxWebPartProps"; - -export interface ISearchBoxProps extends IBaseWebComponentWrapperProps, ISearchBoxWebPartProps { -} diff --git a/packages/spfx/src/webparts/searchBox/components/SearchBox.tsx b/packages/spfx/src/webparts/searchBox/components/SearchBox.tsx deleted file mode 100644 index 4292960..0000000 --- a/packages/spfx/src/webparts/searchBox/components/SearchBox.tsx +++ /dev/null @@ -1,19 +0,0 @@ -import * as React from 'react'; -import { ISearchBoxProps } from './ISearchBoxProps'; -import { wrapWc } from 'wc-react'; -import { SearchInputComponent } from '@pnp/modern-search-core'; - -const SearchInputWebComponent = wrapWc('pnp-search-input'); - -export class SearchBox extends React.Component { - - public render(): React.ReactElement { - - return ; - } -} \ No newline at end of file diff --git a/packages/spfx/src/webparts/searchBox/loc/en-us.js b/packages/spfx/src/webparts/searchBox/loc/en-us.js deleted file mode 100644 index c027fad..0000000 --- a/packages/spfx/src/webparts/searchBox/loc/en-us.js +++ /dev/null @@ -1,52 +0,0 @@ -define([], function() { - return { - General: { - DynamicPropertyDefinition: "Search query", - WebPartDefaultTitle: "Search Box Web Part" - }, - PropertyPane: { - SearchBoxSettingsGroup: { - GroupName: "Search box settings", - PlaceholderTextLabel: "Placeholder text to display in the search box", - SearchInNewPageLabel: "Send the query to a new page", - ReQueryOnClearLabel: "Reset query on clear", - PageUrlLabel: "Page URL", - UrlErrorMessage: "Please provide a valid URL.", - QueryPathBehaviorLabel: "Method", - QueryInputTransformationLabel: "Query input transformation template", - UrlFragmentQueryPathBehavior: "URL fragment", - QueryStringQueryPathBehavior: "Query string parameter", - QueryStringParameterName: "Parameter name", - QueryParameterNotEmpty: "Please provide a value for the parameter." - }, - AvailableConnectionsGroup: { - GroupName: "Available connections", - UseDynamicDataSourceLabel: "Use dynamic data source as default input", - QueryKeywordsPropertyLabel: "" - }, - QuerySuggestionsGroup: { - GroupName: "Query suggestions", - EnableQuerySuggestions: "Enable query suggestions", - EditSuggestionProvidersLabel: "Configure available providers", - SuggestionProvidersLabel: "Suggestion providers", - SuggestionProvidersDescription: "Enable or disable individual suggestion providers.", - EnabledPropertyLabel: "Enabled", - ProviderNamePropertyLabel: "Name", - ProviderDescriptionPropertyLabel: "Description", - DefaultSuggestionGroupName: "Recommended", - NumberOfSuggestionsToShow: "Number of suggestions to show per group" - }, - InformationPage: { - Extensibility: { - PanelHeader: "Configure extensibility libraries to load at startup for custom suggestions providers", - PanelDescription: "Add/Remove your custom extensibility library IDs here. You can specify a display name and decide if the library should be loaded or not at startup. Only custom suggestions providers will be loaded here.", - } - }, - - }, - SearchBox: { - DefaultPlaceholder: "Enter your search terms...", - SearchButtonLabel: "Search" - } - } -}); diff --git a/packages/spfx/src/webparts/searchBox/loc/mystrings.d.ts b/packages/spfx/src/webparts/searchBox/loc/mystrings.d.ts deleted file mode 100644 index 2512b0c..0000000 --- a/packages/spfx/src/webparts/searchBox/loc/mystrings.d.ts +++ /dev/null @@ -1,54 +0,0 @@ -declare interface ISearchBoxWebPartStrings { - General: { - DynamicPropertyDefinition: string; - WebPartDefaultTitle: string; - }, - PropertyPane: { - SearchBoxSettingsGroup: { - GroupName: string; - PlaceholderTextLabel: string; - SearchInNewPageLabel: string; - ReQueryOnClearLabel: string; - PageUrlLabel: string; - UrlErrorMessage: string; - QueryPathBehaviorLabel: string; - QueryInputTransformationLabel: string; - UrlFragmentQueryPathBehavior: string; - QueryStringQueryPathBehavior: string; - QueryStringParameterName: string; - QueryParameterNotEmpty: string; - }, - AvailableConnectionsGroup: { - GroupName: string; - UseDynamicDataSourceLabel: string; - QueryKeywordsPropertyLabel: string; - } - QuerySuggestionsGroup: { - GroupName: string; - EnableQuerySuggestions: string; - EditSuggestionProvidersLabel: string; - SuggestionProvidersLabel: string; - SuggestionProvidersDescription: string; - EnabledPropertyLabel: string; - ProviderNamePropertyLabel: string; - ProviderDescriptionPropertyLabel: string; - DefaultSuggestionGroupName: string; - NumberOfSuggestionsToShow: string; - }, - InformationPage: { - Extensibility: { - PanelHeader: string; - PanelDescription: string; - } - }, - }, - SearchBox: { - DefaultPlaceholder: string; - SearchButtonLabel: string; - } - } - -declare module 'SearchBoxWebPartStrings' { - const strings: ISearchBoxWebPartStrings; - export = strings; -} diff --git a/packages/spfx/src/webparts/searchFilters/ISearchFiltersWebPartProps.ts b/packages/spfx/src/webparts/searchFilters/ISearchFiltersWebPartProps.ts deleted file mode 100644 index 4a91552..0000000 --- a/packages/spfx/src/webparts/searchFilters/ISearchFiltersWebPartProps.ts +++ /dev/null @@ -1,32 +0,0 @@ -import { FilterConditionOperator } from "@pnp/modern-search-core/dist/es6/models/common/IDataFilter"; -import { IDataFilterConfiguration } from "@pnp/modern-search-core/dist/es6/models/common/IDataFilterConfiguration"; -import { IBaseWebPartProps } from "../../models/common/IBaseWebPartProps"; - -export interface ISearchFiltersWebPartProps extends IBaseWebPartProps { - - /** - * The configured logical operator to use between filters - */ - filterOperator: FilterConditionOperator; - - /** - * The filters configuration - */ - filtersConfiguration: IDataFilterConfiguration[]; - - /** - * Dynamic data connection references for connected Search Results Web Parts - */ - searchResultsDataSourceReferences: string[]; - - /** - * Enables verticals - */ - useVerticals: boolean; - - /** - * Reference to the Verticals WebPart if any connected - */ - verticalsDataSourceReference: string; - -} \ No newline at end of file diff --git a/packages/spfx/src/webparts/searchFilters/SearchFiltersWebPart.manifest.json b/packages/spfx/src/webparts/searchFilters/SearchFiltersWebPart.manifest.json deleted file mode 100644 index 2e76b4f..0000000 --- a/packages/spfx/src/webparts/searchFilters/SearchFiltersWebPart.manifest.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "$schema": "https://developer.microsoft.com/json-schemas/spfx/client-side-web-part-manifest.schema.json", - "id": "4f2451b5-c1ea-4a68-8097-90edc9da61ce", - "alias": "PnPModernSearchCoreFiltersPart", - "componentType": "WebPart", - "version": "1.0.0", - "manifestVersion": 2, - "requiresCustomScript": false, - "supportedHosts": [ - "SharePointWebPart", - "TeamsPersonalApp", - "TeamsTab", - "SharePointFullPage" - ], - "supportsThemeVariants": true, - "preconfiguredEntries": [ - { - "groupId": "5c03119e-3074-46fd-976b-c60198311f70", - "group": { - "default": "Advanced" - }, - "title": { - "default": "PnP Modern Search Core Components - Search Filters", - "fr-fr": "PnP Modern Search Core Components - Filtres de recherche" - }, - "description": { - "default": "Filters results from the search results Web Part", - "fr-fr": "Filtre les résultats provenant du Web Part de résultats de recherche" - }, - "iconImageUrl": "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0nNDAnIGhlaWdodD0nMjgnIHZpZXdCb3g9JzAgMCA0MCAyOCcgZmlsbD0nbm9uZScgeG1sbnM9J2h0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnJz48cGF0aCBmaWxsLXJ1bGU9J2V2ZW5vZGQnIGNsaXAtcnVsZT0nZXZlbm9kZCcgZD0nTTIuODk5OCAyMUgyMy44OTk4QzI0Ljc5OTggMjEgMjUuNDk5OCAyMS43IDI1LjQ5OTggMjIuNkMyNS40OTk4IDIzLjUgMjQuNzk5OCAyNC4yIDIzLjg5OTggMjQuMkgyLjg5OThDMS45OTk4IDI0LjIgMS4yOTk4IDIzLjUgMS4yOTk4IDIyLjZDMS4yOTk4IDIxLjcgMS45OTk4IDIxIDIuODk5OCAyMVonIGZpbGw9JyMwMDc4ZDQnLz48cGF0aCBmaWxsLXJ1bGU9J2V2ZW5vZGQnIGNsaXAtcnVsZT0nZXZlbm9kZCcgZD0nTTMwLjEwMDEgMjIuNkMzMC4xMDAxIDIxLjcgMzAuODAwMSAyMSAzMS43MDAxIDIxSDM3LjEwMDFDMzguMDAwMSAyMSAzOC43MDAxIDIxLjcgMzguNzAwMSAyMi42QzM4LjcwMDEgMjMuNSAzOC4wMDAxIDI0LjIgMzcuMTAwMSAyNC4ySDMxLjcwMDFDMzAuODAwMSAyNC4xIDMwLjEwMDEgMjMuNCAzMC4xMDAxIDIyLjZaJyBmaWxsPScjMDA3OGQ0Jy8+PHBhdGggZD0nTTIyLjI5OTggMjIuNkMyMi4yOTk4IDE5LjYgMjQuNjk5OCAxNy4yIDI3LjY5OTggMTcuMkMzMC42OTk4IDE3LjIgMzMuMDk5OCAxOS42IDMzLjA5OTggMjIuNkMzMy4wOTk4IDI1LjYgMzAuNjk5OCAyOCAyNy42OTk4IDI4QzI0LjY5OTggMjggMjIuMjk5OCAyNS42IDIyLjI5OTggMjIuNlonIGZpbGw9JyMwMDc4ZDQnLz48cGF0aCBmaWxsLXJ1bGU9J2V2ZW5vZGQnIGNsaXAtcnVsZT0nZXZlbm9kZCcgZD0nTTEuMjk5OCA1LjRDMS4yOTk4IDQuNSAxLjk5OTggMy44IDIuODk5OCAzLjhIMTEuNDk5OEMxMi4zOTk4IDMuOCAxMy4wOTk4IDQuNSAxMy4wOTk4IDUuNEMxMi45OTk4IDYuMyAxMi4yOTk4IDcgMTEuMzk5OCA3SDIuODk5OEMxLjk5OTggNyAxLjI5OTggNi4zIDEuMjk5OCA1LjRaJyBmaWxsPScjMDA3OGQ0Jy8+PHBhdGggZmlsbC1ydWxlPSdldmVub2RkJyBjbGlwLXJ1bGU9J2V2ZW5vZGQnIGQ9J00xOS4yMDAxIDMuOUgzNy4xMDAxQzM4LjAwMDEgMy45IDM4LjcwMDEgNC42IDM4LjcwMDEgNS41QzM4LjcwMDEgNi4zIDM4LjAwMDEgNyAzNy4xMDAxIDdIMTkuMjAwMUMxOC4zMDAxIDcgMTcuNjAwMSA2LjMgMTcuNjAwMSA1LjRDMTcuNjAwMSA0LjUgMTguNDAwMSAzLjkgMTkuMjAwMSAzLjlaJyBmaWxsPScjMDA3OGQ0Jy8+PHBhdGggZmlsbC1ydWxlPSdldmVub2RkJyBjbGlwLXJ1bGU9J2V2ZW5vZGQnIGQ9J005Ljg5OTkgNS40QzkuODk5OSAyLjQgMTIuMjk5OSAwIDE1LjI5OTkgMEMxOC4yOTk5IDAgMjAuNjk5OSAyLjQgMjAuNjk5OSA1LjRDMjAuNjk5OSA4LjQgMTguMjk5OSAxMC44IDE1LjI5OTkgMTAuOEMxMi4yOTk5IDEwLjggOS44OTk5IDguNSA5Ljg5OTkgNS40WicgZmlsbD0nIzAwNzhkNCcvPjwvc3ZnPgo=", - "properties": { - "issueLink": "https://github.com/microsoft-search/pnp-modern-search-core-components/issues/new", - "documentationLink": "https://microsoft-search.github.io/pnp-modern-search-core-components/docs/sharepoint-webparts/available-webparts/search-filters" - } - } - ] -} \ No newline at end of file diff --git a/packages/spfx/src/webparts/searchFilters/SearchFiltersWebPart.manifest.template.json b/packages/spfx/src/webparts/searchFilters/SearchFiltersWebPart.manifest.template.json deleted file mode 100644 index 63dd2c8..0000000 --- a/packages/spfx/src/webparts/searchFilters/SearchFiltersWebPart.manifest.template.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "$schema": "https://developer.microsoft.com/json-schemas/spfx/client-side-web-part-manifest.schema.json", - "id": "4f2451b5-c1ea-4a68-8097-90edc9da61ce", - "alias": "PnPModernSearchCoreFiltersPart", - "componentType": "WebPart", - "version": "1.0.0", - "manifestVersion": 2, - "requiresCustomScript": false, - "supportedHosts": [ - "SharePointWebPart", - "TeamsPersonalApp", - "TeamsTab", - "SharePointFullPage" - ], - "supportsThemeVariants": true, - "preconfiguredEntries": [ - { - "groupId": "5c03119e-3074-46fd-976b-c60198311f70", - "group": { - "default": "Advanced" - }, - "title": { - "default": "PnP Modern Search Core Components - Search Filters", - "fr-fr": "PnP Modern Search Core Components - Filtres de recherche" - }, - "description": { - "default": "Filters results from the search results Web Part", - "fr-fr": "Filtre les résultats provenant du Web Part de résultats de recherche" - }, - "iconImageUrl": "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0nNDAnIGhlaWdodD0nMjgnIHZpZXdCb3g9JzAgMCA0MCAyOCcgZmlsbD0nbm9uZScgeG1sbnM9J2h0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnJz48cGF0aCBmaWxsLXJ1bGU9J2V2ZW5vZGQnIGNsaXAtcnVsZT0nZXZlbm9kZCcgZD0nTTIuODk5OCAyMUgyMy44OTk4QzI0Ljc5OTggMjEgMjUuNDk5OCAyMS43IDI1LjQ5OTggMjIuNkMyNS40OTk4IDIzLjUgMjQuNzk5OCAyNC4yIDIzLjg5OTggMjQuMkgyLjg5OThDMS45OTk4IDI0LjIgMS4yOTk4IDIzLjUgMS4yOTk4IDIyLjZDMS4yOTk4IDIxLjcgMS45OTk4IDIxIDIuODk5OCAyMVonIGZpbGw9JyMwMDc4ZDQnLz48cGF0aCBmaWxsLXJ1bGU9J2V2ZW5vZGQnIGNsaXAtcnVsZT0nZXZlbm9kZCcgZD0nTTMwLjEwMDEgMjIuNkMzMC4xMDAxIDIxLjcgMzAuODAwMSAyMSAzMS43MDAxIDIxSDM3LjEwMDFDMzguMDAwMSAyMSAzOC43MDAxIDIxLjcgMzguNzAwMSAyMi42QzM4LjcwMDEgMjMuNSAzOC4wMDAxIDI0LjIgMzcuMTAwMSAyNC4ySDMxLjcwMDFDMzAuODAwMSAyNC4xIDMwLjEwMDEgMjMuNCAzMC4xMDAxIDIyLjZaJyBmaWxsPScjMDA3OGQ0Jy8+PHBhdGggZD0nTTIyLjI5OTggMjIuNkMyMi4yOTk4IDE5LjYgMjQuNjk5OCAxNy4yIDI3LjY5OTggMTcuMkMzMC42OTk4IDE3LjIgMzMuMDk5OCAxOS42IDMzLjA5OTggMjIuNkMzMy4wOTk4IDI1LjYgMzAuNjk5OCAyOCAyNy42OTk4IDI4QzI0LjY5OTggMjggMjIuMjk5OCAyNS42IDIyLjI5OTggMjIuNlonIGZpbGw9JyMwMDc4ZDQnLz48cGF0aCBmaWxsLXJ1bGU9J2V2ZW5vZGQnIGNsaXAtcnVsZT0nZXZlbm9kZCcgZD0nTTEuMjk5OCA1LjRDMS4yOTk4IDQuNSAxLjk5OTggMy44IDIuODk5OCAzLjhIMTEuNDk5OEMxMi4zOTk4IDMuOCAxMy4wOTk4IDQuNSAxMy4wOTk4IDUuNEMxMi45OTk4IDYuMyAxMi4yOTk4IDcgMTEuMzk5OCA3SDIuODk5OEMxLjk5OTggNyAxLjI5OTggNi4zIDEuMjk5OCA1LjRaJyBmaWxsPScjMDA3OGQ0Jy8+PHBhdGggZmlsbC1ydWxlPSdldmVub2RkJyBjbGlwLXJ1bGU9J2V2ZW5vZGQnIGQ9J00xOS4yMDAxIDMuOUgzNy4xMDAxQzM4LjAwMDEgMy45IDM4LjcwMDEgNC42IDM4LjcwMDEgNS41QzM4LjcwMDEgNi4zIDM4LjAwMDEgNyAzNy4xMDAxIDdIMTkuMjAwMUMxOC4zMDAxIDcgMTcuNjAwMSA2LjMgMTcuNjAwMSA1LjRDMTcuNjAwMSA0LjUgMTguNDAwMSAzLjkgMTkuMjAwMSAzLjlaJyBmaWxsPScjMDA3OGQ0Jy8+PHBhdGggZmlsbC1ydWxlPSdldmVub2RkJyBjbGlwLXJ1bGU9J2V2ZW5vZGQnIGQ9J005Ljg5OTkgNS40QzkuODk5OSAyLjQgMTIuMjk5OSAwIDE1LjI5OTkgMEMxOC4yOTk5IDAgMjAuNjk5OSAyLjQgMjAuNjk5OSA1LjRDMjAuNjk5OSA4LjQgMTguMjk5OSAxMC44IDE1LjI5OTkgMTAuOEMxMi4yOTk5IDEwLjggOS44OTk5IDguNSA5Ljg5OTkgNS40WicgZmlsbD0nIzAwNzhkNCcvPjwvc3ZnPgo=", - "properties": { - "issueLink": "https://github.com/microsoft-search/pnp-modern-search-core-components/issues/new", - "documentationLink": "{{DOCUMENTATION_HOST_URL}}/docs/sharepoint-webparts/available-webparts/search-filters" - } - } - ] -} \ No newline at end of file diff --git a/packages/spfx/src/webparts/searchFilters/SearchFiltersWebPart.ts b/packages/spfx/src/webparts/searchFilters/SearchFiltersWebPart.ts deleted file mode 100644 index 2f722d3..0000000 --- a/packages/spfx/src/webparts/searchFilters/SearchFiltersWebPart.ts +++ /dev/null @@ -1,376 +0,0 @@ -//#region Imports -import * as React from 'react'; -import * as ReactDom from 'react-dom'; -import { DisplayMode } from '@microsoft/sp-core-library'; -import { - IPropertyPaneConfiguration, IPropertyPaneField, PropertyPaneChoiceGroup, PropertyPaneDropdown, PropertyPaneToggle} from '@microsoft/sp-property-pane'; -import * as webPartStrings from 'SearchFiltersWebPartStrings'; -import SearchFilters from './components/SearchFilters'; -import { ISearchFiltersProps } from './components/ISearchFiltersProps'; -import { BaseWebPart } from '../../common/BaseWebPart'; -import { IDynamicDataCallables, IDynamicDataPropertyDefinition } from '@microsoft/sp-dynamic-data'; -import { ComponentType } from '../../common/ComponentType'; -import { FilterConditionOperator } from '@pnp/modern-search-core/dist/es6/models/common/IDataFilter'; -import { DynamicProperty } from '@microsoft/sp-component-base'; -import { IPlaceholderProps } from '@pnp/spfx-controls-react'; -import WebPartPlaceholder from '../../controls/WebPartPlaceholder/WebPartPlaceholder'; -import { IComboBoxOption } from 'office-ui-fabric-react'; -import { IPropertyFieldMultiSelectProps, PropertyFieldMultiSelect } from '@pnp/spfx-property-controls/lib/PropertyFieldMultiSelect'; -import { ISearchFiltersWebPartProps } from './ISearchFiltersWebPartProps'; -import { PropertyPaneFiltersConfiguration } from '../../propertyPane/PropertyPaneFiltersConfiguration/PropertyPaneFiltersConfiguration'; -import { ISearchVerticalSourceData } from '../../models/dynamicData/ISearchVerticalSourceData'; -import { IDataVerticalConfiguration } from '@pnp/modern-search-core/dist/es6/models/common/IDataVerticalConfiguration'; -import { ILayoutDefinition, LayoutType } from '../../models/common/ILayoutDefinition'; -import { AvailableLayouts, BuiltinLayoutsKeys } from '../../layouts/AvailableLayouts'; - -//#endregion - -export default class SearchFiltersWebPart extends BaseWebPart implements IDynamicDataCallables { - - //#region Class attributes - - /** - * Dynamic properties for all connected sources - */ - private _resultsConnectionSourceData: DynamicProperty[] = []; - private _verticalsConnectionSourceData: DynamicProperty; - - private _propertyPaneSearchResultsFields: IPropertyPaneField[] = []; - private _propertyPaneSearchVerticalsFields: IPropertyPaneField[]; - - private verticalsConfiguration: IDataVerticalConfiguration[]; - - /** - * The available layout definitions (not instanciated) - */ - protected availableLayoutDefinitions: ILayoutDefinition[] = AvailableLayouts.BuiltinLayouts.filter(layout => { return layout.type === LayoutType.Filters; }); - - //#endregion - - //#region Class methods - - //#region Dynamic data methods - public getPropertyDefinitions(): IDynamicDataPropertyDefinition[] { - - const propertyDefinitions: IDynamicDataPropertyDefinition[] = []; - - propertyDefinitions.push( - { - id: ComponentType.SearchFilters, - title: this.properties.title ? `${this.properties.title} - ${this.instanceId}` : `${webPartStrings.General.WebPartDefaultTitle} - ${this.instanceId}`, - } - ); - - return propertyDefinitions; - } - - public getPropertyValue(propertyId: string): string { - return; - } - - /** - * Make sure the dynamic properties are correctly connected to the corresponding sources according to the proeprty pane settings - */ - private ensureDynamicDataSourcesConnection(): void { - - // First, unregister the properties every time. Simpler than updated existing ones. - this._resultsConnectionSourceData.forEach(dynamicProperty => { - dynamicProperty.unregister(this.render); - }); - - // Then reset the dynamic properties to an empty array to start connections over. - this._resultsConnectionSourceData = []; - - // Search Results Web Part data sources - if (this.properties.searchResultsDataSourceReferences.length > 0) { - - this.properties.searchResultsDataSourceReferences.forEach(reference => { - - const dataSourceDynamicProperty = new DynamicProperty(this.context.dynamicDataProvider); - - // Register the data source manually since we don't want user select properties manually via native property pane controls - dataSourceDynamicProperty.setReference(reference); - dataSourceDynamicProperty.register(this.render); - - this._resultsConnectionSourceData.push(dataSourceDynamicProperty); - }); - } - - // Verticals WebPart data source - if (this.properties.verticalsDataSourceReference) { - - if (!this._verticalsConnectionSourceData) { - this._verticalsConnectionSourceData = new DynamicProperty(this.context.dynamicDataProvider); - } - - this._verticalsConnectionSourceData.setReference(this.properties.verticalsDataSourceReference); - this._verticalsConnectionSourceData.register(this.render); - - } else { - - if (this._verticalsConnectionSourceData) { - this._verticalsConnectionSourceData.unregister(this.render); - } - } - - } - - protected async onInit(): Promise { - - this.initializeProperties(); - - await super.onInit(); - - this.context.dynamicDataSourceManager.initializeSource(this); - - this.ensureDynamicDataSourcesConnection(); - - return; - } - - //#endregion - - //#region WebPart lifecycle methods - - protected get isRenderAsync(): boolean { - return true; - } - - public async render(): Promise { - - await super.initTemplate(); - - return this.renderCompleted(); - } - - public renderCompleted(): void { - - let renderRootElement: JSX.Element; - - if (this.properties.filtersConfiguration.length > 0) { - - const element: React.ReactElement = React.createElement( - SearchFilters, - { - id: this.getComponentId(ComponentType.SearchFilters), - filtersConfiguration: this.properties.filtersConfiguration, - searchResultsComponentIds: this.properties.searchResultsDataSourceReferences, - searchVerticalsComponentId: this.properties.verticalsDataSourceReference, - operator: this.properties.filterOperator, - enableDebugMode: this.properties.enableDebugMode, - useMicrosoftGraphToolkit: this.properties.useMicrosoftGraphToolkit, - templateContent: this.templateContentToDisplay, - theme: this._themeVariant.isInverted ? "dark" : "" - } - ); - - renderRootElement = element; - - } else { - - if (this.displayMode === DisplayMode.Edit) { - - const placeholder: React.ReactElement = React.createElement( - this._placeholderComponent, - { - iconName: "", - iconText: webPartStrings.General.PlaceHolder.IconText, - description: () => React.createElement(WebPartPlaceholder, { - description: webPartStrings.General.PlaceHolder.Description, - documentationLink: this.properties.documentationLink - } , null), - buttonLabel: webPartStrings.General.PlaceHolder.ConfigureBtnLabel, - onConfigure: () => { this.context.propertyPane.open(); } - } - ); - - renderRootElement = placeholder; - } - } - - ReactDom.render(renderRootElement, this.domElement); - } - - protected onDispose(): void { - ReactDom.unmountComponentAtNode(this.domElement); - } - - private initializeProperties(): void { - - if (!this.properties.filtersConfiguration) { - this.properties.filtersConfiguration = []; - } - - this.properties.filterOperator = this.properties.filterOperator ? this.properties.filterOperator : FilterConditionOperator.OR; - this.properties.searchResultsDataSourceReferences = this.properties.searchResultsDataSourceReferences ? this.properties.searchResultsDataSourceReferences : []; - - this.properties.selectedLayoutKey = this.properties.selectedLayoutKey ? this.properties.selectedLayoutKey : BuiltinLayoutsKeys.FiltersDefault; - } - - //#endregion - - //#region Property Pane methods - - protected getPropertyPaneConfiguration(): IPropertyPaneConfiguration { - return { - pages: [ - { - groups: [ - { - groupName: "General", - groupFields: [ - ...this._propertyPaneSearchResultsFields, - PropertyPaneChoiceGroup('filterOperator',{ - label: webPartStrings.PropertyPane.CommonSettings.FilterOperatorLabel, - options: [ - { - key: FilterConditionOperator.AND, - text: webPartStrings.PropertyPane.CommonSettings.ANDOperator - }, - { - key: FilterConditionOperator.OR, - text: webPartStrings.PropertyPane.CommonSettings.OROperator - } - ] - }), - ...this._propertyPaneSearchVerticalsFields - ] - }, - { - groupName: "Filter settings", - isCollapsed: false, - groupFields: [ - new PropertyPaneFiltersConfiguration('filtersConfiguration', { - serviceScope: this.context.serviceScope, - defaultValue: this.properties.filtersConfiguration, - verticalsConfiguration: this.verticalsConfiguration - }) - ] - } - ], - displayGroupsAsAccordion: true - }, - // Templating page - { - displayGroupsAsAccordion: true, - groups: [this.getTemplateOptionsGroup()] - - }, - // Common page - { - displayGroupsAsAccordion: true, - groups: [this.getThemePageGroup()] - }, - // 'About' infos - { - displayGroupsAsAccordion: true, - groups: [ - ...this.getPropertyPaneWebPartInfoGroups(), - ] - } - ] - }; - } - - public override async onPropertyPaneFieldChanged(propertyPath: string, oldValue: unknown, newValue: unknown): Promise { - - if (propertyPath.localeCompare("verticalsDataSourceReference") === 0 || - propertyPath.localeCompare("searchResultsDataSourceReferences") === 0) { - this.ensureDynamicDataSourcesConnection(); - } - - if (propertyPath.localeCompare('useVerticals') === 0) { - if (!this.properties.useVerticals) { - this.properties.verticalsDataSourceReference = undefined; - this._verticalsConnectionSourceData = undefined; - this.verticalsConfiguration = undefined; - - // Reset vertical keys for all filters - this.properties.filtersConfiguration = this.properties.filtersConfiguration.map(f => { - f.verticalKeys = []; - return f; - }); - } - } - - this._propertyPaneSearchResultsFields = await this.getSearchResultsConnectionField(); - this._propertyPaneSearchVerticalsFields = await this.getVerticalsConnectionField(); - this.context.propertyPane.refresh(); - - await super.onPropertyPaneFieldChanged(propertyPath, oldValue, newValue); - } - - protected async onPropertyPaneConfigurationStart(): Promise { - await this.loadPropertyPaneResources(); - } - - protected async loadPropertyPaneResources(): Promise { - this._propertyPaneSearchResultsFields = await this.getSearchResultsConnectionField(); - this._propertyPaneSearchVerticalsFields = await this.getVerticalsConnectionField(); - - await super.loadPropertyPaneResources(); - } - - private async getSearchResultsConnectionField(): Promise[]> { - - const availableSources = await this.dynamicDataService.getAvailableDataSourcesByType(ComponentType.SearchResults); - - const sourceOptions = availableSources.map(source => { - return { - text: source.text, - key: source.key, - } as IComboBoxOption; - }); - - this.properties.searchResultsDataSourceReferences.map(ref => { - const existingSource = sourceOptions.filter(s =>s.key === ref)[0]; - if (!existingSource) { - sourceOptions.push( { - key: ref, - text: `(Not available) ${ref}` - }); - } - }); - - return [ - PropertyFieldMultiSelect('searchResultsDataSourceReferences', { - key: "searchResultsDataSourceReferences", - label: webPartStrings.PropertyPane.CommonSettings.UseSearchResultsWebPartLabel, - options: sourceOptions, - selectedKeys: this.properties.searchResultsDataSourceReferences - }) - ]; - } - - private async getVerticalsConnectionField(): Promise[]> { - - const verticalFields = [ - PropertyPaneToggle('useVerticals', { - label: "Use verticals", - checked: this.properties.useVerticals - }), - ]; - - if (this.properties.useVerticals) { - verticalFields.push( - PropertyPaneDropdown('verticalsDataSourceReference', { - options: await this.dynamicDataService.getAvailableDataSourcesByType(ComponentType.SearchVerticals), - label: "Search verticals component to connect to" - }) - ); - } - - if (this.properties.verticalsDataSourceReference && this._verticalsConnectionSourceData) { - - const { verticalsConfiguration } = this._verticalsConnectionSourceData.tryGetValue(); - this.verticalsConfiguration = verticalsConfiguration; - - } - - return verticalFields; - } - - //#endregion - - //#endregion -} diff --git a/packages/spfx/src/webparts/searchFilters/components/ISearchFiltersProps.ts b/packages/spfx/src/webparts/searchFilters/components/ISearchFiltersProps.ts deleted file mode 100644 index 36c9096..0000000 --- a/packages/spfx/src/webparts/searchFilters/components/ISearchFiltersProps.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { FilterConditionOperator } from "@pnp/modern-search-core/dist/es6/models/common/IDataFilter"; -import { IDataFilterConfiguration } from "@pnp/modern-search-core/dist/es6/models/common/IDataFilterConfiguration"; -import { IBaseWebComponentWrapperProps } from "../../../models/common/IBaseWebComponentWrapper"; - -export interface ISearchFiltersProps extends IBaseWebComponentWrapperProps { - - /** - * The default logical operator to use between filters - */ - operator: FilterConditionOperator; - - /** - * Connected search results - */ - searchResultsComponentIds: string[]; - - /** - * Connected search verticals - */ - searchVerticalsComponentId: string; - - /** - * The filters configuration - */ - filtersConfiguration: IDataFilterConfiguration[]; -} - diff --git a/packages/spfx/src/webparts/searchFilters/components/SearchFilters.tsx b/packages/spfx/src/webparts/searchFilters/components/SearchFilters.tsx deleted file mode 100644 index 894e9be..0000000 --- a/packages/spfx/src/webparts/searchFilters/components/SearchFilters.tsx +++ /dev/null @@ -1,53 +0,0 @@ -import * as React from 'react'; -import { ISearchFiltersProps } from './ISearchFiltersProps'; -import { SearchFiltersComponent } from '@pnp/modern-search-core'; -import { wrapWc } from 'wc-react'; -import parse, { } from 'html-react-parser'; -import { isEqual } from '@microsoft/sp-lodash-subset'; -import { Guid } from '@microsoft/sp-core-library'; -import { ComponentElements } from '@pnp/modern-search-core/dist/es6/common/Constants'; -import { CheckboxFilterComponent } from '@pnp/modern-search-core/dist/es6/components/search-filters/sub-components/filters/checkbox-filter/CheckboxFilterComponent'; - -const SearchFiltersWebComponent = wrapWc('pnp-search-filters'); - -export default class SearchFilters extends React.Component { - - private componentRef = React.createRef(); - - public render(): React.ReactElement { - - // eslint-disable-next-line @typescript-eslint/explicit-function-return-type - const TemplateContent = () => { - return (this.props.templateContent ? parse(this.props.templateContent) : null) as JSX.Element; - }; - - return - - ; - } - - public componentDidUpdate(prevProps: Readonly): void { - - if (!isEqual(prevProps.templateContent, this.props.templateContent)) { - - // Forces a tempalte re-render by faking an update to the template context - // TODO: Find a better way to do that at component level - // https://github.com/microsoftgraph/microsoft-graph-toolkit/blob/d27ffa723d36fa39533a4e705965ba656a71b82a/packages/mgt-element/src/components/templatedComponent.ts#L141C35-L141C46 - this.componentRef.current.templateContext = {...this.componentRef.current.templateContext, random: Guid.newGuid() } - this.componentRef.current.shadowRoot.querySelectorAll(ComponentElements.CheckboxFilterComponent).forEach((e: CheckboxFilterComponent) => { - e.templateContext = {...e.templateContext, random: Guid.newGuid()}; - }); - } - } -} diff --git a/packages/spfx/src/webparts/searchFilters/loc/en-us.js b/packages/spfx/src/webparts/searchFilters/loc/en-us.js deleted file mode 100644 index c464a48..0000000 --- a/packages/spfx/src/webparts/searchFilters/loc/en-us.js +++ /dev/null @@ -1,24 +0,0 @@ -define([], function() { - return { - General: { - PlaceHolder: { - EditLabel: "Edit", - IconText: "Search Filters Web Part by PnP", - Description: "Displays search filters from connected search results Web Parts on the page", - ConfigureBtnLabel: "Get started" - }, - WebPartDefaultTitle: "Search Filters Web Part", - }, - PropertyPane: { - CommonSettings: { - UseSearchResultsWebPartLabel: "Get filter values from these Web Parts", - FilterOperatorLabel: "Operator to use between filters", - ANDOperator: "AND", - OROperator: "OR" - }, - FiltersSettings: { - SettingsGroupName: "Filters settings" - } - } - } -}); \ No newline at end of file diff --git a/packages/spfx/src/webparts/searchFilters/loc/mystrings.d.ts b/packages/spfx/src/webparts/searchFilters/loc/mystrings.d.ts deleted file mode 100644 index 3d9eb55..0000000 --- a/packages/spfx/src/webparts/searchFilters/loc/mystrings.d.ts +++ /dev/null @@ -1,28 +0,0 @@ -declare interface ISearchFiltersWebPartStrings { - General: { - PlaceHolder: { - EditLabel: string; - IconText: string; - Description: string; - ConfigureBtnLabel: string; - }, - NoAvailableFilterMessage: string; - WebPartDefaultTitle: string; -}, -PropertyPane: { - CommonSettings: { - UseSearchResultsWebPartLabel: string; - FilterOperatorLabel: string; - ANDOperator: string; - OROperator: string; - }, - FiltersSettings: { - SettingsGroupName: string; - } -} -} - -declare module 'SearchFiltersWebPartStrings' { - const strings: ISearchFiltersWebPartStrings; - export = strings; -} diff --git a/packages/spfx/src/webparts/searchResults/ISearchResultsWebPartProps.ts b/packages/spfx/src/webparts/searchResults/ISearchResultsWebPartProps.ts deleted file mode 100644 index e5473d0..0000000 --- a/packages/spfx/src/webparts/searchResults/ISearchResultsWebPartProps.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { IBaseWebPartProps } from "../../models/common/IBaseWebPartProps"; -import { IMicrosoftSearchDataSourceProperties } from "../../datasources/MicrosoftSearchDataSource"; - -export interface ISearchResultsWebPartProps extends IBaseWebPartProps, IMicrosoftSearchDataSourceProperties { - - /** - * Enables verticals - */ - useVerticals: boolean; - - /** - * Reference to the Verticals WebPart if any connected - */ - verticalsDataSourceReference: string; - - /** - * The configured selected vertical keys when results should be displayed - */ - selectedVerticalKeys: string[]; - - /** - * To show the results count or not - */ - showResultsCount: boolean; -} - \ No newline at end of file diff --git a/packages/spfx/src/webparts/searchResults/SearchResultsWebPart.manifest.json b/packages/spfx/src/webparts/searchResults/SearchResultsWebPart.manifest.json deleted file mode 100644 index 20fc098..0000000 --- a/packages/spfx/src/webparts/searchResults/SearchResultsWebPart.manifest.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "$schema": "https://developer.microsoft.com/json-schemas/spfx/client-side-web-part-manifest.schema.json", - "id": "6aa5f17d-c6f5-4853-8017-86ad27f396f1", - "alias": "PnPModernSearchCoreResultsWebPart", - "componentType": "WebPart", - "version": "1.0.0", - "manifestVersion": 2, - "requiresCustomScript": false, - "supportedHosts": [ - "SharePointWebPart", - "TeamsPersonalApp", - "TeamsTab", - "SharePointFullPage" - ], - "supportsThemeVariants": true, - "preconfiguredEntries": [ - { - "groupId": "5c03119e-3074-46fd-976b-c60198311f70", - "group": { - "default": "Advanced" - }, - "title": { - "default": "PnP Modern Search Core Components - Search Results", - "fr-fr": "PnP Modern Search Core Components - Résultats de recherche" - }, - "description": { - "default": "Displays results from Microsoft Search using customizable templates", - "fr-fr": "Affiche des données de multiples source de données au format JSON selon des modèles d'affichage personnalisables." - }, - "iconImageUrl": "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0nNDAnIGhlaWdodD0nMjgnIHZpZXdCb3g9JzAgMCA0MCAyOCcgZmlsbD0nbm9uZScgeG1sbnM9J2h0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnJz48cGF0aCBkPSdNMTEuNjk5OCA5LjdIMTYuNTk5OFYxN0gxMS42OTk4VjkuN1pNMzUuOTk5OCAyLjRWMjYuN0MzNS45OTk4IDI2LjkgMzUuODk5OCAyNy4xIDM1Ljc5OTggMjcuM0MzNS42OTk4IDI3LjUgMzUuNTk5OCAyNy42IDM1LjM5OTggMjcuN0MzNS4xOTk4IDI3LjkgMzQuOTk5OCAyOCAzNC43OTk4IDI4QzM0LjU5OTggMjggMzQuMzk5OCAyOCAzNC4xOTk4IDI3LjlMMjkuODk5OCAyNS43TDI1LjU5OTggMjcuOUMyNS4zOTk4IDI3LjkgMjUuMTk5OCAyOCAyNC45OTk4IDI4QzI0Ljc5OTggMjggMjQuNTk5OCAyOCAyNC40OTk4IDI3LjlMMjAuMTk5OCAyNS43TDE1Ljg5OTggMjcuOUMxNS42OTk4IDI4IDE1LjQ5OTggMjggMTUuMzk5OCAyOEMxNS4xOTk4IDI4IDE0Ljk5OTggMjggMTQuODk5OCAyNy45TDEwLjU5OTggMjUuN0w2LjI5OTggMjcuOUM1Ljg5OTggMjggNS42OTk4IDI4IDUuNDk5OCAyOEM1LjI5OTggMjggNS4wOTk4IDI3LjkgNC44OTk4IDI3LjhDNC42OTk4IDI3LjcgNC41OTk4IDI3LjUgNC40OTk4IDI3LjRDNC4zOTk4IDI3LjIgNC4yOTk4IDI3IDQuMjk5OCAyNi44VjIuNEM0LjI5OTggMS44IDQuNTk5OCAxLjEgNC45OTk4IDAuN0M1LjQ5OTggMC4zIDYuMDk5OCAwIDYuNzk5OCAwSDMzLjU5OThDMzQuMTk5OCAwIDM0Ljg5OTggMC4zIDM1LjI5OTggMC43QzM1LjY5OTggMS4yIDM1Ljk5OTggMS44IDM1Ljk5OTggMi40Wk0xOC45OTk4IDguNUMxOC45OTk4IDguMiAxOC44OTk4IDcuOSAxOC41OTk4IDcuNkMxOC4zOTk4IDcuNCAxOC4wOTk4IDcuMiAxNy42OTk4IDcuMkgxMC4zOTk4QzEwLjA5OTggNy4yIDkuNzk5OCA3LjMgOS40OTk4IDcuNkM5LjI5OTggNy45IDkuMTk5OCA4LjIgOS4xOTk4IDguNVYxOC4yQzkuMTk5OCAxOC41IDkuMjk5OCAxOC44IDkuNTk5OCAxOS4xQzkuNzk5OCAxOS4zIDEwLjA5OTggMTkuNSAxMC40OTk4IDE5LjVIMTcuNzk5OEMxOC4wOTk4IDE5LjUgMTguMzk5OCAxOS40IDE4LjY5OTggMTkuMUMxOC44OTk4IDE4LjkgMTkuMDk5OCAxOC42IDE5LjA5OTggMTguMlY4LjVIMTguOTk5OFpNMzEuMDk5OCAxNS44QzMxLjA5OTggMTUuNSAzMC45OTk4IDE1LjIgMzAuNjk5OCAxNC45QzMwLjQ5OTggMTQuNyAzMC4xOTk4IDE0LjUgMjkuNzk5OCAxNC41SDIyLjQ5OThDMjIuMTk5OCAxNC41IDIxLjg5OTggMTQuNiAyMS41OTk4IDE0LjlDMjEuMzk5OCAxNS4xIDIxLjE5OTggMTUuNCAyMS4xOTk4IDE1LjhDMjEuMTk5OCAxNi4xIDIxLjI5OTggMTYuNCAyMS41OTk4IDE2LjdDMjEuNzk5OCAxNi45IDIyLjA5OTggMTcuMSAyMi40OTk4IDE3LjFIMjkuNzk5OEMzMC4wOTk4IDE3LjEgMzAuMzk5OCAxNyAzMC42OTk4IDE2LjdDMzAuOTk5OCAxNi41IDMxLjA5OTggMTYuMSAzMS4wOTk4IDE1LjhaTTMxLjA5OTggMTFDMzEuMDk5OCAxMC43IDMwLjk5OTggMTAuNCAzMC42OTk4IDEwLjFDMzAuNDk5OCA5LjkgMzAuMTk5OCA5LjcgMjkuNzk5OCA5LjdIMjIuNDk5OEMyMi4xOTk4IDkuNyAyMS44OTk4IDkuOCAyMS41OTk4IDEwLjFDMjEuMzk5OCAxMC4zIDIxLjE5OTggMTAuNiAyMS4xOTk4IDExQzIxLjE5OTggMTEuMyAyMS4yOTk4IDExLjYgMjEuNTk5OCAxMS45QzIxLjc5OTggMTIuMSAyMi4wOTk4IDEyLjMgMjIuNDk5OCAxMi4zSDI5Ljc5OThDMzAuMDk5OCAxMi4zIDMwLjM5OTggMTIuMiAzMC42OTk4IDExLjlDMzAuOTk5OCAxMS42IDMxLjA5OTggMTEuMyAzMS4wOTk4IDExWicgZmlsbD0nIzAwNzhkNCcvPjwvc3ZnPg==", - "properties": { - "issueLink": "https://github.com/microsoft-search/pnp-modern-search-core-components/issues/new", - "documentationLink": "https://microsoft-search.github.io/pnp-modern-search-core-components/docs/sharepoint-webparts/available-webparts/search-results" - } - } - ] -} \ No newline at end of file diff --git a/packages/spfx/src/webparts/searchResults/SearchResultsWebPart.manifest.template.json b/packages/spfx/src/webparts/searchResults/SearchResultsWebPart.manifest.template.json deleted file mode 100644 index 453a025..0000000 --- a/packages/spfx/src/webparts/searchResults/SearchResultsWebPart.manifest.template.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "$schema": "https://developer.microsoft.com/json-schemas/spfx/client-side-web-part-manifest.schema.json", - "id": "6aa5f17d-c6f5-4853-8017-86ad27f396f1", - "alias": "PnPModernSearchCoreResultsWebPart", - "componentType": "WebPart", - "version": "1.0.0", - "manifestVersion": 2, - "requiresCustomScript": false, - "supportedHosts": [ - "SharePointWebPart", - "TeamsPersonalApp", - "TeamsTab", - "SharePointFullPage" - ], - "supportsThemeVariants": true, - "preconfiguredEntries": [ - { - "groupId": "5c03119e-3074-46fd-976b-c60198311f70", - "group": { - "default": "Advanced" - }, - "title": { - "default": "PnP Modern Search Core Components - Search Results", - "fr-fr": "PnP Modern Search Core Components - Résultats de recherche" - }, - "description": { - "default": "Displays results from Microsoft Search using customizable templates", - "fr-fr": "Affiche des données de multiples source de données au format JSON selon des modèles d'affichage personnalisables." - }, - "iconImageUrl": "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0nNDAnIGhlaWdodD0nMjgnIHZpZXdCb3g9JzAgMCA0MCAyOCcgZmlsbD0nbm9uZScgeG1sbnM9J2h0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnJz48cGF0aCBkPSdNMTEuNjk5OCA5LjdIMTYuNTk5OFYxN0gxMS42OTk4VjkuN1pNMzUuOTk5OCAyLjRWMjYuN0MzNS45OTk4IDI2LjkgMzUuODk5OCAyNy4xIDM1Ljc5OTggMjcuM0MzNS42OTk4IDI3LjUgMzUuNTk5OCAyNy42IDM1LjM5OTggMjcuN0MzNS4xOTk4IDI3LjkgMzQuOTk5OCAyOCAzNC43OTk4IDI4QzM0LjU5OTggMjggMzQuMzk5OCAyOCAzNC4xOTk4IDI3LjlMMjkuODk5OCAyNS43TDI1LjU5OTggMjcuOUMyNS4zOTk4IDI3LjkgMjUuMTk5OCAyOCAyNC45OTk4IDI4QzI0Ljc5OTggMjggMjQuNTk5OCAyOCAyNC40OTk4IDI3LjlMMjAuMTk5OCAyNS43TDE1Ljg5OTggMjcuOUMxNS42OTk4IDI4IDE1LjQ5OTggMjggMTUuMzk5OCAyOEMxNS4xOTk4IDI4IDE0Ljk5OTggMjggMTQuODk5OCAyNy45TDEwLjU5OTggMjUuN0w2LjI5OTggMjcuOUM1Ljg5OTggMjggNS42OTk4IDI4IDUuNDk5OCAyOEM1LjI5OTggMjggNS4wOTk4IDI3LjkgNC44OTk4IDI3LjhDNC42OTk4IDI3LjcgNC41OTk4IDI3LjUgNC40OTk4IDI3LjRDNC4zOTk4IDI3LjIgNC4yOTk4IDI3IDQuMjk5OCAyNi44VjIuNEM0LjI5OTggMS44IDQuNTk5OCAxLjEgNC45OTk4IDAuN0M1LjQ5OTggMC4zIDYuMDk5OCAwIDYuNzk5OCAwSDMzLjU5OThDMzQuMTk5OCAwIDM0Ljg5OTggMC4zIDM1LjI5OTggMC43QzM1LjY5OTggMS4yIDM1Ljk5OTggMS44IDM1Ljk5OTggMi40Wk0xOC45OTk4IDguNUMxOC45OTk4IDguMiAxOC44OTk4IDcuOSAxOC41OTk4IDcuNkMxOC4zOTk4IDcuNCAxOC4wOTk4IDcuMiAxNy42OTk4IDcuMkgxMC4zOTk4QzEwLjA5OTggNy4yIDkuNzk5OCA3LjMgOS40OTk4IDcuNkM5LjI5OTggNy45IDkuMTk5OCA4LjIgOS4xOTk4IDguNVYxOC4yQzkuMTk5OCAxOC41IDkuMjk5OCAxOC44IDkuNTk5OCAxOS4xQzkuNzk5OCAxOS4zIDEwLjA5OTggMTkuNSAxMC40OTk4IDE5LjVIMTcuNzk5OEMxOC4wOTk4IDE5LjUgMTguMzk5OCAxOS40IDE4LjY5OTggMTkuMUMxOC44OTk4IDE4LjkgMTkuMDk5OCAxOC42IDE5LjA5OTggMTguMlY4LjVIMTguOTk5OFpNMzEuMDk5OCAxNS44QzMxLjA5OTggMTUuNSAzMC45OTk4IDE1LjIgMzAuNjk5OCAxNC45QzMwLjQ5OTggMTQuNyAzMC4xOTk4IDE0LjUgMjkuNzk5OCAxNC41SDIyLjQ5OThDMjIuMTk5OCAxNC41IDIxLjg5OTggMTQuNiAyMS41OTk4IDE0LjlDMjEuMzk5OCAxNS4xIDIxLjE5OTggMTUuNCAyMS4xOTk4IDE1LjhDMjEuMTk5OCAxNi4xIDIxLjI5OTggMTYuNCAyMS41OTk4IDE2LjdDMjEuNzk5OCAxNi45IDIyLjA5OTggMTcuMSAyMi40OTk4IDE3LjFIMjkuNzk5OEMzMC4wOTk4IDE3LjEgMzAuMzk5OCAxNyAzMC42OTk4IDE2LjdDMzAuOTk5OCAxNi41IDMxLjA5OTggMTYuMSAzMS4wOTk4IDE1LjhaTTMxLjA5OTggMTFDMzEuMDk5OCAxMC43IDMwLjk5OTggMTAuNCAzMC42OTk4IDEwLjFDMzAuNDk5OCA5LjkgMzAuMTk5OCA5LjcgMjkuNzk5OCA5LjdIMjIuNDk5OEMyMi4xOTk4IDkuNyAyMS44OTk4IDkuOCAyMS41OTk4IDEwLjFDMjEuMzk5OCAxMC4zIDIxLjE5OTggMTAuNiAyMS4xOTk4IDExQzIxLjE5OTggMTEuMyAyMS4yOTk4IDExLjYgMjEuNTk5OCAxMS45QzIxLjc5OTggMTIuMSAyMi4wOTk4IDEyLjMgMjIuNDk5OCAxMi4zSDI5Ljc5OThDMzAuMDk5OCAxMi4zIDMwLjM5OTggMTIuMiAzMC42OTk4IDExLjlDMzAuOTk5OCAxMS42IDMxLjA5OTggMTEuMyAzMS4wOTk4IDExWicgZmlsbD0nIzAwNzhkNCcvPjwvc3ZnPg==", - "properties": { - "issueLink": "https://github.com/microsoft-search/pnp-modern-search-core-components/issues/new", - "documentationLink": "{{DOCUMENTATION_HOST_URL}}/docs/sharepoint-webparts/available-webparts/search-results" - } - } - ] -} \ No newline at end of file diff --git a/packages/spfx/src/webparts/searchResults/SearchResultsWebPart.tsx b/packages/spfx/src/webparts/searchResults/SearchResultsWebPart.tsx deleted file mode 100644 index 50632e9..0000000 --- a/packages/spfx/src/webparts/searchResults/SearchResultsWebPart.tsx +++ /dev/null @@ -1,610 +0,0 @@ -//#region Imports -import * as React from 'react'; -import * as ReactDom from 'react-dom'; -import { DisplayMode, ServiceKey } from '@microsoft/sp-core-library'; -import { - IPropertyPaneConfiguration, - IPropertyPaneField, - IPropertyPaneGroup, - PropertyPaneDropdown, - PropertyPaneToggle} from '@microsoft/sp-property-pane'; -import * as webPartStrings from 'SearchResultsWebPartStrings'; -import SearchResults from './components/SearchResults'; -import { BaseWebPart } from '../../common/BaseWebPart'; -import { ISearchResultsWebPartProps } from './ISearchResultsWebPartProps'; -import { IDynamicDataPropertyDefinition } from '@microsoft/sp-dynamic-data'; -import { ComponentType } from '../../common/ComponentType'; -import IDataSource from '../../models/common/IDataSource'; -import { ServiceScopeHelper } from '../../helpers/ServiceScopeHelper'; -import { SharePointTokenService } from '../../services/tokenService/SharePointTokenService'; -import { ISharePointTokenService } from '../../services/tokenService/ISharePointTokenService'; -import WebPartPlaceholder from '../../controls/WebPartPlaceholder/WebPartPlaceholder'; -import { IPlaceholderProps } from '@pnp/spfx-controls-react'; -import { DynamicProperty } from '@microsoft/sp-component-base'; -import { isEmpty } from '@microsoft/sp-lodash-subset'; -import { LayoutHelper } from '../../helpers/LayoutHelper'; -import { ILayoutDefinition, LayoutType } from '../../models/common/ILayoutDefinition'; -import { AvailableLayouts, BuiltinLayoutsKeys } from '../../layouts/AvailableLayouts'; -import { ITemplateContext } from '../../models/common/ITemplateContext'; -import { ISearchVerticalSourceData } from '../../models/dynamicData/ISearchVerticalSourceData'; -import { LocalizedStringHelper } from '@pnp/modern-search-core/dist/es6/helpers/LocalizedStringHelper'; -import { PropertyFieldMultiSelect } from '@pnp/spfx-property-controls'; -import { MessageBar, MessageBarType } from 'office-ui-fabric-react'; -import { DynamicPropertyHelper } from '../../helpers/DynamicPropertyHelper'; -import { EntityType } from '@pnp/modern-search-core/dist/es6/models/search/IMicrosoftSearchRequest'; - -//#endregion - -export default class SearchResultsWebPart extends BaseWebPart { - - //#region Class attributes - - //#region Services - - - /** - * The SharePoint token service instance - */ - private sharePointTokenService: ISharePointTokenService; - - //#endregion - - //#region Source fields - - /** - * The Microsoft Search source for the WebPart - */ - private microsoftSearchDataSource: IDataSource; - - private availableFields: string[] = []; - - //#endregion - - //#region Layout fields - - /** - * The available layout definitions (not instanciated) - */ - protected availableLayoutDefinitions: ILayoutDefinition[] = AvailableLayouts.BuiltinLayouts.filter(layout => { return layout.type === LayoutType.Results; }); - - //#endregion - - //#region Connection fields - - /** - * Dynamic data related fields - */ - private _filtersConnectionSourceData: DynamicProperty; - private _verticalsConnectionSourceData: DynamicProperty; - - //#endregion - - //#region Property pane fields - private propertyPaneFiltersConnectionField: IPropertyPaneField[]; - - //#endregion - - //#region Misc fields - - /** - * Querty template - */ - private _resolvedQueryTemplate: string; - - //#endregion - - //#endregion - - //#region Class methods - - //#region WebPart lifecycle methods - - protected get isRenderAsync(): boolean { - return true; - } - - protected async onInit(): Promise { - - this.inializeProperties(); - - await super.onInit(); - - this.initializeWebPartServices(); - - await this.loadResources(); - - // Initialize data source instance - if (!this.microsoftSearchDataSource) { - this.microsoftSearchDataSource = await this.getMicrosoftSearchSourceInstance(); - } - - this.context.dynamicDataSourceManager.initializeSource(this); - - this.ensureDynamicDataSourcesConnection(); - } - - public async render(): Promise { - - await this.initTemplate(); - - // Refresh the token values with the latest information from environment (i.e connections and settings) - this._resolvedQueryTemplate = await this.sharePointTokenService.resolveTokens(this.properties.queryTemplate); - - return this.renderCompleted(); - } - - protected renderCompleted(): void { - - let renderRootElement: JSX.Element; - let renderElement: React.ReactElement = null; - - if (this.isValidSearchQuery()) { - - // The component needs to be always rendered even if not selected on current vertical - // This is required to keep proper lifecycle of underlying web component properties - const renderSearchResults = - { - this.availableFields = data.availableFields; - this.context.propertyPane.refresh(); - }} - /> - - if (!this.shouldRenderComponent() && this.displayMode === DisplayMode.Edit) { - renderElement = <> - {renderSearchResults} - Current vertical is not part of configured vertical for that WebPart - - } else { - renderElement = renderSearchResults; - } - - renderRootElement = renderElement; - - } else { - - if (this.displayMode === DisplayMode.Edit) { - - const placeholder: React.ReactElement = React.createElement( - this._placeholderComponent, - { - iconName: "", - iconText: webPartStrings.General.PlaceHolder.IconText, - description: () => React.createElement(WebPartPlaceholder, { - description: webPartStrings.General.PlaceHolder.Description, - documentationLink: this.properties.documentationLink - } , null), - buttonLabel: webPartStrings.General.PlaceHolder.ConfigureBtnLabel, - onConfigure: () => { this.context.propertyPane.open(); } - } - ); - - renderRootElement = placeholder; - } - } - - ReactDom.render(renderRootElement, this.domElement); - - super.renderCompleted(); - } - - protected onDispose(): void { - ReactDom.unmountComponentAtNode(this.domElement); - } - - //#endregion - - //#region Dynamic data methods - - public getPropertyDefinitions(): IDynamicDataPropertyDefinition[] { - - // Use the Web Part title as property title since we don't expose sub properties - const propertyDefinitions: IDynamicDataPropertyDefinition[] = []; - - propertyDefinitions.push( - { - id: ComponentType.SearchResults, - title: this.properties.title ? `${this.properties.title} - ${this.instanceId}` : `${webPartStrings.General.WebPartDefaultTitle} - ${this.instanceId}`, - } - ); - - return propertyDefinitions; - } - - public getPropertyValue(propertyId: string): string { - return; - } - - //#endregion - - //#region Property Pane methods - - protected getPropertyPaneConfiguration(): IPropertyPaneConfiguration { - return { - pages: [ - // Query configuration page - { - groups: [ - ...this.microsoftSearchDataSource.getPropertyPaneGroupsConfiguration(), - ], - displayGroupsAsAccordion: true - }, - // Templating page - { - displayGroupsAsAccordion: true, - groups: this.getStylingPageGroups() - }, - // Common page - { - displayGroupsAsAccordion: true, - groups: [this.getThemePageGroup()] - }, - // 'About' infos - { - displayGroupsAsAccordion: true, - groups: [ - ...this.getPropertyPaneWebPartInfoGroups(), - ] - } - ] - }; - } - - protected async onPropertyPaneFieldChanged(propertyPath: string, oldValue: unknown, newValue: unknown): Promise { - - //#region Source related properties - - if (this.microsoftSearchDataSource) { - - this.microsoftSearchDataSource.onPropertyPaneFieldChanged(propertyPath, oldValue, newValue); - - // Bind connected data sources - if (propertyPath.localeCompare('filtersDataSourceReference') === 0 && this.properties.filtersDataSourceReference || - propertyPath.localeCompare('verticalsDataSourceReference') === 0 && this.properties.verticalsDataSourceReference - ) { - this.ensureDynamicDataSourcesConnection(); - this.context.propertyPane.refresh(); - } - - if (propertyPath.localeCompare('useFilters') === 0) { - if (!this.properties.useFilters) { - this.properties.filtersDataSourceReference = undefined; - this._filtersConnectionSourceData = undefined; - this.context.dynamicDataSourceManager.notifyPropertyChanged(ComponentType.SearchResults); - } - } - - if (propertyPath.localeCompare('useVerticals') === 0) { - if (!this.properties.useVerticals) { - this.properties.verticalsDataSourceReference = undefined; - this.properties.selectedVerticalKeys = []; - this._verticalsConnectionSourceData = undefined; - } - } - } - - //#endregion - - this.propertyPaneFiltersConnectionField = await this.getVerticalsConnectionField(); - - await super.onPropertyPaneFieldChanged(propertyPath, oldValue, newValue); - - this.context.propertyPane.refresh(); - - //#endregion - } - - /** - * Returns layout template options if any - */ - private getLayoutTemplateOptions(): IPropertyPaneField[] { - - if (this.layout) { - return this.layout.getPropertyPaneFieldsConfiguration(this.availableFields); - } else { - return []; - } - } - - private async getVerticalsConnectionField(): Promise[]> { - - const verticalFields = [ - PropertyPaneToggle('useVerticals', { - label: webPartStrings.PropertyPane.LayoutPage.UseSearchVerticalsField, - checked: this.properties.useVerticals - }), - ]; - - if (this.properties.useVerticals) { - verticalFields.push( - PropertyPaneDropdown('verticalsDataSourceReference', { - options: await this.dynamicDataService.getAvailableDataSourcesByType(ComponentType.SearchVerticals), - label: webPartStrings.PropertyPane.LayoutPage.SearchVerticalsConnectToComponentField - }) - ); - } - - if (this.properties.verticalsDataSourceReference && this._verticalsConnectionSourceData) { - - const { verticalsConfiguration } = this._verticalsConnectionSourceData.tryGetValue(); - - verticalFields.push( - PropertyFieldMultiSelect('selectedVerticalKeys', { - key: "selectedVerticalKeys", - label: webPartStrings.PropertyPane.LayoutPage.SearchVerticalsConnectionField, - options: verticalsConfiguration.map(v => { return { key: v.key,text: LocalizedStringHelper.getDefaultValue(v.tabName)}}), - selectedKeys: this.properties.selectedVerticalKeys - }) - ) - } - - return verticalFields; - } - - /** - * Returns property pane 'Styling' page groups - */ - private getStylingPageGroups(): IPropertyPaneGroup[] { - - const groups: IPropertyPaneGroup[] = [ - this.getTemplateOptionsGroup(), - { - groupName: webPartStrings.PropertyPane.LayoutPage.CommonLayoutOptionsGroupName, - groupFields: [ - ...LayoutHelper.getCommonLayoutsOptionFields(this.properties), - ...this.propertyPaneFiltersConnectionField - ] - } - ]; - - // Add template options if any - const layoutOptions = this.getLayoutTemplateOptions(); - if (layoutOptions.length > 0) { - groups.push({ - groupName: webPartStrings.PropertyPane.LayoutPage.LayoutTemplateOptionsGroupName, - groupFields: layoutOptions - }); - } - - return groups; - } - - //#endregion - - //#region Utility methods - - private initializeWebPartServices(): void { - - this.context.serviceScope.whenFinished(() => { - this.sharePointTokenService = this.context.serviceScope.consume(SharePointTokenService.ServiceKey); - }); - } - - private inializeProperties(): void { - this.properties.selectedLayoutKey = this.properties.selectedLayoutKey ? this.properties.selectedLayoutKey : BuiltinLayoutsKeys.ResultsDefault; - } - - protected async loadPropertyPaneResources(): Promise { - this.propertyPaneFiltersConnectionField = await this.getVerticalsConnectionField(); - - await super.loadPropertyPaneResources(); - } - - /** - * Gets the data source instance according to the current selected one - * @param dataSourceKey the selected data source provider key - * @param dataSourceDefinitions the available source definitions - * @returns the data source provider instance - */ - private async getMicrosoftSearchSourceInstance(): Promise { - - let dataSource: IDataSource = undefined; - let serviceKey: ServiceKey = undefined; - - // eslint-disable-next-line no-case-declarations - const { MicrosoftSearchDataSource } = await import( - /* webpackChunkName: 'pnp-modern-search-core-microsoft-search-datasource' */ - '../../datasources/MicrosoftSearchDataSource' - ); - - serviceKey = ServiceKey.create('ModernSearchCore:MicrosoftSearchDataSource', MicrosoftSearchDataSource); - - return new Promise((resolve) => { - - // Register here services we want to expose to custom data source (ex: TokenService) - // The instances are shared across all data sources. It means when properties will be set once for all consumers. Be careful manipulating these instance properties. - const childServiceScope = ServiceScopeHelper.registerChildServices(this.webPartInstanceServiceScope, [ - serviceKey - ]); - - childServiceScope.whenFinished(async () => { - - // Register the data source service in the Web Part scope only (child scope of the current scope) - dataSource = childServiceScope.consume(serviceKey); - - // Initialize the data source with current Web Part properties - if (dataSource) { - - // Initializes Web part lifecycle methods and properties - dataSource.properties = this.properties; - dataSource.context = this.context; - dataSource.render = this.render; - - await dataSource.onInit(); - - resolve(dataSource); - } - }); - }); - } - - /** - * Make sure the dynamic properties are correctly connected to the corresponding sources according to the proeprty pane settings - */ - private ensureDynamicDataSourcesConnection(): void { - - // Filters Web Part data source - if (this.properties.filtersDataSourceReference) { - - if (!this._filtersConnectionSourceData) { - this._filtersConnectionSourceData = new DynamicProperty(this.context.dynamicDataProvider); - } - - this._filtersConnectionSourceData.setReference(this.properties.filtersDataSourceReference); - this._filtersConnectionSourceData.register(this.render); - - } else { - - if (this._filtersConnectionSourceData) { - this._filtersConnectionSourceData.unregister(this.render); - } - } - - // Verticals WebPart data source - if (this.properties.verticalsDataSourceReference) { - - if (!this._verticalsConnectionSourceData) { - this._verticalsConnectionSourceData = new DynamicProperty(this.context.dynamicDataProvider); - } - - this._verticalsConnectionSourceData.setReference(this.properties.verticalsDataSourceReference); - this._verticalsConnectionSourceData.register(this.render); - - } else { - - if (this._verticalsConnectionSourceData) { - this._verticalsConnectionSourceData.unregister(this.render); - } - } - } - - private getTemplateContext(): ITemplateContext { - return { - layoutProperties: {...this.properties.layoutProperties}, - slots: LayoutHelper.convertTemplateSlotsToHashtable(this.properties.layoutProperties.slots) - }; - } - - private isValidSearchQuery(): boolean { - - let hasValidEntityTypes = false; - - if (this.properties.entityTypes.length > 0) { - if (this.properties.entityTypes.indexOf(EntityType.ExternalItem) !== -1 && this.properties.contentSources.length === 0) { - hasValidEntityTypes = false; - } else { - hasValidEntityTypes= true; - } - } - - const canExecuteQuery = !!this.microsoftSearchDataSource && - (this.properties.queryText.reference || !this.properties.queryText.reference && !isEmpty(this.getQueryTextValue())) && - hasValidEntityTypes; - - return canExecuteQuery; - } - - /** - * If connected to a search verticales, determines if the component should be displayed according to current selected vertical - * @returns 'true' if it should render, 'false' otherwise - */ - private shouldRenderComponent(): boolean { - - let shouldRender = true; - if (this._verticalsConnectionSourceData) { - - const { selectedVerticalKey } = this._verticalsConnectionSourceData.tryGetValue(); - - if (this.properties.selectedVerticalKeys.indexOf(selectedVerticalKey) === -1) { - shouldRender = false - } - } - - return shouldRender; - } - - /** - * Resolves the search b ox component id if connected - * @returns the component ID - */ - private getSearchBoxComponentId(): string { - - let searchBoxComponentId: string = undefined; - - // Because 'queryText' can have a value other than a SearchBox component (ex: search query from top bar), we need it to resolve if manually - if (this.properties.queryText.reference?.indexOf(ComponentType.SearchBox) !== -1) { - searchBoxComponentId = this.properties.queryText.reference; - } - - return searchBoxComponentId; - } - - /** - * Determines the input query text value based on dynamic data connections - */ - private getQueryTextValue(): string { - - let inputQueryText: string = undefined; - - // tryGetValue() will resolve to '' if no Web Part is connected or if the connection is removed - // The value can be also 'undefined' if the data source is not already loaded on the page. - let inputQueryFromDataSource: string | undefined = ""; - if (this.properties.queryText.reference && this.properties.useDefaultQueryText) { - try { - inputQueryFromDataSource = DynamicPropertyHelper.tryGetValueSafe(this.properties.queryText); - if (inputQueryFromDataSource !== undefined && typeof (inputQueryFromDataSource) === 'string') { - inputQueryFromDataSource = decodeURIComponent(inputQueryFromDataSource); - } - - } catch (error) { - // Likely issue when q=%25 in spfx - } - } else { - inputQueryFromDataSource = DynamicPropertyHelper.tryGetValueSafe(this.properties.queryText); - } - - if (!inputQueryFromDataSource) { // '' or 'undefined' - - if (this.properties.useDefaultQueryText) { - inputQueryText = this.properties.defaultQueryText; - } else if (inputQueryFromDataSource !== undefined) { - inputQueryText = inputQueryFromDataSource; - } - - } else if (typeof (inputQueryFromDataSource) === 'string') { - inputQueryText = decodeURIComponent(inputQueryFromDataSource); - } - - return inputQueryText; - } - - //#endregion - - //#endregion -} \ No newline at end of file diff --git a/packages/spfx/src/webparts/searchResults/components/ISearchResultComponentProps.ts b/packages/spfx/src/webparts/searchResults/components/ISearchResultComponentProps.ts deleted file mode 100644 index 5a53d8c..0000000 --- a/packages/spfx/src/webparts/searchResults/components/ISearchResultComponentProps.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { ISortFieldConfiguration } from "@pnp/modern-search-core/dist/es6/models/common/ISortFieldConfiguration"; -import { EntityType } from "@pnp/modern-search-core/dist/es6/models/search/IMicrosoftSearchRequest"; - -export interface ISearchResultsComponentProps { - defaultQueryText: string; - queryTemplate: string; - selectedFields: string[]; - showPaging: boolean; - pageSize: number; - numberOfPagesToDisplay: number; - enableResultTypes: boolean; - connectionIds: string[]; - enableModification: boolean; - enableSuggestion: boolean; - entityTypes: EntityType[]; - searchInputComponentId: string; - searchFiltersComponentId: string; - searchVerticalsComponentId: string; - selectedVerticalKeys: string[]; - useBetaEndpoint: boolean; - showCount: boolean; - sortFieldsConfiguration: ISortFieldConfiguration[]; -} \ No newline at end of file diff --git a/packages/spfx/src/webparts/searchResults/components/ISearchResultsProps.ts b/packages/spfx/src/webparts/searchResults/components/ISearchResultsProps.ts deleted file mode 100644 index ea57482..0000000 --- a/packages/spfx/src/webparts/searchResults/components/ISearchResultsProps.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { ITemplateContext } from "../../../models/common/ITemplateContext"; -import { ISearchResultsEventData } from "@pnp/modern-search-core/dist/es6/models/events/ISearchResultsEventData"; -import { ISearchResultsComponentProps } from "./ISearchResultComponentProps"; -import { ILayoutSlot } from "../../../models/common/ILayoutSlot"; -import { IBaseWebComponentWrapperProps } from "../../../models/common/IBaseWebComponentWrapper"; - -export interface ISearchResultsProps extends ISearchResultsComponentProps, IBaseWebComponentWrapperProps { - - /** - * Callback handler when results have been fetched - * @param data the results data - */ - onResultsFetched: (data: ISearchResultsEventData) => void; - - /** - * The curent UI culture name - */ - currentUICultureName: string; - - /** - * The context to pass to web component - */ - templateContext: ITemplateContext; - - /** - * The current available slots from template - */ - templateSlots: ILayoutSlot[]; -} \ No newline at end of file diff --git a/packages/spfx/src/webparts/searchResults/components/ISearchResultsState.ts b/packages/spfx/src/webparts/searchResults/components/ISearchResultsState.ts deleted file mode 100644 index f991ef7..0000000 --- a/packages/spfx/src/webparts/searchResults/components/ISearchResultsState.ts +++ /dev/null @@ -1,2 +0,0 @@ -export interface ISearchResultsState { -} \ No newline at end of file diff --git a/packages/spfx/src/webparts/searchResults/components/SearchResults.tsx b/packages/spfx/src/webparts/searchResults/components/SearchResults.tsx deleted file mode 100644 index d3364a3..0000000 --- a/packages/spfx/src/webparts/searchResults/components/SearchResults.tsx +++ /dev/null @@ -1,123 +0,0 @@ -import * as React from 'react'; -import { ISearchResultsProps } from './ISearchResultsProps'; -import { SearchResultsComponent } from '@pnp/modern-search-core'; -import { isEqual } from '@microsoft/sp-lodash-subset'; -import { ObjectHelper } from '@pnp/modern-search-core/dist/es6/helpers/ObjectHelper'; -import { ISearchResultsState } from './ISearchResultsState'; -import { ISearchResultsEventData } from '@pnp/modern-search-core/dist/es6/models/events/ISearchResultsEventData'; -import { wrapWc } from 'wc-react'; -import parse from 'html-react-parser'; -import { SlotType } from '../../../models/common/ILayoutSlot'; -import { EventConstants } from '@pnp/modern-search-core/dist/es6/common/Constants'; - -const SearchResultsWebComponent = wrapWc('pnp-search-results'); - -export default class SearchResults extends React.Component { - - private componentRef = React.createRef(); - - constructor(props: ISearchResultsProps) { - - super(props); - - this.handleResultsFetched = this.handleResultsFetched.bind(this); - } - - public render(): React.ReactElement { - - // eslint-disable-next-line @typescript-eslint/explicit-function-return-type - const TemplateContent = () => { - return (this.props.templateContent ? parse(this.props.templateContent) : null) as JSX.Element; - }; - - return - - ; - } - - public componentDidMount(): void { - this.initTemplateContext(); - - this.componentRef.current.addEventListener(EventConstants.SEARCH_RESULTS_EVENT, this.handleResultsFetched); - } - - public async componentDidUpdate(prevProps: Readonly): Promise { - - if (!isEqual(prevProps.templateContext, this.props.templateContext) || - !isEqual(prevProps.templateContent, this.props.templateContent)) { - this.initTemplateContext(); - } - } - - public componentWillUnmount(): void { - this.componentRef.current.removeEventListener(EventConstants.SEARCH_RESULTS_EVENT,this.handleResultsFetched); - } - - private initTemplateContext(): void { - - this.componentRef.current.templateContext = { - - /** - * Merges the context from web component and web part so it can be used as an unique context object - * @param item the current item data - * @returns the merge context - */ - mergeContext: (item: {[key:string]: string}) => { - return { - ...item, - context: this.props.templateContext - }; - }, - context: this.props.templateContext, - slot: (slotName: string, item?: {[key:string]: string}) => { - - const slot = this.props.templateSlots.filter(slots => slots.slotName === slotName)[0]; - if (slot) { - - switch(slot.slotType) { - case SlotType.DynamicField: { - const value = ObjectHelper.byPath(item, slot.slotValue); - return value; - } - - case SlotType.RawValue: - return slot.slotValue; - } - - } - - } - }; - } - - private handleResultsFetched(data: CustomEvent): void { - this.props.onResultsFetched(data.detail); - } -} diff --git a/packages/spfx/src/webparts/searchResults/loc/en-us.js b/packages/spfx/src/webparts/searchResults/loc/en-us.js deleted file mode 100644 index 503b5af..0000000 --- a/packages/spfx/src/webparts/searchResults/loc/en-us.js +++ /dev/null @@ -1,23 +0,0 @@ -// eslint-disable-next-line no-undef -define([], function() { - return { - General: { - PlaceHolder: { - EditLabel: "Edit", - IconText: "Search Results Web Part by PnP", - Description: "Displays search results from Microsoft Search", - ConfigureBtnLabel: "Get started" - }, - WebPartDefaultTitle: "Search Results Web Part", - }, - PropertyPane: { - LayoutPage: { - LayoutTemplateOptionsGroupName: "Templates options", - CommonLayoutOptionsGroupName: "General options", - UseSearchVerticalsField: "Use verticals", - SearchVerticalsConnectToComponentField: "Connect to this component", - SearchVerticalsConnectionField: "Show results when these verticals are selected" - } - } - } -}); \ No newline at end of file diff --git a/packages/spfx/src/webparts/searchResults/loc/mystrings.d.ts b/packages/spfx/src/webparts/searchResults/loc/mystrings.d.ts deleted file mode 100644 index f087ce1..0000000 --- a/packages/spfx/src/webparts/searchResults/loc/mystrings.d.ts +++ /dev/null @@ -1,25 +0,0 @@ -declare interface ISearchResultsWebPartStrings { - General: { - PlaceHolder: { - EditLabel: string; - IconText: string; - Description: string; - ConfigureBtnLabel: string; - }, - WebPartDefaultTitle: string; - }, - PropertyPane: { - LayoutPage: { - LayoutTemplateOptionsGroupName: string; - CommonLayoutOptionsGroupName: string; - UseSearchVerticalsField: string; - SearchVerticalsConnectToComponentField: string; - SearchVerticalsConnectionField: string; - } - } -} - -declare module 'SearchResultsWebPartStrings' { - const strings: ISearchResultsWebPartStrings; - export = strings; -} diff --git a/packages/spfx/src/webparts/searchVerticals/ISearchVerticalsWebPartProps.ts b/packages/spfx/src/webparts/searchVerticals/ISearchVerticalsWebPartProps.ts deleted file mode 100644 index 355a2be..0000000 --- a/packages/spfx/src/webparts/searchVerticals/ISearchVerticalsWebPartProps.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { IDataVerticalConfiguration } from "@pnp/modern-search-core/dist/es6/models/common/IDataVerticalConfiguration"; -import { IBaseWebPartProps } from "../../models/common/IBaseWebPartProps"; - -export interface ISearchVerticalsWebPartProps extends IBaseWebPartProps { - verticalConfiguration: IDataVerticalConfiguration[]; -} \ No newline at end of file diff --git a/packages/spfx/src/webparts/searchVerticals/SearchVerticalsWebPart.manifest.json b/packages/spfx/src/webparts/searchVerticals/SearchVerticalsWebPart.manifest.json deleted file mode 100644 index 61f6d43..0000000 --- a/packages/spfx/src/webparts/searchVerticals/SearchVerticalsWebPart.manifest.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "$schema": "https://developer.microsoft.com/json-schemas/spfx/client-side-web-part-manifest.schema.json", - "id": "aac5f315-4ce8-4386-88fa-897566e2a710", - "alias": "PnPModernSearchCoreVerticalsWebPart", - "componentType": "WebPart", - "version": "1.0.0", - "manifestVersion": 2, - "requiresCustomScript": false, - "supportedHosts": [ - "SharePointWebPart", - "TeamsPersonalApp", - "TeamsTab", - "SharePointFullPage" - ], - "supportsThemeVariants": true, - "preconfiguredEntries": [ - { - "groupId": "5c03119e-3074-46fd-976b-c60198311f70", - "group": { - "default": "Advanced" - }, - "title": { - "default": "PnP Modern Search Core Components - Search Verticals", - "fr-fr": "PnP Modern Search Core Components - Verticaux de recherche" - }, - "description": { - "default": "Allows to browse data as verticals (i.e silos)", - "fr-fr": "Permet de parcourir les données de manière verticale (en silos)" - }, - "iconImageUrl": "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0nNDAnIGhlaWdodD0nMjgnIHZpZXdCb3g9JzAgMCA0MCAyOCcgZmlsbD0nbm9uZScgeG1sbnM9J2h0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnJz48cGF0aCBkPSdNNS43MDAyIDI0QzUuNzAwMiAxOC40IDUuNzAwMiAxMi45IDUuNzAwMiA3LjNDNS43MDAyIDYuOCA1LjgwMDIgNi4zIDUuOTAwMiA1LjhDNS45MDAyIDUuNyA2LjAwMDIgNS42IDYuMDAwMiA1LjZDNi42MDAyIDQuMyA3LjYwMDIgMy42IDguOTAwMiAzLjNDOS4wMDAyIDMuMyA5LjAwMDIgMy4yIDkuMTAwMiAzLjFDOS4yMDAyIDIuOCA5LjMwMDIgMi40IDkuNTAwMiAyQzkuOTAwMiAxLjIgMTAuNTAwMiAwLjcgMTEuNDAwMiAwLjNDMTEuOTAwMiAwLjEgMTIuNTAwMiAwIDEzLjEwMDIgMEMxOC40MDAyIDAgMjMuNzAwMiAwIDI5LjAwMDIgMEMyOS41MDAyIDAgMzAuMDAwMiAwIDMwLjQwMDIgMC4xQzMxLjYwMDIgMC4zIDMyLjQwMDIgMC45IDMzLjEwMDIgMS44QzMzLjYwMDIgMi41IDMzLjgwMDIgMy4zIDMzLjgwMDIgNC4yQzMzLjgwMDIgOS42IDMzLjgwMDIgMTUuMSAzMy44MDAyIDIwLjVDMzMuODAwMiAyMC45IDMzLjgwMDIgMjEuMyAzMy43MDAyIDIxLjZDMzMuNDAwMiAyMy4yIDMyLjIwMDIgMjQuMyAzMC43MDAyIDI0LjdDMzAuNTAwMiAyNC44IDMwLjQwMDIgMjQuOCAzMC40MDAyIDI1QzMwLjAwMDIgMjYuNyAyOC41MDAyIDI3LjkgMjYuODAwMiAyOEMyNi43MDAyIDI4IDI2LjcwMDIgMjggMjYuNjAwMiAyOEMyMS4wMDAyIDI4IDE1LjUwMDIgMjggOS45MDAyIDI4QzkuNzAwMiAyOCA5LjYwMDIgMjggOS40MDAyIDI4QzkuMjAwMiAyOCA4LjkwMDIgMjggOC43MDAyIDI3LjlDNy41MDAyIDI3LjUgNi42MDAyIDI2LjggNi4xMDAyIDI1LjZDNS44MDAyIDI1LjEgNS43MDAyIDI0LjUgNS43MDAyIDI0Wk0xOC4wMDAyIDI2LjZDMjAuODAwMiAyNi42IDIzLjcwMDIgMjYuNiAyNi41MDAyIDI2LjZDMjYuNjAwMiAyNi42IDI2LjcwMDIgMjYuNiAyNi44MDAyIDI2LjZDMjguMTAwMiAyNi4zIDI5LjAwMDIgMjUuNCAyOS4wMDAyIDI0LjFDMjkuMDAwMiAxOC41IDI5LjAwMDIgMTIuOCAyOS4wMDAyIDcuMkMyOS4wMDAyIDYuOCAyOC45MDAyIDYuNSAyOC43MDAyIDYuMUMyOC4yMDAyIDUuMSAyNy40MDAyIDQuNiAyNi4zMDAyIDQuNkMyMC43MDAyIDQuNiAxNS4yMDAyIDQuNiA5LjYwMDIgNC42QzkuNDAwMiA0LjYgOS4yMDAyIDQuNiA5LjAwMDIgNC43QzcuODAwMiA1IDcuMDAwMiA2IDcuMTAwMiA3LjJDNy4xMDAyIDEyLjggNy4xMDAyIDE4LjQgNy4xMDAyIDI0QzcuMTAwMiAyNC4zIDcuMjAwMiAyNC42IDcuMzAwMiAyNC45QzcuNjAwMiAyNS44IDguNjAwMiAyNi42IDkuNjAwMiAyNi42QzEyLjQwMDIgMjYuNiAxNS4yMDAyIDI2LjYgMTguMDAwMiAyNi42WicgZmlsbD0nIzAwNzhkNCcvPjxwYXRoIGQ9J00xNy40MDAxIDEwLjRDMTcuNDAwMSAxMCAxNy42MDAxIDkuNyAxOC4wMDAxIDkuN0MxOC40MDAxIDkuNiAxOC43MDAxIDkuOSAxOC44MDAxIDEwLjNDMTguODAwMSAxMC40IDE4LjgwMDEgMTAuNSAxOC44MDAxIDEwLjZDMTguODAwMSAxMS45IDE4LjgwMDEgMTMuMyAxOC44MDAxIDE0LjZDMTguODAwMSAxNC43IDE4LjgwMDEgMTQuOCAxOC44MDAxIDE0LjlDMTguOTAwMSAxNC45IDE5LjAwMDEgMTQuOSAxOS4xMDAxIDE0LjlDMjAuNTAwMSAxNC45IDIxLjkwMDEgMTQuOSAyMy4yMDAxIDE0LjlDMjMuNjAwMSAxNC45IDIzLjkwMDEgMTUuMSAyNC4wMDAxIDE1LjVDMjQuMTAwMSAxNS45IDIzLjcwMDEgMTYuMyAyMy4zMDAxIDE2LjNDMjEuOTAwMSAxNi4zIDIwLjUwMDEgMTYuMyAxOS4xMDAxIDE2LjNDMTkuMDAwMSAxNi4zIDE4LjkwMDEgMTYuMyAxOC44MDAxIDE2LjNDMTguODAwMSAxNi40IDE4LjgwMDEgMTYuNSAxOC44MDAxIDE2LjZDMTguODAwMSAxOCAxOC44MDAxIDE5LjMgMTguODAwMSAyMC43QzE4LjgwMDEgMjEgMTguNzAwMSAyMS4zIDE4LjQwMDEgMjEuNUMxNy45MDAxIDIxLjggMTcuNDAwMSAyMS4zIDE3LjQwMDEgMjAuOUMxNy40MDAxIDE5LjUgMTcuNDAwMSAxOC4xIDE3LjQwMDEgMTYuN0MxNy40MDAxIDE2LjYgMTcuNDAwMSAxNi41IDE3LjQwMDEgMTYuNEMxNy4zMDAxIDE2LjQgMTcuMjAwMSAxNi40IDE3LjEwMDEgMTYuNEMxNS43MDAxIDE2LjQgMTQuMzAwMSAxNi40IDEyLjgwMDEgMTYuNEMxMi40MDAxIDE2LjQgMTIuMTAwMSAxNi4xIDEyLjEwMDEgMTUuOEMxMi4xMDAxIDE1LjQgMTIuNDAwMSAxNS4xIDEyLjgwMDEgMTUuMUMxMy44MDAxIDE1LjEgMTQuODAwMSAxNS4xIDE1LjgwMDEgMTUuMUMxNi4zMDAxIDE1LjEgMTYuODAwMSAxNS4xIDE3LjMwMDEgMTUuMUMxNy40MDAxIDEzLjQgMTcuNDAwMSAxMS45IDE3LjQwMDEgMTAuNFonIGZpbGw9JyMwMDc4ZDQnLz48L3N2Zz4=", - "properties": { - "issueLink": "https://github.com/microsoft-search/pnp-modern-search-core-components/issues/new", - "documentationLink": "https://microsoft-search.github.io/pnp-modern-search-core-components/docs/sharepoint-webparts/available-webparts/search-verticals" - } - } - ] -} \ No newline at end of file diff --git a/packages/spfx/src/webparts/searchVerticals/SearchVerticalsWebPart.manifest.template.json b/packages/spfx/src/webparts/searchVerticals/SearchVerticalsWebPart.manifest.template.json deleted file mode 100644 index 13bcbd4..0000000 --- a/packages/spfx/src/webparts/searchVerticals/SearchVerticalsWebPart.manifest.template.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "$schema": "https://developer.microsoft.com/json-schemas/spfx/client-side-web-part-manifest.schema.json", - "id": "aac5f315-4ce8-4386-88fa-897566e2a710", - "alias": "PnPModernSearchCoreVerticalsWebPart", - "componentType": "WebPart", - "version": "1.0.0", - "manifestVersion": 2, - "requiresCustomScript": false, - "supportedHosts": [ - "SharePointWebPart", - "TeamsPersonalApp", - "TeamsTab", - "SharePointFullPage" - ], - "supportsThemeVariants": true, - "preconfiguredEntries": [ - { - "groupId": "5c03119e-3074-46fd-976b-c60198311f70", - "group": { - "default": "Advanced" - }, - "title": { - "default": "PnP Modern Search Core Components - Search Verticals", - "fr-fr": "PnP Modern Search Core Components - Verticaux de recherche" - }, - "description": { - "default": "Allows to browse data as verticals (i.e silos)", - "fr-fr": "Permet de parcourir les données de manière verticale (en silos)" - }, - "iconImageUrl": "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0nNDAnIGhlaWdodD0nMjgnIHZpZXdCb3g9JzAgMCA0MCAyOCcgZmlsbD0nbm9uZScgeG1sbnM9J2h0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnJz48cGF0aCBkPSdNNS43MDAyIDI0QzUuNzAwMiAxOC40IDUuNzAwMiAxMi45IDUuNzAwMiA3LjNDNS43MDAyIDYuOCA1LjgwMDIgNi4zIDUuOTAwMiA1LjhDNS45MDAyIDUuNyA2LjAwMDIgNS42IDYuMDAwMiA1LjZDNi42MDAyIDQuMyA3LjYwMDIgMy42IDguOTAwMiAzLjNDOS4wMDAyIDMuMyA5LjAwMDIgMy4yIDkuMTAwMiAzLjFDOS4yMDAyIDIuOCA5LjMwMDIgMi40IDkuNTAwMiAyQzkuOTAwMiAxLjIgMTAuNTAwMiAwLjcgMTEuNDAwMiAwLjNDMTEuOTAwMiAwLjEgMTIuNTAwMiAwIDEzLjEwMDIgMEMxOC40MDAyIDAgMjMuNzAwMiAwIDI5LjAwMDIgMEMyOS41MDAyIDAgMzAuMDAwMiAwIDMwLjQwMDIgMC4xQzMxLjYwMDIgMC4zIDMyLjQwMDIgMC45IDMzLjEwMDIgMS44QzMzLjYwMDIgMi41IDMzLjgwMDIgMy4zIDMzLjgwMDIgNC4yQzMzLjgwMDIgOS42IDMzLjgwMDIgMTUuMSAzMy44MDAyIDIwLjVDMzMuODAwMiAyMC45IDMzLjgwMDIgMjEuMyAzMy43MDAyIDIxLjZDMzMuNDAwMiAyMy4yIDMyLjIwMDIgMjQuMyAzMC43MDAyIDI0LjdDMzAuNTAwMiAyNC44IDMwLjQwMDIgMjQuOCAzMC40MDAyIDI1QzMwLjAwMDIgMjYuNyAyOC41MDAyIDI3LjkgMjYuODAwMiAyOEMyNi43MDAyIDI4IDI2LjcwMDIgMjggMjYuNjAwMiAyOEMyMS4wMDAyIDI4IDE1LjUwMDIgMjggOS45MDAyIDI4QzkuNzAwMiAyOCA5LjYwMDIgMjggOS40MDAyIDI4QzkuMjAwMiAyOCA4LjkwMDIgMjggOC43MDAyIDI3LjlDNy41MDAyIDI3LjUgNi42MDAyIDI2LjggNi4xMDAyIDI1LjZDNS44MDAyIDI1LjEgNS43MDAyIDI0LjUgNS43MDAyIDI0Wk0xOC4wMDAyIDI2LjZDMjAuODAwMiAyNi42IDIzLjcwMDIgMjYuNiAyNi41MDAyIDI2LjZDMjYuNjAwMiAyNi42IDI2LjcwMDIgMjYuNiAyNi44MDAyIDI2LjZDMjguMTAwMiAyNi4zIDI5LjAwMDIgMjUuNCAyOS4wMDAyIDI0LjFDMjkuMDAwMiAxOC41IDI5LjAwMDIgMTIuOCAyOS4wMDAyIDcuMkMyOS4wMDAyIDYuOCAyOC45MDAyIDYuNSAyOC43MDAyIDYuMUMyOC4yMDAyIDUuMSAyNy40MDAyIDQuNiAyNi4zMDAyIDQuNkMyMC43MDAyIDQuNiAxNS4yMDAyIDQuNiA5LjYwMDIgNC42QzkuNDAwMiA0LjYgOS4yMDAyIDQuNiA5LjAwMDIgNC43QzcuODAwMiA1IDcuMDAwMiA2IDcuMTAwMiA3LjJDNy4xMDAyIDEyLjggNy4xMDAyIDE4LjQgNy4xMDAyIDI0QzcuMTAwMiAyNC4zIDcuMjAwMiAyNC42IDcuMzAwMiAyNC45QzcuNjAwMiAyNS44IDguNjAwMiAyNi42IDkuNjAwMiAyNi42QzEyLjQwMDIgMjYuNiAxNS4yMDAyIDI2LjYgMTguMDAwMiAyNi42WicgZmlsbD0nIzAwNzhkNCcvPjxwYXRoIGQ9J00xNy40MDAxIDEwLjRDMTcuNDAwMSAxMCAxNy42MDAxIDkuNyAxOC4wMDAxIDkuN0MxOC40MDAxIDkuNiAxOC43MDAxIDkuOSAxOC44MDAxIDEwLjNDMTguODAwMSAxMC40IDE4LjgwMDEgMTAuNSAxOC44MDAxIDEwLjZDMTguODAwMSAxMS45IDE4LjgwMDEgMTMuMyAxOC44MDAxIDE0LjZDMTguODAwMSAxNC43IDE4LjgwMDEgMTQuOCAxOC44MDAxIDE0LjlDMTguOTAwMSAxNC45IDE5LjAwMDEgMTQuOSAxOS4xMDAxIDE0LjlDMjAuNTAwMSAxNC45IDIxLjkwMDEgMTQuOSAyMy4yMDAxIDE0LjlDMjMuNjAwMSAxNC45IDIzLjkwMDEgMTUuMSAyNC4wMDAxIDE1LjVDMjQuMTAwMSAxNS45IDIzLjcwMDEgMTYuMyAyMy4zMDAxIDE2LjNDMjEuOTAwMSAxNi4zIDIwLjUwMDEgMTYuMyAxOS4xMDAxIDE2LjNDMTkuMDAwMSAxNi4zIDE4LjkwMDEgMTYuMyAxOC44MDAxIDE2LjNDMTguODAwMSAxNi40IDE4LjgwMDEgMTYuNSAxOC44MDAxIDE2LjZDMTguODAwMSAxOCAxOC44MDAxIDE5LjMgMTguODAwMSAyMC43QzE4LjgwMDEgMjEgMTguNzAwMSAyMS4zIDE4LjQwMDEgMjEuNUMxNy45MDAxIDIxLjggMTcuNDAwMSAyMS4zIDE3LjQwMDEgMjAuOUMxNy40MDAxIDE5LjUgMTcuNDAwMSAxOC4xIDE3LjQwMDEgMTYuN0MxNy40MDAxIDE2LjYgMTcuNDAwMSAxNi41IDE3LjQwMDEgMTYuNEMxNy4zMDAxIDE2LjQgMTcuMjAwMSAxNi40IDE3LjEwMDEgMTYuNEMxNS43MDAxIDE2LjQgMTQuMzAwMSAxNi40IDEyLjgwMDEgMTYuNEMxMi40MDAxIDE2LjQgMTIuMTAwMSAxNi4xIDEyLjEwMDEgMTUuOEMxMi4xMDAxIDE1LjQgMTIuNDAwMSAxNS4xIDEyLjgwMDEgMTUuMUMxMy44MDAxIDE1LjEgMTQuODAwMSAxNS4xIDE1LjgwMDEgMTUuMUMxNi4zMDAxIDE1LjEgMTYuODAwMSAxNS4xIDE3LjMwMDEgMTUuMUMxNy40MDAxIDEzLjQgMTcuNDAwMSAxMS45IDE3LjQwMDEgMTAuNFonIGZpbGw9JyMwMDc4ZDQnLz48L3N2Zz4=", - "properties": { - "issueLink": "https://github.com/microsoft-search/pnp-modern-search-core-components/issues/new", - "documentationLink": "{{DOCUMENTATION_HOST_URL}}/docs/sharepoint-webparts/available-webparts/search-verticals" - } - } - ] -} \ No newline at end of file diff --git a/packages/spfx/src/webparts/searchVerticals/SearchVerticalsWebPart.tsx b/packages/spfx/src/webparts/searchVerticals/SearchVerticalsWebPart.tsx deleted file mode 100644 index 7cd8c9d..0000000 --- a/packages/spfx/src/webparts/searchVerticals/SearchVerticalsWebPart.tsx +++ /dev/null @@ -1,335 +0,0 @@ -//#region Imports -import * as React from 'react'; -import * as ReactDom from 'react-dom'; -import { - IPropertyPaneConfiguration} from '@microsoft/sp-property-pane'; -import * as webPartStrings from 'SearchVerticalsWebPartStrings'; -import SearchVerticals from './components/SearchVerticals'; -import { ISearchVerticalsProps } from './components/ISearchVerticalsProps'; -import { ISearchVerticalsWebPartProps } from './ISearchVerticalsWebPartProps'; -import { IDataVerticalConfiguration } from '@pnp/modern-search-core/dist/es6/models/common/IDataVerticalConfiguration'; -import { PageOpenBehavior } from '@pnp/modern-search-core/dist/es6/helpers/UrlHelper'; -import { ConfigurationFieldType, IConfigurationTabField } from '../../controls/ConfigurationPanel/IConfigurationTabField'; -import { isEmpty, isEqual } from '@microsoft/sp-lodash-subset'; -import { IChoiceGroupProps, ITextFieldProps, IToggleProps } from 'office-ui-fabric-react'; -import { ConfigurationPanel } from '../../controls/ConfigurationPanel/ConfigurationPanel'; -import { ItemRepeater } from '../../controls/ItemRepeater/ItemRepeater'; -import { IConfigurationTab } from '../../controls/ConfigurationPanel/IConfigurationTab'; -import { ILocalizedFieldProps } from '../../controls/LocalizedTextField/ILocalizedFieldProps'; -import { BaseWebPart } from '../../common/BaseWebPart'; -import { IDynamicDataCallables, IDynamicDataPropertyDefinition } from '@microsoft/sp-dynamic-data'; -import { ComponentType } from '../../common/ComponentType'; -import { ISearchVerticalSourceData } from '../../models/dynamicData/ISearchVerticalSourceData'; -import { DisplayMode } from '@microsoft/sp-core-library'; -import { IPlaceholderProps } from '@pnp/spfx-controls-react'; -import WebPartPlaceholder from '../../controls/WebPartPlaceholder/WebPartPlaceholder'; -import { LocalizedStringHelper } from '@pnp/modern-search-core/dist/es6/helpers/LocalizedStringHelper'; -import { PropertyPaneFormDataCollection } from '../../propertyPane/PropertyPaneFormDataCollection/PropertyPaneFormDataCollection'; -import { ILayoutDefinition, LayoutType } from '../../models/common/ILayoutDefinition'; -import { AvailableLayouts, BuiltinLayoutsKeys } from '../../layouts/AvailableLayouts'; -//#endregion - -const getErrorMessage = (value: string): string => { - return !isEmpty(value) ? '' : `Field must have a value`; -}; - -export default class SearchVerticalsWebPart extends BaseWebPart implements IDynamicDataCallables { - - /** - * The available layout definitions (not instanciated) - */ - protected availableLayoutDefinitions: ILayoutDefinition[] = AvailableLayouts.BuiltinLayouts.filter(layout => { return layout.type === LayoutType.Verticals; }); - - //#region Class attributes - - private _itemRepeaterRef = React.createRef>(); - private _lastCreatedConfigurationPanelRef: React.RefObject> = null; - private _lastRowId: string; - - private currentSelectedVerticalKey: string; - - //#endregion - - //#region Class methods - - //#region Dynamic data methods - - public getPropertyDefinitions(): IDynamicDataPropertyDefinition[] { - - const propertyDefinitions: IDynamicDataPropertyDefinition[] = []; - - propertyDefinitions.push( - { - id: ComponentType.SearchVerticals, - title: this.properties.title ? `${this.properties.title} - ${this.instanceId}` : `${webPartStrings.General.WebPartDefaultTitle} - ${this.instanceId}`, - } - ); - - return propertyDefinitions; - } - - public getPropertyValue(propertyId: string): ISearchVerticalSourceData { - - switch (propertyId) { - case ComponentType.SearchVerticals: - return { - verticalsConfiguration: this.properties.verticalConfiguration, - selectedVerticalKey: this.currentSelectedVerticalKey - } as ISearchVerticalSourceData; - } - - throw new Error('Bad property id'); - } - - //#endregion - - //#region WebPart lifecycle methods - - protected get isRenderAsync(): boolean { - return true; - } - - /** - * Initializes required Web Part properties - */ - private initializeProperties(): void { - this.properties.verticalConfiguration = this.properties.verticalConfiguration ? this.properties.verticalConfiguration : []; - this.properties.selectedLayoutKey = this.properties.selectedLayoutKey ? this.properties.selectedLayoutKey : BuiltinLayoutsKeys.VerticalsDefault; - } - - protected async onInit(): Promise { - - await super.onInit(); - - this.initializeProperties(); - - this.context.dynamicDataSourceManager.initializeSource(this); - } - - public async render(): Promise { - - await super.initTemplate(); - - return this.renderCompleted(); - } - - public renderCompleted(): void { - - let renderRootElement: JSX.Element; - - if (this.properties.verticalConfiguration.length > 0) { - - const element: React.ReactElement = React.createElement( - SearchVerticals, - { - verticalConfiguration: this.properties.verticalConfiguration, - id: this.getComponentId(ComponentType.SearchVerticals), - theme: this._themeVariant.isInverted ? "dark" : "", - templateContent: this.templateContentToDisplay, - enableDebugMode: this.properties.enableDebugMode, - useMicrosoftGraphToolkit: this.properties.useMicrosoftGraphToolkit, - onVerticalSelected: (selectedVerticalKey) => { - this.currentSelectedVerticalKey = selectedVerticalKey; - this.context.dynamicDataSourceManager.notifySourceChanged(); - } - } as ISearchVerticalsProps - ); - - renderRootElement = element; - - } else { - - if (this.displayMode === DisplayMode.Edit) { - - const placeholder: React.ReactElement = React.createElement( - this._placeholderComponent, - { - iconName: "", - iconText: webPartStrings.General.PlaceHolder.IconText, - description: () => React.createElement(WebPartPlaceholder, { - description: webPartStrings.General.PlaceHolder.Description, - documentationLink: this.properties.documentationLink - } , null), - buttonLabel: webPartStrings.General.PlaceHolder.ConfigureBtnLabel, - onConfigure: () => { this.context.propertyPane.open(); } - } - ); - - renderRootElement = placeholder; - } - } - - ReactDom.render(renderRootElement, this.domElement); - } - - protected onDispose(): void { - ReactDom.unmountComponentAtNode(this.domElement); - } - - public override async onPropertyPaneFieldChanged(propertyPath: string, oldValue: unknown, newValue: unknown): Promise { - await super.onPropertyPaneFieldChanged(propertyPath, oldValue, newValue); - } - - //#endregion - - //#region Property Pane methods - - protected getPropertyPaneConfiguration(): IPropertyPaneConfiguration { - - const newVerticalConfiguration: IDataVerticalConfiguration = { - isLink: false, - key: "", - linkUrl: "", - openBehavior: PageOpenBehavior.NewTab, - tabName: "", - tabValue: "" - }; - - const verticalTabsConfiguration: IConfigurationTab[] = [ - { - name: "General", - fields: [ - { - type: ConfigurationFieldType.LocalizedField, - props: { - serviceScope: this.context.serviceScope, - label: webPartStrings.PropertyPane.VerticalConfigurationPane.VerticalName, - onGetErrorMessage: getErrorMessage, - required: true, - } as Partial, - targetProperty: "tabName" - }, - { - type: ConfigurationFieldType.TextField, - props: { - label: webPartStrings.PropertyPane.VerticalConfigurationPane.VerticalKey, - required: true, - onGetErrorMessage: getErrorMessage, - } as Partial, - targetProperty: "key" - }, - { - type: ConfigurationFieldType.TextField, - props: { - label: webPartStrings.PropertyPane.VerticalConfigurationPane.VerticalValue, - } as Partial, - targetProperty: "tabValue", - }, - { - type: ConfigurationFieldType.Toggle, - props: { - label: webPartStrings.PropertyPane.VerticalConfigurationPane.IsLink, - } as Partial, - targetProperty: "isLink" - }, - { - type: ConfigurationFieldType.TextField, - props: { - label: webPartStrings.PropertyPane.VerticalConfigurationPane.LinkUrl, - } as Partial, - targetProperty: "linkUrl", - isVisible: (dataObject: IDataVerticalConfiguration) => { - return dataObject.isLink; - } - }, - { - type: ConfigurationFieldType.ChoiceGroup, - props: { - label: webPartStrings.PropertyPane.VerticalConfigurationPane.OpenBehavior, - options: [ - {key: PageOpenBehavior.NewTab, text: webPartStrings.PropertyPane.VerticalConfigurationPane.NewTabOption}, - {key: PageOpenBehavior.Self, text: webPartStrings.PropertyPane.VerticalConfigurationPane.SelfTabOption,}] - } as Partial, - isVisible: (dataObject: IDataVerticalConfiguration) => { - return dataObject.isLink; - }, - targetProperty: "openBehavior" - } - ] - }, - ]; - - const mainFormFields: IConfigurationTabField[] = [ - { - type: ConfigurationFieldType.Custom, - targetProperty: null, - onCustomRender: (field, defaultValue, onUpdate) => { - - this._lastCreatedConfigurationPanelRef = React.createRef>(); - - return - ref={this._lastCreatedConfigurationPanelRef} - configurationTabs={verticalTabsConfiguration} - renderRowTitle={(vertical: IDataVerticalConfiguration) => { return LocalizedStringHelper.getDefaultValue(vertical.tabName) }} - onFormSave={(formData) => { onUpdate(field, formData)}} - dataObject={defaultValue} - renderPanelTitle={() => webPartStrings.PropertyPane.VerticalConfigurationPane.Title} - onFormDismissed={(configuration: IDataVerticalConfiguration) => { - if (isEqual(configuration, newVerticalConfiguration)) { - // Remove row as no item has been saved - this._itemRepeaterRef.current.deleteItemRow(this._lastRowId) - } - }} - />; - } - } - ]; - - return { - pages: [ - { - groups: [ - { - groupName: webPartStrings.PropertyPane.SettingsPage.VerticalSettingsGroupName, - groupFields: [ - new PropertyPaneFormDataCollection('verticalConfiguration', { - label: webPartStrings.PropertyPane.VerticalConfigurationPane.VerticalsLabel, - itemRepeaterProps: { - innerRef: this._itemRepeaterRef, - addButtonLabel: webPartStrings.PropertyPane.VerticalConfigurationPane.Title, - enableDragDrop: true - }, - items: this.properties.verticalConfiguration, - newRowDefaultObject: () => newVerticalConfiguration, - formConfiguration: mainFormFields, - onRowAdded: (rowId: string) => { - // Save the row id to be able to delete it afterwards - this._lastRowId = rowId; - // Get the last created row (empty at this point) and open the panel - this._lastCreatedConfigurationPanelRef.current.togglePanel(); - }, - onRowsOrderChanged: (value: IDataVerticalConfiguration[]) => { - this.properties.verticalConfiguration = value; - this.renderCompleted() - } - }) - ] - } - ] - }, - // Templating page - { - displayGroupsAsAccordion: true, - groups: [this.getTemplateOptionsGroup()] - - }, - // Common page - { - displayGroupsAsAccordion: true, - groups: [this.getThemePageGroup()] - }, - // 'About' infos - { - displayGroupsAsAccordion: true, - groups: [ - ...this.getPropertyPaneWebPartInfoGroups(), - ] - } - ] - }; - } - - //#endregion - - //#endregion -} diff --git a/packages/spfx/src/webparts/searchVerticals/components/ISearchVerticalsProps.ts b/packages/spfx/src/webparts/searchVerticals/components/ISearchVerticalsProps.ts deleted file mode 100644 index 50ce098..0000000 --- a/packages/spfx/src/webparts/searchVerticals/components/ISearchVerticalsProps.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { IDataVerticalConfiguration } from "@pnp/modern-search-core/dist/es6/models/common/IDataVerticalConfiguration"; -import { IBaseWebComponentWrapperProps } from "../../../models/common/IBaseWebComponentWrapper"; - -export interface ISearchVerticalsProps extends IBaseWebComponentWrapperProps { - - /** - * The verticals configuration - */ - verticalConfiguration: IDataVerticalConfiguration[]; - - /** - * Handler when a vertica ltab is selected - * @param selectedKey the current selected vertical key - */ - onVerticalSelected?: (selectedKey: string) => void; -} diff --git a/packages/spfx/src/webparts/searchVerticals/components/SearchVerticals.tsx b/packages/spfx/src/webparts/searchVerticals/components/SearchVerticals.tsx deleted file mode 100644 index 49af44e..0000000 --- a/packages/spfx/src/webparts/searchVerticals/components/SearchVerticals.tsx +++ /dev/null @@ -1,71 +0,0 @@ -import * as React from 'react'; -import { ISearchVerticalsProps } from './ISearchVerticalsProps'; -import { wrapWc } from 'wc-react'; -import { SearchVerticalsComponent } from '@pnp/modern-search-core'; -import { ComponentElements, EventConstants } from "@pnp/modern-search-core/dist/es6/common/Constants"; -import { ISearchVerticalEventData } from "@pnp/modern-search-core/dist/es6/models/events/ISearchVerticalEventData"; -import parse, { } from 'html-react-parser'; -import { isEqual } from '@microsoft/sp-lodash-subset'; -import { Guid } from '@microsoft/sp-core-library'; - -const SearchVerticalsWebComponent = wrapWc('pnp-search-verticals'); - -export default class SearchVerticals extends React.Component { - - private componentRef = React.createRef(); - - constructor(props: ISearchVerticalsProps) { - super(props); - - this.onVerticalKeySelected = this.onVerticalKeySelected.bind(this); - } - - public render(): React.ReactElement { - - // eslint-disable-next-line @typescript-eslint/explicit-function-return-type - const TemplateContent = () => { - return (this.props.templateContent ? parse(this.props.templateContent) : null) as JSX.Element; - }; - - return - - ; - } - - public componentDidUpdate(prevProps: Readonly): void { - - if (!isEqual(prevProps.templateContent, this.props.templateContent)) { - - // Forces a tempalte re-render by faking an update to the template context - // TODO: Find a better way to do that at component level - // https://github.com/microsoftgraph/microsoft-graph-toolkit/blob/d27ffa723d36fa39533a4e705965ba656a71b82a/packages/mgt-element/src/components/templatedComponent.ts#L141C35-L141C46 - this.componentRef.current.templateContext = {...this.componentRef.current.templateContext, random: Guid.newGuid() } - this.componentRef.current.shadowRoot.querySelectorAll(ComponentElements.CheckboxFilterComponent).forEach((e: SearchVerticalsComponent) => { - e.templateContext = {...e.templateContext, random: Guid.newGuid()}; - }); - } - } - - public componentDidMount(): void { - this.componentRef.current.addEventListener(EventConstants.SEARCH_VERTICAL_EVENT, this.onVerticalKeySelected); - } - - public componentWillUnmount(): void { - this.componentRef.current.removeEventListener(EventConstants.SEARCH_VERTICAL_EVENT, this.onVerticalKeySelected) - } - - private onVerticalKeySelected(ev: CustomEvent): void { - - if (this.props.onVerticalSelected) { - this.props.onVerticalSelected(ev.detail.selectedVertical.key); - } - } -} diff --git a/packages/spfx/src/webparts/searchVerticals/loc/en-us.js b/packages/spfx/src/webparts/searchVerticals/loc/en-us.js deleted file mode 100644 index f9b314b..0000000 --- a/packages/spfx/src/webparts/searchVerticals/loc/en-us.js +++ /dev/null @@ -1,31 +0,0 @@ -// eslint-disable-next-line no-undef -define([], function() { - return { - General: { - PlaceHolder: { - EditLabel: "Edit", - IconText: "Search Verticals Web Part by PnP", - Description: "Control results visbility by search verticals", - ConfigureBtnLabel: "Get started" - }, - WebPartDefaultTitle: "Search Verticals Web Part", - }, - PropertyPane: { - SettingsPage: { - VerticalSettingsGroupName: "Settings" - }, - VerticalConfigurationPane: { - VerticalsLabel: "Verticals", - Title: "Add new vertical", - VerticalName: "Vertical name", - VerticalKey: "Vertical key", - VerticalValue: "Vertical value", - IsLink: "Is link", - LinkUrl: "Link URL", - OpenBehavior: "Open behavior", - NewTabOption: "New tab", - SelfTabOption: "Self tab" - } - } - } -}); \ No newline at end of file diff --git a/packages/spfx/src/webparts/searchVerticals/loc/mystrings.d.ts b/packages/spfx/src/webparts/searchVerticals/loc/mystrings.d.ts deleted file mode 100644 index f053843..0000000 --- a/packages/spfx/src/webparts/searchVerticals/loc/mystrings.d.ts +++ /dev/null @@ -1,33 +0,0 @@ -declare interface ISearchVerticalsWebPartStrings { - General: { - PlaceHolder: { - EditLabel: string; - IconText: string; - Description: string; - ConfigureBtnLabel: string; - }, - WebPartDefaultTitle: string; - }, - PropertyPane: { - SettingsPage: { - VerticalSettingsGroupName: string; - }, - VerticalConfigurationPane: { - VerticalsLabel: string; - Title: string; - VerticalName: string; - VerticalKey: string; - VerticalValue: string; - IsLink: string; - LinkUrl: string; - OpenBehavior: string; - NewTabOption: string; - SelfTabOption: string; - } - } -} - -declare module 'SearchVerticalsWebPartStrings' { - const strings: ISearchVerticalsWebPartStrings; - export = strings; -} diff --git a/packages/spfx/tailwind.config.js b/packages/spfx/tailwind.config.js deleted file mode 100644 index c79d6df..0000000 --- a/packages/spfx/tailwind.config.js +++ /dev/null @@ -1,95 +0,0 @@ - -const defaultTheme = require('tailwindcss/defaultTheme'); - -module.exports = { - mode: 'jit', - content: { - files: [ - './src/**/*.{html,ts,tsx}', - ] - }, - corePlugins: { - preflight: false, // Will conflict with base SPFx styles otherwise (ex: buttons background-color) - }, - darkMode: 'class', - theme: { - extend: { - fontFamily: { - primary: ["var(--pnpsearch-internal-fontFamilyPrimary)","'Segoe UI'", "'Arial, sans-serif'"], - sans: ["var(--pnpsearch-internal-fontFamilySecondary)", "Roboto", ...defaultTheme.fontFamily.sans] - }, - // Map the colors from EGG UI design system - colors: { - - /* Default theme variables */ - - primary: "var(--pnpsearch-internal-colorPrimary, #7C4DFF)", - primaryHover: "var(--pnpsearch-internal-colorPrimaryHover, #651fff)", - primaryBackgroundColor: "var(--pnpsearch-internal-colorBackgroundPrimary, #F3F5F6)", - textColor: "var(--pnpsearch-internal-textColor, #1E252B)", - - /* Dark theme variables */ - primaryBackgroundColorDark: "var(--pnpsearch-internal-colorBackgroundDarkPrimary, #202831)", - textColorDark: "var(--pnpsearch-internal-textColorDark, #FFF)", - }, - keyframes: { - shimmer: { - '0%, 100%': { opacity: 1 }, - '50%': { opacity: .5 }, - }, - fadein: { - '0%': { opacity: 0 }, - '100%': { opacity: 1 }, - } - }, - animation: { - 'shimmer': 'shimmer 2s cubic-bezier(0.4, 0, 0.6, 1) infinite', - 'fadein': 'fadein 0.8s ease ', - } - } - }, - plugins: [ - require('@tailwindcss/forms'), // To be able to style inputs - require('@tailwindcss/line-clamp'), - require('@tailwindcss/container-queries') - ], - // List of classes including for templating purpose - safelist: [ - - 'grid-cols-1', - 'grid-cols-2', - 'grid-cols-3', - 'grid-cols-4', - 'grid-cols-5', - - '@sm:grid-cols-1', - '@sm:grid-cols-2', - '@sm:grid-cols-3', - '@sm:grid-cols-4', - '@sm:grid-cols-5', - - '@md:grid-cols-1', - '@md:grid-cols-2', - '@md:grid-cols-3', - '@md:grid-cols-4', - '@md:grid-cols-5', - - '@lg:grid-cols-1', - '@lg:grid-cols-2', - '@lg:grid-cols-3', - '@lg:grid-cols-4', - '@lg:grid-cols-5', - - '@xl:grid-cols-1', - '@xl:grid-cols-2', - '@xl:grid-cols-3', - '@xl:grid-cols-4', - '@xl:grid-cols-5', - - '@2xl:grid-cols-1', - '@2xl:grid-cols-2', - '@2xl:grid-cols-3', - '@2xl:grid-cols-4', - '@2xl:grid-cols-5' - ] -}; \ No newline at end of file diff --git a/packages/spfx/teams/2ad6c8e4-0912-460b-a65c-7e0bbdb864cf_color.png b/packages/spfx/teams/2ad6c8e4-0912-460b-a65c-7e0bbdb864cf_color.png deleted file mode 100644 index 0e1f764fa8df4791a61c71b4f011c26f9083ee52..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10248 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 KtK_^>#Qy@$+e&%> diff --git a/packages/spfx/teams/2ad6c8e4-0912-460b-a65c-7e0bbdb864cf_outline.png b/packages/spfx/teams/2ad6c8e4-0912-460b-a65c-7e0bbdb864cf_outline.png deleted file mode 100644 index 892868fab31033c06f52dba29917ca79826896aa..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 542 zcmV+(0^$9MP)Px$*hxe|R9HvtmP;r^Q5eVncjjWepV=sxiDA658IMv*Rw!kmB*H@8O0z&Q2}uo7 z6B~&Iu^CyDjSwrA@+xKH85)n0PZUFU4xfx{?p>bqKmYIl{mwn-UJ3vFNdH_PY5u3A2g4wR^IR;II%}onJy17ywBE?rxlbtcBgy zg~pmPmN!cT|5$?44FS+-l?hjesED?SjKyYl`T&KSaAUGZH(Gwm# zNkDWHicW`r9KpHEYK|r9>>Z&Vs}0ag4Rx_W@oqaJ$d)eObsB{?*^J g8bBqW5>N>|11Bq?AqzNewEzGB07*qoM6N<$f*5=3%m4rY diff --git a/packages/spfx/teams/4f2451b5-c1ea-4a68-8097-90edc9da61ce_color.png b/packages/spfx/teams/4f2451b5-c1ea-4a68-8097-90edc9da61ce_color.png deleted file mode 100644 index 0e1f764fa8df4791a61c71b4f011c26f9083ee52..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10248 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 KtK_^>#Qy@$+e&%> diff --git a/packages/spfx/teams/4f2451b5-c1ea-4a68-8097-90edc9da61ce_outline.png b/packages/spfx/teams/4f2451b5-c1ea-4a68-8097-90edc9da61ce_outline.png deleted file mode 100644 index 892868fab31033c06f52dba29917ca79826896aa..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 542 zcmV+(0^$9MP)Px$*hxe|R9HvtmP;r^Q5eVncjjWepV=sxiDA658IMv*Rw!kmB*H@8O0z&Q2}uo7 z6B~&Iu^CyDjSwrA@+xKH85)n0PZUFU4xfx{?p>bqKmYIl{mwn-UJ3vFNdH_PY5u3A2g4wR^IR;II%}onJy17ywBE?rxlbtcBgy zg~pmPmN!cT|5$?44FS+-l?hjesED?SjKyYl`T&KSaAUGZH(Gwm# zNkDWHicW`r9KpHEYK|r9>>Z&Vs}0ag4Rx_W@oqaJ$d)eObsB{?*^J g8bBqW5>N>|11Bq?AqzNewEzGB07*qoM6N<$f*5=3%m4rY diff --git a/packages/spfx/teams/6aa5f17d-c6f5-4853-8017-86ad27f396f1_color.png b/packages/spfx/teams/6aa5f17d-c6f5-4853-8017-86ad27f396f1_color.png deleted file mode 100644 index 0e1f764fa8df4791a61c71b4f011c26f9083ee52..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10248 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 KtK_^>#Qy@$+e&%> diff --git a/packages/spfx/teams/6aa5f17d-c6f5-4853-8017-86ad27f396f1_outline.png b/packages/spfx/teams/6aa5f17d-c6f5-4853-8017-86ad27f396f1_outline.png deleted file mode 100644 index 892868fab31033c06f52dba29917ca79826896aa..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 542 zcmV+(0^$9MP)Px$*hxe|R9HvtmP;r^Q5eVncjjWepV=sxiDA658IMv*Rw!kmB*H@8O0z&Q2}uo7 z6B~&Iu^CyDjSwrA@+xKH85)n0PZUFU4xfx{?p>bqKmYIl{mwn-UJ3vFNdH_PY5u3A2g4wR^IR;II%}onJy17ywBE?rxlbtcBgy zg~pmPmN!cT|5$?44FS+-l?hjesED?SjKyYl`T&KSaAUGZH(Gwm# zNkDWHicW`r9KpHEYK|r9>>Z&Vs}0ag4Rx_W@oqaJ$d)eObsB{?*^J g8bBqW5>N>|11Bq?AqzNewEzGB07*qoM6N<$f*5=3%m4rY diff --git a/packages/spfx/teams/aac5f315-4ce8-4386-88fa-897566e2a710_color.png b/packages/spfx/teams/aac5f315-4ce8-4386-88fa-897566e2a710_color.png deleted file mode 100644 index 0e1f764fa8df4791a61c71b4f011c26f9083ee52..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10248 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 KtK_^>#Qy@$+e&%> diff --git a/packages/spfx/teams/aac5f315-4ce8-4386-88fa-897566e2a710_outline.png b/packages/spfx/teams/aac5f315-4ce8-4386-88fa-897566e2a710_outline.png deleted file mode 100644 index 892868fab31033c06f52dba29917ca79826896aa..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 542 zcmV+(0^$9MP)Px$*hxe|R9HvtmP;r^Q5eVncjjWepV=sxiDA658IMv*Rw!kmB*H@8O0z&Q2}uo7 z6B~&Iu^CyDjSwrA@+xKH85)n0PZUFU4xfx{?p>bqKmYIl{mwn-UJ3vFNdH_PY5u3A2g4wR^IR;II%}onJy17ywBE?rxlbtcBgy zg~pmPmN!cT|5$?44FS+-l?hjesED?SjKyYl`T&KSaAUGZH(Gwm# zNkDWHicW`r9KpHEYK|r9>>Z&Vs}0ag4Rx_W@oqaJ$d)eObsB{?*^J g8bBqW5>N>|11Bq?AqzNewEzGB07*qoM6N<$f*5=3%m4rY diff --git a/packages/spfx/toolchain/gulp.js b/packages/spfx/toolchain/gulp.js deleted file mode 100644 index a3a14a2..0000000 --- a/packages/spfx/toolchain/gulp.js +++ /dev/null @@ -1,86 +0,0 @@ -const fs = require('fs'); -const util = require('util'); -const path = require('path'); -const log = require('fancy-log'); - -const DefaultRegistry = require('undertaker-registry'); - -function PnPModernSearchCommonRegistry(this: any, opts: {}) { - DefaultRegistry.call(this); - opts = opts || {}; -} - -util.inherits(PnPModernSearchCommonRegistry, DefaultRegistry); - -PnPModernSearchCommonRegistry.prototype.init = (gulpInst: any) => { - - const readJson = (filePath: string, cb: { (err: any, pkgSolution: any): void; (err: any, manifest: any): void; (arg0: any, arg1: any): void; }) => { - fs.readFile(require.resolve(filePath), (err: any, data: string) => { - if (err) - log.error(err); - else - cb(null, JSON.parse(data)); - }); - }; - - const findFilesByExt = (base: string, ext: string | any[], files?: any[], result?: any[]) => { - files = files || fs.readdirSync(base); - result = result || []; - - files.forEach( - (file: string) => { - var newbase = path.join(base,file); - if (fs.statSync(newbase).isDirectory()) { - result = findFilesByExt(newbase,ext,fs.readdirSync(newbase),result); - } else { - if ( file.substr(-1*(ext.length+1)) == '.' + ext ) { - result.push(newbase); - } - } - } - ); - return result; - }; - - gulpInst.task('update-version', async () => { - - // List all manifest files - const manifestFiles = findFilesByExt('./src','manifest.json'); - - const semver = require('semver'); - const versionArgIdx = process.argv.indexOf('--value'); - const newVersionNumber = semver.valid(process.argv[versionArgIdx+1]); - - if (versionArgIdx !== -1 && newVersionNumber) { - - // Update version in the package-solution - const pkgSolutionFilePath = path.resolve('./config/package-solution.json'); - - readJson(pkgSolutionFilePath, (err: any, pkgSolution: { solution: { version: string; }; }) => { - log.info('Old package-solution.json version:\t' + pkgSolution.solution.version); - const pkgVersion = `${semver.major(newVersionNumber)}.${semver.minor(newVersionNumber)}.${semver.patch(newVersionNumber)}.0`; - pkgSolution.solution.version = pkgVersion; - log.info('New package-solution.json version:\t' + pkgVersion); - fs.writeFile(pkgSolutionFilePath, JSON.stringify(pkgSolution, null, 4), (error: any) => {}); - }); - - // Updated version in Web Part manifests - manifestFiles.forEach((manifestFile: any) => { - readJson(path.resolve(`./${manifestFile}`), (err: any, manifest: { version: string; }) => { - - log.info(`Updating manifest file: "./${manifestFile}"`); - - log.info('Old manifestFile version:\t' + manifest.version); - const wpVersion = `${semver.major(newVersionNumber)}.${semver.minor(newVersionNumber)}.${semver.patch(newVersionNumber)}`; - manifest.version = wpVersion; - log.info('New manifestFile version:\t' + wpVersion); - fs.writeFile(manifestFile, JSON.stringify(manifest, null, 4), (error: any) => {}); - }); - }); - } else { - log.error(`The provided version ${process.argv[versionArgIdx+1]} is not a valid SemVer version`); - } - }); -}; - -module.exports = PnPModernSearchCommonRegistry; \ No newline at end of file diff --git a/packages/spfx/tsconfig.json b/packages/spfx/tsconfig.json deleted file mode 100644 index 70cf791..0000000 --- a/packages/spfx/tsconfig.json +++ /dev/null @@ -1,38 +0,0 @@ -{ - "extends": "./node_modules/@microsoft/rush-stack-compiler-4.5/includes/tsconfig-web.json", - "compilerOptions": { - "target": "ES2017", - "forceConsistentCasingInFileNames": true, - "module": "esnext", - "moduleResolution": "node", - "jsx": "react", - "declaration": false, - "declarationMap": false, - "sourceMap": true, - "experimentalDecorators": true, - "skipLibCheck": true, - "outDir": "lib", - "inlineSources": false, - "strictNullChecks": false, - "noImplicitAny": true, - "noUnusedLocals": false, - "typeRoots": [ - "./node_modules/@types", - "./node_modules/@microsoft" - ], - "types": [ - "webpack-env" - ], - "lib": [ - "ES2017", - "es5", - "dom", - "es2015.collection", - "es2015.promise" - ] - }, - "include": [ - "src/**/*.ts", - "src/**/*.tsx" - ] -} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 38db7cb..0925ff1 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -134,13 +134,13 @@ importers: version: 2.5.1(eslint@8.33.0)(typescript@4.9.5) '@tailwindcss/container-queries': specifier: 0.1.1 - version: 0.1.1(tailwindcss@3.2.4(postcss@7.0.38)(ts-node@10.9.2(@swc/core@1.3.89(@swc/helpers@0.5.6))(@types/node@20.4.1)(typescript@4.9.5))) + version: 0.1.1(tailwindcss@3.2.4(postcss@8.4.31)(ts-node@10.9.2(@swc/core@1.3.89(@swc/helpers@0.5.6))(@types/node@20.4.1)(typescript@4.9.5))) '@tailwindcss/forms': specifier: 0.5.3 - version: 0.5.3(tailwindcss@3.2.4(postcss@7.0.38)(ts-node@10.9.2(@swc/core@1.3.89(@swc/helpers@0.5.6))(@types/node@20.4.1)(typescript@4.9.5))) + version: 0.5.3(tailwindcss@3.2.4(postcss@8.4.31)(ts-node@10.9.2(@swc/core@1.3.89(@swc/helpers@0.5.6))(@types/node@20.4.1)(typescript@4.9.5))) '@tailwindcss/line-clamp': specifier: 0.4.4 - version: 0.4.4(tailwindcss@3.2.4(postcss@7.0.38)(ts-node@10.9.2(@swc/core@1.3.89(@swc/helpers@0.5.6))(@types/node@20.4.1)(typescript@4.9.5))) + version: 0.4.4(tailwindcss@3.2.4(postcss@8.4.31)(ts-node@10.9.2(@swc/core@1.3.89(@swc/helpers@0.5.6))(@types/node@20.4.1)(typescript@4.9.5))) '@types/dompurify': specifier: 3.0.2 version: 3.0.2 @@ -158,7 +158,7 @@ importers: version: 8.12.0 autoprefixer: specifier: 10.4.16 - version: 10.4.16(postcss@7.0.38) + version: 10.4.16(postcss@8.4.31) babel-loader: specifier: ^8.3.0 version: 8.3.0(@babel/core@7.23.9)(webpack@4.44.2) @@ -195,6 +195,9 @@ importers: null-loader: specifier: 4.0.1 version: 4.0.1(webpack@4.44.2) + postcss: + specifier: 8.4.31 + version: 8.4.31 semver: specifier: 7.5.4 version: 7.5.4 @@ -206,7 +209,7 @@ importers: version: 1.18.0(@microsoft/load-themed-styles@1.10.292)(@types/node@20.4.1)(@types/webpack-sources@3.2.0)(@types/webpack@4.41.24)(encoding@0.1.13)(eslint@8.33.0)(sockjs-client@1.6.1)(type-fest@2.19.0)(typescript@4.9.5)(webpack-hot-middleware@2.25.4) tailwindcss: specifier: 3.2.4 - version: 3.2.4(postcss@7.0.38)(ts-node@10.9.2(@swc/core@1.3.89(@swc/helpers@0.5.6))(@types/node@20.4.1)(typescript@4.9.5)) + version: 3.2.4(postcss@8.4.31)(ts-node@10.9.2(@swc/core@1.3.89(@swc/helpers@0.5.6))(@types/node@20.4.1)(typescript@4.9.5)) typescript: specifier: 4.9.5 version: 4.9.5 @@ -600,211 +603,6 @@ importers: specifier: ^5.8.0 version: 5.8.0 - packages/spfx: - dependencies: - '@fluentui/react': - specifier: ^7.199.1 - version: 7.204.0(@types/react-dom@17.0.17)(@types/react@17.0.45)(react-dom@17.0.1(react@17.0.1))(react@17.0.1) - '@microsoft/microsoft-graph-client': - specifier: 3.0.2 - version: 3.0.2(@azure/msal-browser@2.38.4) - '@microsoft/sp-component-base': - specifier: 1.18.2 - version: 1.18.2(@microsoft/microsoft-graph-client@3.0.2)(@types/node@20.4.1)(@types/react-dom@17.0.17)(@types/react@17.0.45)(encoding@0.1.13)(react-dom@17.0.1(react@17.0.1))(react@17.0.1) - '@microsoft/sp-core-library': - specifier: 1.18.2 - version: 1.18.2(@types/node@20.4.1)(@types/react-dom@17.0.17)(@types/react@17.0.45)(react-dom@17.0.1(react@17.0.1))(react@17.0.1) - '@microsoft/sp-diagnostics': - specifier: 1.18.2 - version: 1.18.2(@types/node@20.4.1)(@types/react-dom@17.0.17)(@types/react@17.0.45)(react-dom@17.0.1(react@17.0.1))(react@17.0.1) - '@microsoft/sp-dynamic-data': - specifier: 1.18.2 - version: 1.18.2(@types/node@20.4.1)(@types/react-dom@17.0.17)(@types/react@17.0.45)(react-dom@17.0.1(react@17.0.1))(react@17.0.1) - '@microsoft/sp-http': - specifier: 1.18.2 - version: 1.18.2(@microsoft/microsoft-graph-client@3.0.2)(@types/node@20.4.1)(@types/react-dom@17.0.17)(@types/react@17.0.45)(encoding@0.1.13)(react-dom@17.0.1(react@17.0.1))(react@17.0.1) - '@microsoft/sp-http-base': - specifier: 1.18.2 - version: 1.18.2(@types/node@20.4.1)(@types/react-dom@17.0.17)(@types/react@17.0.45)(react-dom@17.0.1(react@17.0.1))(react@17.0.1) - '@microsoft/sp-http-msgraph': - specifier: 1.18.2 - version: 1.18.2(@microsoft/microsoft-graph-client@3.0.2)(@types/node@20.4.1)(@types/react-dom@17.0.17)(@types/react@17.0.45)(encoding@0.1.13)(react-dom@17.0.1(react@17.0.1))(react@17.0.1) - '@microsoft/sp-loader': - specifier: 1.18.2 - version: 1.18.2(@types/node@20.4.1)(@types/react-dom@17.0.17)(@types/react@17.0.45) - '@microsoft/sp-lodash-subset': - specifier: 1.18.2 - version: 1.18.2 - '@microsoft/sp-office-ui-fabric-core': - specifier: 1.18.2 - version: 1.18.2 - '@microsoft/sp-page-context': - specifier: 1.18.2 - version: 1.18.2(@types/node@20.4.1)(@types/react-dom@17.0.17)(@types/react@17.0.45)(react-dom@17.0.1(react@17.0.1))(react@17.0.1) - '@microsoft/sp-property-pane': - specifier: 1.18.2 - version: 1.18.2(@microsoft/microsoft-graph-client@3.0.2)(@types/node@20.4.1)(@types/react-dom@17.0.17)(@types/react@17.0.45)(encoding@0.1.13) - '@microsoft/sp-webpart-base': - specifier: 1.18.2 - version: 1.18.2(@microsoft/microsoft-graph-client@3.0.2)(@types/node@20.4.1)(@types/react-dom@17.0.17)(@types/react@17.0.45)(encoding@0.1.13) - '@monaco-editor/react': - specifier: ^4.5.1 - version: 4.5.1(monaco-editor@0.41.0)(react-dom@17.0.1(react@17.0.1))(react@17.0.1) - '@pnp/modern-search-core': - specifier: workspace:* - version: link:../components - '@pnp/spfx-controls-react': - specifier: 3.15.0 - version: 3.15.0(@babel/core@7.23.9)(@babel/template@7.23.9)(@microsoft/microsoft-graph-client@3.0.2)(@types/node@20.4.1)(@types/react-dom@17.0.17)(@types/react@17.0.45)(encoding@0.1.13)(scheduler@0.23.0) - '@pnp/spfx-property-controls': - specifier: 3.1.0 - version: 3.1.0(@types/react-dom@17.0.17)(@types/react@17.0.45) - '@pnp/telemetry-js': - specifier: 2.0.0 - version: 2.0.0 - '@webcomponents/scoped-custom-element-registry': - specifier: 0.0.9 - version: 0.0.9 - dompurify: - specifier: 3.0.5 - version: 3.0.5 - html-react-parser: - specifier: 4.2.1 - version: 4.2.1(react@17.0.1) - office-ui-fabric-react: - specifier: ^7.199.1 - version: 7.204.0(@types/react-dom@17.0.17)(@types/react@17.0.45)(react-dom@17.0.1(react@17.0.1))(react@17.0.1) - react: - specifier: 17.0.1 - version: 17.0.1 - react-dom: - specifier: 17.0.1 - version: 17.0.1(react@17.0.1) - tslib: - specifier: 2.5.0 - version: 2.5.0 - wc-react: - specifier: 0.5.1 - version: 0.5.1 - devDependencies: - '@babel/plugin-transform-logical-assignment-operators': - specifier: 7.23.4 - version: 7.23.4(@babel/core@7.23.9) - '@babel/plugin-transform-nullish-coalescing-operator': - specifier: 7.23.4 - version: 7.23.4(@babel/core@7.23.9) - '@babel/plugin-transform-optional-chaining': - specifier: 7.23.4 - version: 7.23.4(@babel/core@7.23.9) - '@babel/preset-env': - specifier: 7.22.5 - version: 7.22.5(@babel/core@7.23.9) - '@babel/preset-typescript': - specifier: 7.22.15 - version: 7.22.15(@babel/core@7.23.9) - '@microsoft/eslint-config-spfx': - specifier: 1.18.2 - version: 1.18.2(eslint@8.33.0)(typescript@4.9.5) - '@microsoft/eslint-plugin-spfx': - specifier: 1.18.2 - version: 1.18.2(eslint@8.33.0)(typescript@4.9.5) - '@microsoft/rush-stack-compiler-4.5': - specifier: 0.5.0 - version: 0.5.0(eslint@8.33.0) - '@microsoft/sp-build-web': - specifier: 1.18.2 - version: 1.18.2(@types/node@20.4.1)(@types/webpack-sources@3.2.0)(encoding@0.1.13) - '@microsoft/sp-module-interfaces': - specifier: 1.18.2 - version: 1.18.2(@types/node@20.4.1) - '@rushstack/eslint-config': - specifier: 2.5.1 - version: 2.5.1(eslint@8.33.0)(typescript@4.9.5) - '@tailwindcss/container-queries': - specifier: 0.1.1 - version: 0.1.1(tailwindcss@3.2.4(postcss@8.4.31)(ts-node@10.9.2(@swc/core@1.3.89(@swc/helpers@0.5.6))(@types/node@20.4.1)(typescript@4.9.5))) - '@tailwindcss/forms': - specifier: 0.5.3 - version: 0.5.3(tailwindcss@3.2.4(postcss@8.4.31)(ts-node@10.9.2(@swc/core@1.3.89(@swc/helpers@0.5.6))(@types/node@20.4.1)(typescript@4.9.5))) - '@tailwindcss/line-clamp': - specifier: 0.4.4 - version: 0.4.4(tailwindcss@3.2.4(postcss@8.4.31)(ts-node@10.9.2(@swc/core@1.3.89(@swc/helpers@0.5.6))(@types/node@20.4.1)(typescript@4.9.5))) - '@types/dompurify': - specifier: 3.0.2 - version: 3.0.2 - '@types/react': - specifier: 17.0.45 - version: 17.0.45 - '@types/react-dom': - specifier: 17.0.17 - version: 17.0.17 - '@types/webpack-env': - specifier: ~1.15.2 - version: 1.15.3 - ajv: - specifier: 8.12.0 - version: 8.12.0 - autoprefixer: - specifier: 10.4.16 - version: 10.4.16(postcss@8.4.31) - babel-loader: - specifier: ^8.3.0 - version: 8.3.0(@babel/core@7.23.9)(webpack@4.44.2) - babel-plugin-module-resolver: - specifier: 5.0.0 - version: 5.0.0 - eslint: - specifier: ^8.33.0 - version: 8.33.0 - eslint-plugin-react-hooks: - specifier: 4.3.0 - version: 4.3.0(eslint@8.33.0) - fancy-log: - specifier: ^2.0.0 - version: 2.0.0 - gulp: - specifier: ^4.0.2 - version: 4.0.2 - gulp-rename: - specifier: 2.0.0 - version: 2.0.0 - gulp-replace: - specifier: 1.1.4 - version: 1.1.4 - html-loader: - specifier: ^1.1.0 - version: 1.1.0(webpack@4.44.2) - monaco-editor: - specifier: ^0.41.0 - version: 0.41.0 - npm-run-all: - specifier: ^4.1.5 - version: 4.1.5 - null-loader: - specifier: 4.0.1 - version: 4.0.1(webpack@4.44.2) - semver: - specifier: 7.5.4 - version: 7.5.4 - source-map-loader: - specifier: 1.1.3 - version: 1.1.3(webpack@4.44.2) - spfx-fast-serve-helpers: - specifier: ~1.18.0 - version: 1.18.0(@microsoft/load-themed-styles@2.0.63)(@types/node@20.4.1)(@types/webpack-sources@3.2.0)(@types/webpack@4.41.33)(encoding@0.1.13)(eslint@8.33.0)(sockjs-client@1.6.1)(type-fest@2.19.0)(typescript@4.9.5)(webpack-hot-middleware@2.25.4) - tailwindcss: - specifier: 3.2.4 - version: 3.2.4(postcss@8.4.31)(ts-node@10.9.2(@swc/core@1.3.89(@swc/helpers@0.5.6))(@types/node@20.4.1)(typescript@4.9.5)) - typescript: - specifier: 4.9.5 - version: 4.9.5 - undertaker-registry: - specifier: 2.0.0 - version: 2.0.0 - webpack: - specifier: ~4.44.2 - version: 4.44.2(webpack-cli@4.6.0) - packages: '@75lb/deep-merge@1.1.1': @@ -2562,9 +2360,6 @@ packages: '@microsoft/load-themed-styles@1.10.295': resolution: {integrity: sha512-W+IzEBw8a6LOOfRJM02dTT7BDZijxm+Z7lhtOAz1+y9vQm1Kdz9jlAO+qCEKsfxtUOmKilW8DIRqFw2aUgKeGg==} - '@microsoft/load-themed-styles@2.0.63': - resolution: {integrity: sha512-Vi4kD0sTmifwKGh/dJs2MTkcVevYVe25uP1xE27TuxNHy8qyFP8WSgbLnK20HJP0/6wd+qgy1iQdett+fvu7Vw==} - '@microsoft/loader-load-themed-styles@2.0.45': resolution: {integrity: sha512-04foUzzYBbKpBKj16N9pjyKJzt6jthyd2gMzg1fQJPfrIblsJanumlhiUitpZjzyhs/53qYzEsTo0PZCKRHUpQ==} peerDependencies: @@ -16275,7 +16070,7 @@ snapshots: '@types/node-fetch': 2.6.4 '@types/tunnel': 0.0.3 form-data: 4.0.0 - node-fetch: 2.6.12(encoding@0.1.13) + node-fetch: 2.7.0(encoding@0.1.13) process: 0.11.10 tough-cookie: 4.1.3 tslib: 2.5.0 @@ -16295,7 +16090,7 @@ snapshots: '@types/node-fetch': 2.6.4 '@types/tunnel': 0.0.3 form-data: 4.0.0 - node-fetch: 2.6.12(encoding@0.1.13) + node-fetch: 2.7.0(encoding@0.1.13) process: 0.11.10 tslib: 2.5.0 tunnel: 0.0.6 @@ -18651,22 +18446,6 @@ snapshots: - supports-color - utf-8-validate - '@microsoft/gulp-core-build-webpack@5.4.0': - dependencies: - '@microsoft/gulp-core-build': 3.18.1 - '@types/gulp': 4.0.6 - '@types/node': 10.17.13 - colors: 1.2.5 - gulp: 4.0.2 - webpack: 4.47.0 - transitivePeerDependencies: - - bufferutil - - canvas - - supports-color - - utf-8-validate - - webpack-cli - - webpack-command - '@microsoft/gulp-core-build-webpack@5.4.0(webpack-cli@4.6.0)': dependencies: '@microsoft/gulp-core-build': 3.18.1 @@ -18734,8 +18513,6 @@ snapshots: '@microsoft/load-themed-styles@1.10.295': {} - '@microsoft/load-themed-styles@2.0.63': {} - '@microsoft/loader-load-themed-styles@2.0.45(@microsoft/load-themed-styles@1.10.292)(@types/webpack@4.41.24)': dependencies: '@microsoft/load-themed-styles': 1.10.292 @@ -18743,13 +18520,6 @@ snapshots: optionalDependencies: '@types/webpack': 4.41.24 - '@microsoft/loader-load-themed-styles@2.0.45(@microsoft/load-themed-styles@2.0.63)(@types/webpack@4.41.33)': - dependencies: - '@microsoft/load-themed-styles': 2.0.63 - loader-utils: 1.4.2 - optionalDependencies: - '@types/webpack': 4.41.33 - '@microsoft/loader-load-themed-styles@2.0.68(@microsoft/load-themed-styles@1.10.292)(@types/webpack@4.41.24)': dependencies: '@microsoft/load-themed-styles': 1.10.292 @@ -18757,13 +18527,6 @@ snapshots: optionalDependencies: '@types/webpack': 4.41.24 - '@microsoft/loader-load-themed-styles@2.0.68(@microsoft/load-themed-styles@1.10.292)(@types/webpack@4.41.33)': - dependencies: - '@microsoft/load-themed-styles': 1.10.292 - loader-utils: 1.4.2 - optionalDependencies: - '@types/webpack': 4.41.33 - '@microsoft/loader-load-themed-styles@2.1.7(@microsoft/load-themed-styles@1.10.292)(@types/webpack@4.41.24)': dependencies: '@microsoft/load-themed-styles': 1.10.292 @@ -19148,34 +18911,6 @@ snapshots: - react-dom - supports-color - '@microsoft/sp-build-core-tasks@1.18.2(@types/node@20.4.1)(@types/webpack-sources@3.2.0)(encoding@0.1.13)': - dependencies: - '@microsoft/gulp-core-build': 3.18.1 - '@microsoft/gulp-core-build-serve': 3.12.1 - '@microsoft/gulp-core-build-webpack': 5.4.0 - '@microsoft/spfx-heft-plugins': 1.18.2(@types/node@20.4.1)(@types/webpack-sources@3.2.0)(@types/webpack@4.41.24)(encoding@0.1.13) - '@rushstack/node-core-library': 3.61.0(@types/node@20.4.1) - '@types/glob': 5.0.30 - '@types/lodash': 4.14.117 - '@types/webpack': 4.41.24 - colors: 1.2.5 - glob: 7.0.6 - gulp: 4.0.2 - lodash: 4.17.21 - webpack: 4.47.0 - transitivePeerDependencies: - - '@types/node' - - '@types/webpack-sources' - - bluebird - - bufferutil - - canvas - - debug - - encoding - - supports-color - - utf-8-validate - - webpack-cli - - webpack-command - '@microsoft/sp-build-core-tasks@1.18.2(@types/node@20.4.1)(@types/webpack-sources@3.2.0)(encoding@0.1.13)(webpack-cli@4.6.0)': dependencies: '@microsoft/gulp-core-build': 3.18.1 @@ -19204,36 +18939,6 @@ snapshots: - webpack-cli - webpack-command - '@microsoft/sp-build-web@1.18.2(@types/node@20.4.1)(@types/webpack-sources@3.2.0)(encoding@0.1.13)': - dependencies: - '@microsoft/gulp-core-build': 3.18.1 - '@microsoft/gulp-core-build-sass': 4.17.1 - '@microsoft/gulp-core-build-serve': 3.12.1 - '@microsoft/gulp-core-build-typescript': 8.6.1 - '@microsoft/gulp-core-build-webpack': 5.4.0 - '@microsoft/rush-lib': 5.107.4(@types/node@20.4.1)(encoding@0.1.13) - '@microsoft/sp-build-core-tasks': 1.18.2(@types/node@20.4.1)(@types/webpack-sources@3.2.0)(encoding@0.1.13) - '@rushstack/node-core-library': 3.61.0(@types/node@20.4.1) - '@types/webpack': 4.41.24 - gulp: 4.0.2 - postcss: 8.4.31 - semver: 7.3.8 - true-case-path: 2.2.1 - webpack: 4.47.0 - yargs: 4.6.0 - transitivePeerDependencies: - - '@types/node' - - '@types/webpack-sources' - - bluebird - - bufferutil - - canvas - - debug - - encoding - - supports-color - - utf-8-validate - - webpack-cli - - webpack-command - '@microsoft/sp-build-web@1.18.2(@types/node@20.4.1)(@types/webpack-sources@3.2.0)(encoding@0.1.13)(webpack-cli@4.6.0)': dependencies: '@microsoft/gulp-core-build': 3.18.1 @@ -19381,26 +19086,6 @@ snapshots: - webpack-cli - webpack-command - '@microsoft/sp-css-loader@1.18.2(@types/node@20.4.1)': - dependencies: - '@microsoft/load-themed-styles': 1.10.292 - '@rushstack/node-core-library': 3.61.0(@types/node@20.4.1) - autoprefixer: 9.7.1 - css-loader: 3.4.2(webpack@4.47.0) - cssnano: 5.1.15(postcss@8.4.31) - loader-utils: 1.4.2 - postcss: 8.4.31 - postcss-modules-extract-imports: 3.0.0(postcss@8.4.31) - postcss-modules-local-by-default: 4.0.3(postcss@8.4.31) - postcss-modules-scope: 3.0.0(postcss@8.4.31) - postcss-modules-values: 4.0.0(postcss@8.4.31) - webpack: 4.47.0 - transitivePeerDependencies: - - '@types/node' - - supports-color - - webpack-cli - - webpack-command - '@microsoft/sp-css-loader@1.18.2(@types/node@20.4.1)(webpack-cli@4.6.0)': dependencies: '@microsoft/load-themed-styles': 1.10.292 @@ -20067,7 +19752,7 @@ snapshots: '@rushstack/localization-utilities': 0.8.80(@types/node@20.4.1) '@rushstack/node-core-library': 3.59.6(@types/node@20.4.1) '@rushstack/rig-package': 0.4.0 - '@rushstack/set-webpack-public-path-plugin': 4.0.15(@types/node@20.4.1)(@types/webpack@4.41.24)(webpack@4.44.2) + '@rushstack/set-webpack-public-path-plugin': 4.0.15(@types/node@20.4.1)(@types/webpack@4.41.24)(webpack@4.47.0(webpack-cli@4.6.0)) '@rushstack/terminal': 0.5.36(@types/node@20.4.1) '@rushstack/webpack4-localization-plugin': 0.17.46(@rushstack/set-webpack-public-path-plugin@4.0.15(@types/node@20.4.1)(@types/webpack@4.41.24)(webpack@4.44.2))(@types/node@20.4.1)(@types/webpack@4.41.24)(webpack@4.47.0(webpack-cli@4.6.0)) '@rushstack/webpack4-module-minifier-plugin': 0.12.35(@types/node@20.4.1)(@types/webpack-sources@3.2.0)(@types/webpack@4.41.24)(webpack-sources@1.4.3)(webpack@4.47.0(webpack-cli@4.6.0)) @@ -20110,116 +19795,6 @@ snapshots: - webpack-cli - webpack-command - '@microsoft/spfx-heft-plugins@1.18.0(@types/node@20.4.1)(@types/webpack-sources@3.2.0)(@types/webpack@4.41.33)(encoding@0.1.13)(webpack-cli@4.6.0)': - dependencies: - '@azure/storage-blob': 12.11.0(encoding@0.1.13) - '@microsoft/load-themed-styles': 1.10.292 - '@microsoft/loader-load-themed-styles': 2.0.68(@microsoft/load-themed-styles@1.10.292)(@types/webpack@4.41.33) - '@microsoft/rush-lib': 5.100.2(@types/node@20.4.1)(encoding@0.1.13) - '@microsoft/sp-css-loader': 1.18.0(@types/node@20.4.1)(webpack-cli@4.6.0) - '@microsoft/sp-module-interfaces': 1.18.0(@types/node@20.4.1) - '@rushstack/heft-config-file': 0.13.2(@types/node@20.4.1) - '@rushstack/localization-utilities': 0.8.80(@types/node@20.4.1) - '@rushstack/node-core-library': 3.59.6(@types/node@20.4.1) - '@rushstack/rig-package': 0.4.0 - '@rushstack/set-webpack-public-path-plugin': 4.0.15(@types/node@20.4.1)(@types/webpack@4.41.33)(webpack@4.47.0(webpack-cli@4.6.0)) - '@rushstack/terminal': 0.5.36(@types/node@20.4.1) - '@rushstack/webpack4-localization-plugin': 0.17.46(@rushstack/set-webpack-public-path-plugin@4.0.15(@types/node@20.4.1)(@types/webpack@4.41.33)(webpack@4.47.0(webpack-cli@4.6.0)))(@types/node@20.4.1)(@types/webpack@4.41.33)(webpack@4.47.0(webpack-cli@4.6.0)) - '@rushstack/webpack4-module-minifier-plugin': 0.12.35(@types/node@20.4.1)(@types/webpack-sources@3.2.0)(@types/webpack@4.41.33)(webpack-sources@1.4.3)(webpack@4.47.0(webpack-cli@4.6.0)) - '@types/tapable': 1.0.6 - autoprefixer: 9.7.1 - colors: 1.2.5 - copy-webpack-plugin: 6.0.4(webpack@4.47.0(webpack-cli@4.6.0)) - css-loader: 3.4.2(webpack@4.47.0(webpack-cli@4.6.0)) - cssnano: 5.1.15(postcss@8.4.31) - express: 4.18.1 - file-loader: 6.1.0(webpack@4.47.0(webpack-cli@4.6.0)) - git-repo-info: 2.1.1 - glob: 7.0.6 - html-loader: 0.5.5 - jszip: 3.8.0 - lodash: 4.17.21 - mime: 2.5.2 - postcss: 8.4.31 - postcss-loader: 4.2.0(postcss@8.4.31)(webpack@4.47.0(webpack-cli@4.6.0)) - resolve: 1.17.0 - source-map: 0.6.1 - source-map-loader: 1.1.3(webpack@4.47.0(webpack-cli@4.6.0)) - tapable: 1.1.3 - true-case-path: 2.2.1 - uuid: 3.1.0 - webpack: 4.47.0(webpack-cli@4.6.0) - webpack-dev-server: 4.9.3(webpack-cli@4.6.0)(webpack@4.47.0(webpack-cli@4.6.0)) - webpack-sources: 1.4.3 - xml: 1.0.1 - transitivePeerDependencies: - - '@types/node' - - '@types/webpack' - - '@types/webpack-sources' - - bluebird - - bufferutil - - debug - - encoding - - supports-color - - utf-8-validate - - webpack-cli - - webpack-command - - '@microsoft/spfx-heft-plugins@1.18.2(@types/node@20.4.1)(@types/webpack-sources@3.2.0)(@types/webpack@4.41.24)(encoding@0.1.13)': - dependencies: - '@azure/storage-blob': 12.11.0(encoding@0.1.13) - '@microsoft/load-themed-styles': 1.10.292 - '@microsoft/loader-load-themed-styles': 2.1.7(@microsoft/load-themed-styles@1.10.292)(@types/webpack@4.41.24) - '@microsoft/rush-lib': 5.107.4(@types/node@20.4.1)(encoding@0.1.13) - '@microsoft/sp-css-loader': 1.18.2(@types/node@20.4.1) - '@microsoft/sp-module-interfaces': 1.18.2(@types/node@20.4.1) - '@rushstack/heft-config-file': 0.14.2(@types/node@20.4.1) - '@rushstack/localization-utilities': 0.9.7(@types/node@20.4.1) - '@rushstack/node-core-library': 3.61.0(@types/node@20.4.1) - '@rushstack/rig-package': 0.5.1 - '@rushstack/set-webpack-public-path-plugin': 4.1.7(@types/node@20.4.1)(@types/webpack@4.41.24)(webpack@4.47.0) - '@rushstack/terminal': 0.7.7(@types/node@20.4.1) - '@rushstack/webpack4-localization-plugin': 0.18.7(@rushstack/set-webpack-public-path-plugin@4.1.7(@types/node@20.4.1)(@types/webpack@4.41.24)(webpack@4.47.0))(@types/node@20.4.1)(@types/webpack@4.41.24)(webpack@4.47.0) - '@rushstack/webpack4-module-minifier-plugin': 0.13.7(@types/node@20.4.1)(@types/webpack-sources@3.2.0)(@types/webpack@4.41.24)(webpack-sources@1.4.3)(webpack@4.47.0) - '@types/tapable': 1.0.6 - autoprefixer: 9.7.1 - colors: 1.2.5 - copy-webpack-plugin: 6.0.4(webpack@4.47.0) - css-loader: 3.4.2(webpack@4.47.0) - cssnano: 5.1.15(postcss@8.4.31) - express: 4.18.1 - file-loader: 6.1.0(webpack@4.47.0) - git-repo-info: 2.1.1 - glob: 7.0.6 - html-loader: 0.5.5 - jszip: 3.8.0 - lodash: 4.17.21 - mime: 2.5.2 - postcss: 8.4.31 - postcss-loader: 4.2.0(postcss@8.4.31)(webpack@4.47.0) - resolve: 1.17.0 - source-map: 0.6.1 - source-map-loader: 1.1.3(webpack@4.47.0) - tapable: 1.1.3 - true-case-path: 2.2.1 - uuid: 9.0.0 - webpack: 4.47.0 - webpack-dev-server: 4.9.3(webpack@4.47.0) - webpack-sources: 1.4.3 - xml: 1.0.1 - transitivePeerDependencies: - - '@types/node' - - '@types/webpack' - - '@types/webpack-sources' - - bluebird - - bufferutil - - debug - - encoding - - supports-color - - utf-8-validate - - webpack-cli - - webpack-command - '@microsoft/spfx-heft-plugins@1.18.2(@types/node@20.4.1)(@types/webpack-sources@3.2.0)(@types/webpack@4.41.24)(encoding@0.1.13)(webpack-cli@4.6.0)': dependencies: '@azure/storage-blob': 12.11.0(encoding@0.1.13) @@ -20561,7 +20136,7 @@ snapshots: '@octokit/request-error': 3.0.3 '@octokit/types': 9.3.2 is-plain-object: 5.0.0 - node-fetch: 2.6.12(encoding@0.1.13) + node-fetch: 2.7.0(encoding@0.1.13) universal-user-agent: 6.0.0 transitivePeerDependencies: - encoding @@ -20656,27 +20231,7 @@ snapshots: webpack: 4.44.2(webpack-cli@4.6.0) optionalDependencies: '@types/webpack': 4.41.24 - sockjs-client: 1.6.1(supports-color@6.1.0) - type-fest: 2.19.0 - webpack-dev-server: 3.11.2(webpack-cli@4.6.0)(webpack@4.44.2) - webpack-hot-middleware: 2.25.4 - - '@pmmmwh/react-refresh-webpack-plugin@0.5.7(@types/webpack@4.41.33)(react-refresh@0.14.0)(sockjs-client@1.6.1)(type-fest@2.19.0)(webpack-dev-server@3.11.2)(webpack-hot-middleware@2.25.4)(webpack@4.44.2)': - dependencies: - ansi-html-community: 0.0.8 - common-path-prefix: 3.0.0 - core-js-pure: 3.31.1 - error-stack-parser: 2.1.4 - find-up: 5.0.0 - html-entities: 2.4.0 - loader-utils: 2.0.4 - react-refresh: 0.14.0 - schema-utils: 3.3.0 - source-map: 0.7.4 - webpack: 4.44.2(webpack-cli@4.6.0) - optionalDependencies: - '@types/webpack': 4.41.33 - sockjs-client: 1.6.1(supports-color@6.1.0) + sockjs-client: 1.6.1 type-fest: 2.19.0 webpack-dev-server: 3.11.2(webpack-cli@4.6.0)(webpack@4.44.2) webpack-hot-middleware: 2.25.4 @@ -21780,7 +21335,7 @@ snapshots: transitivePeerDependencies: - '@types/node' - '@rushstack/set-webpack-public-path-plugin@4.0.15(@types/node@20.4.1)(@types/webpack@4.41.24)(webpack@4.44.2)': + '@rushstack/set-webpack-public-path-plugin@4.0.15(@types/node@20.4.1)(@types/webpack@4.41.24)(webpack@4.47.0(webpack-cli@4.6.0))': dependencies: '@rushstack/node-core-library': 3.59.6(@types/node@20.4.1) '@rushstack/webpack-plugin-utilities': 0.2.36(@types/webpack@4.41.24)(webpack@4.47.0(webpack-cli@4.6.0)) @@ -21790,16 +21345,6 @@ snapshots: - '@types/node' - webpack - '@rushstack/set-webpack-public-path-plugin@4.0.15(@types/node@20.4.1)(@types/webpack@4.41.33)(webpack@4.47.0(webpack-cli@4.6.0))': - dependencies: - '@rushstack/node-core-library': 3.59.6(@types/node@20.4.1) - '@rushstack/webpack-plugin-utilities': 0.2.36(@types/webpack@4.41.33)(webpack@4.47.0(webpack-cli@4.6.0)) - optionalDependencies: - '@types/webpack': 4.41.33 - transitivePeerDependencies: - - '@types/node' - - webpack - '@rushstack/set-webpack-public-path-plugin@4.1.7(@types/node@20.4.1)(@types/webpack@4.41.24)(webpack@4.47.0(webpack-cli@4.6.0))': dependencies: '@rushstack/node-core-library': 3.61.0(@types/node@20.4.1) @@ -21810,16 +21355,6 @@ snapshots: - '@types/node' - webpack - '@rushstack/set-webpack-public-path-plugin@4.1.7(@types/node@20.4.1)(@types/webpack@4.41.24)(webpack@4.47.0)': - dependencies: - '@rushstack/node-core-library': 3.61.0(@types/node@20.4.1) - '@rushstack/webpack-plugin-utilities': 0.3.7(@types/webpack@4.41.24)(webpack@4.47.0) - optionalDependencies: - '@types/webpack': 4.41.24 - transitivePeerDependencies: - - '@types/node' - - webpack - '@rushstack/stream-collator@4.0.259(@types/node@20.4.1)': dependencies: '@rushstack/node-core-library': 3.59.6(@types/node@20.4.1) @@ -21919,14 +21454,6 @@ snapshots: '@types/webpack': 4.41.24 webpack: 4.47.0(webpack-cli@4.6.0) - '@rushstack/webpack-plugin-utilities@0.2.36(@types/webpack@4.41.33)(webpack@4.47.0(webpack-cli@4.6.0))': - dependencies: - memfs: 3.4.3 - webpack-merge: 5.8.0 - optionalDependencies: - '@types/webpack': 4.41.33 - webpack: 4.47.0(webpack-cli@4.6.0) - '@rushstack/webpack-plugin-utilities@0.3.7(@types/webpack@4.41.24)(webpack@4.47.0(webpack-cli@4.6.0))': dependencies: memfs: 3.4.3 @@ -21935,14 +21462,6 @@ snapshots: '@types/webpack': 4.41.24 webpack: 4.47.0(webpack-cli@4.6.0) - '@rushstack/webpack-plugin-utilities@0.3.7(@types/webpack@4.41.24)(webpack@4.47.0)': - dependencies: - memfs: 3.4.3 - webpack-merge: 5.8.0 - optionalDependencies: - '@types/webpack': 4.41.24 - webpack: 4.47.0 - '@rushstack/webpack4-localization-plugin@0.17.46(@rushstack/set-webpack-public-path-plugin@4.0.15(@types/node@20.4.1)(@types/webpack@4.41.24)(webpack@4.44.2))(@types/node@20.4.1)(@types/webpack@4.41.24)(webpack@4.47.0(webpack-cli@4.6.0))': dependencies: '@rushstack/localization-utilities': 0.8.83(@types/node@20.4.1) @@ -21952,23 +21471,10 @@ snapshots: minimatch: 3.0.8 webpack: 4.47.0(webpack-cli@4.6.0) optionalDependencies: - '@rushstack/set-webpack-public-path-plugin': 4.0.15(@types/node@20.4.1)(@types/webpack@4.41.24)(webpack@4.44.2) + '@rushstack/set-webpack-public-path-plugin': 4.0.15(@types/node@20.4.1)(@types/webpack@4.41.24)(webpack@4.47.0(webpack-cli@4.6.0)) '@types/node': 20.4.1 '@types/webpack': 4.41.24 - '@rushstack/webpack4-localization-plugin@0.17.46(@rushstack/set-webpack-public-path-plugin@4.0.15(@types/node@20.4.1)(@types/webpack@4.41.33)(webpack@4.47.0(webpack-cli@4.6.0)))(@types/node@20.4.1)(@types/webpack@4.41.33)(webpack@4.47.0(webpack-cli@4.6.0))': - dependencies: - '@rushstack/localization-utilities': 0.8.83(@types/node@20.4.1) - '@rushstack/node-core-library': 3.59.7(@types/node@20.4.1) - '@types/tapable': 1.0.6 - loader-utils: 1.4.2 - minimatch: 3.0.8 - webpack: 4.47.0(webpack-cli@4.6.0) - optionalDependencies: - '@rushstack/set-webpack-public-path-plugin': 4.0.15(@types/node@20.4.1)(@types/webpack@4.41.33)(webpack@4.47.0(webpack-cli@4.6.0)) - '@types/node': 20.4.1 - '@types/webpack': 4.41.33 - '@rushstack/webpack4-localization-plugin@0.18.7(@rushstack/set-webpack-public-path-plugin@4.1.7(@types/node@20.4.1)(@types/webpack@4.41.24)(webpack@4.47.0(webpack-cli@4.6.0)))(@types/node@20.4.1)(@types/webpack@4.41.24)(webpack@4.47.0(webpack-cli@4.6.0))': dependencies: '@rushstack/localization-utilities': 0.9.7(@types/node@20.4.1) @@ -21982,19 +21488,6 @@ snapshots: '@types/node': 20.4.1 '@types/webpack': 4.41.24 - '@rushstack/webpack4-localization-plugin@0.18.7(@rushstack/set-webpack-public-path-plugin@4.1.7(@types/node@20.4.1)(@types/webpack@4.41.24)(webpack@4.47.0))(@types/node@20.4.1)(@types/webpack@4.41.24)(webpack@4.47.0)': - dependencies: - '@rushstack/localization-utilities': 0.9.7(@types/node@20.4.1) - '@rushstack/node-core-library': 3.61.0(@types/node@20.4.1) - '@types/tapable': 1.0.6 - loader-utils: 1.4.2 - minimatch: 3.0.8 - webpack: 4.47.0 - optionalDependencies: - '@rushstack/set-webpack-public-path-plugin': 4.1.7(@types/node@20.4.1)(@types/webpack@4.41.24)(webpack@4.47.0) - '@types/node': 20.4.1 - '@types/webpack': 4.41.24 - '@rushstack/webpack4-module-minifier-plugin@0.12.35(@types/node@20.4.1)(@types/webpack-sources@3.2.0)(@types/webpack@4.41.24)(webpack-sources@1.4.3)(webpack@4.47.0(webpack-cli@4.6.0))': dependencies: '@rushstack/module-minifier': 0.3.38(@types/node@20.4.1) @@ -22008,19 +21501,6 @@ snapshots: '@types/webpack': 4.41.24 '@types/webpack-sources': 3.2.0 - '@rushstack/webpack4-module-minifier-plugin@0.12.35(@types/node@20.4.1)(@types/webpack-sources@3.2.0)(@types/webpack@4.41.33)(webpack-sources@1.4.3)(webpack@4.47.0(webpack-cli@4.6.0))': - dependencies: - '@rushstack/module-minifier': 0.3.38(@types/node@20.4.1) - '@rushstack/worker-pool': 0.3.37(@types/node@20.4.1) - '@types/tapable': 1.0.6 - tapable: 1.1.3 - webpack: 4.47.0(webpack-cli@4.6.0) - webpack-sources: 1.4.3 - optionalDependencies: - '@types/node': 20.4.1 - '@types/webpack': 4.41.33 - '@types/webpack-sources': 3.2.0 - '@rushstack/webpack4-module-minifier-plugin@0.13.7(@types/node@20.4.1)(@types/webpack-sources@3.2.0)(@types/webpack@4.41.24)(webpack-sources@1.4.3)(webpack@4.47.0(webpack-cli@4.6.0))': dependencies: '@rushstack/module-minifier': 0.4.7(@types/node@20.4.1) @@ -22034,19 +21514,6 @@ snapshots: '@types/webpack': 4.41.24 '@types/webpack-sources': 3.2.0 - '@rushstack/webpack4-module-minifier-plugin@0.13.7(@types/node@20.4.1)(@types/webpack-sources@3.2.0)(@types/webpack@4.41.24)(webpack-sources@1.4.3)(webpack@4.47.0)': - dependencies: - '@rushstack/module-minifier': 0.4.7(@types/node@20.4.1) - '@rushstack/worker-pool': 0.4.7(@types/node@20.4.1) - '@types/tapable': 1.0.6 - tapable: 1.1.3 - webpack: 4.47.0 - webpack-sources: 1.4.3 - optionalDependencies: - '@types/node': 20.4.1 - '@types/webpack': 4.41.24 - '@types/webpack-sources': 3.2.0 - '@rushstack/worker-pool@0.3.37(@types/node@20.4.1)': optionalDependencies: '@types/node': 20.4.1 @@ -22765,10 +22232,6 @@ snapshots: dependencies: defer-to-connect: 1.1.3 - '@tailwindcss/container-queries@0.1.1(tailwindcss@3.2.4(postcss@7.0.38)(ts-node@10.9.2(@swc/core@1.3.89(@swc/helpers@0.5.6))(@types/node@20.4.1)(typescript@4.9.5)))': - dependencies: - tailwindcss: 3.2.4(postcss@7.0.38)(ts-node@10.9.2(@swc/core@1.3.89(@swc/helpers@0.5.6))(@types/node@20.4.1)(typescript@4.9.5)) - '@tailwindcss/container-queries@0.1.1(tailwindcss@3.2.4(postcss@8.4.31)(ts-node@10.9.2(@swc/core@1.3.89(@swc/helpers@0.5.6))(@types/node@18.19.17)(typescript@4.9.5)))': dependencies: tailwindcss: 3.2.4(postcss@8.4.31)(ts-node@10.9.2(@swc/core@1.3.89(@swc/helpers@0.5.6))(@types/node@18.19.17)(typescript@4.9.5)) @@ -22777,11 +22240,6 @@ snapshots: dependencies: tailwindcss: 3.2.4(postcss@8.4.31)(ts-node@10.9.2(@swc/core@1.3.89(@swc/helpers@0.5.6))(@types/node@20.4.1)(typescript@4.9.5)) - '@tailwindcss/forms@0.5.3(tailwindcss@3.2.4(postcss@7.0.38)(ts-node@10.9.2(@swc/core@1.3.89(@swc/helpers@0.5.6))(@types/node@20.4.1)(typescript@4.9.5)))': - dependencies: - mini-svg-data-uri: 1.4.4 - tailwindcss: 3.2.4(postcss@7.0.38)(ts-node@10.9.2(@swc/core@1.3.89(@swc/helpers@0.5.6))(@types/node@20.4.1)(typescript@4.9.5)) - '@tailwindcss/forms@0.5.3(tailwindcss@3.2.4(postcss@8.4.31)(ts-node@10.9.2(@swc/core@1.3.89(@swc/helpers@0.5.6))(@types/node@18.19.17)(typescript@4.9.5)))': dependencies: mini-svg-data-uri: 1.4.4 @@ -22797,10 +22255,6 @@ snapshots: mini-svg-data-uri: 1.4.4 tailwindcss: 3.4.4(ts-node@10.9.2(@swc/core@1.3.89(@swc/helpers@0.5.6))(@types/node@20.4.1)(typescript@5.3.3)) - '@tailwindcss/line-clamp@0.4.4(tailwindcss@3.2.4(postcss@7.0.38)(ts-node@10.9.2(@swc/core@1.3.89(@swc/helpers@0.5.6))(@types/node@20.4.1)(typescript@4.9.5)))': - dependencies: - tailwindcss: 3.2.4(postcss@7.0.38)(ts-node@10.9.2(@swc/core@1.3.89(@swc/helpers@0.5.6))(@types/node@20.4.1)(typescript@4.9.5)) - '@tailwindcss/line-clamp@0.4.4(tailwindcss@3.2.4(postcss@8.4.31)(ts-node@10.9.2(@swc/core@1.3.89(@swc/helpers@0.5.6))(@types/node@18.19.17)(typescript@4.9.5)))': dependencies: tailwindcss: 3.2.4(postcss@8.4.31)(ts-node@10.9.2(@swc/core@1.3.89(@swc/helpers@0.5.6))(@types/node@18.19.17)(typescript@4.9.5)) @@ -23080,7 +22534,7 @@ snapshots: '@types/keyv@3.1.4': dependencies: - '@types/node': 18.19.17 + '@types/node': 18.19.47 '@types/koa-compose@3.2.5': dependencies: @@ -23172,7 +22626,7 @@ snapshots: '@types/nodemon@1.19.6': dependencies: - '@types/node': 18.19.17 + '@types/node': 18.19.47 '@types/normalize-package-data@2.4.1': {} @@ -23220,7 +22674,7 @@ snapshots: '@types/responselike@1.0.0': dependencies: - '@types/node': 18.19.17 + '@types/node': 18.19.47 '@types/retry@0.12.0': {} @@ -24119,7 +23573,7 @@ snapshots: ip: 2.0.1 nanocolors: 0.2.13 open: 8.4.2 - portfinder: 1.0.32(supports-color@6.1.0) + portfinder: 1.0.32 transitivePeerDependencies: - bufferutil - supports-color @@ -24300,7 +23754,7 @@ snapshots: diff: 5.1.0 globby: 11.1.0 nanocolors: 0.2.13 - portfinder: 1.0.32(supports-color@6.1.0) + portfinder: 1.0.32 source-map: 0.7.4 transitivePeerDependencies: - bufferutil @@ -25046,16 +24500,6 @@ snapshots: postcss: 8.4.31 postcss-value-parser: 4.2.0 - autoprefixer@10.4.16(postcss@7.0.38): - dependencies: - browserslist: 4.23.0 - caniuse-lite: 1.0.30001588 - fraction.js: 4.3.7 - normalize-range: 0.1.2 - picocolors: 1.0.0 - postcss: 7.0.38 - postcss-value-parser: 4.2.0 - autoprefixer@10.4.16(postcss@8.4.31): dependencies: browserslist: 4.23.0 @@ -26474,23 +25918,6 @@ snapshots: transitivePeerDependencies: - bluebird - copy-webpack-plugin@6.0.4(webpack@4.47.0): - dependencies: - cacache: 15.3.0 - fast-glob: 3.3.2 - find-cache-dir: 3.3.2 - glob-parent: 5.1.2 - globby: 11.1.0 - loader-utils: 2.0.4 - normalize-path: 3.0.0 - p-limit: 3.1.0 - schema-utils: 2.7.1 - serialize-javascript: 4.0.0 - webpack: 4.47.0 - webpack-sources: 1.4.3 - transitivePeerDependencies: - - bluebird - copy-webpack-plugin@6.4.0(webpack@4.44.2): dependencies: cacache: 15.3.0 @@ -26586,7 +26013,7 @@ snapshots: cross-fetch@4.0.0(encoding@0.1.13): dependencies: - node-fetch: 2.6.12(encoding@0.1.13) + node-fetch: 2.7.0(encoding@0.1.13) transitivePeerDependencies: - encoding @@ -26654,22 +26081,6 @@ snapshots: schema-utils: 2.7.1 webpack: 4.47.0(webpack-cli@4.6.0) - css-loader@3.4.2(webpack@4.47.0): - dependencies: - camelcase: 5.3.1 - cssesc: 3.0.0 - icss-utils: 4.1.1 - loader-utils: 1.4.2 - normalize-path: 3.0.0 - postcss: 7.0.38 - postcss-modules-extract-imports: 2.0.0 - postcss-modules-local-by-default: 3.0.3 - postcss-modules-scope: 2.2.0 - postcss-modules-values: 3.0.0 - postcss-value-parser: 4.2.0 - schema-utils: 2.7.1 - webpack: 4.47.0 - css-loader@5.2.4(webpack@4.44.2): dependencies: camelcase: 6.3.0 @@ -28333,12 +27744,6 @@ snapshots: schema-utils: 2.7.1 webpack: 4.47.0(webpack-cli@4.6.0) - file-loader@6.1.0(webpack@4.47.0): - dependencies: - loader-utils: 2.0.4 - schema-utils: 2.7.1 - webpack: 4.47.0 - file-loader@6.2.0(webpack@4.44.2): dependencies: loader-utils: 2.0.4 @@ -30178,7 +29583,7 @@ snapshots: isomorphic-fetch@3.0.0(encoding@0.1.13): dependencies: - node-fetch: 2.6.12(encoding@0.1.13) + node-fetch: 2.7.0(encoding@0.1.13) whatwg-fetch: 3.6.2 transitivePeerDependencies: - encoding @@ -30423,10 +29828,7 @@ snapshots: pretty-format: 25.5.0 throat: 5.0.0 transitivePeerDependencies: - - bufferutil - - canvas - supports-color - - utf-8-validate jest-leak-detector@25.5.0: dependencies: @@ -30945,7 +30347,7 @@ snapshots: koa-static@5.0.0: dependencies: - debug: 3.2.7(supports-color@6.1.0) + debug: 3.2.7(supports-color@5.5.0) koa-send: 5.0.1 transitivePeerDependencies: - supports-color @@ -33462,6 +32864,14 @@ snapshots: dependencies: '@babel/runtime': 7.22.6 + portfinder@1.0.32: + dependencies: + async: 2.6.4 + debug: 3.2.7(supports-color@5.5.0) + mkdirp: 0.5.6 + transitivePeerDependencies: + - supports-color + portfinder@1.0.32(supports-color@6.1.0): dependencies: async: 2.6.4 @@ -33625,13 +33035,6 @@ snapshots: postcss: 8.4.31 postcss-value-parser: 4.2.0 - postcss-import@14.1.0(postcss@7.0.38): - dependencies: - postcss: 7.0.38 - postcss-value-parser: 4.2.0 - read-cache: 1.0.0 - resolve: 1.22.2 - postcss-import@14.1.0(postcss@8.4.31): dependencies: postcss: 8.4.31 @@ -33650,11 +33053,6 @@ snapshots: dependencies: postcss: 8.4.31 - postcss-js@4.0.1(postcss@7.0.38): - dependencies: - camelcase-css: 2.0.1 - postcss: 7.0.38 - postcss-js@4.0.1(postcss@8.4.31): dependencies: camelcase-css: 2.0.1 @@ -33675,14 +33073,6 @@ snapshots: transitivePeerDependencies: - supports-color - postcss-load-config@3.1.4(postcss@7.0.38)(ts-node@10.9.2(@swc/core@1.3.89(@swc/helpers@0.5.6))(@types/node@20.4.1)(typescript@4.9.5)): - dependencies: - lilconfig: 2.1.0 - yaml: 1.10.2 - optionalDependencies: - postcss: 7.0.38 - ts-node: 10.9.2(@swc/core@1.3.89(@swc/helpers@0.5.6))(@types/node@20.4.1)(typescript@4.9.5) - postcss-load-config@3.1.4(postcss@8.4.31)(ts-node@10.9.2(@swc/core@1.3.89(@swc/helpers@0.5.6))(@types/node@18.19.17)(typescript@4.9.5)): dependencies: lilconfig: 2.1.0 @@ -33727,16 +33117,6 @@ snapshots: semver: 7.5.4 webpack: 4.47.0(webpack-cli@4.6.0) - postcss-loader@4.2.0(postcss@8.4.31)(webpack@4.47.0): - dependencies: - cosmiconfig: 7.1.0 - klona: 2.0.6 - loader-utils: 2.0.4 - postcss: 8.4.31 - schema-utils: 3.3.0 - semver: 7.5.4 - webpack: 4.47.0 - postcss-loader@7.0.1(postcss@8.4.31)(webpack@5.88.1): dependencies: cosmiconfig: 7.1.0 @@ -33898,11 +33278,6 @@ snapshots: postcss: 7.0.38 string-hash: 1.1.3 - postcss-nested@6.0.0(postcss@7.0.38): - dependencies: - postcss: 7.0.38 - postcss-selector-parser: 6.0.13 - postcss-nested@6.0.0(postcss@8.4.31): dependencies: postcss: 8.4.31 @@ -35588,6 +34963,17 @@ snapshots: transitivePeerDependencies: - supports-color + sockjs-client@1.6.1: + dependencies: + debug: 3.2.7(supports-color@5.5.0) + eventsource: 2.0.2 + faye-websocket: 0.11.4 + inherits: 2.0.4 + url-parse: 1.5.10 + transitivePeerDependencies: + - supports-color + optional: true + sockjs-client@1.6.1(supports-color@6.1.0): dependencies: debug: 3.2.7(supports-color@6.1.0) @@ -35659,16 +35045,6 @@ snapshots: webpack: 4.47.0(webpack-cli@4.6.0) whatwg-mimetype: 2.3.0 - source-map-loader@1.1.3(webpack@4.47.0): - dependencies: - abab: 2.0.6 - iconv-lite: 0.6.3 - loader-utils: 2.0.4 - schema-utils: 3.3.0 - source-map: 0.6.1 - webpack: 4.47.0 - whatwg-mimetype: 2.3.0 - source-map-resolve@0.5.3: dependencies: atob: 2.1.2 @@ -35801,70 +35177,6 @@ snapshots: - webpack-hot-middleware - webpack-plugin-serve - spfx-fast-serve-helpers@1.18.0(@microsoft/load-themed-styles@2.0.63)(@types/node@20.4.1)(@types/webpack-sources@3.2.0)(@types/webpack@4.41.33)(encoding@0.1.13)(eslint@8.33.0)(sockjs-client@1.6.1)(type-fest@2.19.0)(typescript@4.9.5)(webpack-hot-middleware@2.25.4): - dependencies: - '@microsoft/loader-load-themed-styles': 2.0.45(@microsoft/load-themed-styles@2.0.63)(@types/webpack@4.41.33) - '@microsoft/spfx-heft-plugins': 1.18.0(@types/node@20.4.1)(@types/webpack-sources@3.2.0)(@types/webpack@4.41.33)(encoding@0.1.13)(webpack-cli@4.6.0) - '@pmmmwh/react-refresh-webpack-plugin': 0.5.7(@types/webpack@4.41.33)(react-refresh@0.14.0)(sockjs-client@1.6.1)(type-fest@2.19.0)(webpack-dev-server@3.11.2)(webpack-hot-middleware@2.25.4)(webpack@4.44.2) - '@types/copy-webpack-plugin': 6.4.3 - '@types/loader-utils': 2.0.2 - '@types/webpack-dev-server': 3.11.4 - '@types/yargs': 6.6.0 - autoprefixer: 9.8.8 - clean-css-loader: 3.0.0(webpack@4.44.2) - colors: 1.4.0 - copy-webpack-plugin: 6.4.0(webpack@4.44.2) - css-loader: 5.2.4(webpack@4.44.2) - del: 6.0.0 - eslint-webpack-plugin: 2.5.4(eslint@8.33.0)(webpack@4.44.2) - file-loader: 6.2.0(webpack@4.44.2) - fork-ts-checker-webpack-plugin: 6.4.0(eslint@8.33.0)(typescript@4.9.5)(webpack@4.44.2) - get-port: 5.1.1 - globby: 11.0.3 - kill-port: 1.6.1 - loader-utils: 2.0.0 - node-fetch: 2.6.1 - postcss: 7.0.38 - postcss-loader: 4.2.0(postcss@7.0.38)(webpack@4.44.2) - react-refresh: 0.14.0 - react-refresh-typescript: 2.0.6(react-refresh@0.14.0)(typescript@4.9.5) - sass: 1.44.0 - sass-loader: 9.0.3(sass@1.44.0)(webpack@4.44.2) - spfx-css-modules-typescript-loader: 4.0.6 - style-loader: 1.1.3(webpack@4.44.2) - ts-loader: 8.1.0(typescript@4.9.5)(webpack@4.44.2) - tsconfig: 7.0.0 - tsconfig-paths-webpack-plugin: 3.5.2 - webpack: 4.44.2(webpack-cli@4.6.0) - webpack-cli: 4.6.0(webpack-dev-server@3.11.2)(webpack@4.44.2) - webpack-dev-server: 3.11.2(webpack-cli@4.6.0)(webpack@4.44.2) - webpack-merge: 5.7.3 - yargs: 4.6.0 - transitivePeerDependencies: - - '@microsoft/load-themed-styles' - - '@types/node' - - '@types/webpack' - - '@types/webpack-sources' - - '@webpack-cli/generators' - - '@webpack-cli/migrate' - - bluebird - - bufferutil - - debug - - encoding - - eslint - - fibers - - node-sass - - sockjs-client - - supports-color - - type-fest - - typescript - - utf-8-validate - - vue-template-compiler - - webpack-bundle-analyzer - - webpack-command - - webpack-hot-middleware - - webpack-plugin-serve - spfx-uifabric-themes@0.9.0: {} split-string@3.1.0: @@ -36321,34 +35633,6 @@ snapshots: typical: 7.1.1 wordwrapjs: 5.1.0 - tailwindcss@3.2.4(postcss@7.0.38)(ts-node@10.9.2(@swc/core@1.3.89(@swc/helpers@0.5.6))(@types/node@20.4.1)(typescript@4.9.5)): - dependencies: - arg: 5.0.2 - chokidar: 3.5.3 - color-name: 1.1.4 - detective: 5.2.1 - didyoumean: 1.2.2 - dlv: 1.1.3 - fast-glob: 3.3.2 - glob-parent: 6.0.2 - is-glob: 4.0.3 - lilconfig: 2.1.0 - micromatch: 4.0.5 - normalize-path: 3.0.0 - object-hash: 3.0.0 - picocolors: 1.0.0 - postcss: 7.0.38 - postcss-import: 14.1.0(postcss@7.0.38) - postcss-js: 4.0.1(postcss@7.0.38) - postcss-load-config: 3.1.4(postcss@7.0.38)(ts-node@10.9.2(@swc/core@1.3.89(@swc/helpers@0.5.6))(@types/node@20.4.1)(typescript@4.9.5)) - postcss-nested: 6.0.0(postcss@7.0.38) - postcss-selector-parser: 6.0.13 - postcss-value-parser: 4.2.0 - quick-lru: 5.1.1 - resolve: 1.22.2 - transitivePeerDependencies: - - ts-node - tailwindcss@3.2.4(postcss@8.4.31)(ts-node@10.9.2(@swc/core@1.3.89(@swc/helpers@0.5.6))(@types/node@18.19.17)(typescript@4.9.5)): dependencies: arg: 5.0.2 @@ -36557,19 +35841,6 @@ snapshots: webpack-sources: 1.4.3 worker-farm: 1.7.0 - terser-webpack-plugin@1.4.5(webpack@4.47.0): - dependencies: - cacache: 12.0.4 - find-cache-dir: 2.1.0 - is-wsl: 1.1.0 - schema-utils: 1.0.0 - serialize-javascript: 4.0.0 - source-map: 0.6.1 - terser: 4.8.1 - webpack: 4.47.0 - webpack-sources: 1.4.3 - worker-farm: 1.7.0 - terser-webpack-plugin@5.3.9(@swc/core@1.3.89(@swc/helpers@0.5.6))(esbuild@0.18.20)(webpack@5.88.1): dependencies: '@jridgewell/trace-mapping': 0.3.18 @@ -36660,7 +35931,7 @@ snapshots: tiny-lr@1.1.1: dependencies: body: 5.1.0 - debug: 3.2.7(supports-color@6.1.0) + debug: 3.2.7(supports-color@5.5.0) faye-websocket: 0.10.0 livereload-js: 2.4.0 object-assign: 4.1.1 @@ -37551,15 +36822,6 @@ snapshots: schema-utils: 4.2.0 webpack: 4.47.0(webpack-cli@4.6.0) - webpack-dev-middleware@5.3.3(webpack@4.47.0): - dependencies: - colorette: 2.0.20 - memfs: 3.5.3 - mime-types: 2.1.35 - range-parser: 1.2.1 - schema-utils: 4.2.0 - webpack: 4.47.0 - webpack-dev-middleware@5.3.3(webpack@5.88.1): dependencies: colorette: 2.0.20 @@ -37701,44 +36963,6 @@ snapshots: - supports-color - utf-8-validate - webpack-dev-server@4.9.3(webpack@4.47.0): - dependencies: - '@types/bonjour': 3.5.10 - '@types/connect-history-api-fallback': 1.5.0 - '@types/express': 4.17.17 - '@types/serve-index': 1.9.1 - '@types/serve-static': 1.15.2 - '@types/sockjs': 0.3.33 - '@types/ws': 8.5.5 - ansi-html-community: 0.0.8 - bonjour-service: 1.1.1 - chokidar: 3.5.3 - colorette: 2.0.20 - compression: 1.7.4(supports-color@6.1.0) - connect-history-api-fallback: 2.0.0 - default-gateway: 6.0.3 - express: 4.19.2(supports-color@6.1.0) - graceful-fs: 4.2.11 - html-entities: 2.4.0 - http-proxy-middleware: 2.0.6(@types/express@4.17.17) - ipaddr.js: 2.1.0 - open: 8.4.2 - p-retry: 4.6.2 - rimraf: 3.0.2 - schema-utils: 4.2.0 - selfsigned: 2.1.1 - serve-index: 1.9.1(supports-color@6.1.0) - sockjs: 0.3.24 - spdy: 4.0.2(supports-color@6.1.0) - webpack: 4.47.0 - webpack-dev-middleware: 5.3.3(webpack@4.47.0) - ws: 8.16.0 - transitivePeerDependencies: - - bufferutil - - debug - - supports-color - - utf-8-validate - webpack-hot-middleware@2.25.4: dependencies: ansi-html-community: 0.0.8 @@ -37804,34 +37028,6 @@ snapshots: transitivePeerDependencies: - supports-color - webpack@4.47.0: - dependencies: - '@webassemblyjs/ast': 1.9.0 - '@webassemblyjs/helper-module-context': 1.9.0 - '@webassemblyjs/wasm-edit': 1.9.0 - '@webassemblyjs/wasm-parser': 1.9.0 - acorn: 6.4.2 - ajv: 6.12.6 - ajv-keywords: 3.5.2(ajv@6.12.6) - chrome-trace-event: 1.0.3 - enhanced-resolve: 4.5.0 - eslint-scope: 4.0.3 - json-parse-better-errors: 1.0.2 - loader-runner: 2.4.0 - loader-utils: 1.4.2 - memory-fs: 0.4.1 - micromatch: 3.1.10(supports-color@6.1.0) - mkdirp: 0.5.6 - neo-async: 2.6.2 - node-libs-browser: 2.2.1 - schema-utils: 1.0.0 - tapable: 1.1.3 - terser-webpack-plugin: 1.4.5(webpack@4.47.0) - watchpack: 1.7.5 - webpack-sources: 1.4.3 - transitivePeerDependencies: - - supports-color - webpack@4.47.0(webpack-cli@4.6.0): dependencies: '@webassemblyjs/ast': 1.9.0