feat: Implement SharePoint People Picker for selecting starting person and update version to 1.0.3
This commit is contained in:
@@ -4,6 +4,10 @@
|
||||
color: "[theme:bodyText, default:#323130]";
|
||||
font-family: "Segoe UI", "Segoe UI Web (West European)", -apple-system, BlinkMacSystemFont, Roboto, "Helvetica Neue", sans-serif;
|
||||
}
|
||||
.pickerPanel { background: "[theme:neutralLighterAlt, default:#faf9f8]"; border: 1px solid "[theme:neutralLight, default:#edebe9]"; margin-bottom: 16px; padding: 12px; }
|
||||
.pickerLabel { color: "[theme:bodyText, default:#323130]"; display: block; font-size: 14px; font-weight: 600; margin-bottom: 6px; }
|
||||
.pickerDescription { color: "[theme:neutralSecondary, default:#605e5c]"; font-size: 12px; line-height: 17px; margin-top: 6px; }
|
||||
.pickerError { color: "[theme:errorText, default:#a80000]"; font-size: 12px; line-height: 17px; margin-top: 6px; }
|
||||
.header { align-items: baseline; display: flex; justify-content: space-between; margin-bottom: 12px; }
|
||||
.heading { font-size: 24px; font-weight: 300; line-height: 32px; margin: 0; }
|
||||
.count { color: "[theme:neutralSecondary, default:#605e5c]"; font-size: 12px; }
|
||||
|
||||
@@ -0,0 +1,127 @@
|
||||
import * as React from 'react';
|
||||
import {
|
||||
NormalPeoplePicker,
|
||||
ValidationState
|
||||
} from 'office-ui-fabric-react/lib/Pickers';
|
||||
import { IPersonaProps } from 'office-ui-fabric-react/lib/Persona';
|
||||
import { IOrganizationChartPersonSuggestion } from '../OrganizationChartTypes';
|
||||
import styles from './OrganizationChart.module.scss';
|
||||
|
||||
export interface IOrganizationChartPickerItem extends IPersonaProps {
|
||||
accountName: string;
|
||||
key: string;
|
||||
loginName: string;
|
||||
}
|
||||
|
||||
export interface IOrganizationChartPeoplePickerProps {
|
||||
description: string;
|
||||
label: string;
|
||||
loadingText: string;
|
||||
noResultsText: string;
|
||||
onChange: (loginName: string, accountName: string) => void;
|
||||
placeholder: string;
|
||||
removeButtonAriaLabel: string;
|
||||
searchPeople: (query: string) => Promise<IOrganizationChartPersonSuggestion[]>;
|
||||
selectedDisplayName: string;
|
||||
selectedAccountName: string;
|
||||
selectedLoginName: string;
|
||||
suggestionsHeaderText: string;
|
||||
validationErrorText: string;
|
||||
validatePerson: (loginName: string, accountName: string) => Promise<boolean>;
|
||||
}
|
||||
|
||||
export interface IOrganizationChartPeoplePickerState {
|
||||
validationError: string;
|
||||
}
|
||||
|
||||
export class OrganizationChartPeoplePicker
|
||||
extends React.Component<IOrganizationChartPeoplePickerProps, IOrganizationChartPeoplePickerState> {
|
||||
|
||||
public constructor(props: IOrganizationChartPeoplePickerProps) {
|
||||
super(props);
|
||||
this.resolveSuggestions = this.resolveSuggestions.bind(this);
|
||||
this.onSelectionChanged = this.onSelectionChanged.bind(this);
|
||||
this.onItemSelected = this.onItemSelected.bind(this);
|
||||
this.getTextFromItem = this.getTextFromItem.bind(this);
|
||||
this.state = { validationError: '' };
|
||||
}
|
||||
|
||||
public render(): React.ReactElement<HTMLDivElement> {
|
||||
const selectedItems: IOrganizationChartPickerItem[] = this.props.selectedLoginName ? [{
|
||||
key: this.props.selectedLoginName,
|
||||
accountName: this.props.selectedAccountName,
|
||||
loginName: this.props.selectedLoginName,
|
||||
primaryText: this.props.selectedDisplayName || this.props.selectedLoginName,
|
||||
secondaryText: this.props.selectedLoginName
|
||||
}] : [];
|
||||
return (
|
||||
<div className={styles.pickerPanel}>
|
||||
<label className={styles.pickerLabel}>{this.props.label}</label>
|
||||
<NormalPeoplePicker
|
||||
selectedItems={selectedItems}
|
||||
onResolveSuggestions={this.resolveSuggestions}
|
||||
onChange={this.onSelectionChanged}
|
||||
onItemSelected={this.onItemSelected}
|
||||
getTextFromItem={this.getTextFromItem}
|
||||
onValidateInput={(): ValidationState => ValidationState.invalid}
|
||||
itemLimit={1}
|
||||
inputProps={{
|
||||
'aria-label': this.props.label,
|
||||
placeholder: this.props.placeholder
|
||||
}}
|
||||
pickerSuggestionsProps={{
|
||||
loadingText: this.props.loadingText,
|
||||
noResultsFoundText: this.props.noResultsText,
|
||||
suggestionsHeaderText: this.props.suggestionsHeaderText
|
||||
}}
|
||||
removeButtonAriaLabel={this.props.removeButtonAriaLabel}
|
||||
/>
|
||||
{this.state.validationError ?
|
||||
<div className={styles.pickerError} role='alert'>{this.state.validationError}</div> : null}
|
||||
<div className={styles.pickerDescription}>{this.props.description}</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
private resolveSuggestions(filter: string): Promise<IOrganizationChartPickerItem[]> {
|
||||
return this.props.searchPeople(filter).then(
|
||||
(suggestions: IOrganizationChartPersonSuggestion[]): IOrganizationChartPickerItem[] =>
|
||||
suggestions.map((suggestion: IOrganizationChartPersonSuggestion): IOrganizationChartPickerItem => ({
|
||||
key: suggestion.loginName,
|
||||
accountName: suggestion.accountName,
|
||||
loginName: suggestion.loginName,
|
||||
primaryText: suggestion.displayName,
|
||||
secondaryText: suggestion.email || suggestion.accountName || suggestion.loginName
|
||||
})),
|
||||
(): IOrganizationChartPickerItem[] => []
|
||||
);
|
||||
}
|
||||
|
||||
private onSelectionChanged(items?: IOrganizationChartPickerItem[]): void {
|
||||
this.setState({ validationError: '' });
|
||||
this.props.onChange(
|
||||
items && items.length ? items[0].loginName : '',
|
||||
items && items.length ? items[0].accountName : ''
|
||||
);
|
||||
}
|
||||
|
||||
private onItemSelected(item?: IOrganizationChartPickerItem): Promise<IOrganizationChartPickerItem> {
|
||||
if (!item) { return Promise.resolve(undefined as IOrganizationChartPickerItem); }
|
||||
this.setState({ validationError: '' });
|
||||
return this.props.validatePerson(item.loginName, item.accountName).then(
|
||||
(valid: boolean): IOrganizationChartPickerItem => {
|
||||
if (valid) { return item; }
|
||||
this.setState({ validationError: this.props.validationErrorText });
|
||||
return undefined as IOrganizationChartPickerItem;
|
||||
},
|
||||
(): IOrganizationChartPickerItem => {
|
||||
this.setState({ validationError: this.props.validationErrorText });
|
||||
return undefined as IOrganizationChartPickerItem;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
private getTextFromItem(item: IOrganizationChartPickerItem): string {
|
||||
return item.primaryText || item.loginName;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user