SPFx Office UI Fabric People Picker + SharePoint Search API (#219)

This commit is contained in:
Giuliano De Luca 2017-06-12 12:15:57 +02:00 committed by Vesa Juvonen
parent a03afe573e
commit 2172eff640
33 changed files with 1508 additions and 0 deletions

View File

@ -0,0 +1,25 @@
# EditorConfig helps developers define and maintain consistent
# coding styles between different editors and IDEs
# editorconfig.org
root = true
[*]
# change these settings to your own preference
indent_style = space
indent_size = 2
# we recommend you to keep these unchanged
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
[*.md]
trim_trailing_whitespace = false
[{package,bower}.json]
indent_style = space
indent_size = 2

View File

@ -0,0 +1 @@
* text=auto

32
samples/react-peoplepicker/.gitignore vendored Normal file
View File

@ -0,0 +1,32 @@
# Logs
logs
*.log
npm-debug.log*
# Dependency directories
node_modules
# Build generated files
dist
lib
solution
temp
*.sppkg
# Coverage directory used by tools like istanbul
coverage
# OSX
.DS_Store
# Visual Studio files
.ntvs_analysis.dat
.vs
bin
obj
# Resx Generated Code
*.resx.ts
# Styles Generated Code
*.scss.ts

View File

@ -0,0 +1,14 @@
# Folders
.vscode
coverage
node_modules
sharepoint
src
temp
# Files
*.csproj
.git*
.yo-rc.json
gulpfile.js
tsconfig.json

View File

@ -0,0 +1,7 @@
{
"@microsoft/generator-sharepoint": {
"libraryName": "spfx-office-ui-fabric-people-picker",
"libraryId": "6349ba8f-d5aa-4cbf-87b4-910dad47324b",
"framework": "react"
}
}

View File

@ -0,0 +1,52 @@
# People Picker (React)
## Summary
SharePoint Framework solution with the Office UI Fabric People Picker, the client web part across the SharePoint Search API is able to retrieve people.
![React-People-Picker-gif](./assets/preview.gif)
## Used SharePoint Framework Version
![drop](https://img.shields.io/badge/version-GA-green.svg)
## Applies to
* [SharePoint Framework](https://blogs.office.com/2017/02/23/sharepoint-framework-reaches-general-availability-build-and-deploy-engaging-web-parts-today/)
* [Office 365 tenant](https://dev.office.com/sharepoint/docs/spfx/set-up-your-development-environment)
## Solution
Solution|Author(s)
--------|---------
spfx-react-peoplepicker | Giuliano De Luca ([@giuleon](https://twitter.com/giuleon) , [www.delucagiuliano.com](http://www.delucagiuliano.com))
## Version history
Version|Date|Comments
-------|----|--------
1.0|May 21, 2017|Initial release
## Disclaimer
**THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.**
---
## Minimal Path to Awesome
- Clone this repository
- in the command line run:
- `npm install`
- `gulp serve`
## Features
- Use [TypeScript](https://www.typescriptlang.org) to create the custom property pane control containing the taxonomy picker control.
- Use the SharePoint Search API to grab people.
#### Local Mode
A browser in local mode (localhost) will be opened.
https://localhost:4321/temp/workbench.html
#### SharePoint Mode
If you want to try on a real environment, open:
https://your-domain.sharepoint.com/_layouts/15/workbench.aspx
<img src="https://telemetry.sharepointpnp.com/sp-dev-fx-webparts/samples/react-peoplepicker" />

Binary file not shown.

After

Width:  |  Height:  |  Size: 678 KiB

View File

@ -0,0 +1,13 @@
{
"entries": [
{
"entry": "./lib/webparts/officeUiFabricPeoplePicker/OfficeUiFabricPeoplePickerWebPart.js",
"manifest": "./src/webparts/officeUiFabricPeoplePicker/OfficeUiFabricPeoplePickerWebPart.manifest.json",
"outputPath": "./dist/office-ui-fabric-people-picker.bundle.js"
}
],
"externals": {},
"localizedResources": {
"officeUiFabricPeoplePickerStrings": "webparts/officeUiFabricPeoplePicker/loc/{locale}.js"
}
}

View File

@ -0,0 +1,6 @@
{
"workingDir": "./temp/deploy/",
"account": "<!-- STORAGE ACCOUNT NAME -->",
"container": "spfx-office-ui-fabric-people-picker",
"accessKey": "<!-- ACCESS KEY -->"
}

View File

@ -0,0 +1,10 @@
{
"solution": {
"name": "spfx-office-ui-fabric-people-picker",
"id": "6349ba8f-d5aa-4cbf-87b4-910dad47324b",
"version": "1.0.0.0"
},
"paths": {
"zippedPackage": "solution/spfx-office-ui-fabric-people-picker.sppkg"
}
}

View File

@ -0,0 +1,3 @@
{
"deployCdnPath": "temp/deploy"
}

View File

@ -0,0 +1,9 @@
{
"port": 4321,
"initialPage": "https://localhost:5432/workbench",
"https": true,
"api": {
"port": 5432,
"entryPath": "node_modules/@microsoft/sp-webpart-workbench/lib/api/"
}
}

View File

@ -0,0 +1,50 @@
{
// Display errors as warnings
"displayAsWarning": true,
// The TSLint task may have been configured with several custom lint rules
// before this config file is read (for example lint rules from the tslint-microsoft-contrib
// project). If true, this flag will deactivate any of these rules.
"removeExistingRules": true,
// When true, the TSLint task is configured with some default TSLint "rules.":
"useDefaultConfigAsBase": false,
// Since removeExistingRules=true and useDefaultConfigAsBase=false, there will be no lint rules
// which are active, other than the list of rules below.
"lintConfig": {
// Opt-in to Lint rules which help to eliminate bugs in JavaScript
"rules": {
"class-name": false,
"export-name": false,
"forin": false,
"label-position": false,
"label-undefined": false,
"member-access": true,
"no-arg": false,
"no-console": false,
"no-construct": false,
"no-duplicate-case": true,
"no-duplicate-key": false,
"no-duplicate-variable": true,
"no-eval": false,
"no-function-expression": true,
"no-internal-module": true,
"no-shadowed-variable": true,
"no-switch-case-fall-through": true,
"no-unnecessary-semicolons": true,
"no-unused-expression": true,
"no-unused-imports": true,
"no-unused-variable": true,
"no-unreachable": true,
"no-use-before-declare": true,
"no-with-statement": true,
"semicolon": true,
"trailing-comma": false,
"typedef": false,
"typedef-whitespace": false,
"use-named-parameter": true,
"valid-typeof": true,
"variable-name": false,
"whitespace": false,
"prefer-const": true
}
}
}

View File

@ -0,0 +1,3 @@
{
"cdnBasePath": "<!-- PATH TO CDN -->"
}

View File

@ -0,0 +1,6 @@
'use strict';
const gulp = require('gulp');
const build = require('@microsoft/sp-build-web');
build.initialize(gulp);

View File

@ -0,0 +1,36 @@
{
"name": "spfx-office-ui-fabric-people-picker",
"version": "0.0.1",
"private": true,
"engines": {
"node": ">=0.10.0"
},
"dependencies": {
"@microsoft/sp-client-base": "~0.7.0",
"@microsoft/sp-client-preview": "~0.9.0",
"@microsoft/sp-core-library": "~0.1.2",
"@microsoft/sp-webpart-base": "~0.4.0",
"@types/react": "0.14.46",
"@types/react-addons-shallow-compare": "0.14.17",
"@types/react-addons-test-utils": "0.14.15",
"@types/react-addons-update": "0.14.14",
"@types/react-dom": "0.14.18",
"@types/webpack-env": ">=1.12.1 <1.14.0",
"office-ui-fabric-react": "0.69.0",
"react": "0.14.8",
"react-dom": "0.14.8"
},
"devDependencies": {
"@microsoft/sp-build-web": "~0.9.0",
"@microsoft/sp-module-interfaces": "~0.7.0",
"@microsoft/sp-webpart-workbench": "~0.8.0",
"gulp": "~3.9.1",
"@types/chai": ">=3.4.34 <3.6.0",
"@types/mocha": ">=2.2.33 <2.6.0"
},
"scripts": {
"build": "gulp bundle",
"clean": "gulp clean",
"test": "gulp test"
}
}

View File

@ -0,0 +1,5 @@
var context = require.context('.', true, /.+\.test\.js?$/);
context.keys().forEach(context);
module.exports = context;

View File

@ -0,0 +1,4 @@
export interface IOfficeUiFabricPeoplePickerWebPartProps {
description: string;
typePicker: string;
}

View File

@ -0,0 +1,21 @@
{
"$schema": "../../../node_modules/@microsoft/sp-module-interfaces/lib/manifestSchemas/jsonSchemas/clientSideComponentManifestSchema.json",
"id": "bb13df23-35f7-42c6-8c43-16be4fcd8daa",
"alias": "OfficeUiFabricPeoplePickerWebPart",
"componentType": "WebPart",
"version": "0.0.1",
"manifestVersion": 2,
"preconfiguredEntries": [{
"groupId": "bb13df23-35f7-42c6-8c43-16be4fcd8daa",
"group": { "default": "Under Development" },
"title": { "default": "People Picker" },
"description": { "default": "Office UI Fabric People Picker and SharePoint search better together" },
"officeFabricIconFontName": "AddGroup",
"properties": {
"description": "Office UI Fabric People Picker",
"typePicker": ""
}
}]
}

View File

@ -0,0 +1,63 @@
import * as React from 'react';
import * as ReactDom from 'react-dom';
import { Version } from '@microsoft/sp-core-library';
import {
BaseClientSideWebPart,
IPropertyPaneConfiguration,
PropertyPaneTextField,
PropertyPaneDropdown,
IWebPartContext
} from '@microsoft/sp-webpart-base';
import * as strings from 'officeUiFabricPeoplePickerStrings';
import OfficeUiFabricPeoplePicker from './components/OfficeUiFabricPeoplePicker';
import { IOfficeUiFabricPeoplePickerProps } from './components/IOfficeUiFabricPeoplePickerProps';
import { IOfficeUiFabricPeoplePickerWebPartProps } from './IOfficeUiFabricPeoplePickerWebPartProps';
export default class OfficeUiFabricPeoplePickerWebPart extends BaseClientSideWebPart<IOfficeUiFabricPeoplePickerWebPartProps> {
public render(): void {
const element: React.ReactElement<IOfficeUiFabricPeoplePickerProps> = React.createElement(
OfficeUiFabricPeoplePicker,
{
description: this.properties.description,
spHttpClient: this.context.spHttpClient,
siteUrl: this.context.pageContext.web.absoluteUrl,
typePicker: this.properties.typePicker
}
);
ReactDom.render(element, this.domElement);
}
protected get dataVersion(): Version {
return Version.parse('1.0');
}
protected getPropertyPaneConfiguration(): IPropertyPaneConfiguration {
return {
pages: [
{
header: {
description: strings.PropertyPaneDescription
},
groups: [
{
groupName: strings.BasicGroupName,
groupFields: [
PropertyPaneDropdown('typePicker', {
label: strings.TypePickerLabel,
selectedKey: "Normal",
options: [
{ key: 'Normal', text: 'Normal' },
{ key: 'Compact', text: 'Compact' }
]
}),
]
}
]
}
]
};
}
}

View File

@ -0,0 +1,8 @@
import { SPHttpClient, SPHttpClientResponse } from '@microsoft/sp-http';
export interface IOfficeUiFabricPeoplePickerProps {
description: string;
spHttpClient: SPHttpClient;
siteUrl: string;
typePicker: string;
}

View File

@ -0,0 +1,14 @@
export interface IPeopleDataResult {
RelevantResults: {
TotalRows: number,
Table: {
Rows: [{
Cells: [{
Key: string,
Value: string,
ValueType: string,
}]
}]
}
}
}

View File

@ -0,0 +1,23 @@
.helloWorld {
.container {
max-width: 700px;
margin: 0px auto;
box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.2), 0 25px 50px 0 rgba(0, 0, 0, 0.1);
}
.row {
padding: 20px;
}
.listItem {
max-width: 715px;
margin: 5px auto 5px auto;
box-shadow: 0 0 4px 0 rgba(0, 0, 0, 0.2), 0 25px 50px 0 rgba(0, 0, 0, 0.1);
}
.button {
text-decoration: none;
}
}

View File

@ -0,0 +1,186 @@
import * as React from 'react';
import { css } from 'office-ui-fabric-react';
import styles from './OfficeUiFabricPeoplePicker.module.scss';
import { IOfficeUiFabricPeoplePickerProps } from './IOfficeUiFabricPeoplePickerProps';
import {
CompactPeoplePicker,
IBasePickerSuggestionsProps,
ListPeoplePicker,
NormalPeoplePicker
} from 'office-ui-fabric-react/lib/Pickers';
import { IPersonaProps } from 'office-ui-fabric-react/lib/Persona';
const suggestionProps: IBasePickerSuggestionsProps = {
suggestionsHeaderText: 'Suggested People',
noResultsFoundText: 'No results found',
loadingText: 'Loading'
};
import {
BaseComponent,
assign,
autobind
} from 'office-ui-fabric-react/lib//Utilities';
import { people } from './PeoplePickerExampleData';
import { Label } from 'office-ui-fabric-react/lib/Label';
import { IPeopleDataResult } from './IPeopleDataResult';
import { IPersonaWithMenu } from 'office-ui-fabric-react/lib/components/pickers/PeoplePicker/PeoplePickerItems/PeoplePickerItem.Props';
import { IContextualMenuItem } from 'office-ui-fabric-react/lib/ContextualMenu';
import { SPHttpClient, SPHttpClientResponse } from '@microsoft/sp-http';
export interface IOfficeUiFabricPeoplePickerState {
currentPicker?: number | string;
delayResults?: boolean;
}
export interface IPeopleSearchProps {
JobTitle: string;
PictureURL: string;
PreferredName: string;
}
export default class OfficeUiFabricPeoplePicker extends React.Component<IOfficeUiFabricPeoplePickerProps, IOfficeUiFabricPeoplePickerState> {
private _peopleList;
private contextualMenuItems: IContextualMenuItem[] = [
{
key: 'newItem',
icon: 'circlePlus',
name: 'New'
},
{
key: 'upload',
icon: 'upload',
name: 'Upload'
},
{
key: 'divider_1',
name: '-',
},
{
key: 'rename',
name: 'Rename'
},
{
key: 'properties',
name: 'Properties'
},
{
key: 'disabled',
name: 'Disabled item',
disabled: true
}
];
constructor() {
super();
this._peopleList = [];
people.forEach((persona: IPersonaProps) => {
let target: IPersonaWithMenu = {};
assign(target, persona, { menuItems: this.contextualMenuItems });
this._peopleList.push(target);
});
this.state = {
currentPicker: 1,
delayResults: false
};
}
public render(): React.ReactElement<IOfficeUiFabricPeoplePickerProps> {
if (this.props.typePicker == "Normal") {
return (
<NormalPeoplePicker
onResolveSuggestions={this._onFilterChanged}
getTextFromItem={(persona: IPersonaProps) => persona.primaryText}
pickerSuggestionsProps={suggestionProps}
className={'ms-PeoplePicker'}
key={'normal'}
/>
);
} else {
return (
<CompactPeoplePicker
onResolveSuggestions={this._onFilterChanged}
getTextFromItem={(persona: IPersonaProps) => persona.primaryText}
pickerSuggestionsProps={suggestionProps}
className={'ms-PeoplePicker'}
key={'normal'}
/>
);
}
}
@autobind
private _onFilterChanged(filterText: string, currentPersonas: IPersonaProps[], limitResults?: number) {
if (filterText) {
if (filterText.length > 4) {
return this.searchPeople(filterText, this._peopleList);
}
} else {
return [];
}
}
private searchPeople(terms: string, results: IPersonaProps[]): IPersonaProps[] | Promise<IPersonaProps[]> {
//return new Promise<IPersonaProps[]>((resolve, reject) => setTimeout(() => resolve(results), 2000));
return new Promise<IPersonaProps[]>((resolve, reject) =>
this.props.spHttpClient.get(`${this.props.siteUrl}/_api/search/query?querytext='*${terms}*'&rowlimit=10&sourceid='b09a7990-05ea-4af9-81ef-edfab16c4e31'`,
SPHttpClient.configurations.v1,
{
headers: {
'Accept': 'application/json;odata=nometadata',
'odata-version': ''
}
})
.then((response: SPHttpClientResponse): Promise<{ PrimaryQueryResult: IPeopleDataResult }> => {
return response.json();
})
.then((response: { PrimaryQueryResult: IPeopleDataResult }): void => {
let relevantResults: any = response.PrimaryQueryResult.RelevantResults;
let resultCount: number = relevantResults.TotalRows;
let people = [];
let persona: IPersonaProps = {};
if (resultCount > 0) {
relevantResults.Table.Rows.forEach(function (row) {
row.Cells.forEach(function (cell) {
//person[cell.Key] = cell.Value;
if (cell.Key === 'JobTitle')
persona.secondaryText = cell.Value;
if (cell.Key === 'PictureURL')
persona.imageUrl = cell.Value;
if (cell.Key === 'PreferredName')
persona.primaryText = cell.Value;
});
people.push(persona);
});
}
resolve(people);
}, (error: any): void => {
reject(this._peopleList = []);
}));
}
private _filterPersonasByText(filterText: string): IPersonaProps[] {
return this._peopleList.filter(item => this._doesTextStartWith(item.primaryText, filterText));
}
private _removeDuplicates(personas: IPersonaProps[], possibleDupes: IPersonaProps[]) {
return personas.filter(persona => !this._listContainsPersona(persona, possibleDupes));
}
private _listContainsPersona(persona: IPersonaProps, personas: IPersonaProps[]) {
if (!personas || !personas.length || personas.length === 0) {
return false;
}
return personas.filter(item => item.primaryText === persona.primaryText).length > 0;
}
private _filterPromise(personasToReturn: IPersonaProps[]): IPersonaProps[] | Promise<IPersonaProps[]> {
if (this.state.delayResults) {
return this._convertResultsToPromise(personasToReturn);
} else {
return personasToReturn;
}
}
private _convertResultsToPromise(results: IPersonaProps[]): Promise<IPersonaProps[]> {
return new Promise<IPersonaProps[]>((resolve, reject) => setTimeout(() => resolve(results), 2000));
}
private _doesTextStartWith(text: string, filterText: string): boolean {
return text.toLowerCase().indexOf(filterText.toLowerCase()) === 0;
}
}

View File

@ -0,0 +1,220 @@
import { IPersonaProps } from 'office-ui-fabric-react/lib/Persona';
export const people: IPersonaProps[] = [
{
key: 0,
imageUrl: './images/persona-female.png',
imageInitials: 'PV',
primaryText: 'Annie Lindqvist',
secondaryText: 'Designer',
tertiaryText: 'In a meeting',
optionalText: 'Available at 4:00pm'
},
{
key: 1,
imageUrl: './images/persona-male.png',
imageInitials: 'AR',
primaryText: 'Aaron Reid',
secondaryText: 'Designer',
tertiaryText: 'In a meeting',
optionalText: 'Available at 4:00pm'
},
{
key: 2,
imageUrl: './images/persona-male.png',
imageInitials: 'AL',
primaryText: 'Alex Lundberg',
secondaryText: 'Software Developer',
tertiaryText: 'In a meeting',
optionalText: 'Available at 4:00pm'
},
{
key: 3,
imageUrl: './images/persona-male.png',
imageInitials: 'RK',
primaryText: 'Roko Kolar',
secondaryText: 'Financial Analyst',
tertiaryText: 'In a meeting',
optionalText: 'Available at 4:00pm'
},
{
key: 4,
imageUrl: './images/persona-male.png',
imageInitials: 'CB',
primaryText: 'Christian Bergqvist',
secondaryText: 'Sr. Designer',
tertiaryText: 'In a meeting',
optionalText: 'Available at 4:00pm'
},
{
key: 5,
imageUrl: './images/persona-female.png',
imageInitials: 'VL',
primaryText: 'Valentina Lovric',
secondaryText: 'Design Developer',
tertiaryText: 'In a meeting',
optionalText: 'Available at 4:00pm'
},
{
key: 6,
imageUrl: './images/persona-male.png',
imageInitials: 'MS',
primaryText: 'Maor Sharett',
secondaryText: 'UX Designer',
tertiaryText: 'In a meeting',
optionalText: 'Available at 4:00pm'
},
{
key: 7,
imageUrl: './images/persona-female.png',
imageInitials: 'PV',
primaryText: 'Anny Lindqvist',
secondaryText: 'Designer',
tertiaryText: 'In a meeting',
optionalText: 'Available at 4:00pm'
},
{
key: 8,
imageUrl: './images/persona-male.png',
imageInitials: 'AR',
primaryText: 'Aron Reid',
secondaryText: 'Designer',
tertiaryText: 'In a meeting',
optionalText: 'Available at 4:00pm'
},
{
key: 9,
imageUrl: './images/persona-male.png',
imageInitials: 'AL',
primaryText: 'Alix Lundberg',
secondaryText: 'Software Developer',
tertiaryText: 'In a meeting',
optionalText: 'Available at 4:00pm'
},
{
key: 10,
imageUrl: './images/persona-male.png',
imageInitials: 'RK',
primaryText: 'Roko Kular',
secondaryText: 'Financial Analyst',
tertiaryText: 'In a meeting',
optionalText: 'Available at 4:00pm'
},
{
key: 11,
imageUrl: './images/persona-male.png',
imageInitials: 'CB',
primaryText: 'Christian Bergqvest',
secondaryText: 'Sr. Designer',
tertiaryText: 'In a meeting',
optionalText: 'Available at 4:00pm'
},
{
key: 12,
imageUrl: './images/persona-female.png',
imageInitials: 'VL',
primaryText: 'Valintina Lovric',
secondaryText: 'Design Developer',
tertiaryText: 'In a meeting',
optionalText: 'Available at 4:00pm'
},
{
key: 13,
imageUrl: './images/persona-male.png',
imageInitials: 'MS',
primaryText: 'Maor Sharet',
secondaryText: 'UX Designer',
tertiaryText: 'In a meeting',
optionalText: 'Available at 4:00pm'
},
{
key: 14,
imageUrl: './images/persona-female.png',
imageInitials: 'VL',
primaryText: 'Anny Lindqvest',
secondaryText: 'SDE',
tertiaryText: 'In a meeting',
optionalText: 'Available at 4:00pm'
},
{
key: 15,
imageUrl: './images/persona-male.png',
imageInitials: 'MS',
primaryText: 'Alix Lunberg',
secondaryText: 'SE',
tertiaryText: 'In a meeting',
optionalText: 'Available at 4:00pm'
},
{
key: 16,
imageUrl: './images/persona-female.png',
imageInitials: 'VL',
primaryText: 'Annie Lindqvest',
secondaryText: 'SDET',
tertiaryText: 'In a meeting',
optionalText: 'Available at 4:00pm'
},
{
key: 17,
imageUrl: './images/persona-male.png',
imageInitials: 'MS',
primaryText: 'Alixander Lundberg',
secondaryText: 'Senior Manager of SDET',
tertiaryText: 'In a meeting',
optionalText: 'Available at 4:00pm'
},
{
key: 18,
imageUrl: './images/persona-female.png',
imageInitials: 'VL',
primaryText: 'Anny Lundqvist',
secondaryText: 'Junior Manager of Software',
tertiaryText: 'In a meeting',
optionalText: 'Available at 4:00pm'
},
{
key: 13,
imageUrl: './images/persona-male.png',
imageInitials: 'MS',
primaryText: 'Maor Shorett',
secondaryText: 'UX Designer',
tertiaryText: 'In a meeting',
optionalText: 'Available at 4:00pm'
},
{
key: 12,
imageUrl: './images/persona-female.png',
imageInitials: 'VL',
primaryText: 'Valentina Lovrics',
secondaryText: 'Design Developer',
tertiaryText: 'In a meeting',
optionalText: 'Available at 4:00pm'
},
{
key: 13,
imageUrl: './images/persona-male.png',
imageInitials: 'MS',
primaryText: 'Maor Sharet',
secondaryText: 'UX Designer',
tertiaryText: 'In a meeting',
optionalText: 'Available at 4:00pm'
},
{
key: 12,
imageUrl: './images/persona-female.png',
imageInitials: 'VL',
primaryText: 'Valentina Lovrecs',
secondaryText: 'Design Developer',
tertiaryText: 'In a meeting',
optionalText: 'Available at 4:00pm'
},
{
key: 13,
imageUrl: './images/persona-male.png',
imageInitials: 'MS',
primaryText: 'Maor Sharitt',
secondaryText: 'UX Designer',
tertiaryText: 'In a meeting',
optionalText: 'Available at 4:00pm'
},
];

View File

@ -0,0 +1,8 @@
define([], function() {
return {
"PropertyPaneDescription": "Description",
"BasicGroupName": "Group Name",
"DescriptionFieldLabel": "Description Field",
"TypePickerLabel": "Choose the type of People Picker"
}
});

View File

@ -0,0 +1,11 @@
declare interface IOfficeUiFabricPeoplePickerStrings {
PropertyPaneDescription: string;
BasicGroupName: string;
DescriptionFieldLabel: string;
TypePickerLabel: string;
}
declare module 'officeUiFabricPeoplePickerStrings' {
const strings: IOfficeUiFabricPeoplePickerStrings;
export = strings;
}

View File

@ -0,0 +1,9 @@
/// <reference types="mocha" />
import { assert } from 'chai';
describe('OfficeUiFabricPeoplePickerWebPart', () => {
it('should do something', () => {
assert.ok(true);
});
});

View File

@ -0,0 +1,15 @@
{
"compilerOptions": {
"target": "es5",
"forceConsistentCasingInFileNames": true,
"module": "commonjs",
"jsx": "react",
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"declaration": true,
"sourceMap": true,
"types": [
"webpack-env"
]
}
}

View File

@ -0,0 +1,5 @@
// Type definitions for Microsoft ODSP projects
// Project: ODSP
/* Global definition for UNIT_TEST builds */
declare const UNIT_TEST: boolean;

View File

@ -0,0 +1,15 @@
// Type definitions for assertion-error 1.0.0
// Project: https://github.com/chaijs/assertion-error
// Definitions by: Bart van der Schoor <https://github.com/Bartvds>
// Definitions: https://github.com/borisyankov/DefinitelyTyped
declare module 'assertion-error' {
class AssertionError implements Error {
constructor(message: string, props?: any, ssf?: Function);
name: string;
message: string;
showDiff: boolean;
stack: string;
}
export = AssertionError;
}

View File

@ -0,0 +1,631 @@
// Type definitions for Knockout v3.2.0
// Project: http://knockoutjs.com
// Definitions by: Boris Yankov <https://github.com/borisyankov/>, Igor Oleinikov <https://github.com/Igorbek/>, Clément Bourgeois <https://github.com/moonpyk/>
// Definitions: https://github.com/borisyankov/DefinitelyTyped
interface KnockoutSubscribableFunctions<T> {
[key: string]: KnockoutBindingHandler;
notifySubscribers(valueToWrite?: T, event?: string): void;
}
interface KnockoutComputedFunctions<T> {
[key: string]: KnockoutBindingHandler;
}
interface KnockoutObservableFunctions<T> {
[key: string]: KnockoutBindingHandler;
equalityComparer(a: any, b: any): boolean;
}
interface KnockoutObservableArrayFunctions<T> {
// General Array functions
indexOf(searchElement: T, fromIndex?: number): number;
slice(start: number, end?: number): T[];
splice(start: number): T[];
splice(start: number, deleteCount: number, ...items: T[]): T[];
pop(): T;
push(...items: T[]): void;
shift(): T;
unshift(...items: T[]): number;
reverse(): KnockoutObservableArray<T>;
sort(): KnockoutObservableArray<T>;
sort(compareFunction: (left: T, right: T) => number): KnockoutObservableArray<T>;
// Ko specific
[key: string]: KnockoutBindingHandler;
replace(oldItem: T, newItem: T): void;
remove(item: T): T[];
remove(removeFunction: (item: T) => boolean): T[];
removeAll(items: T[]): T[];
removeAll(): T[];
destroy(item: T): void;
destroy(destroyFunction: (item: T) => boolean): void;
destroyAll(items: T[]): void;
destroyAll(): void;
}
interface KnockoutSubscribableStatic {
fn: KnockoutSubscribableFunctions<any>;
new <T>(): KnockoutSubscribable<T>;
}
interface KnockoutSubscription {
dispose(): void;
}
interface KnockoutSubscribable<T> extends KnockoutSubscribableFunctions<T> {
subscribe(callback: (newValue: T) => void, target?: any, event?: string): KnockoutSubscription;
subscribe<TEvent>(callback: (newValue: TEvent) => void, target: any, event: string): KnockoutSubscription;
extend(requestedExtenders: { [key: string]: any; }): KnockoutSubscribable<T>;
getSubscriptionsCount(): number;
}
interface KnockoutComputedStatic {
fn: KnockoutComputedFunctions<any>;
<T>(): KnockoutComputed<T>;
<T>(func: () => T, context?: any, options?: any): KnockoutComputed<T>;
<T>(def: KnockoutComputedDefine<T>, context?: any): KnockoutComputed<T>;
}
interface KnockoutComputed<T> extends KnockoutObservable<T>, KnockoutComputedFunctions<T> {
fn: KnockoutComputedFunctions<any>;
dispose(): void;
isActive(): boolean;
getDependenciesCount(): number;
extend(requestedExtenders: { [key: string]: any; }): KnockoutComputed<T>;
}
interface KnockoutObservableArrayStatic {
fn: KnockoutObservableArrayFunctions<any>;
<T>(value?: T[]): KnockoutObservableArray<T>;
}
interface KnockoutObservableArray<T> extends KnockoutObservable<T[]>, KnockoutObservableArrayFunctions<T> {
extend(requestedExtenders: { [key: string]: any; }): KnockoutObservableArray<T>;
}
interface KnockoutObservableStatic {
fn: KnockoutObservableFunctions<any>;
<T>(value?: T): KnockoutObservable<T>;
}
interface KnockoutObservable<T> extends KnockoutSubscribable<T>, KnockoutObservableFunctions<T> {
(): T;
(value: T): void;
peek(): T;
valueHasMutated?:{(): void;};
valueWillMutate?:{(): void;};
extend(requestedExtenders: { [key: string]: any; }): KnockoutObservable<T>;
}
interface KnockoutComputedDefine<T> {
read(): T;
write? (value: T): void;
disposeWhenNodeIsRemoved?: Node;
disposeWhen? (): boolean;
owner?: any;
deferEvaluation?: boolean;
pure?: boolean;
}
interface KnockoutBindingContext {
$parent: any;
$parents: any[];
$root: any;
$data: any;
$rawData: any | KnockoutObservable<any>;
$index?: KnockoutObservable<number>;
$parentContext?: KnockoutBindingContext;
$component: any;
$componentTemplateNodes: Node[];
extend(properties: any): any;
createChildContext(dataItemOrAccessor: any, dataItemAlias?: any, extendCallback?: Function): any;
}
interface KnockoutAllBindingsAccessor {
(): any;
get(name: string): any;
has(name: string): boolean;
}
interface KnockoutBindingHandler {
after?: Array<string>;
init?: (element: any, valueAccessor: () => any, allBindingsAccessor?: KnockoutAllBindingsAccessor, viewModel?: any, bindingContext?: KnockoutBindingContext) => void | { controlsDescendantBindings: boolean; };
update?: (element: any, valueAccessor: () => any, allBindingsAccessor?: KnockoutAllBindingsAccessor, viewModel?: any, bindingContext?: KnockoutBindingContext) => void;
options?: any;
preprocess?: (value: string, name: string, addBindingCallback?: (name: string, value: string) => void) => string;
}
interface KnockoutBindingHandlers {
[bindingHandler: string]: KnockoutBindingHandler;
// Controlling text and appearance
visible: KnockoutBindingHandler;
text: KnockoutBindingHandler;
html: KnockoutBindingHandler;
css: KnockoutBindingHandler;
style: KnockoutBindingHandler;
attr: KnockoutBindingHandler;
// Control Flow
foreach: KnockoutBindingHandler;
if: KnockoutBindingHandler;
ifnot: KnockoutBindingHandler;
with: KnockoutBindingHandler;
// Working with form fields
click: KnockoutBindingHandler;
event: KnockoutBindingHandler;
submit: KnockoutBindingHandler;
enable: KnockoutBindingHandler;
disable: KnockoutBindingHandler;
value: KnockoutBindingHandler;
textInput: KnockoutBindingHandler;
hasfocus: KnockoutBindingHandler;
checked: KnockoutBindingHandler;
options: KnockoutBindingHandler;
selectedOptions: KnockoutBindingHandler;
uniqueName: KnockoutBindingHandler;
// Rendering templates
template: KnockoutBindingHandler;
// Components (new for v3.2)
component: KnockoutBindingHandler;
}
interface KnockoutMemoization {
memoize(callback: () => string): string;
unmemoize(memoId: string, callbackParams: any[]): boolean;
unmemoizeDomNodeAndDescendants(domNode: any, extraCallbackParamsArray: any[]): boolean;
parseMemoText(memoText: string): string;
}
interface KnockoutVirtualElement {}
interface KnockoutVirtualElements {
allowedBindings: { [bindingName: string]: boolean; };
emptyNode(node: KnockoutVirtualElement ): void;
firstChild(node: KnockoutVirtualElement ): KnockoutVirtualElement;
insertAfter( container: KnockoutVirtualElement, nodeToInsert: Node, insertAfter: Node ): void;
nextSibling(node: KnockoutVirtualElement): Node;
prepend(node: KnockoutVirtualElement, toInsert: Node ): void;
setDomNodeChildren(node: KnockoutVirtualElement, newChildren: { length: number;[index: number]: Node; } ): void;
childNodes(node: KnockoutVirtualElement ): Node[];
}
interface KnockoutExtenders {
throttle(target: any, timeout: number): KnockoutComputed<any>;
notify(target: any, notifyWhen: string): any;
rateLimit(target: any, timeout: number): any;
rateLimit(target: any, options: { timeout: number; method?: string; }): any;
trackArrayChanges(target: any): any;
}
//
// NOTE TO MAINTAINERS AND CONTRIBUTORS : pay attention to only include symbols that are
// publicly exported in the minified version of ko, without that you can give the false
// impression that some functions will be available in production builds.
//
interface KnockoutUtils {
//////////////////////////////////
// utils.domData.js
//////////////////////////////////
domData: {
get (node: Element, key: string): any;
set (node: Element, key: string, value: any): void;
getAll(node: Element, createIfNotFound: boolean): any;
clear(node: Element): boolean;
};
//////////////////////////////////
// utils.domNodeDisposal.js
//////////////////////////////////
domNodeDisposal: {
addDisposeCallback(node: Element, callback: Function): void;
removeDisposeCallback(node: Element, callback: Function): void;
cleanNode(node: Node): Element;
removeNode(node: Node): void;
};
addOrRemoveItem<T>(array: T[] | KnockoutObservable<T>, value: T, included: T): void;
arrayFilter<T>(array: T[], predicate: (item: T) => boolean): T[];
arrayFirst<T>(array: T[], predicate: (item: T) => boolean, predicateOwner?: any): T;
arrayForEach<T>(array: T[], action: (item: T, index: number) => void): void;
arrayGetDistinctValues<T>(array: T[]): T[];
arrayIndexOf<T>(array: T[], item: T): number;
arrayMap<T, U>(array: T[], mapping: (item: T) => U): U[];
arrayPushAll<T>(array: T[] | KnockoutObservableArray<T>, valuesToPush: T[]): T[];
arrayRemoveItem(array: any[], itemToRemove: any): void;
compareArrays<T>(a: T[], b: T[]): Array<KnockoutArrayChange<T>>;
extend(target: Object, source: Object): Object;
fieldsIncludedWithJsonPost: any[];
getFormFields(form: any, fieldName: string): any[];
objectForEach(obj: any, action: (key: any, value: any) => void): void;
parseHtmlFragment(html: string): any[];
parseJson(jsonString: string): any;
postJson(urlOrForm: any, data: any, options: any): void;
peekObservable<T>(value: KnockoutObservable<T>): T;
range(min: any, max: any): any;
registerEventHandler(element: any, eventType: any, handler: Function): void;
setHtml(node: Element, html: () => string): void;
setHtml(node: Element, html: string): void;
setTextContent(element: any, textContent: string | KnockoutObservable<string>): void;
stringifyJson(data: any, replacer?: Function, space?: string): string;
toggleDomNodeCssClass(node: any, className: string, shouldHaveClass: boolean): void;
triggerEvent(element: any, eventType: any): void;
unwrapObservable<T>(value: KnockoutObservable<T> | T): T;
// NOT PART OF THE MINIFIED API SURFACE (ONLY IN knockout-{version}.debug.js) https://github.com/SteveSanderson/knockout/issues/670
// forceRefresh(node: any): void;
// ieVersion: number;
// isIe6: boolean;
// isIe7: boolean;
// jQueryHtmlParse(html: string): any[];
// makeArray(arrayLikeObject: any): any[];
// moveCleanedNodesToContainerElement(nodes: any[]): HTMLElement;
// replaceDomNodes(nodeToReplaceOrNodeArray: any, newNodesArray: any[]): void;
// setDomNodeChildren(domNode: any, childNodes: any[]): void;
// setElementName(element: any, name: string): void;
// setOptionNodeSelectionState(optionNode: any, isSelected: boolean): void;
// simpleHtmlParse(html: string): any[];
// stringStartsWith(str: string, startsWith: string): boolean;
// stringTokenize(str: string, delimiter: string): string[];
// stringTrim(str: string): string;
// tagNameLower(element: any): string;
}
interface KnockoutArrayChange<T> {
status: string;
value: T;
index: number;
moved?: number;
}
//////////////////////////////////
// templateSources.js
//////////////////////////////////
interface KnockoutTemplateSourcesDomElement {
text(): any;
text(value: any): void;
data(key: string): any;
data(key: string, value: any): any;
}
interface KnockoutTemplateAnonymous extends KnockoutTemplateSourcesDomElement {
nodes(): any;
nodes(value: any): void;
}
interface KnockoutTemplateSources {
domElement: {
prototype: KnockoutTemplateSourcesDomElement
new (element: Element): KnockoutTemplateSourcesDomElement
};
anonymousTemplate: {
prototype: KnockoutTemplateAnonymous;
new (element: Element): KnockoutTemplateAnonymous;
};
}
//////////////////////////////////
// nativeTemplateEngine.js
//////////////////////////////////
interface KnockoutNativeTemplateEngine {
renderTemplateSource(templateSource: Object, bindingContext?: KnockoutBindingContext, options?: Object): any[];
}
//////////////////////////////////
// templateEngine.js
//////////////////////////////////
interface KnockoutTemplateEngine extends KnockoutNativeTemplateEngine {
createJavaScriptEvaluatorBlock(script: string): string;
makeTemplateSource(template: any, templateDocument?: Document): any;
renderTemplate(template: any, bindingContext: KnockoutBindingContext, options: Object, templateDocument: Document): any;
isTemplateRewritten(template: any, templateDocument: Document): boolean;
rewriteTemplate(template: any, rewriterCallback: Function, templateDocument: Document): void;
}
/////////////////////////////////
interface KnockoutStatic {
utils: KnockoutUtils;
memoization: KnockoutMemoization;
bindingHandlers: KnockoutBindingHandlers;
getBindingHandler(handler: string): KnockoutBindingHandler;
virtualElements: KnockoutVirtualElements;
extenders: KnockoutExtenders;
applyBindings(viewModelOrBindingContext?: any, rootNode?: any): void;
applyBindingsToDescendants(viewModelOrBindingContext: any, rootNode: any): void;
applyBindingAccessorsToNode(node: Node, bindings: (bindingContext: KnockoutBindingContext, node: Node) => {}, bindingContext: KnockoutBindingContext): void;
applyBindingAccessorsToNode(node: Node, bindings: {}, bindingContext: KnockoutBindingContext): void;
applyBindingAccessorsToNode(node: Node, bindings: (bindingContext: KnockoutBindingContext, node: Node) => {}, viewModel: any): void;
applyBindingAccessorsToNode(node: Node, bindings: {}, viewModel: any): void;
applyBindingsToNode(node: Node, bindings: any, viewModelOrBindingContext?: any): any;
subscribable: KnockoutSubscribableStatic;
observable: KnockoutObservableStatic;
computed: KnockoutComputedStatic;
pureComputed<T>(evaluatorFunction: () => T, context?: any): KnockoutComputed<T>;
pureComputed<T>(options: KnockoutComputedDefine<T>, context?: any): KnockoutComputed<T>;
observableArray: KnockoutObservableArrayStatic;
contextFor(node: any): any;
isSubscribable(instance: any): boolean;
toJSON(viewModel: any, replacer?: Function, space?: any): string;
toJS(viewModel: any): any;
isObservable(instance: any): boolean;
isWriteableObservable(instance: any): boolean;
isComputed(instance: any): boolean;
dataFor(node: any): any;
removeNode(node: Element): void;
cleanNode(node: Element): Element;
renderTemplate(template: Function, viewModel: any, options?: any, target?: any, renderMode?: any): any;
renderTemplate(template: string, viewModel: any, options?: any, target?: any, renderMode?: any): any;
unwrap<T>(value: KnockoutObservable<T> | T): T;
computedContext: KnockoutComputedContext;
//////////////////////////////////
// templateSources.js
//////////////////////////////////
templateSources: KnockoutTemplateSources;
//////////////////////////////////
// templateEngine.js
//////////////////////////////////
templateEngine: {
prototype: KnockoutTemplateEngine;
new (): KnockoutTemplateEngine;
};
//////////////////////////////////
// templateRewriting.js
//////////////////////////////////
templateRewriting: {
ensureTemplateIsRewritten(template: Node, templateEngine: KnockoutTemplateEngine, templateDocument: Document): any;
ensureTemplateIsRewritten(template: string, templateEngine: KnockoutTemplateEngine, templateDocument: Document): any;
memoizeBindingAttributeSyntax(htmlString: string, templateEngine: KnockoutTemplateEngine): any;
applyMemoizedBindingsToNextSibling(bindings: any, nodeName: string): string;
};
//////////////////////////////////
// nativeTemplateEngine.js
//////////////////////////////////
nativeTemplateEngine: {
prototype: KnockoutNativeTemplateEngine;
new (): KnockoutNativeTemplateEngine;
instance: KnockoutNativeTemplateEngine;
};
//////////////////////////////////
// jqueryTmplTemplateEngine.js
//////////////////////////////////
jqueryTmplTemplateEngine: {
prototype: KnockoutTemplateEngine;
renderTemplateSource(templateSource: Object, bindingContext: KnockoutBindingContext, options: Object): Node[];
createJavaScriptEvaluatorBlock(script: string): string;
addTemplate(templateName: string, templateMarkup: string): void;
};
//////////////////////////////////
// templating.js
//////////////////////////////////
setTemplateEngine(templateEngine: KnockoutNativeTemplateEngine): void;
renderTemplate(template: Function, dataOrBindingContext: KnockoutBindingContext, options: Object, targetNodeOrNodeArray: Node, renderMode: string): any;
renderTemplate(template: any, dataOrBindingContext: KnockoutBindingContext, options: Object, targetNodeOrNodeArray: Node, renderMode: string): any;
renderTemplate(template: Function, dataOrBindingContext: any, options: Object, targetNodeOrNodeArray: Node, renderMode: string): any;
renderTemplate(template: any, dataOrBindingContext: any, options: Object, targetNodeOrNodeArray: Node, renderMode: string): any;
renderTemplate(template: Function, dataOrBindingContext: KnockoutBindingContext, options: Object, targetNodeOrNodeArray: Node[], renderMode: string): any;
renderTemplate(template: any, dataOrBindingContext: KnockoutBindingContext, options: Object, targetNodeOrNodeArray: Node[], renderMode: string): any;
renderTemplate(template: Function, dataOrBindingContext: any, options: Object, targetNodeOrNodeArray: Node[], renderMode: string): any;
renderTemplate(template: any, dataOrBindingContext: any, options: Object, targetNodeOrNodeArray: Node[], renderMode: string): any;
renderTemplateForEach(template: Function, arrayOrObservableArray: any[], options: Object, targetNode: Node, parentBindingContext: KnockoutBindingContext): any;
renderTemplateForEach(template: any, arrayOrObservableArray: any[], options: Object, targetNode: Node, parentBindingContext: KnockoutBindingContext): any;
renderTemplateForEach(template: Function, arrayOrObservableArray: KnockoutObservable<any>, options: Object, targetNode: Node, parentBindingContext: KnockoutBindingContext): any;
renderTemplateForEach(template: any, arrayOrObservableArray: KnockoutObservable<any>, options: Object, targetNode: Node, parentBindingContext: KnockoutBindingContext): any;
expressionRewriting: {
bindingRewriteValidators: any;
parseObjectLiteral: { (objectLiteralString: string): any[] }
};
/////////////////////////////////
bindingProvider: {
instance: KnockoutBindingProvider;
new (): KnockoutBindingProvider;
}
/////////////////////////////////
// selectExtensions.js
/////////////////////////////////
selectExtensions: {
readValue(element: HTMLElement): any;
writeValue(element: HTMLElement, value: any): void;
};
components: KnockoutComponents;
}
interface KnockoutBindingProvider {
nodeHasBindings(node: Node): boolean;
getBindings(node: Node, bindingContext: KnockoutBindingContext): {};
getBindingAccessors?(node: Node, bindingContext: KnockoutBindingContext): { [key: string]: string; };
}
interface KnockoutComputedContext {
getDependenciesCount(): number;
isInitial: () => boolean;
isSleeping: boolean;
}
//
// refactored types into a namespace to reduce global pollution
// and used Union Types to simplify overloads (requires TypeScript 1.4)
//
declare module KnockoutComponentTypes {
interface Config {
viewModel?: ViewModelFunction | ViewModelSharedInstance | ViewModelFactoryFunction | AMDModule;
template: string | Node[]| DocumentFragment | TemplateElement | AMDModule;
synchronous?: boolean;
}
interface ComponentConfig {
viewModel?: ViewModelFunction | ViewModelSharedInstance | ViewModelFactoryFunction | AMDModule;
template: any;
createViewModel?: any;
}
interface EmptyConfig {
}
// common AMD type
interface AMDModule {
require: string;
}
// viewmodel types
interface ViewModelFunction {
(params?: any): any;
}
interface ViewModelSharedInstance {
instance: any;
}
interface ViewModelFactoryFunction {
createViewModel: (params?: any, componentInfo?: ComponentInfo) => any;
}
interface ComponentInfo {
element: Node;
templateNodes: Node[];
}
interface TemplateElement {
element: string | Node;
}
interface Loader {
getConfig? (componentName: string, callback: (result: ComponentConfig) => void): void;
loadComponent? (componentName: string, config: ComponentConfig, callback: (result: Definition) => void): void;
loadTemplate? (componentName: string, templateConfig: any, callback: (result: Node[]) => void): void;
loadViewModel? (componentName: string, viewModelConfig: any, callback: (result: any) => void): void;
suppressLoaderExceptions?: boolean;
}
interface Definition {
template: Node[];
createViewModel? (params: any, options: { element: Node; }): any;
}
}
interface KnockoutComponents {
// overloads for register method:
register(componentName: string, config: KnockoutComponentTypes.Config | KnockoutComponentTypes.EmptyConfig): void;
isRegistered(componentName: string): boolean;
unregister(componentName: string): void;
get(componentName: string, callback: (definition: KnockoutComponentTypes.Definition) => void): void;
clearCachedDefinition(componentName: string): void
defaultLoader: KnockoutComponentTypes.Loader;
loaders: KnockoutComponentTypes.Loader[];
getComponentNameForNode(node: Node): string;
}
declare var ko: KnockoutStatic;
declare module "knockout" {
export = ko;
}

View File

@ -0,0 +1,3 @@
/// <reference path="@ms/odsp.d.ts" />
/// <reference path="assertion-error/assertion-error.d.ts" />
/// <reference path="knockout/knockout.d.ts" />