Skip to content

Commit 2a4287b

Browse files
authored
Person card 2.0 updates (continued) (#774)
* added additional details template, graph fixes * added message text box visibility to config * work in progress * organization functional * updated files, messages, contacts * fixed scrolling * working profile, fixed layout, made sure card is always visible, and more * Added Providers.me * cleanup * Fixed contact and groups in person card * added license * Added getScopes * finished merge * Added story * Fixed issues with sections rendering when there is no data
1 parent 756c1e2 commit 2a4287b

File tree

29 files changed

+1228
-1187
lines changed

29 files changed

+1228
-1187
lines changed
Lines changed: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,152 @@
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 { BatchResponse, IBatch, IGraph } from '@microsoft/mgt-element';
9+
import { Profile } from '@microsoft/microsoft-graph-types-beta';
10+
11+
import { getEmailFromGraphEntity } from '../../graph/graph.people';
12+
import { IDynamicPerson } from '../../graph/types';
13+
import { MgtPersonCardConfig, MgtPersonCardState } from './mgt-person-card.types';
14+
15+
// tslint:disable-next-line:completed-docs
16+
const userProperties =
17+
'businessPhones,companyName,department,displayName,givenName,jobTitle,mail,mobilePhone,officeLocation,preferredLanguage,surname,userPrincipalName,id';
18+
19+
// tslint:disable-next-line:completed-docs
20+
const batchKeys = {
21+
directReports: 'directReports',
22+
files: 'files',
23+
messages: 'messages',
24+
people: 'people',
25+
person: 'person'
26+
};
27+
28+
/**
29+
* Get data to populate the person card
30+
*
31+
* @export
32+
* @param {IGraph} graph
33+
* @param {IDynamicPerson} personDetails
34+
* @param {boolean} isMe
35+
* @param {MgtPersonCardConfig} config
36+
* @return {*} {Promise<MgtPersonCardState>}
37+
*/
38+
export async function getPersonCardGraphData(
39+
graph: IGraph,
40+
personDetails: IDynamicPerson,
41+
isMe: boolean,
42+
config: MgtPersonCardConfig
43+
): Promise<MgtPersonCardState> {
44+
const userId = personDetails.id;
45+
const email = getEmailFromGraphEntity(personDetails);
46+
47+
const isContactOrGroup =
48+
'classification' in personDetails ||
49+
('personType' in personDetails &&
50+
(personDetails.personType.subclass === 'PersonalContact' || personDetails.personType.class === 'Group'));
51+
52+
const batch = graph.createBatch();
53+
54+
if (!isContactOrGroup) {
55+
if (config.sections.organization) {
56+
buildOrgStructureRequest(batch, userId);
57+
58+
if (typeof config.sections.organization !== 'boolean' && config.sections.organization.showWorksWith) {
59+
buildWorksWithRequest(batch, userId);
60+
}
61+
}
62+
}
63+
64+
if (config.sections.mailMessages && email) {
65+
buildMessagesWithUserRequest(batch, email);
66+
}
67+
68+
if (config.sections.files) {
69+
buildFilesRequest(batch, isMe ? null : email);
70+
}
71+
72+
let response: Map<string, BatchResponse>;
73+
const data: MgtPersonCardState = {}; // TODO
74+
try {
75+
response = await batch.executeAll();
76+
} catch {
77+
// nop
78+
}
79+
80+
if (response) {
81+
for (const [key, value] of response) {
82+
data[key] = value.content.value || value.content;
83+
}
84+
}
85+
86+
if (!isContactOrGroup && config.sections.profile) {
87+
try {
88+
const profile = await getProfile(graph, userId);
89+
if (profile) {
90+
data.profile = profile;
91+
}
92+
} catch {
93+
// nop
94+
}
95+
}
96+
97+
return data;
98+
}
99+
100+
// tslint:disable-next-line:completed-docs
101+
function buildOrgStructureRequest(batch: IBatch, userId: string) {
102+
const expandManagers = `manager($levels=max;$select=${userProperties})`;
103+
104+
batch.get(
105+
batchKeys.person,
106+
`users/${userId}?$expand=${expandManagers}&$select=${userProperties}&$count=true`,
107+
['user.read.all'],
108+
{
109+
ConsistencyLevel: 'eventual'
110+
}
111+
);
112+
113+
batch.get(batchKeys.directReports, `users/${userId}/directReports?$select=${userProperties}`);
114+
}
115+
116+
// tslint:disable-next-line:completed-docs
117+
function buildWorksWithRequest(batch: IBatch, userId: string) {
118+
batch.get(batchKeys.people, `users/${userId}/people?$filter=personType/class eq 'Person'`, ['People.Read.All']);
119+
}
120+
121+
// tslint:disable-next-line:completed-docs
122+
function buildMessagesWithUserRequest(batch: IBatch, emailAddress: string) {
123+
batch.get(batchKeys.messages, `me/messages?$search="from:${emailAddress}"`, ['Mail.ReadBasic']);
124+
}
125+
126+
// tslint:disable-next-line:completed-docs
127+
function buildFilesRequest(batch: IBatch, emailAddress?: string) {
128+
let request: string;
129+
130+
if (emailAddress) {
131+
request = `me/insights/shared?$filter=lastshared/sharedby/address eq '${emailAddress}'`;
132+
} else {
133+
request = 'me/insights/used';
134+
}
135+
136+
batch.get(batchKeys.files, request, ['Sites.Read.All']);
137+
}
138+
139+
/**
140+
* Get the profile for a user
141+
*
142+
* @param {IGraph} graph
143+
* @param {string} userId
144+
* @return {*} {Promise<Profile>}
145+
*/
146+
async function getProfile(graph: IGraph, userId: string): Promise<Profile> {
147+
const profile = await graph
148+
.api(`/users/${userId}/profile`)
149+
.version('beta')
150+
.get();
151+
return profile;
152+
}

packages/mgt-components/src/components/mgt-person-card/mgt-person-card.scss

Lines changed: 31 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -28,11 +28,14 @@ $person-card-background-color: var(--person-card-background-color, #ffffff);
2828
user-select: none;
2929

3030
.nav {
31-
display: flex;
31+
height: 0px;
32+
position: relative;
33+
z-index: 100;
3234

3335
.nav__back {
34-
padding: 10px;
35-
display: flex;
36+
padding: 8px;
37+
height: 32px;
38+
width: 32px;
3639
align-items: center;
3740
justify-content: center;
3841

@@ -53,8 +56,8 @@ $person-card-background-color: var(--person-card-background-color, #ffffff);
5356
.person-details-container {
5457
display: flex;
5558
flex-direction: column;
56-
width: calc(var(--mgt-flyout-set-width, 340px) - 30px);
57-
padding: 15px 15px 20px 15px;
59+
width: calc(var(--mgt-flyout-set-width, 340px) - 40px);
60+
padding: 20px;
5861

5962
.person-image {
6063
--presence-background-color: var(--person-card-background-color, #ffffff);
@@ -72,8 +75,8 @@ $person-card-background-color: var(--person-card-background-color, #ffffff);
7275
-webkit-align-items: center;
7376
align-items: center;
7477
max-width: 120px;
75-
margin-left: 87px;
76-
margin-top: 4px;
78+
// margin-left: 87px;
79+
margin-top: 16px;
7780

7881
.icon {
7982
display: flex;
@@ -212,17 +215,24 @@ $person-card-background-color: var(--person-card-background-color, #ffffff);
212215
}
213216
}
214217

218+
.loading {
219+
margin: 40px 20px;
220+
display: flex;
221+
justify-content: center;
222+
height: 360px;
223+
}
224+
215225
.section-host {
216-
max-height: 600px;
226+
max-height: 360px;
227+
min-height: 360px;
217228
overflow-y: auto;
218229
overflow-x: hidden;
219230
}
220231

221232
.quick-message {
222233
display: flex;
223234
flex-direction: row;
224-
padding: 8px 10px;
225-
border-bottom: 1px solid #e8e8e8;
235+
padding: 12px 10px 8px 10px;
226236

227237
.quick-message__input {
228238
flex-grow: 1;
@@ -261,8 +271,14 @@ $person-card-background-color: var(--person-card-background-color, #ffffff);
261271
flex-direction: column;
262272
position: relative;
263273

264-
&:not(:last-child) {
274+
&:not(:last-child):after {
275+
position: absolute;
276+
content: '';
277+
width: 90%;
278+
transform: translateX(-50%);
265279
border-bottom: 1px solid #eaeaea;
280+
left: 50%;
281+
bottom: 0;
266282
}
267283

268284
.section__header {
@@ -293,6 +309,10 @@ $person-card-background-color: var(--person-card-background-color, #ffffff);
293309
.section__content {
294310
margin-top: 14px;
295311
}
312+
313+
.additional-details {
314+
padding: 0 20px;
315+
}
296316
}
297317
}
298318
}

0 commit comments

Comments
 (0)