1+ import * as React from 'react' ;
2+ import cloneDeep from 'lodash/cloneDeep' ;
3+ import { Dropdown , IDropdownOption , IDropdownProps } from 'office-ui-fabric-react/lib/Dropdown' ;
4+ import { Async } from 'office-ui-fabric-react/lib/Utilities' ;
5+ import { Label } from 'office-ui-fabric-react/lib/Label' ;
6+ import { Spinner , SpinnerSize } from 'office-ui-fabric-react/lib/Spinner' ;
7+ import * as telemetry from '../../common/telemetry' ;
8+ import { ISPService } from '../../services/ISPService' ;
9+ import { SPViewPickerService } from '../../services/SPViewPickerService' ;
10+ import { IViewPickerProps , IViewPickerState } from './IViewPicker' ;
11+ import { ISPView , ISPViews } from "../../common/SPEntities" ;
12+
13+
14+ // Empty view value
15+ const EMPTY_VIEW_KEY = 'NO_VIEW_SELECTED' ;
16+
17+ export class ViewPicker extends React . Component < IViewPickerProps , IViewPickerState > {
18+ private options : IDropdownOption [ ] = [ ] ;
19+ private selectedKey : string | string [ ] = null ;
20+ private latestValidateValue : string ;
21+ private async : Async ;
22+ private delayedValidate : ( value : string ) => void ;
23+
24+
25+ constructor ( props : IViewPickerProps ) {
26+ super ( props ) ;
27+
28+ telemetry . track ( 'ViewPicker' ) ;
29+ this . state = {
30+ results : this . options
31+ }
32+
33+ this . async = new Async ( this ) ;
34+ this . validate = this . validate . bind ( this ) ;
35+ this . onChanged = this . onChanged . bind ( this ) ;
36+ this . notifyAfterValidate = this . notifyAfterValidate . bind ( this ) ;
37+ this . delayedValidate = this . async . debounce ( this . validate , this . props . deferredValidationTime ) ;
38+ }
39+
40+
41+ public componentDidMount ( ) : void {
42+ // Start retrieving the list views
43+ this . loadViews ( ) ;
44+ }
45+
46+ public componentDidUpdate ( prevProps : IViewPickerProps , _prevState : IViewPickerState ) : void {
47+ if (
48+ this . props . listId !== prevProps . listId ||
49+ this . props . webAbsoluteUrl !== prevProps . webAbsoluteUrl ||
50+ this . props . orderBy !== prevProps . orderBy
51+ ) {
52+ this . loadViews ( ) ;
53+ }
54+ }
55+
56+ /**
57+ * Called when the component will unmount
58+ */
59+ public componentWillUnmount ( ) : void {
60+ if ( typeof this . async !== 'undefined' ) {
61+ this . async . dispose ( ) ;
62+ }
63+ }
64+
65+ private loadViews ( ) : void {
66+
67+ const viewService : SPViewPickerService = new SPViewPickerService ( this . props , this . props . context ) ;
68+ const viewsToExclude : string [ ] = this . props . viewsToExclude || [ ] ;
69+ this . options = [ ] ;
70+ viewService . getViews ( ) . then ( ( response : ISPViews ) => {
71+ // Start mapping the views that are selected
72+ response . value . forEach ( ( view : ISPView ) => {
73+ if ( this . props . selectedView === view . Id ) {
74+ this . selectedKey = view . Id ;
75+ }
76+
77+ // Make sure that the current view is NOT in the 'viewsToExclude' array
78+ if ( viewsToExclude . indexOf ( view . Title ) === - 1 && viewsToExclude . indexOf ( view . Id ) === - 1 ) {
79+ this . options . push ( {
80+ key : view . Id ,
81+ text : view . Title
82+ } ) ;
83+ }
84+ } ) ;
85+
86+ // Option to unselect the view
87+ this . options . unshift ( {
88+ key : EMPTY_VIEW_KEY ,
89+ text : EMPTY_VIEW_KEY
90+ } ) ;
91+
92+ // Update the current component state
93+ this . setState ( {
94+ results : this . options ,
95+ selectedKey : this . selectedKey
96+ } ) ;
97+ } ) . catch ( ( ) => { /* no-op; */ } ) ;
98+ }
99+
100+ private onChanged ( event : React . FormEvent < HTMLDivElement > , option : IDropdownOption , _index ?: number ) : void {
101+ const newValue : string = option . key as string ;
102+ this . delayedValidate ( newValue ) ;
103+ }
104+
105+ /**
106+ * Validates the new custom field value
107+ */
108+ private validate ( value : string ) : void {
109+ this . notifyAfterValidate ( this . props . selectedView , value ) ;
110+ if ( this . latestValidateValue === value ) {
111+ return ;
112+ }
113+ }
114+
115+
116+ /**
117+ * Notifies the parent Web Part of a property value change
118+ */
119+ private notifyAfterValidate ( oldValue : string , newValue : string ) : void {
120+ // Check if the user wanted to unselect the view
121+ const propValue = newValue === EMPTY_VIEW_KEY ? '' : newValue ;
122+
123+ // Deselect all options
124+ this . options = this . state . results . map ( option => {
125+ if ( option . selected ) {
126+ option . selected = false ;
127+ }
128+ return option ;
129+ } ) ;
130+ // Set the current selected key
131+ this . selectedKey = newValue ;
132+ console . log ( 'Selected View key :' + this . selectedKey ) ;
133+ // Update the state
134+ this . setState ( {
135+ selectedKey : this . selectedKey ,
136+ results : this . options
137+ } ) ;
138+ }
139+
140+ /**
141+ * Renders the SPViewPicker controls with Office UI Fabric
142+ */
143+ public render ( ) : JSX . Element {
144+ const { results, selectedKey } = this . state ;
145+ const { className, disabled, label, placeholder, showBlankOption} = this . props ;
146+
147+ const options : IDropdownOption [ ] = results . map ( v => ( {
148+ key : v . key ,
149+ text : v . text
150+ } ) ) ;
151+
152+ if ( showBlankOption ) {
153+ // Provide empty option
154+ options . unshift ( {
155+ key : EMPTY_VIEW_KEY ,
156+ text : '' ,
157+ } ) ;
158+ }
159+
160+ const dropdownProps : IDropdownProps = {
161+ className,
162+ options,
163+ disabled : disabled ,
164+ label,
165+ placeholder,
166+ onChange : this . onChanged ,
167+ } ;
168+
169+ // Renders content
170+ return (
171+ < >
172+ < Dropdown { ...dropdownProps } />
173+ </ >
174+ ) ;
175+ }
176+
177+ }
0 commit comments