Skip to content

Commit 64ba21b

Browse files
committed
functionality is ready
1 parent 6913544 commit 64ba21b

File tree

3 files changed

+55
-23
lines changed

3 files changed

+55
-23
lines changed

src/controls/sitePicker/ISitePicker.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,5 +90,10 @@ export interface ISitePickerProps {
9090
* The list will be filtered after users stop typing for `deferredSearchTime` milliseconds.
9191
* Default value is 200.
9292
*/
93-
deferredSearchTime?: number;
93+
deferredSearchTime?: number;
94+
95+
/**
96+
* If provided, additional class name to provide on the dropdown element.
97+
*/
98+
className?: string;
9499
}

src/controls/sitePicker/SitePicker.tsx

Lines changed: 45 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@ import { Async } from '@uifabric/utilities/lib/Async';
1414
const styles = mergeStyleSets({
1515
loadingSpinnerContainer: {
1616
width: '100%',
17-
textAlign: 'center'
17+
textAlign: 'center',
18+
marginTop: '8px'
1819
},
1920
searchBox: {
2021
margin: '4px 0'
@@ -66,10 +67,11 @@ export const SitePicker: React.FunctionComponent<ISitePickerProps> = (props: Rea
6667
onChange,
6768
placeholder,
6869
searchPlaceholder,
69-
deferredSearchTime
70+
deferredSearchTime,
71+
className
7072
} = props;
7173

72-
const [isLoading, setIsLoading] = React.useState<boolean>(true);
74+
const [isLoading, setIsLoading] = React.useState<boolean>();
7375
const [selectedSites, setSelectedSites] = React.useState<ISite[]>();
7476
const [allSites, setAllSites] = React.useState<ISite[]>();
7577
const [filteredSites, setFilteredSites] = React.useState<ISite[]>();
@@ -88,9 +90,10 @@ export const SitePicker: React.FunctionComponent<ISitePickerProps> = (props: Rea
8890
}, [allSites]);
8991

9092
const onSelectionChange = React.useCallback((e, item: IDropdownOption, index: number) => {
91-
const newSelectedSites = selectedSites ? [...selectedSites] : [];
93+
let newSelectedSites: ISite[] = [];
9294

9395
if (multiSelect !== false) {
96+
newSelectedSites = selectedSites ? [...selectedSites] : [];
9497
const existingIndex = findIndex(newSelectedSites, s => s.url === item.key);
9598

9699
if (existingIndex >= 0) {
@@ -102,6 +105,11 @@ export const SitePicker: React.FunctionComponent<ISitePickerProps> = (props: Rea
102105
});
103106
}
104107
}
108+
else {
109+
newSelectedSites = [{
110+
...item.data!
111+
}];
112+
}
105113

106114
if (onChange) {
107115
onChange(newSelectedSites);
@@ -112,6 +120,15 @@ export const SitePicker: React.FunctionComponent<ISitePickerProps> = (props: Rea
112120
}, [selectedSites, multiSelect, onChange]);
113121

114122
const getOptions = React.useCallback((): IDropdownOption[] => {
123+
124+
if (!allSites) {
125+
return [{
126+
key: 'spinner',
127+
text: '',
128+
itemType: SelectableOptionMenuItemType.Header
129+
}];
130+
}
131+
115132
const result: IDropdownOption[] = [];
116133

117134
if (allowSearch) {
@@ -136,19 +153,32 @@ export const SitePicker: React.FunctionComponent<ISitePickerProps> = (props: Rea
136153
}
137154

138155
return result;
139-
}, [allowSearch, selectedSites, filteredSites]);
156+
}, [allowSearch, selectedSites, filteredSites, allSites]);
140157

141158
const onRenderOption = (option?: ISelectableOption, defaultRender?: (props?: ISelectableOption) => JSX.Element | null): JSX.Element | null => {
142159
if (!props) {
143160
return null;
144161
}
145162

146163
if (option.itemType === SelectableOptionMenuItemType.Header) {
147-
return <SearchBox
148-
placeholder={searchPlaceholder}
149-
value={searchQuery}
150-
onChange={async.debounce(onSearchChange, deferredSearchTime || 200)}
151-
className={styles.searchBox} />;
164+
if (option.key === 'search') {
165+
return <SearchBox
166+
placeholder={searchPlaceholder}
167+
value={searchQuery}
168+
onChange={async.debounce(onSearchChange, deferredSearchTime || 200)}
169+
className={styles.searchBox} />;
170+
}
171+
else if (option.key === 'spinner') {
172+
//
173+
// This happens when the dropdown is opened for the first time.
174+
// That's when we want to load the sites
175+
//
176+
setIsLoading(true);
177+
178+
return <div className={styles.loadingSpinnerContainer}>
179+
<Spinner size={SpinnerSize.medium} />
180+
</div>;
181+
}
152182
}
153183
// {multiSelect !== false && <Checkbox className={styles.siteOptionCheckbox} checked={option.selected} disabled={option.disabled} />}
154184
return <div className={styles.siteOption}>
@@ -174,11 +204,10 @@ export const SitePicker: React.FunctionComponent<ISitePickerProps> = (props: Rea
174204
}, [initialSites]);
175205

176206
React.useEffect(() => {
177-
if (!context) {
207+
if (!context || !isLoading) {
178208
return;
179209
}
180210

181-
setIsLoading(true);
182211
setSearchQuery('');
183212
setFilteredSites([]);
184213

@@ -195,7 +224,8 @@ export const SitePicker: React.FunctionComponent<ISitePickerProps> = (props: Rea
195224
setAllSites(copy);
196225
setIsLoading(false);
197226
});
198-
}, [context, mode, limitToCurrentSiteCollection]);
227+
228+
}, [context, isLoading, mode, limitToCurrentSiteCollection]);
199229

200230
React.useEffect(() => {
201231
setAllSites(sites => {
@@ -215,25 +245,20 @@ export const SitePicker: React.FunctionComponent<ISitePickerProps> = (props: Rea
215245
setFilteredSites([...allSites]);
216246
}, [allSites]);
217247

218-
if (isLoading) {
219-
return <div className={styles.loadingSpinnerContainer}>
220-
<Spinner size={SpinnerSize.medium} />
221-
</div>;
222-
}
223-
224248
return (
225249
<>
226250
<Dropdown
227251
label={label}
228252
placeholder={placeholder}
229253
options={getOptions()}
230254
selectedKey={multiSelect === false && !!selectedSites && !!selectedSites[0] ? selectedSites[0].url : undefined}
231-
selectedKeys = { multiSelect !== false && !!selectedSites ? selectedSites.map(s => s.url) : undefined }
255+
selectedKeys={multiSelect !== false && !!selectedSites ? selectedSites.map(s => s.url) : undefined}
232256
disabled={disabled}
233257
multiSelect={multiSelect !== false}
234258
onRenderOption={onRenderOption}
235259
onChange={onSelectionChange}
236260
notifyOnReselect={true}
261+
className={className}
237262
/>
238263
</>
239264
);

src/webparts/controlsTest/components/ControlsTest.tsx

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1315,10 +1315,12 @@ export default class ControlsTest extends React.Component<IControlsTestProps, IC
13151315
<SitePicker
13161316
context={this.props.context}
13171317
label={'select sites'}
1318-
mode={'web'}
1318+
mode={'site'}
13191319
allowSearch={true}
13201320
multiSelect={false}
1321-
onChange={(sites) => { console.log(sites); }} />
1321+
onChange={(sites) => { console.log(sites); }}
1322+
placeholder={'Select sites'}
1323+
searchPlaceholder={'Filter sites'} />
13221324
</div>
13231325

13241326
<div className="ms-font-m">List picker tester:

0 commit comments

Comments
 (0)