From 0be98c6f48e6e206e28661435387fa7caeb0fb77 Mon Sep 17 00:00:00 2001 From: Nishkalank Bezawada <47456098+NishkalankBezawada@users.noreply.github.com> Date: Fri, 28 Apr 2023 18:40:53 +0200 Subject: [PATCH 01/90] New control - ViewPicker - Fix for Issue 1439 --- .../documentation/docs/controls/ViewPicker.md | 72 +++++++ package-lock.json | 112 +++++------ src/ViewPicker.ts | 1 + src/common/SPEntities.ts | 12 ++ src/common/utilities/GeneralHelper.ts | 13 ++ src/controls/viewPicker/IViewPicker.ts | 100 ++++++++++ src/controls/viewPicker/ViewPicker.tsx | 180 ++++++++++++++++++ src/controls/viewPicker/index.ts | 2 + src/services/ISPViewPickerService.ts | 5 + src/services/SPViewPickerService.ts | 88 +++++++++ .../controlsTest/components/ControlsTest.tsx | 21 +- 11 files changed, 550 insertions(+), 56 deletions(-) create mode 100644 docs/documentation/docs/controls/ViewPicker.md create mode 100644 src/ViewPicker.ts create mode 100644 src/controls/viewPicker/IViewPicker.ts create mode 100644 src/controls/viewPicker/ViewPicker.tsx create mode 100644 src/controls/viewPicker/index.ts create mode 100644 src/services/ISPViewPickerService.ts create mode 100644 src/services/SPViewPickerService.ts diff --git a/docs/documentation/docs/controls/ViewPicker.md b/docs/documentation/docs/controls/ViewPicker.md new file mode 100644 index 000000000..895c5aae8 --- /dev/null +++ b/docs/documentation/docs/controls/ViewPicker.md @@ -0,0 +1,72 @@ +# ViewPicker control + +This control allows you to select available views from lists/libraries of the current site. + +Here is an example of the control: + +![ViewPicker initial](../assets/ViewPicker1.PNG) + +`ViewPicker` selection mode: + +![ViewPicker selection](../assets/ViewPicker2.png) + + +## How to use this control in your solutions + +- Check that you installed the `@pnp/spfx-controls-react` dependency. Check out the [getting started](../../#getting-started) page for more information about installing the dependency. +- Import the control into your component: + + +```TypeScript +import { ViewPicker } from "@pnp/spfx-controls-react/lib/ViewPicker"; +``` + +- Use the `ViewPicker` control in your code as follows: + +```TypeScript + +``` + +- The `onChange` change event returns the selected view(s) and can be implemented as follows in your webpart: + +```TypeScript +private onViewPickerChange = (newValue: string | string[]) => { + console.log("newView:", newValue); +} +``` + + +## Implementation + +The `ViewPicker` control can be configured with the following properties + +| Property | What is it used for? +| --------------- | --- +| context (Mandatory) | Context of the current web part +| className (Not mandatory) | If provided, additional class name to provide on the dropdown element. +| deferredValidationTime (Not mandatory) | Custom Field will start to validate after users stop typing for `deferredValidationTime` milliseconds. Default value is 200. +| disabled (Not mandatory) | Whether the property pane field is enabled or not. +| filter (Not Mandatory) | Filter views from Odata query +| label (mandatory) | Property field label displayed on top +| listId (Not mandatory) | The List Id of the list where you want to get the views. +| placeholder (Not mandatory) | Input placeholder text. Displayed until option is selected. +| orderBy (Not mandatory) | Specify the property on which you want to order the retrieve set of views. orderBy viewId and by title +| selectedView (Not Mandatory) | Initial selected view of the control. +| showBlankOption (mandatory) | Whether or not to show a blank option. Default false. +| viewsToExclude (Not mandatory) | Defines view titles which should be excluded from the view picker control. +| webAbsoluteUrl (Not mandatory) | Absolute Web Url of target site (user requires permissions). +| onViewPickerPropertyChange (Mandatory) | Defines a change function to raise when the selected value changed. +| onViewsRetrieved (Not mandatory) | Callback that is called before the dropdown is populated. + + +Enum `PropertyFieldViewPickerOrderBy` + +| Value | +| ---- | +| Id | +| Title | diff --git a/package-lock.json b/package-lock.json index 39546a4aa..9aadeeae9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2899,23 +2899,6 @@ } } }, - "@microsoft/microsoft-graph-clientv1": { - "version": "npm:@microsoft/microsoft-graph-client@1.7.2-spfx", - "resolved": "https://registry.npmjs.org/@microsoft/microsoft-graph-client/-/microsoft-graph-client-1.7.2-spfx.tgz", - "integrity": "sha512-BQN50r3tohWYOaQ0de7LJ5eCRjI6eg4RQqLhGDlgRmZIZhWzH0bhR6QBMmmxtYtwKWifhPhJSxYDW+cP67TJVw==", - "requires": { - "es6-promise": "^4.2.6", - "isomorphic-fetch": "^3.0.0", - "tslib": "^1.9.3" - }, - "dependencies": { - "tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" - } - } - }, "@microsoft/microsoft-graph-types": { "version": "2.25.0", "resolved": "https://registry.npmjs.org/@microsoft/microsoft-graph-types/-/microsoft-graph-types-2.25.0.tgz", @@ -3799,6 +3782,25 @@ "@microsoft/sp-http-base": "1.16.1", "@microsoft/sp-http-msgraph": "1.16.1", "tslib": "2.3.1" + }, + "dependencies": { + "@microsoft/microsoft-graph-clientv1": { + "version": "npm:@microsoft/microsoft-graph-client@1.7.2-spfx", + "resolved": "https://registry.npmjs.org/@microsoft/microsoft-graph-client/-/microsoft-graph-client-1.7.2-spfx.tgz", + "integrity": "sha512-BQN50r3tohWYOaQ0de7LJ5eCRjI6eg4RQqLhGDlgRmZIZhWzH0bhR6QBMmmxtYtwKWifhPhJSxYDW+cP67TJVw==", + "requires": { + "es6-promise": "^4.2.6", + "isomorphic-fetch": "^3.0.0", + "tslib": "^1.9.3" + }, + "dependencies": { + "tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" + } + } + } } }, "@microsoft/sp-http-base": { @@ -3817,6 +3819,44 @@ "msalBrowserLegacy": "npm:@azure/msal-browser@2.22.0", "msalLegacy": "npm:msal@1.4.12", "tslib": "2.3.1" + }, + "dependencies": { + "@azure/msal-common": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/@azure/msal-common/-/msal-common-6.4.0.tgz", + "integrity": "sha512-WZdgq9f9O8cbxGzdRwLLMM5xjmLJ2mdtuzgXeiGxIRkVVlJ9nZ6sWnDFKa2TX8j72UXD1IfL0p/RYNoTXYoGfg==" + }, + "@microsoft/teams-js-v2": { + "version": "npm:@microsoft/teams-js@2.4.1", + "resolved": "https://registry.npmjs.org/@microsoft/teams-js/-/teams-js-2.4.1.tgz", + "integrity": "sha512-rHOVt3Duw1HJrsZq0FO09qMGVGI5eg6hkVKIxsuyJQ5WMPaGMAcF5A0QlXBzVwa9cocNyv8JYeMeJAh+svnLnw==", + "requires": { + "debug": "4.3.3" + } + }, + "msalBrowserLegacy": { + "version": "npm:@azure/msal-browser@2.22.0", + "resolved": "https://registry.npmjs.org/@azure/msal-browser/-/msal-browser-2.22.0.tgz", + "integrity": "sha512-ZpnbnzjYGRGHjWDPOLjSp47CQvhK927+W9avtLoNNCMudqs2dBfwj76lnJwObDE7TAKmCUueTiieglBiPb1mgQ==", + "requires": { + "@azure/msal-common": "^6.1.0" + } + }, + "msalLegacy": { + "version": "npm:msal@1.4.12", + "resolved": "https://registry.npmjs.org/msal/-/msal-1.4.12.tgz", + "integrity": "sha512-gjupwQ6nvNL6mZkl5NIXyUmZhTiEMRu5giNdgHMh8l5EPOnV2Xj6nukY1NIxFacSTkEYUSDB47Pej9GxDYf+1w==", + "requires": { + "tslib": "^1.9.3" + }, + "dependencies": { + "tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" + } + } + } } }, "@microsoft/sp-http-msgraph": { @@ -4540,14 +4580,6 @@ "resolved": "https://registry.npmjs.org/@microsoft/teams-js/-/teams-js-1.12.1.tgz", "integrity": "sha512-BRy6vZOseN9F/MG0NWTojYpenuo9XlZ4AfAvwnsG+C36UDPPgW0skWlZ6ub+7RBPhOHcxz8sNg2uHOdGRebWkQ==" }, - "@microsoft/teams-js-v2": { - "version": "npm:@microsoft/teams-js@2.4.1", - "resolved": "https://registry.npmjs.org/@microsoft/teams-js/-/teams-js-2.4.1.tgz", - "integrity": "sha512-rHOVt3Duw1HJrsZq0FO09qMGVGI5eg6hkVKIxsuyJQ5WMPaGMAcF5A0QlXBzVwa9cocNyv8JYeMeJAh+svnLnw==", - "requires": { - "debug": "4.3.3" - } - }, "@microsoft/tsdoc": { "version": "0.12.24", "resolved": "https://registry.npmjs.org/@microsoft/tsdoc/-/tsdoc-0.12.24.tgz", @@ -18657,36 +18689,6 @@ } } }, - "msalBrowserLegacy": { - "version": "npm:@azure/msal-browser@2.22.0", - "resolved": "https://registry.npmjs.org/@azure/msal-browser/-/msal-browser-2.22.0.tgz", - "integrity": "sha512-ZpnbnzjYGRGHjWDPOLjSp47CQvhK927+W9avtLoNNCMudqs2dBfwj76lnJwObDE7TAKmCUueTiieglBiPb1mgQ==", - "requires": { - "@azure/msal-common": "^6.1.0" - }, - "dependencies": { - "@azure/msal-common": { - "version": "6.4.0", - "resolved": "https://registry.npmjs.org/@azure/msal-common/-/msal-common-6.4.0.tgz", - "integrity": "sha512-WZdgq9f9O8cbxGzdRwLLMM5xjmLJ2mdtuzgXeiGxIRkVVlJ9nZ6sWnDFKa2TX8j72UXD1IfL0p/RYNoTXYoGfg==" - } - } - }, - "msalLegacy": { - "version": "npm:msal@1.4.12", - "resolved": "https://registry.npmjs.org/msal/-/msal-1.4.12.tgz", - "integrity": "sha512-gjupwQ6nvNL6mZkl5NIXyUmZhTiEMRu5giNdgHMh8l5EPOnV2Xj6nukY1NIxFacSTkEYUSDB47Pej9GxDYf+1w==", - "requires": { - "tslib": "^1.9.3" - }, - "dependencies": { - "tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" - } - } - }, "mu2": { "version": "0.5.21", "resolved": "https://registry.npmjs.org/mu2/-/mu2-0.5.21.tgz", diff --git a/src/ViewPicker.ts b/src/ViewPicker.ts new file mode 100644 index 000000000..408513b95 --- /dev/null +++ b/src/ViewPicker.ts @@ -0,0 +1 @@ +export * from './controls/viewPicker/index'; \ No newline at end of file diff --git a/src/common/SPEntities.ts b/src/common/SPEntities.ts index 5d5bac307..531c89acc 100644 --- a/src/common/SPEntities.ts +++ b/src/common/SPEntities.ts @@ -206,3 +206,15 @@ export interface IUploadImageResult { ServerRelativeUrl: string; UniqueId: string; } + +export interface ISPView { + Id: string; + Title: string; +} + + /** + * Defines a collection of SharePoint list views + */ +export interface ISPViews { + value: ISPView[]; +} \ No newline at end of file diff --git a/src/common/utilities/GeneralHelper.ts b/src/common/utilities/GeneralHelper.ts index ed359782d..89a00f523 100644 --- a/src/common/utilities/GeneralHelper.ts +++ b/src/common/utilities/GeneralHelper.ts @@ -4,6 +4,7 @@ import * as strings from 'ControlStrings'; export const IMG_SUPPORTED_EXTENSIONS = ".gif,.jpg,.jpeg,.bmp,.dib,.tif,.tiff,.ico,.png,.jxr,.svg"; +import * as _ from '@microsoft/sp-lodash-subset'; /** * Helper with general methods to simplify some routines */ @@ -405,3 +406,15 @@ export function dateToNumber(date: string | number | Date): number { return dateObj.getTime(); } + +export const setPropertyValue = (properties: any, targetProperty: string, value: any): void => { // eslint-disable-line @typescript-eslint/no-explicit-any + if (!properties) { + return; + } + if (targetProperty.indexOf('.') === -1) { // simple prop + properties[targetProperty] = value; + } + else { + _.set(properties, targetProperty, value); + } +}; diff --git a/src/controls/viewPicker/IViewPicker.ts b/src/controls/viewPicker/IViewPicker.ts new file mode 100644 index 000000000..5e3159cb2 --- /dev/null +++ b/src/controls/viewPicker/IViewPicker.ts @@ -0,0 +1,100 @@ +import { BaseComponentContext } from '@microsoft/sp-component-base'; +import { ISPView } from "../../../src/common/SPEntities"; +import { IDropdownOption } from 'office-ui-fabric-react/lib/Dropdown'; + + +/** + * Enum for specifying how the views should be sorted + */ +export enum PropertyFieldViewPickerOrderBy { + Id = 1, + Title +} + +export interface IViewPickerProps { + /** + * Context of the current web part + */ + context: BaseComponentContext; + + /** + * If provided, additional class name to provide on the dropdown element. + */ + className?: string; + + /** + * Custom Field will start to validate after users stop typing for `deferredValidationTime` milliseconds. + * Default value is 200. + */ + deferredValidationTime?: number; + + /** + * Whether the property pane field is enabled or not. + */ + disabled?: boolean; + + /** + * Filter views from Odata query + */ + filter?: string; + + /** + * Property field label displayed on top + */ + label: string; + + /** + * The List Id of the list where you want to get the views + */ + listId?: string; + + /** + * Input placeholder text. Displayed until option is selected. + */ + placeholder?: string; + + /** + * Specify the property on which you want to order the retrieve set of views. + */ + orderBy?: PropertyFieldViewPickerOrderBy; + + /** + * Initial selected view of the control + */ + selectedView?: string; + + /** + * Whether or not to show a blank option. Default false. + */ + showBlankOption?: boolean; + + /** + * Defines view titles which should be excluded from the view picker control + */ + viewsToExclude?: string[]; + + /** + * Absolute Web Url of target site (user requires permissions) + */ + webAbsoluteUrl?: string; + + + + /** + * Defines a change function to raise when the selected value changed. + * Normally this function must be always defined with the 'this.onChange' + * method of the web part object. + */ + onChange : (newValue: string | string[]) => void; + /** + * Callback that is called before the dropdown is populated + */ + onViewsRetrieved?: (views: ISPView[]) => PromiseLike | ISPView[]; + +} + +export interface IViewPickerState { + results: IDropdownOption[]; + selectedKey?: string | string[]; + errorMessage?: string | string[]; +} \ No newline at end of file diff --git a/src/controls/viewPicker/ViewPicker.tsx b/src/controls/viewPicker/ViewPicker.tsx new file mode 100644 index 000000000..a81a019dc --- /dev/null +++ b/src/controls/viewPicker/ViewPicker.tsx @@ -0,0 +1,180 @@ +import * as React from 'react'; +import cloneDeep from 'lodash/cloneDeep'; +import { Dropdown, IDropdownOption, IDropdownProps } from 'office-ui-fabric-react/lib/Dropdown'; +import { Async } from 'office-ui-fabric-react/lib/Utilities'; +import { Label } from 'office-ui-fabric-react/lib/Label'; +import { Spinner, SpinnerSize } from 'office-ui-fabric-react/lib/Spinner'; +import * as telemetry from '../../common/telemetry'; +import { ISPService } from '../../services/ISPService'; +import { SPViewPickerService } from '../../services/SPViewPickerService'; +import { IViewPickerProps, IViewPickerState } from './IViewPicker'; +import { ISPView, ISPViews } from "../../common/SPEntities"; + + +// Empty view value +const EMPTY_VIEW_KEY = 'NO_VIEW_SELECTED'; + +export class ViewPicker extends React.Component { + private options: IDropdownOption[] = []; + private selectedKey: string| string[] = null; + private latestValidateValue: string; + private async: Async; + private delayedValidate: (value: string) => void; + + + constructor(props: IViewPickerProps){ + super(props); + + telemetry.track('ViewPicker'); + this.state = { + results: this.options + } + + this.async = new Async(this); + this.validate = this.validate.bind(this); + this.onChanged = this.onChanged.bind(this); + this.notifyAfterValidate = this.notifyAfterValidate.bind(this); + this.delayedValidate = this.async.debounce(this.validate, this.props.deferredValidationTime); + } + + + public componentDidMount(): void { + // Start retrieving the list views + this.loadViews(); + } + + public componentDidUpdate(prevProps: IViewPickerProps, _prevState: IViewPickerState): void { + if ( + this.props.listId !== prevProps.listId || + this.props.webAbsoluteUrl !== prevProps.webAbsoluteUrl || + this.props.orderBy !== prevProps.orderBy + ) { + this.loadViews(); + } + } + + /** + * Called when the component will unmount + */ + public componentWillUnmount(): void { + if (typeof this.async !== 'undefined') { + this.async.dispose(); + } + } + + private loadViews(): void { + + const viewService: SPViewPickerService = new SPViewPickerService(this.props, this.props.context); + const viewsToExclude: string[] = this.props.viewsToExclude || []; + this.options = []; + viewService.getViews().then((response: ISPViews) => { + // Start mapping the views that are selected + response.value.forEach((view: ISPView) => { + if (this.props.selectedView === view.Id) { + this.selectedKey = view.Id; + } + + // Make sure that the current view is NOT in the 'viewsToExclude' array + if (viewsToExclude.indexOf(view.Title) === -1 && viewsToExclude.indexOf(view.Id) === -1) { + this.options.push({ + key: view.Id, + text: view.Title + }); + } + }); + + // Option to unselect the view + this.options.unshift({ + key: EMPTY_VIEW_KEY, + text: EMPTY_VIEW_KEY + }); + + // Update the current component state + this.setState({ + results: this.options, + selectedKey: this.selectedKey + }); + }).catch(() => { /* no-op; */ }); + } + + private onChanged(event: React.FormEvent,option: IDropdownOption, _index?: number): void { + const newValue: string = option.key as string; + this.delayedValidate(newValue); + } + + /** + * Validates the new custom field value + */ + private validate(value: string): void { + this.notifyAfterValidate(this.props.selectedView, value); + if (this.latestValidateValue === value) { + return; + } + } + + + /** + * Notifies the parent Web Part of a property value change + */ + private notifyAfterValidate(oldValue: string, newValue: string): void { + // Check if the user wanted to unselect the view + const propValue = newValue === EMPTY_VIEW_KEY ? '' : newValue; + + // Deselect all options + this.options = this.state.results.map(option => { + if (option.selected) { + option.selected = false; + } + return option; + }); + // Set the current selected key + this.selectedKey = newValue; + console.log('Selected View key :'+this.selectedKey); + // Update the state + this.setState({ + selectedKey: this.selectedKey, + results: this.options + }); + + //Callback to the parent webpart + this.props.onChange(this.selectedKey); + } + + /** + * Renders the SPViewPicker controls with Office UI Fabric + */ + public render(): JSX.Element { + const { results, selectedKey } = this.state; + const {className, disabled, label, placeholder, showBlankOption} = this.props; + + const options : IDropdownOption[] = results.map(v => ({ + key : v.key, + text: v.text + })); + + if (showBlankOption) { + // Provide empty option + options.unshift({ + key: EMPTY_VIEW_KEY, + text: '', + }); + } + + const dropdownProps: IDropdownProps = { + className, + options, + disabled: disabled, + label, + placeholder, + onChange: this.onChanged, + }; + + // Renders content + return ( + <> + + + ); + } + +} \ No newline at end of file diff --git a/src/controls/viewPicker/index.ts b/src/controls/viewPicker/index.ts new file mode 100644 index 000000000..374101160 --- /dev/null +++ b/src/controls/viewPicker/index.ts @@ -0,0 +1,2 @@ +export * from './IViewPicker'; +export * from './ViewPicker'; \ No newline at end of file diff --git a/src/services/ISPViewPickerService.ts b/src/services/ISPViewPickerService.ts new file mode 100644 index 000000000..1f36c97e6 --- /dev/null +++ b/src/services/ISPViewPickerService.ts @@ -0,0 +1,5 @@ +import { ISPViews } from "../../src/common/SPEntities"; + +export interface ISPViewPickerService { + getViews(): Promise; +} \ No newline at end of file diff --git a/src/services/SPViewPickerService.ts b/src/services/SPViewPickerService.ts new file mode 100644 index 000000000..38c389988 --- /dev/null +++ b/src/services/SPViewPickerService.ts @@ -0,0 +1,88 @@ +import { SPHttpClient } from '@microsoft/sp-http'; +import { BaseComponentContext } from '@microsoft/sp-component-base'; +import {IViewPickerProps, PropertyFieldViewPickerOrderBy } from '../controls/viewPicker/IViewPicker'; +import { ISPViewPickerService } from './ISPViewPickerService'; +import { ISPView, ISPViews } from "../../src/common/SPEntities"; + +/** + * Service implementation to get list & list items from current SharePoint site + */ +export class SPViewPickerService implements ISPViewPickerService { + private context: BaseComponentContext; + private props: IViewPickerProps; + + /** + * Service constructor + */ + constructor(_props: IViewPickerProps, pageContext: BaseComponentContext) { + this.props = _props; + this.context = pageContext; + } + + /** + * Gets the collection of view for a selected list + */ + public async getViews(): Promise { + if (this.props.listId === undefined || this.props.listId === "") { + return this.getEmptyViews(); + } + + const webAbsoluteUrl = this.props.webAbsoluteUrl ? this.props.webAbsoluteUrl : this.context.pageContext.web.absoluteUrl; + + // If the running environment is SharePoint, request the lists REST service + let queryUrl: string = `${webAbsoluteUrl}/_api/lists(guid'${this.props.listId}')/Views?$select=Title,Id`; + + // Check if the orderBy property is provided + if (this.props.orderBy !== null) { + queryUrl += '&$orderby='; + switch (this.props.orderBy) { + case PropertyFieldViewPickerOrderBy.Id: + queryUrl += 'Id'; + break; + case PropertyFieldViewPickerOrderBy.Title: + queryUrl += 'Title'; + break; + } + + // Adds an OData Filter to the list + if (this.props.filter) { + queryUrl += `&$filter=${encodeURIComponent(this.props.filter)}`; + } + + const response = await this.context.spHttpClient.get(queryUrl, SPHttpClient.configurations.v1); + const views = (await response.json()) as ISPViews; + + // Check if onViewsRetrieved callback is defined + if (this.props.onViewsRetrieved) { + //Call onViewsRetrieved + const lr = this.props.onViewsRetrieved(views.value); + let output: ISPView[]; + + //Conditional checking to see of PromiseLike object or array + if (lr instanceof Array) { + output = lr; + } else { + output = await lr; + } + + views.value = output; + } + + return views; + } + } + + /** + * Returns an empty view for when a list isn't selected + */ + private getEmptyViews(): Promise { + return new Promise((resolve) => { + const listData: ISPViews = { + value: [ + ] + }; + + resolve(listData); + }); + } +} \ No newline at end of file diff --git a/src/webparts/controlsTest/components/ControlsTest.tsx b/src/webparts/controlsTest/components/ControlsTest.tsx index d23d5184a..fb1342dfe 100644 --- a/src/webparts/controlsTest/components/ControlsTest.tsx +++ b/src/webparts/controlsTest/components/ControlsTest.tsx @@ -192,7 +192,7 @@ import { ModernAudio, ModernAudioLabelPosition } from "../../../ModernAudio"; import { SPTaxonomyService, TaxonomyTree } from "../../../ModernTaxonomyPicker"; import { TestControl } from "./TestControl"; import { UploadFiles } from "../../../controls/uploadFiles"; - +import { ViewPicker } from "../../../controls/viewPicker"; // Used to render document card /** * The sample data below was randomly generated (except for the title). It is used by the grid layout @@ -748,6 +748,15 @@ export default class ControlsTest extends React.Component { + console.log("ViewPicker control - newView:", newValue); + } + private _onRenderGridItem = (item: any, _finalSize: ISize, isCompact: boolean): JSX.Element => { const previewProps: IDocumentCardPreviewProps = { previewImages: [ @@ -1515,6 +1524,16 @@ export default class ControlsTest extends React.Component + +
View picker tester: + +
+
Icon Picker
Date: Fri, 28 Apr 2023 18:54:42 +0200 Subject: [PATCH 02/90] Updated Images in assests for Issue 1439 --- docs/documentation/docs/assets/ViewPicker1.PNG | Bin 0 -> 15147 bytes docs/documentation/docs/assets/ViewPicker2.png | Bin 0 -> 32302 bytes 2 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 docs/documentation/docs/assets/ViewPicker1.PNG create mode 100644 docs/documentation/docs/assets/ViewPicker2.png diff --git a/docs/documentation/docs/assets/ViewPicker1.PNG b/docs/documentation/docs/assets/ViewPicker1.PNG new file mode 100644 index 0000000000000000000000000000000000000000..76fc3495ec3589a7f55eb2a4a58fe75b2bd11dcf GIT binary patch literal 15147 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 k`#)jU{RSDp{;G=Un%^>vdn#Xj5aoLkC0;aB*=R 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 V{M;d3N@T*oEj8`yW!J18{y%2mIPw4h literal 0 HcmV?d00001 From f4bef3f31d9e117f08427a86a3a8417270f05e46 Mon Sep 17 00:00:00 2001 From: Nishkalank Bezawada <47456098+NishkalankBezawada@users.noreply.github.com> Date: Sat, 3 Jun 2023 20:59:33 +0200 Subject: [PATCH 03/90] Resolving comments by Alex --- .../docs/assets/ViewPicker-multi.png | Bin 0 -> 30936 bytes .../documentation/docs/controls/ViewPicker.md | 60 +++--- src/common/utilities/GeneralHelper.ts | 12 -- src/controls/viewPicker/IViewPicker.ts | 56 ++--- .../viewPicker/ViewPicker.module.scss | 7 + src/controls/viewPicker/ViewPicker.tsx | 196 ++++++++++-------- src/services/ISPService.ts | 9 +- src/services/ISPViewPickerService.ts | 5 - src/services/SPService.ts | 54 ++++- src/services/SPServiceMock.ts | 6 +- src/services/SPViewPickerService.ts | 88 -------- .../controlsTest/components/ControlsTest.tsx | 24 ++- 12 files changed, 253 insertions(+), 264 deletions(-) create mode 100644 docs/documentation/docs/assets/ViewPicker-multi.png create mode 100644 src/controls/viewPicker/ViewPicker.module.scss delete mode 100644 src/services/ISPViewPickerService.ts delete mode 100644 src/services/SPViewPickerService.ts diff --git a/docs/documentation/docs/assets/ViewPicker-multi.png b/docs/documentation/docs/assets/ViewPicker-multi.png new file mode 100644 index 0000000000000000000000000000000000000000..840bb80bb6897b3c3dcac8b58bfbb7335288f16d GIT binary patch literal 30936 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 + orderBy={orderBy.Title} + multiSelect={true} + onSelectionChanged={this.onViewPickerChange} /> ``` -- The `onChange` change event returns the selected view(s) and can be implemented as follows in your webpart: +- The `onSelectionChanged` change event returns the selected view(s) and can be implemented as follows in your webpart: ```TypeScript -private onViewPickerChange = (newValue: string | string[]) => { - console.log("newView:", newValue); -} + private onViewPickerChange = (views: string | string[]) => { + console.log("Views:", views); + } ``` @@ -45,26 +49,24 @@ private onViewPickerChange = (newValue: string | string[]) => { The `ViewPicker` control can be configured with the following properties -| Property | What is it used for? -| --------------- | --- -| context (Mandatory) | Context of the current web part -| className (Not mandatory) | If provided, additional class name to provide on the dropdown element. -| deferredValidationTime (Not mandatory) | Custom Field will start to validate after users stop typing for `deferredValidationTime` milliseconds. Default value is 200. -| disabled (Not mandatory) | Whether the property pane field is enabled or not. -| filter (Not Mandatory) | Filter views from Odata query -| label (mandatory) | Property field label displayed on top -| listId (Not mandatory) | The List Id of the list where you want to get the views. -| placeholder (Not mandatory) | Input placeholder text. Displayed until option is selected. -| orderBy (Not mandatory) | Specify the property on which you want to order the retrieve set of views. orderBy viewId and by title -| selectedView (Not Mandatory) | Initial selected view of the control. -| showBlankOption (mandatory) | Whether or not to show a blank option. Default false. -| viewsToExclude (Not mandatory) | Defines view titles which should be excluded from the view picker control. -| webAbsoluteUrl (Not mandatory) | Absolute Web Url of target site (user requires permissions). -| onViewPickerPropertyChange (Mandatory) | Defines a change function to raise when the selected value changed. -| onViewsRetrieved (Not mandatory) | Callback that is called before the dropdown is populated. - - -Enum `PropertyFieldViewPickerOrderBy` +| Property | Type | Required | Description | +| ---- | ---- | ---- | ---- | +| context | BaseComponentContext | yes | The context object of the SPFx loaded webpart or customizer. | +| className | string | no | If provided, additional class name to provide on the dropdown element. | +| disabled | boolean | no | Whether or not the view picker control is disabled. | +| filter | string | no | Filter views from Odata query. | +| label | string | no | Label to use for the control. | +| listId | string | no | The List Id of the list. | +| placeholder | string | no | Placeholder label to show in the dropdown. | +| orderBy | Enum | no | How to order the set of views (By ID or Title). | +| selectedView | string OR string[] | no | Keys(View Ids) of the selected item(s). If you provide this, you must maintain selection state by observing onSelectionChanged events and passing a new value in when changed. | +| multiSelect | boolean | no | Optional mode indicates if multi-choice selections is allowed. Default to `false`. | +| showBlankOption | boolean | no | Whether or not to show a blank option. Default to `false`. | +| viewsToExclude | string[] | no | Defines view titles which should be excluded from the view picker control. | +| webAbsoulteUrl | string | no | Absolute Web Url of target site (user requires permissions) | +| onSelectionChanged | (newValue: string OR string[]): void | no | Callback function when the selected option changes. | + +Enum `orderBy` | Value | | ---- | diff --git a/src/common/utilities/GeneralHelper.ts b/src/common/utilities/GeneralHelper.ts index 89a00f523..5d9215b6e 100644 --- a/src/common/utilities/GeneralHelper.ts +++ b/src/common/utilities/GeneralHelper.ts @@ -406,15 +406,3 @@ export function dateToNumber(date: string | number | Date): number { return dateObj.getTime(); } - -export const setPropertyValue = (properties: any, targetProperty: string, value: any): void => { // eslint-disable-line @typescript-eslint/no-explicit-any - if (!properties) { - return; - } - if (targetProperty.indexOf('.') === -1) { // simple prop - properties[targetProperty] = value; - } - else { - _.set(properties, targetProperty, value); - } -}; diff --git a/src/controls/viewPicker/IViewPicker.ts b/src/controls/viewPicker/IViewPicker.ts index 5e3159cb2..49505876c 100644 --- a/src/controls/viewPicker/IViewPicker.ts +++ b/src/controls/viewPicker/IViewPicker.ts @@ -6,7 +6,7 @@ import { IDropdownOption } from 'office-ui-fabric-react/lib/Dropdown'; /** * Enum for specifying how the views should be sorted */ -export enum PropertyFieldViewPickerOrderBy { +export enum orderBy { Id = 1, Title } @@ -23,13 +23,7 @@ export interface IViewPickerProps { className?: string; /** - * Custom Field will start to validate after users stop typing for `deferredValidationTime` milliseconds. - * Default value is 200. - */ - deferredValidationTime?: number; - - /** - * Whether the property pane field is enabled or not. + * Whether the view control is enabled or not. */ disabled?: boolean; @@ -39,12 +33,12 @@ export interface IViewPickerProps { filter?: string; /** - * Property field label displayed on top + * Specifies the text describing the ViewPicker */ - label: string; + label?: string; /** - * The List Id of the list where you want to get the views + * The List Id of the list */ listId?: string; @@ -54,14 +48,19 @@ export interface IViewPickerProps { placeholder?: string; /** - * Specify the property on which you want to order the retrieve set of views. + * How to order the set of views (By ID or Title). + */ + orderBy?: orderBy; + + /** + * Initial selected view(s) of the control */ - orderBy?: PropertyFieldViewPickerOrderBy; + selectedView?: string | string[]; /** - * Initial selected view of the control + * Indicates if multi-choice selections is allowed. Default to false. */ - selectedView?: string; + multiSelect?: boolean; /** * Whether or not to show a blank option. Default false. @@ -79,22 +78,23 @@ export interface IViewPickerProps { webAbsoluteUrl?: string; - /** - * Defines a change function to raise when the selected value changed. - * Normally this function must be always defined with the 'this.onChange' - * method of the web part object. + * Callback issued when the selected option changes. */ - onChange : (newValue: string | string[]) => void; - /** - * Callback that is called before the dropdown is populated - */ - onViewsRetrieved?: (views: ISPView[]) => PromiseLike | ISPView[]; - + onSelectionChanged?: (newValue: string | string[]) => void; } export interface IViewPickerState { - results: IDropdownOption[]; - selectedKey?: string | string[]; - errorMessage?: string | string[]; + /** + * The results fetched to the viewPicker + */ + results: IDropdownOption[]; + /** + * Keys of the currently selected item(s). + */ + selectedView?: string | string[]; + /** + * Whether or not the viewPicker options are loading + */ + loading: boolean; } \ No newline at end of file diff --git a/src/controls/viewPicker/ViewPicker.module.scss b/src/controls/viewPicker/ViewPicker.module.scss new file mode 100644 index 000000000..3718e73e6 --- /dev/null +++ b/src/controls/viewPicker/ViewPicker.module.scss @@ -0,0 +1,7 @@ +.viewPicker { + .spinner { + float: right; + margin-top: 10px; + margin-right: -20px; + } +} \ No newline at end of file diff --git a/src/controls/viewPicker/ViewPicker.tsx b/src/controls/viewPicker/ViewPicker.tsx index a81a019dc..be854566e 100644 --- a/src/controls/viewPicker/ViewPicker.tsx +++ b/src/controls/viewPicker/ViewPicker.tsx @@ -6,35 +6,30 @@ import { Label } from 'office-ui-fabric-react/lib/Label'; import { Spinner, SpinnerSize } from 'office-ui-fabric-react/lib/Spinner'; import * as telemetry from '../../common/telemetry'; import { ISPService } from '../../services/ISPService'; -import { SPViewPickerService } from '../../services/SPViewPickerService'; +import { SPServiceFactory } from '../../services/SPServiceFactory'; import { IViewPickerProps, IViewPickerState } from './IViewPicker'; import { ISPView, ISPViews } from "../../common/SPEntities"; - +import styles from './ViewPicker.module.scss'; // Empty view value const EMPTY_VIEW_KEY = 'NO_VIEW_SELECTED'; export class ViewPicker extends React.Component { - private options: IDropdownOption[] = []; - private selectedKey: string| string[] = null; - private latestValidateValue: string; - private async: Async; - private delayedValidate: (value: string) => void; + private selectedKey: string | string[] = null; + private async: Async; + private _selectedView: string | string[] = null; constructor(props: IViewPickerProps){ super(props); telemetry.track('ViewPicker'); this.state = { - results: this.options + results: [], + loading: false } this.async = new Async(this); - this.validate = this.validate.bind(this); - this.onChanged = this.onChanged.bind(this); - this.notifyAfterValidate = this.notifyAfterValidate.bind(this); - this.delayedValidate = this.async.debounce(this.validate, this.props.deferredValidationTime); } @@ -43,6 +38,11 @@ export class ViewPicker extends React.Component { + + // Show the loading indicator and disable the dropdown + this.setState({ loading: true }); - const viewService: SPViewPickerService = new SPViewPickerService(this.props, this.props.context); const viewsToExclude: string[] = this.props.viewsToExclude || []; - this.options = []; - viewService.getViews().then((response: ISPViews) => { - // Start mapping the views that are selected - response.value.forEach((view: ISPView) => { - if (this.props.selectedView === view.Id) { - this.selectedKey = view.Id; - } - - // Make sure that the current view is NOT in the 'viewsToExclude' array - if (viewsToExclude.indexOf(view.Title) === -1 && viewsToExclude.indexOf(view.Id) === -1) { - this.options.push({ - key: view.Id, - text: view.Title - }); - } + let options: IDropdownOption[] = []; + const service: ISPService = SPServiceFactory.createService(this.props.context, true, 5000, this.props.webAbsoluteUrl); + let results = await service.getViews( + this.props.listId, + this.props.webAbsoluteUrl, + this.props.orderBy, + this.props.filter + ); + + // Start mapping the views that are selected + results.value.forEach((view: ISPView) => { + if (this.props.selectedView === view.Id) { + this.selectedKey = view.Id; + } + // Make sure that the current view is NOT in the 'viewsToExclude' array + if (viewsToExclude.indexOf(view.Title) === -1 && viewsToExclude.indexOf(view.Id) === -1) { + options.push({ + key: view.Id, + text: view.Title + }); + } + }); + + if (this.props.showBlankOption) { + // Provide empty option + options.unshift({ + key: EMPTY_VIEW_KEY, + text: '', }); - + } else{ // Option to unselect the view - this.options.unshift({ + options.unshift({ key: EMPTY_VIEW_KEY, text: EMPTY_VIEW_KEY }); - - // Update the current component state - this.setState({ - results: this.options, - selectedKey: this.selectedKey - }); - }).catch(() => { /* no-op; */ }); - } + } - private onChanged(event: React.FormEvent,option: IDropdownOption, _index?: number): void { - const newValue: string = option.key as string; - this.delayedValidate(newValue); - } + this.setSelectedViews(); + // Update the current component state + this.setState({ + loading: false, + results: options + }); + + } /** - * Validates the new custom field value + * Set the currently selected views(s); */ - private validate(value: string): void { - this.notifyAfterValidate(this.props.selectedView, value); - if (this.latestValidateValue === value) { - return; - } + private setSelectedViews(): void { + this._selectedView = cloneDeep(this.props.selectedView); + + this.setState({ + selectedView: this._selectedView, + }); } - /** - * Notifies the parent Web Part of a property value change - */ - private notifyAfterValidate(oldValue: string, newValue: string): void { - // Check if the user wanted to unselect the view - const propValue = newValue === EMPTY_VIEW_KEY ? '' : newValue; - - // Deselect all options - this.options = this.state.results.map(option => { - if (option.selected) { - option.selected = false; - } - return option; - }); - // Set the current selected key - this.selectedKey = newValue; - console.log('Selected View key :'+this.selectedKey); - // Update the state - this.setState({ - selectedKey: this.selectedKey, - results: this.options - }); - - //Callback to the parent webpart - this.props.onChange(this.selectedKey); + /** + * Fires when a view has been selected from the dropdown. + * @param option The new selection. + * @param index Index of the selection. + */ + private onChange = (event: React.FormEvent, option: IDropdownOption, index?: number): void => { + const { multiSelect, onSelectionChanged } = this.props; + + if (multiSelect) { + let selectedViews = this._selectedView ? cloneDeep(this._selectedView) as string[] : []; + + if (option.selected) { + selectedViews.push(option.key.toString()); + } + else { + selectedViews = selectedViews.filter(view => view !== option.key); + } + this._selectedView = selectedViews; + } + else { + this._selectedView = option.key.toString(); + } + if (onSelectionChanged) { + onSelectionChanged(cloneDeep(this._selectedView)); } + } + + /** - * Renders the SPViewPicker controls with Office UI Fabric + * Renders the ViewPicker controls with Office UI Fabric */ public render(): JSX.Element { - const { results, selectedKey } = this.state; - const {className, disabled, label, placeholder, showBlankOption} = this.props; + const { loading, results, selectedView } = this.state; + const {className, disabled,multiSelect, label, placeholder} = this.props; const options : IDropdownOption[] = results.map(v => ({ key : v.key, text: v.text })); - if (showBlankOption) { - // Provide empty option - options.unshift({ - key: EMPTY_VIEW_KEY, - text: '', - }); - } + const dropdownProps: IDropdownProps = { className, @@ -166,14 +179,21 @@ export class ViewPicker extends React.Component +
+ {loading && } - +
); } diff --git a/src/services/ISPService.ts b/src/services/ISPService.ts index 8a86e11d7..1e97747c5 100644 --- a/src/services/ISPService.ts +++ b/src/services/ISPService.ts @@ -1,4 +1,5 @@ -import { ISPContentType, ISPField, ISPLists } from "../common/SPEntities"; +import { ISPContentType, ISPField, ISPLists, ISPView, ISPViews } from "../common/SPEntities"; +import {orderBy } from '../controls/viewPicker/IViewPicker'; export enum LibsOrderBy { Id = 1, @@ -63,4 +64,10 @@ export interface ISPService { * @param options Options used to order and filter during the API query. */ getContentTypes(options?: IContentTypesOptions): Promise; + + /** + * Get the views from lists or libraries + * @params listId, webAbsoluteUrl, orderBy, onViewsRetrived + */ + getViews(listId?: string, _webAbsoluteUrl?:string, orderBy?: orderBy, filter?: string): Promise; } diff --git a/src/services/ISPViewPickerService.ts b/src/services/ISPViewPickerService.ts deleted file mode 100644 index 1f36c97e6..000000000 --- a/src/services/ISPViewPickerService.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { ISPViews } from "../../src/common/SPEntities"; - -export interface ISPViewPickerService { - getViews(): Promise; -} \ No newline at end of file diff --git a/src/services/SPService.ts b/src/services/SPService.ts index 0d9ad83ea..1a49d60e0 100644 --- a/src/services/SPService.ts +++ b/src/services/SPService.ts @@ -2,9 +2,10 @@ import { BaseComponentContext } from '@microsoft/sp-component-base'; import { ISPHttpClientOptions, SPHttpClient } from "@microsoft/sp-http"; import filter from 'lodash/filter'; import find from 'lodash/find'; -import { ISPContentType, ISPField, ISPList, ISPLists, IUploadImageResult } from "../common/SPEntities"; +import { ISPContentType, ISPField, ISPList, ISPLists, IUploadImageResult, ISPView, ISPViews } from "../common/SPEntities"; import { SPHelper, urlCombine } from "../common/utilities"; import { IContentTypesOptions, IFieldsOptions, ILibsOptions, ISPService, LibsOrderBy } from "./ISPService"; +import {orderBy } from '../controls/viewPicker/IViewPicker'; interface ICachedListItems { // eslint-disable-next-line @typescript-eslint/no-explicit-any @@ -735,4 +736,55 @@ export default class SPService implements ISPService { return substringSearch ? fieldValue.indexOf(lowercasedFilterText) > -1 : fieldValue.startsWith(lowercasedFilterText); }); } + + /** + * Gets the collection of view for a selected list + */ + public async getViews(listId?: string, _webAbsoluteUrl?:string, _orderBy?: orderBy, filter?: string): Promise { + if (listId === undefined || listId === "") { + return this.getEmptyViews(); + } + + const webAbsoluteUrl = _webAbsoluteUrl ? _webAbsoluteUrl : this._context.pageContext.web.absoluteUrl; + + // If the running environment is SharePoint, request the lists REST service + let queryUrl: string = `${webAbsoluteUrl}/_api/lists(guid'${listId}')/Views?$select=Title,Id`; + + // Check if the orderBy property is provided + if (_orderBy !== null) { + queryUrl += '&$orderby='; + switch (_orderBy) { + case orderBy.Id: + queryUrl += 'Id'; + break; + case orderBy.Title: + queryUrl += 'Title'; + break; + } + + // Adds an OData Filter to the list + if (filter) { + queryUrl += `&$filter=${encodeURIComponent(filter)}`; + } + + const response = await this._context.spHttpClient.get(queryUrl, SPHttpClient.configurations.v1); + const views = (await response.json()) as ISPViews; + + return views; + } + } + + /** + * Returns an empty view for when a list isn't selected + */ + private getEmptyViews(): Promise { + return new Promise((resolve) => { + const listData: ISPViews = { + value: [ + ] + }; + + resolve(listData); + }); + } } diff --git a/src/services/SPServiceMock.ts b/src/services/SPServiceMock.ts index f7569a264..148158e0c 100644 --- a/src/services/SPServiceMock.ts +++ b/src/services/SPServiceMock.ts @@ -1,5 +1,6 @@ import { ISPService, ILibsOptions, IFieldsOptions, IContentTypesOptions } from "./ISPService"; -import { ISPContentType, ISPField, ISPLists } from "../common/SPEntities"; +import { ISPContentType, ISPField, ISPLists, ISPView, ISPViews } from "../common/SPEntities"; +import {orderBy } from '../controls/viewPicker/IViewPicker'; export default class SPServiceMock implements ISPService { private _includeDelay?: boolean; @@ -21,6 +22,9 @@ export default class SPServiceMock implements ISPService { public getField = async (listId: string, internalColumnName: string, webUrl?: string): Promise => { return; } + public getViews(listId?: string, _webAbsoluteUrl?:string, orderBy?: orderBy, filter?: string) : Promise { + return; + } /** * The mock lists to present to the local workbench diff --git a/src/services/SPViewPickerService.ts b/src/services/SPViewPickerService.ts deleted file mode 100644 index 38c389988..000000000 --- a/src/services/SPViewPickerService.ts +++ /dev/null @@ -1,88 +0,0 @@ -import { SPHttpClient } from '@microsoft/sp-http'; -import { BaseComponentContext } from '@microsoft/sp-component-base'; -import {IViewPickerProps, PropertyFieldViewPickerOrderBy } from '../controls/viewPicker/IViewPicker'; -import { ISPViewPickerService } from './ISPViewPickerService'; -import { ISPView, ISPViews } from "../../src/common/SPEntities"; - -/** - * Service implementation to get list & list items from current SharePoint site - */ -export class SPViewPickerService implements ISPViewPickerService { - private context: BaseComponentContext; - private props: IViewPickerProps; - - /** - * Service constructor - */ - constructor(_props: IViewPickerProps, pageContext: BaseComponentContext) { - this.props = _props; - this.context = pageContext; - } - - /** - * Gets the collection of view for a selected list - */ - public async getViews(): Promise { - if (this.props.listId === undefined || this.props.listId === "") { - return this.getEmptyViews(); - } - - const webAbsoluteUrl = this.props.webAbsoluteUrl ? this.props.webAbsoluteUrl : this.context.pageContext.web.absoluteUrl; - - // If the running environment is SharePoint, request the lists REST service - let queryUrl: string = `${webAbsoluteUrl}/_api/lists(guid'${this.props.listId}')/Views?$select=Title,Id`; - - // Check if the orderBy property is provided - if (this.props.orderBy !== null) { - queryUrl += '&$orderby='; - switch (this.props.orderBy) { - case PropertyFieldViewPickerOrderBy.Id: - queryUrl += 'Id'; - break; - case PropertyFieldViewPickerOrderBy.Title: - queryUrl += 'Title'; - break; - } - - // Adds an OData Filter to the list - if (this.props.filter) { - queryUrl += `&$filter=${encodeURIComponent(this.props.filter)}`; - } - - const response = await this.context.spHttpClient.get(queryUrl, SPHttpClient.configurations.v1); - const views = (await response.json()) as ISPViews; - - // Check if onViewsRetrieved callback is defined - if (this.props.onViewsRetrieved) { - //Call onViewsRetrieved - const lr = this.props.onViewsRetrieved(views.value); - let output: ISPView[]; - - //Conditional checking to see of PromiseLike object or array - if (lr instanceof Array) { - output = lr; - } else { - output = await lr; - } - - views.value = output; - } - - return views; - } - } - - /** - * Returns an empty view for when a list isn't selected - */ - private getEmptyViews(): Promise { - return new Promise((resolve) => { - const listData: ISPViews = { - value: [ - ] - }; - - resolve(listData); - }); - } -} \ No newline at end of file diff --git a/src/webparts/controlsTest/components/ControlsTest.tsx b/src/webparts/controlsTest/components/ControlsTest.tsx index fb1342dfe..07534b71a 100644 --- a/src/webparts/controlsTest/components/ControlsTest.tsx +++ b/src/webparts/controlsTest/components/ControlsTest.tsx @@ -193,6 +193,8 @@ import { SPTaxonomyService, TaxonomyTree } from "../../../ModernTaxonomyPicker"; import { TestControl } from "./TestControl"; import { UploadFiles } from "../../../controls/uploadFiles"; import { ViewPicker } from "../../../controls/viewPicker"; +import {orderBy } from '../../../controls/viewPicker/IViewPicker'; + // Used to render document card /** * The sample data below was randomly generated (except for the title). It is used by the grid layout @@ -622,6 +624,14 @@ export default class ControlsTest extends React.Component { + console.log("Views:", views); + } + /** * Deletes second item from the list */ @@ -749,14 +759,6 @@ export default class ControlsTest extends React.Component { - console.log("ViewPicker control - newView:", newValue); - } - private _onRenderGridItem = (item: any, _finalSize: ISize, isCompact: boolean): JSX.Element => { const previewProps: IDocumentCardPreviewProps = { previewImages: [ @@ -1527,11 +1529,11 @@ export default class ControlsTest extends React.ComponentView picker tester: + orderBy={orderBy.Title} + multiSelect={true} + onSelectionChanged={this.onViewPickerChange} />
Icon Picker
From 950807c35cfd78dd0ad074852b0af90fe1367aa5 Mon Sep 17 00:00:00 2001 From: Nishkalank Bezawada <47456098+NishkalankBezawada@users.noreply.github.com> Date: Sun, 25 Jun 2023 17:49:08 +0200 Subject: [PATCH 04/90] Resolving requested changes by Alex dated 24-06-2023 --- src/common/utilities/GeneralHelper.ts | 1 - src/controls/viewPicker/IViewPicker.ts | 6 +----- src/controls/viewPicker/ViewPicker.tsx | 10 ++-------- src/services/ISPService.ts | 4 ++-- src/services/SPService.ts | 6 ++---- src/services/SPServiceMock.ts | 2 +- 6 files changed, 8 insertions(+), 21 deletions(-) diff --git a/src/common/utilities/GeneralHelper.ts b/src/common/utilities/GeneralHelper.ts index 5d9215b6e..ed359782d 100644 --- a/src/common/utilities/GeneralHelper.ts +++ b/src/common/utilities/GeneralHelper.ts @@ -4,7 +4,6 @@ import * as strings from 'ControlStrings'; export const IMG_SUPPORTED_EXTENSIONS = ".gif,.jpg,.jpeg,.bmp,.dib,.tif,.tiff,.ico,.png,.jxr,.svg"; -import * as _ from '@microsoft/sp-lodash-subset'; /** * Helper with general methods to simplify some routines */ diff --git a/src/controls/viewPicker/IViewPicker.ts b/src/controls/viewPicker/IViewPicker.ts index 49505876c..a5bbac3d9 100644 --- a/src/controls/viewPicker/IViewPicker.ts +++ b/src/controls/viewPicker/IViewPicker.ts @@ -1,5 +1,5 @@ import { BaseComponentContext } from '@microsoft/sp-component-base'; -import { ISPView } from "../../../src/common/SPEntities"; +import { ISPView } from '../../../src/common/SPEntities'; import { IDropdownOption } from 'office-ui-fabric-react/lib/Dropdown'; @@ -93,8 +93,4 @@ export interface IViewPickerState { * Keys of the currently selected item(s). */ selectedView?: string | string[]; - /** - * Whether or not the viewPicker options are loading - */ - loading: boolean; } \ No newline at end of file diff --git a/src/controls/viewPicker/ViewPicker.tsx b/src/controls/viewPicker/ViewPicker.tsx index be854566e..909654103 100644 --- a/src/controls/viewPicker/ViewPicker.tsx +++ b/src/controls/viewPicker/ViewPicker.tsx @@ -25,8 +25,7 @@ export class ViewPicker extends React.Component { - // Show the loading indicator and disable the dropdown - this.setState({ loading: true }); const viewsToExclude: string[] = this.props.viewsToExclude || []; let options: IDropdownOption[] = []; const service: ISPService = SPServiceFactory.createService(this.props.context, true, 5000, this.props.webAbsoluteUrl); let results = await service.getViews( this.props.listId, - this.props.webAbsoluteUrl, this.props.orderBy, this.props.filter ); @@ -112,7 +108,6 @@ export class ViewPicker extends React.Component ({ @@ -191,7 +186,6 @@ export class ViewPicker extends React.Component - {loading && } ); diff --git a/src/services/ISPService.ts b/src/services/ISPService.ts index 1e97747c5..c2e2992e8 100644 --- a/src/services/ISPService.ts +++ b/src/services/ISPService.ts @@ -67,7 +67,7 @@ export interface ISPService { /** * Get the views from lists or libraries - * @params listId, webAbsoluteUrl, orderBy, onViewsRetrived + * @params listId, orderBy, onViewsRetrived */ - getViews(listId?: string, _webAbsoluteUrl?:string, orderBy?: orderBy, filter?: string): Promise; + getViews(listId?: string, orderBy?: orderBy, filter?: string): Promise; } diff --git a/src/services/SPService.ts b/src/services/SPService.ts index 1a49d60e0..0088c0ed9 100644 --- a/src/services/SPService.ts +++ b/src/services/SPService.ts @@ -740,15 +740,13 @@ export default class SPService implements ISPService { /** * Gets the collection of view for a selected list */ - public async getViews(listId?: string, _webAbsoluteUrl?:string, _orderBy?: orderBy, filter?: string): Promise { + public async getViews(listId?: string, _orderBy?: orderBy, filter?: string): Promise { if (listId === undefined || listId === "") { return this.getEmptyViews(); } - const webAbsoluteUrl = _webAbsoluteUrl ? _webAbsoluteUrl : this._context.pageContext.web.absoluteUrl; - // If the running environment is SharePoint, request the lists REST service - let queryUrl: string = `${webAbsoluteUrl}/_api/lists(guid'${listId}')/Views?$select=Title,Id`; + let queryUrl: string = `${this._webAbsoluteUrl}/_api/lists(guid'${listId}')/Views?$select=Title,Id`; // Check if the orderBy property is provided if (_orderBy !== null) { diff --git a/src/services/SPServiceMock.ts b/src/services/SPServiceMock.ts index 148158e0c..5365d4b94 100644 --- a/src/services/SPServiceMock.ts +++ b/src/services/SPServiceMock.ts @@ -22,7 +22,7 @@ export default class SPServiceMock implements ISPService { public getField = async (listId: string, internalColumnName: string, webUrl?: string): Promise => { return; } - public getViews(listId?: string, _webAbsoluteUrl?:string, orderBy?: orderBy, filter?: string) : Promise { + public getViews(listId?: string, orderBy?: orderBy, filter?: string) : Promise { return; } From 86867c3cbd0d3135178aeec725e113e2d02fab8a Mon Sep 17 00:00:00 2001 From: Nishkalank Bezawada <47456098+NishkalankBezawada@users.noreply.github.com> Date: Sun, 25 Jun 2023 18:02:40 +0200 Subject: [PATCH 05/90] Resolving changes requested by alex dated 25/06/2023 --- src/services/SPService.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/services/SPService.ts b/src/services/SPService.ts index 0088c0ed9..22b5df036 100644 --- a/src/services/SPService.ts +++ b/src/services/SPService.ts @@ -740,7 +740,7 @@ export default class SPService implements ISPService { /** * Gets the collection of view for a selected list */ - public async getViews(listId?: string, _orderBy?: orderBy, filter?: string): Promise { + public async getViews(listId?: string, orderby?: orderBy, filter?: string): Promise { if (listId === undefined || listId === "") { return this.getEmptyViews(); } @@ -749,9 +749,9 @@ export default class SPService implements ISPService { let queryUrl: string = `${this._webAbsoluteUrl}/_api/lists(guid'${listId}')/Views?$select=Title,Id`; // Check if the orderBy property is provided - if (_orderBy !== null) { + if (orderby !== null) { queryUrl += '&$orderby='; - switch (_orderBy) { + switch (orderby) { case orderBy.Id: queryUrl += 'Id'; break; From bcdc5a6ba3f491cd97faf0b6f02840056f32acf5 Mon Sep 17 00:00:00 2001 From: Nishkalank Bezawada <47456098+NishkalankBezawada@users.noreply.github.com> Date: Mon, 26 Jun 2023 18:56:21 +0200 Subject: [PATCH 06/90] Changes requested by Alex dated 25Jun2023 --- src/controls/viewPicker/ViewPicker.tsx | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/src/controls/viewPicker/ViewPicker.tsx b/src/controls/viewPicker/ViewPicker.tsx index 909654103..ccd120ae7 100644 --- a/src/controls/viewPicker/ViewPicker.tsx +++ b/src/controls/viewPicker/ViewPicker.tsx @@ -18,7 +18,6 @@ export class ViewPicker extends React.Component, option: IDropdownOption, index?: number): void => { const { multiSelect, onSelectionChanged } = this.props; - + let selectedViews : string | string[] = null; if (multiSelect) { - let selectedViews = this._selectedView ? cloneDeep(this._selectedView) as string[] : []; + selectedViews = this.state.selectedView ? cloneDeep(this.state.selectedView) as string[] : []; if (option.selected) { selectedViews.push(option.key.toString()); @@ -142,13 +140,17 @@ export class ViewPicker extends React.Component view !== option.key); } - this._selectedView = selectedViews; + this.setState({ + selectedView:selectedViews + }); } else { - this._selectedView = option.key.toString(); + this.setState({ + selectedView:option.key.toString() + }); } if (onSelectionChanged) { - onSelectionChanged(cloneDeep(this._selectedView)); + onSelectionChanged(cloneDeep(selectedViews)); } } From 4dc8b6fb163a9798f85eee70de53b0ff38b0f506 Mon Sep 17 00:00:00 2001 From: Nishkalank Bezawada <47456098+NishkalankBezawada@users.noreply.github.com> Date: Fri, 7 Jul 2023 18:44:46 +0200 Subject: [PATCH 07/90] Correcting merge conflicts on local with Dev branch --- src/controls/viewPicker/ViewPicker.tsx | 13 +- .../controlsTest/components/ControlsTest.tsx | 448 +----------------- .../components/IControlsTestState.ts | 1 + 3 files changed, 29 insertions(+), 433 deletions(-) diff --git a/src/controls/viewPicker/ViewPicker.tsx b/src/controls/viewPicker/ViewPicker.tsx index ccd120ae7..675a1e9d9 100644 --- a/src/controls/viewPicker/ViewPicker.tsx +++ b/src/controls/viewPicker/ViewPicker.tsx @@ -140,15 +140,16 @@ export class ViewPicker extends React.Component view !== option.key); } - this.setState({ - selectedView:selectedViews - }); + } else { - this.setState({ - selectedView:option.key.toString() - }); + selectedViews = option.key.toString(); } + + this.setState({ + selectedView:selectedViews + }); + if (onSelectionChanged) { onSelectionChanged(cloneDeep(selectedViews)); } diff --git a/src/webparts/controlsTest/components/ControlsTest.tsx b/src/webparts/controlsTest/components/ControlsTest.tsx index d5615dadf..6904499de 100644 --- a/src/webparts/controlsTest/components/ControlsTest.tsx +++ b/src/webparts/controlsTest/components/ControlsTest.tsx @@ -197,8 +197,8 @@ import { UploadFiles } from "../../../controls/uploadFiles"; import { IFileInfo } from "@pnp/sp/files"; import { FieldPicker } from "../../../FieldPicker"; import { Toggle } from "office-ui-fabric-react"; - import { ViewPicker } from "../../../controls/viewPicker"; + // Used to render document card /** * The sample data below was randomly generated (except for the title). It is used by the grid layout @@ -557,7 +557,8 @@ export default class ControlsTest extends React.Component { this.setState({ isTreeViewDivVisible: checked, toggleAll: false }); }} className={styles.toggleFilter}/> { this.setState({ isUploadFilesDivVisible: checked, toggleAll: false }); }} className={styles.toggleFilter}/> { this.setState({ isVariantThemeProviderDivVisible: checked, toggleAll: false }); }} className={styles.toggleFilter}/> + { this.setState({ isViewPickerDivVisible: checked, toggleAll: false }); }} className={styles.toggleFilter}/> { this.setState({ isWebPartTitleDivVisible: checked, toggleAll: false }); }} className={styles.toggleFilter}/> @@ -1336,429 +1339,6 @@ export default class ControlsTest extends React.Component true - }], - termActionsDisplayMode: TermActionsDisplayMode.buttons, - termActionsDisplayStyle: TermActionsDisplayStyle.textAndIcon - }} /> - - { - this.setState({ - initialValues: [{ - key: "ab703558-2546-4b23-b8b8-2bcb2c0086f5", - name: "HR", - path: "HR", - termSet: "b3e9b754-2593-4ae6-abc2-35345402e186" - }], - errorMessage: "" - }); - }} /> - - - - console.log("DateTimePicker value:", value)} placeholder="Pick a date" /> - console.log("DateTimePicker value:", value)} timeDisplayControlType={TimeDisplayControlType.Dropdown} minutesIncrementStep={15} /> - console.log("DateTimePicker value:", value)} /> - console.log("DateTimePicker value:", value)} /> - console.log("DateTimePicker value:", value)} /> - console.log("DateTimePicker value:", value)} /> - console.log("DateTimePicker value:", value)} - minDate={new Date("05/01/2019")} - maxDate={new Date("05/01/2020")} /> - - {/* { this.richTextValue = value; return value; }} /> */} - { this.setState({ richTextValue: value }); return value; }} /> - { this.setState({ richTextValue: 'test' }); }} /> - - {/* */} - - Please configure the web part.} - buttonLabel='Configure' - hideButton={this.props.displayMode === DisplayMode.Read} - onConfigure={this._onConfigure} - theme={this.props.themeVariant} /> - - - - - - - - - - - - - { - if (!items || items.length < 2) { - return 'error'; - } - return ''; - }} /> - - - - - - - - - - - - - - - - - `${d.getFullYear()} - ${d.getMonth() + 1} - ${d.getDate()}`} - dateConvention={DateConvention.DateTime} - timeConvention={TimeConvention.Hours24} - firstDayOfWeek={DayOfWeek.Monday} - value={this.state.dateTimeValue} - onChange={this._onDateTimePickerChange} - isMonthPickerVisible={false} - showMonthPickerAsOverlay={true} - showWeekNumbers={true} - showSeconds={true} - timeDisplayControlType={TimeDisplayControlType.Dropdown} - /> - { - - this.setState({ - dateTimeValue: undefined - }); - }} /> - - - - - -

- Drag and Drop Files - - Drag files or folder with files here...} - buttonLabel='Configure' - hideButton={this.props.displayMode === DisplayMode.Read} - onConfigure={this._onConfigure} /> - -

- - - - - - console.log("Updated location:", coordinates)} - // zoom={15} - //mapType={MapType.cycle} - //width="50" - //height={150} - //loadingMessage="Loading maps" - //errorMessage="Hmmm, we do not have maps for Mars yet. Working on it..." - /> - - - -
-
-
- Controls testing - - You do not have permissions.

}> -

You have permissions to view list items.

-
- -

- File type icon control -

-
- Font icons:  -   -   -   -   -   - -
-
- Image icons:  -   -   -   -   -   - -
-
Icon size tester: - - - - -
- - -
Site picker tester: - { console.log(sites); }} - placeholder={'Select sites'} - searchPlaceholder={'Filter sites'} /> -
- -
List picker tester: - -
- -
List Item picker list data tester: - - - -
- -
Field picker tester: - { - console.log(fields); - }} - /> -
- -
View picker tester: - -
- -
Icon Picker
-
- { console.log(value); }} - currentIcon={'Warning'} - buttonLabel="Icon Picker"> - -
- -
ComboBoxListItemPicker: - - { - console.log(`Item(s):`, data); - }} - defaultSelectedItems={this.state.comboBoxListItemPickerIds} - webUrl={this.props.context.pageContext.web.absoluteUrl} - spHttpClient={this.props.context.spHttpClient} /> - - { - this.setState({ - comboBoxListItemPickerListId: '71210430-8436-4962-a14d-5525475abd6b' - }); - }} /> - { - this.setState({ - comboBoxListItemPickerIds: [{ Id: 2, Title: '222' }] - }); - }} /> - -
- -
iframe dialog tester: - { this.setState({ iFrameDialogOpened: true }); }} /> - { console.log('iframe loaded'); }} - hidden={!this.state.iFrameDialogOpened} - onDismiss={() => { this.setState({ iFrameDialogOpened: false }); }} - modalProps={{ - isBlocking: true, - styles: { - root: { - backgroundColor: '#00ff00' - }, - main: { - backgroundColor: '#ff0000' - } } return { updateActionType: UpdateType.hideTerm, @@ -2110,6 +1690,19 @@ export default class ControlsTest extends React.Component
+ + +