Skip to content

Commit 9213d99

Browse files
vogtnnmetulev
authored andcommitted
[WIP] Adding people picker (#112)
* adding people-pciker to components * People picker scaffolding and basic functionality * People picker styles commit * arrow selection on people picker * [people-picker] updating people picker UI * [people-picker] input selection changes * [people-picker] updating handling of tab control (for people selection) * [people-picker] adding backspace with no input will delete previous selection, and autofill highlight on first selection * [people-picker] Updating dispatched event to selectionChanged which updates even when person is deleted from selected people * [people-picker] tracking mouse focus state, if the user clicks away from the input box, selections will hide * [people-picker] reseting previous search if there is no info entered bug * [people-picker] updating filter to continuously check selected people * [Graph] Updating graph with request for people by group-id * [people-picker] updating properties for request people by group-id * [people-picker] updating filter method to render no choices if additional people aren't found * [people-picker] updating edgecase search * [people-picker] refactor of people list, proper handling of tab selection * [people-picker] updating the arrow highlight logic to not rerender peoplelist * [people-picker] updating focus tracking for tabbing as well * [people-picker] updating custom events to utilze global handler and updating tab tracking * [people-picker] fixing arrow selection count * [people-picker] updating for group selection * [people-picker] adding sample html * updated example to fetch groups from the graph * [people-picker] updating focus on input if the user does mouse interaction anywhere near the control * [people-picker] updating keycode selection of people to include enter key * [people-picker] preventing default action of user arrow key selection on input affecting cursor position * [people-picker] adding settimeout for user input on search * [people-picker] updating styles so that control is fixed * [people-picker] updating styles * [people-picker] adding group attribute feature, scaffolding for styles * [people-picker] updating styles to reflect floating person selection * [people-picker] updating render method for error message * [people-picker] updating logic for people list render * [people-picker] restructuring people list and divider * [people-picker] updating scaffolding for divider and text highlight rework * [people-picker] adding case sensitve handling for matching people * [people-picker] updating method to call people image * [people-picker] updating group fetching to occur in attribute changed callback function * [people-picker] updating properties and variables with comments, as well as cleaning up extra unused variables * [people-picker] adding comments for keycodes in arrow handling logic * [people-picker] adding debounce function for searching * [people-picker] uncommenting search * [people-picker] updating debounce handler logic * [people-picker] updating styles * [people-picker] updating error message so that it floats on top of content below * [people-picker] updating box shadow and refactor styles * [people-picker] refactor including class changes for arrow selection * [people-picker] fixing the arrow selection * [people-picker] updating people * refactored filter function and general clean up
1 parent 51d19aa commit 9213d99

File tree

6 files changed

+781
-1
lines changed

6 files changed

+781
-1
lines changed
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
<!DOCTYPE html>
2+
<html>
3+
<head>
4+
<meta charset="utf-8" />
5+
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
6+
<title>Microsoft Graph Toolkit Test</title>
7+
<meta name="viewport" content="width=device-width, initial-scale=1" />
8+
9+
<link href="https://cdnjs.cloudflare.com/ajax/libs/normalize/8.0.1/normalize.min.css" rel="stylesheet" />
10+
<!-- <script src="./node_modules/@webcomponents/webcomponentsjs/webcomponents-loader.js"></script> -->
11+
12+
<script type="module" src="../../dist/es6/index.js"></script>
13+
<script type="module" src="../../dist/es6/mock/mgt-mock-provider.js"></script>
14+
</head>
15+
16+
<body>
17+
<mgt-msal-provider client-id="a974dfa0-9f57-49b9-95db-90f04ce2111a"></mgt-msal-provider>
18+
19+
<!-- <mgt-mock-provider></mgt-mock-provider> -->
20+
21+
<mgt-login></mgt-login>
22+
23+
<mgt-people-picker id="picker1"></mgt-people-picker>
24+
<h2>hello</h2>
25+
26+
<div style="position: fixed; bottom: 0;">
27+
<h3>Group:</h3>
28+
<select id="groupChooser" name="group">
29+
<option value="">none</option>
30+
</select>
31+
<h3>Chosen People:</h3>
32+
<ul id="chosenPeople"></ul>
33+
</div>
34+
</body>
35+
<script type="module">
36+
import { Providers, ProviderState } from '../../dist/es6/index.js';
37+
38+
let picker1 = document.getElementById('picker1');
39+
let chosenArea = document.getElementById('chosenPeople');
40+
let groupChooser = document.getElementById('groupChooser');
41+
42+
groupChooser.addEventListener('change', getGroupValue);
43+
44+
let provider = Providers.globalProvider;
45+
46+
loadGroups();
47+
provider.onStateChanged(loadGroups);
48+
49+
function loadGroups() {
50+
if (provider && provider.state === ProviderState.SignedIn) {
51+
let client = provider.graph.client;
52+
53+
client
54+
.api('/groups')
55+
.get()
56+
.then(groups => {
57+
console.log(groups);
58+
for (let group of groups.value) {
59+
let option = document.createElement('option');
60+
option.value = group.id;
61+
option.text = group.displayName;
62+
63+
groupChooser.appendChild(option);
64+
}
65+
});
66+
}
67+
}
68+
69+
picker1.addEventListener('selectionChanged', function(e) {
70+
//reset area
71+
chosenArea.innerHTML = '';
72+
//render selected people to chosen people div
73+
for (var i = 0; i < e.detail.length; i++) {
74+
let newElem = document.createElement('li');
75+
newElem.innerHTML = e.detail[i].displayName + ' ' + e.detail[i].id;
76+
chosenArea.append(newElem);
77+
}
78+
});
79+
80+
function getGroupValue(e) {
81+
let selection = groupChooser.selectedOptions[0];
82+
if (selection !== undefined) {
83+
setGroupValue(selection.value);
84+
}
85+
}
86+
87+
function setGroupValue(selected) {
88+
picker1.setAttribute('group', selected);
89+
}
90+
</script>
91+
</html>

src/Graph.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -262,6 +262,17 @@ export class Graph {
262262
return people ? people.value : null;
263263
}
264264

265+
async getPeopleFromGroup(groupId: string): Promise<Array<MicrosoftGraph.Person>> {
266+
let scopes = 'people.read';
267+
268+
let uri = `/groups/${groupId}/members`;
269+
let people = await this.client
270+
.api(uri)
271+
.middlewareOptions(prepScopes(scopes))
272+
.get();
273+
return people ? people.value : null;
274+
}
275+
265276
// Planner Methods
266277
public async planner_getAllMyPlans(): Promise<MicrosoftGraph.PlannerPlan[]> {
267278
let plans = await this.client

src/components/components.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,14 @@ import './mgt-agenda/mgt-agenda';
1010
import './mgt-person/mgt-person';
1111
import './mgt-people/mgt-people';
1212
import './mgt-tasks/mgt-tasks';
13+
import './mgt-people-picker/mgt-people-picker';
1314

1415
export * from './mgt-login/mgt-login';
1516
export * from './mgt-agenda/mgt-agenda';
1617
export * from './mgt-person/mgt-person';
1718
export * from './mgt-people/mgt-people';
1819
export * from './mgt-tasks/mgt-tasks';
19-
20+
export * from './mgt-people-picker/mgt-people-picker';
2021
// Sub-Components, not for export!
2122
// export * from './sub-components/mgt-dot-options/mgt-dot-options';
2223
// export * from './sub-components/mgt-arrow-options/mgt-arrow-options';
Lines changed: 250 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,250 @@
1+
/**
2+
* -------------------------------------------------------------------------------------------
3+
* Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License.
4+
* See License in the project root for license information.
5+
* -------------------------------------------------------------------------------------------
6+
*/
7+
8+
@import '../../../node_modules/office-ui-fabric-core/dist/sass/References';
9+
@import '../../styles/shared-styles.scss';
10+
11+
$list-margin: var(--list-margin, 20px 4px 8px 8px);
12+
$avatar-margin: var(--avatar-margin, 0 4px 0 0);
13+
$avatar-size-s: var(--avatar-size-s, 24px);
14+
$avatar-size: var(--avatar-size, 48px);
15+
$initials-color: var(--initials-color, white);
16+
$initials-background-color: var(--initials-background-color, #{$ms-color-magenta});
17+
18+
:host {
19+
box-shadow: 0px 1.3289px 2.65781px rgba(180, 180, 180, 0.182), 0px 10.6312px 13.289px rgba(180, 180, 180, 0.182);
20+
border-radius: 2px;
21+
}
22+
:host .root,
23+
mgt-people-picker .root {
24+
display: block;
25+
}
26+
27+
:host .people-picker,
28+
mgt-people-picker .people-picker {
29+
position: relative;
30+
margin: 7px 0 0 0;
31+
background-color: white;
32+
padding-bottom: 8px;
33+
}
34+
35+
:host .people-list,
36+
mgt-people-picker .people-list {
37+
position: absolute;
38+
margin: 7px 0px 0px 0px;
39+
padding: 0;
40+
box-shadow: 0px 1.3289px 2.65781px rgba(180, 180, 180, 0.182), 0px 1.3289px 2.65781px rgba(68, 68, 68, 0.3);
41+
border-radius: 2px;
42+
background-color: white;
43+
z-index: 1; /* Sit on top */
44+
width: 100%;
45+
text-align: left;
46+
list-style-type: none;
47+
font-family: Segoe UI;
48+
font-style: normal;
49+
font-weight: normal;
50+
}
51+
:host .people-list-separator,
52+
mgt-people-picker .people-list-separator {
53+
height: 2px;
54+
background: #0078d4;
55+
margin-top: 5px;
56+
margin-left: 16px;
57+
margin-right: 16px;
58+
text-align: center;
59+
}
60+
61+
:host .people-chosen-input,
62+
mgt-people-picker .people-chosen-input {
63+
position: relative;
64+
border: none;
65+
line-height: normal;
66+
outline: none;
67+
font-family: Segoe UI;
68+
font-style: normal;
69+
font-weight: normal;
70+
font-size: 14px;
71+
line-height: 19px;
72+
}
73+
74+
:host .people-chosen-list,
75+
mgt-people-picker .people-chosen-list {
76+
display: flex;
77+
flex-wrap: wrap;
78+
vertical-align: middle;
79+
margin: 0 0 0 0;
80+
list-style-type: none;
81+
padding-left: 10px;
82+
font-family: Segoe UI;
83+
font-style: normal;
84+
font-weight: normal;
85+
}
86+
.CloseIcon,
87+
mgt-people-picker .CloseIcon {
88+
line-height: normal;
89+
font-family: 'FabricMDL2Icons';
90+
padding-right: 8px;
91+
padding-left: 4px;
92+
margin-top: 3px;
93+
}
94+
:host .SearchIcon,
95+
mgt-people-picker .SearchIcon {
96+
font-family: 'FabricMDL2Icons';
97+
color: #0078d4;
98+
}
99+
100+
:host .people-person,
101+
mgt-people-picker .people-person {
102+
display: flex;
103+
margin: 4px 5px 0 0;
104+
align-items: center;
105+
background-color: rgba(196, 196, 196, 0.24);
106+
border-radius: 15px;
107+
max-height: 24px;
108+
}
109+
110+
:host .people-person-list,
111+
mgt-people-picker .people-person-list {
112+
display: flex;
113+
flex-direction: row;
114+
flex-wrap: wrap;
115+
align-items: center;
116+
padding: 12px;
117+
font-family: Segoe UI;
118+
font-style: normal;
119+
font-weight: 600;
120+
font-size: 14px;
121+
}
122+
123+
:host .people-person-list-fill,
124+
mgt-people-picker .people-person-list-fill {
125+
display: flex;
126+
align-items: center;
127+
padding: 12px;
128+
font-family: Segoe UI;
129+
font-style: normal;
130+
font-weight: 600;
131+
font-size: 14px;
132+
background-color: #f1f1f1;
133+
}
134+
135+
:host .people-person-text,
136+
mgt-people-picker .people-person-text {
137+
font-size: 14px;
138+
font-weight: normal;
139+
margin: 0;
140+
padding: 0;
141+
}
142+
143+
:host .input-search,
144+
mgt-people-picker .input-search {
145+
margin: 7px 2px 0px 3px;
146+
}
147+
:host .input-search-start,
148+
mgt-people-picker .input-search-start {
149+
margin: 7px 0px 0px 0px;
150+
line-height: normal;
151+
margin-inline-start: 0px;
152+
margin-inline-end: 0px;
153+
}
154+
155+
:host .people-picker-input,
156+
mgt-people-picker .people-picker-input {
157+
padding-inline-start: 14px;
158+
display: flex;
159+
order: 2;
160+
background-color: white;
161+
margin: $avatar-margin;
162+
font-size: 14px;
163+
line-height: 19px;
164+
}
165+
166+
:host .duplicate-person,
167+
mgt-people-picker .duplicate-person {
168+
text-decoration: none;
169+
border-bottom: 1px solid red;
170+
}
171+
172+
:host .remove-person-button,
173+
mgt-people-picker .remove-person-button {
174+
background: #767676;
175+
transform: matrix(-0.71, -0.71, 0.71, -0.71, 0, 0);
176+
}
177+
178+
:host .remove-person-button-secondary,
179+
mgt-people-picker .remove-person-button-secondary {
180+
background: #767676;
181+
transform: matrix(0.71, -0.71, 0.71, 0.71, 0, 0);
182+
}
183+
184+
:host .person-display-name,
185+
mgt-people-picker .person-display-name {
186+
margin-left: 8px;
187+
font-family: Segoe UI;
188+
font-style: normal;
189+
font-weight: 600;
190+
font-size: 14px;
191+
line-height: 19px;
192+
text-align: center;
193+
color: #000000;
194+
}
195+
196+
mgt-person {
197+
--avatar-size-s: 32px;
198+
margin-left: 12px;
199+
}
200+
.chosen-person {
201+
--avatar-size-s: 24px;
202+
margin-left: 0px;
203+
}
204+
205+
:host .search-error-text,
206+
mgt-people-picker .search-error-text {
207+
font-family: Segoe UI;
208+
font-style: normal;
209+
font-weight: 600;
210+
font-size: 14px;
211+
line-height: 19px;
212+
text-align: center;
213+
color: #232222;
214+
}
215+
216+
:host .SearchErrorIcon,
217+
mgt-people-picker .SearchErrorIcon {
218+
display: inline-block;
219+
font-family: 'FabricMDL2Icons';
220+
color: #cf0000;
221+
}
222+
223+
:host .error-message-parent,
224+
mgt-people-picker .error-message-parent {
225+
margin-top: 30px;
226+
margin-bottom: 30px;
227+
display: flex;
228+
align-items: center;
229+
justify-content: center;
230+
vertical-align: middle;
231+
}
232+
233+
:host .highlight-search-text,
234+
mgt-people-picker .highlight-search-text {
235+
font-weight: bold;
236+
}
237+
:host .people-person-job-title,
238+
mgt-people-picker .people-person-job-title {
239+
flex: 100%;
240+
order: 3;
241+
font-weight: normal;
242+
font-size: 12px;
243+
text-transform: uppercase;
244+
}
245+
:host .people-person-text-area,
246+
mgt-people-picker .people-person-text-area {
247+
margin-left: 13px;
248+
flex: 1 1 0;
249+
max-height: 40px;
250+
}

0 commit comments

Comments
 (0)