@@ -9,6 +9,7 @@ import orderBy from 'lodash/orderBy';
9
9
import findIndex from 'lodash/findIndex' ;
10
10
import { SearchBox } from 'office-ui-fabric-react/lib/SearchBox' ;
11
11
import { toRelativeUrl } from '../../common/utilities/GeneralHelper' ;
12
+ import { Async } from '@uifabric/utilities/lib/Async' ;
12
13
13
14
const styles = mergeStyleSets ( {
14
15
loadingSpinnerContainer : {
@@ -44,6 +45,8 @@ const styles = mergeStyleSets({
44
45
}
45
46
} ) ;
46
47
48
+ const async = new Async ( ) ;
49
+
47
50
export const SitePicker : React . FunctionComponent < ISitePickerProps > = ( props : React . PropsWithChildren < ISitePickerProps > ) => {
48
51
49
52
const {
@@ -57,7 +60,10 @@ export const SitePicker: React.FunctionComponent<ISitePickerProps> = (props: Rea
57
60
allowSearch,
58
61
orderBy : propOrderBy ,
59
62
isDesc,
60
- onChange
63
+ onChange,
64
+ placeholder,
65
+ searchPlaceholder,
66
+ deferredSearchTime
61
67
} = props ;
62
68
63
69
const [ isLoading , setIsLoading ] = React . useState < boolean > ( true ) ;
@@ -66,24 +72,45 @@ export const SitePicker: React.FunctionComponent<ISitePickerProps> = (props: Rea
66
72
const [ filteredSites , setFilteredSites ] = React . useState < ISite [ ] > ( ) ;
67
73
const [ searchQuery , setSearchQuery ] = React . useState < string > ( ) ;
68
74
69
- const onRenderOption = ( option ?: ISelectableOption , defaultRender ?: ( props ?: ISelectableOption ) => JSX . Element | null ) : JSX . Element | null => {
70
- if ( ! props ) {
71
- return null ;
75
+ const onSearchChange = React . useCallback ( ( newSearchQuery : string ) => {
76
+ if ( ! allSites ) {
77
+ return ;
72
78
}
73
79
74
- if ( option . itemType === SelectableOptionMenuItemType . Header ) {
75
- return < SearchBox /> ;
80
+ const loweredNewSearchQuery = newSearchQuery . toLowerCase ( ) ;
81
+ const newFilteredSites = allSites . filter ( s => s . title && s . title . toLowerCase ( ) . indexOf ( loweredNewSearchQuery ) !== - 1 ) ;
82
+
83
+ setSearchQuery ( newSearchQuery ) ;
84
+ // hack to make dropdown update
85
+ setFilteredSites ( [ ] ) ;
86
+ setFilteredSites ( newFilteredSites ) ;
87
+ } , [ allSites ] ) ;
88
+
89
+ const onSelectionChange = React . useCallback ( ( e , item : IDropdownOption , index : number ) => {
90
+ const newSelectedSites = selectedSites ? [ ...selectedSites ] : [ ] ;
91
+
92
+ if ( multiSelect !== false ) {
93
+ const existingIndex = findIndex ( newSelectedSites , s => s . id === item . key ) ;
94
+
95
+ if ( existingIndex >= 0 ) {
96
+ newSelectedSites . splice ( existingIndex , 1 ) ;
97
+ }
98
+ else {
99
+ newSelectedSites . push ( {
100
+ ...item . data !
101
+ } ) ;
102
+ }
103
+ }
104
+
105
+ if ( onChange ) {
106
+ onChange ( newSelectedSites ) ;
76
107
}
77
- // {multiSelect !== false && <Checkbox className={styles.siteOptionCheckbox} checked={option.selected} disabled={option.disabled} /> }
78
- return < div className = { styles . siteOption } >
79
- < div className = { styles . siteOptionContent } >
80
- < span className = { styles . siteOptionTitle } > { option . text } </ span >
81
- < span className = { styles . siteOptionUrl } > { toRelativeUrl ( option . data ! . url ) } </ span >
82
- </ div >
83
- </ div > ;
84
- } ;
85
108
86
- const getOptions = ( ) : IDropdownOption [ ] => {
109
+ setSelectedSites ( newSelectedSites ) ;
110
+
111
+ } , [ selectedSites , multiSelect , onChange ] ) ;
112
+
113
+ const getOptions = React . useCallback ( ( ) : IDropdownOption [ ] => {
87
114
const result : IDropdownOption [ ] = [ ] ;
88
115
89
116
if ( allowSearch ) {
@@ -107,32 +134,29 @@ export const SitePicker: React.FunctionComponent<ISitePickerProps> = (props: Rea
107
134
} ) ;
108
135
}
109
136
137
+ console . log ( result ) ;
110
138
return result ;
111
- } ;
139
+ } , [ allowSearch , selectedSites , filteredSites ] ) ;
112
140
113
- const onSelectionChange = React . useCallback ( ( e , item : IDropdownOption , index : number ) => {
114
- const newSelectedSites = selectedSites ? [ ...selectedSites ] : [ ] ;
115
-
116
- if ( multiSelect !== false ) {
117
- const existingIndex = findIndex ( newSelectedSites , s => s . id === item . key ) ;
118
-
119
- if ( existingIndex >= 0 ) {
120
- newSelectedSites . splice ( existingIndex , 1 ) ;
121
- }
122
- else {
123
- newSelectedSites . push ( {
124
- ...item . data !
125
- } ) ;
126
- }
141
+ const onRenderOption = ( option ?: ISelectableOption , defaultRender ?: ( props ?: ISelectableOption ) => JSX . Element | null ) : JSX . Element | null => {
142
+ if ( ! props ) {
143
+ return null ;
127
144
}
128
145
129
- if ( onChange ) {
130
- onChange ( newSelectedSites ) ;
146
+ if ( option . itemType === SelectableOptionMenuItemType . Header ) {
147
+ return < SearchBox
148
+ placeholder = { searchPlaceholder }
149
+ value = { searchQuery }
150
+ onChange = { async . debounce ( onSearchChange , deferredSearchTime || 200 ) } /> ;
131
151
}
132
-
133
- setSelectedSites ( newSelectedSites ) ;
134
-
135
- } , [ selectedSites , multiSelect , onChange ] ) ;
152
+ // {multiSelect !== false && <Checkbox className={styles.siteOptionCheckbox} checked={option.selected} disabled={option.disabled} /> }
153
+ return < div className = { styles . siteOption } >
154
+ < div className = { styles . siteOptionContent } >
155
+ < span className = { styles . siteOptionTitle } > { option . text } </ span >
156
+ < span className = { styles . siteOptionUrl } > { toRelativeUrl ( option . data ! . url ) } </ span >
157
+ </ div >
158
+ </ div > ;
159
+ } ;
136
160
137
161
React . useEffect ( ( ) => {
138
162
if ( ! initialSites ) {
@@ -200,11 +224,15 @@ export const SitePicker: React.FunctionComponent<ISitePickerProps> = (props: Rea
200
224
< >
201
225
< Dropdown
202
226
label = { label }
227
+ placeholder = { placeholder }
203
228
options = { getOptions ( ) }
229
+ selectedKey = { multiSelect === false && ! ! selectedSites && ! ! selectedSites [ 0 ] ? selectedSites [ 0 ] . id : undefined }
230
+ selectedKeys = { multiSelect !== false && ! ! selectedSites ? selectedSites . map ( s => s . id ) : undefined }
204
231
disabled = { disabled }
205
232
multiSelect = { multiSelect !== false }
206
233
onRenderOption = { onRenderOption }
207
234
onChange = { onSelectionChange }
235
+ notifyOnReselect = { true }
208
236
/>
209
237
</ >
210
238
) ;
0 commit comments