@atlaskit/smart-user-picker 6.0.3 → 6.0.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +12 -0
- package/dist/cjs/analytics.js +12 -37
- package/dist/cjs/components/MessagesIntlProvider.js +4 -22
- package/dist/cjs/components/SmartUserPicker.js +22 -123
- package/dist/cjs/components/index.js +0 -7
- package/dist/cjs/i18n/cs.js +0 -1
- package/dist/cjs/i18n/da.js +0 -1
- package/dist/cjs/i18n/de.js +0 -1
- package/dist/cjs/i18n/en_ZZ.js +0 -1
- package/dist/cjs/i18n/es.js +0 -1
- package/dist/cjs/i18n/et.js +0 -1
- package/dist/cjs/i18n/fi.js +0 -1
- package/dist/cjs/i18n/fr.js +0 -1
- package/dist/cjs/i18n/hu.js +0 -1
- package/dist/cjs/i18n/index.js +0 -31
- package/dist/cjs/i18n/it.js +0 -1
- package/dist/cjs/i18n/ja.js +0 -1
- package/dist/cjs/i18n/ko.js +0 -1
- package/dist/cjs/i18n/nb.js +0 -1
- package/dist/cjs/i18n/nl.js +0 -1
- package/dist/cjs/i18n/pl.js +0 -1
- package/dist/cjs/i18n/pt_BR.js +0 -1
- package/dist/cjs/i18n/pt_PT.js +0 -1
- package/dist/cjs/i18n/ru.js +0 -1
- package/dist/cjs/i18n/sk.js +0 -1
- package/dist/cjs/i18n/sv.js +0 -1
- package/dist/cjs/i18n/th.js +0 -1
- package/dist/cjs/i18n/tr.js +0 -1
- package/dist/cjs/i18n/uk.js +0 -1
- package/dist/cjs/i18n/vi.js +0 -1
- package/dist/cjs/i18n/zh.js +0 -1
- package/dist/cjs/i18n/zh_TW.js +0 -1
- package/dist/cjs/i18n.js +0 -2
- package/dist/cjs/index.js +0 -4
- package/dist/cjs/service/default-value-hydration-client.js +0 -49
- package/dist/cjs/service/graphqlUtils.js +0 -5
- package/dist/cjs/service/index.js +0 -3
- package/dist/cjs/service/recommendation-client.js +0 -11
- package/dist/cjs/service/teams-client.js +0 -10
- package/dist/cjs/service/users-client.js +2 -20
- package/dist/cjs/service/users-transformer.js +0 -17
- package/dist/cjs/types.js +0 -1
- package/dist/cjs/ufoExperiences.js +8 -26
- package/dist/cjs/util/i18n-util.js +0 -43
- package/dist/cjs/version.json +1 -1
- package/dist/es2019/analytics.js +12 -10
- package/dist/es2019/components/MessagesIntlProvider.js +2 -4
- package/dist/es2019/components/SmartUserPicker.js +23 -55
- package/dist/es2019/components/index.js +0 -2
- package/dist/es2019/config/index.js +0 -4
- package/dist/es2019/index.js +4 -2
- package/dist/es2019/service/default-value-hydration-client.js +4 -22
- package/dist/es2019/service/graphqlUtils.js +0 -4
- package/dist/es2019/service/recommendation-client.js +0 -4
- package/dist/es2019/service/teams-client.js +2 -5
- package/dist/es2019/service/users-client.js +2 -6
- package/dist/es2019/service/users-transformer.js +0 -11
- package/dist/es2019/types.js +0 -1
- package/dist/es2019/ufoExperiences.js +8 -7
- package/dist/es2019/util/i18n-util.js +30 -120
- package/dist/es2019/version.json +1 -1
- package/dist/esm/analytics.js +12 -19
- package/dist/esm/components/MessagesIntlProvider.js +4 -11
- package/dist/esm/components/SmartUserPicker.js +24 -115
- package/dist/esm/components/index.js +0 -2
- package/dist/esm/index.js +4 -2
- package/dist/esm/service/default-value-hydration-client.js +0 -40
- package/dist/esm/service/graphqlUtils.js +0 -4
- package/dist/esm/service/recommendation-client.js +0 -7
- package/dist/esm/service/teams-client.js +0 -7
- package/dist/esm/service/users-client.js +2 -13
- package/dist/esm/service/users-transformer.js +0 -13
- package/dist/esm/types.js +0 -1
- package/dist/esm/ufoExperiences.js +8 -13
- package/dist/esm/util/i18n-util.js +30 -126
- package/dist/esm/version.json +1 -1
- package/package.json +7 -14
- package/report.api.md +26 -5
- package/tmp/api-report-tmp.d.ts +268 -0
- package/dist/types-ts4.0/analytics.d.ts +0 -21
- package/dist/types-ts4.0/components/MessagesIntlProvider.d.ts +0 -9
- package/dist/types-ts4.0/components/SmartUserPicker.d.ts +0 -34
- package/dist/types-ts4.0/components/index.d.ts +0 -4
- package/dist/types-ts4.0/config/index.d.ts +0 -6
- package/dist/types-ts4.0/i18n/cs.d.ts +0 -18
- package/dist/types-ts4.0/i18n/da.d.ts +0 -18
- package/dist/types-ts4.0/i18n/de.d.ts +0 -18
- package/dist/types-ts4.0/i18n/en.d.ts +0 -7
- package/dist/types-ts4.0/i18n/en_GB.d.ts +0 -7
- package/dist/types-ts4.0/i18n/en_ZZ.d.ts +0 -18
- package/dist/types-ts4.0/i18n/es.d.ts +0 -18
- package/dist/types-ts4.0/i18n/et.d.ts +0 -8
- package/dist/types-ts4.0/i18n/fi.d.ts +0 -18
- package/dist/types-ts4.0/i18n/fr.d.ts +0 -18
- package/dist/types-ts4.0/i18n/hu.d.ts +0 -18
- package/dist/types-ts4.0/i18n/index.d.ts +0 -36
- package/dist/types-ts4.0/i18n/is.d.ts +0 -7
- package/dist/types-ts4.0/i18n/it.d.ts +0 -18
- package/dist/types-ts4.0/i18n/ja.d.ts +0 -18
- package/dist/types-ts4.0/i18n/ko.d.ts +0 -18
- package/dist/types-ts4.0/i18n/languages.d.ts +0 -27
- package/dist/types-ts4.0/i18n/nb.d.ts +0 -18
- package/dist/types-ts4.0/i18n/nl.d.ts +0 -18
- package/dist/types-ts4.0/i18n/pl.d.ts +0 -18
- package/dist/types-ts4.0/i18n/pt_BR.d.ts +0 -18
- package/dist/types-ts4.0/i18n/pt_PT.d.ts +0 -8
- package/dist/types-ts4.0/i18n/ro.d.ts +0 -7
- package/dist/types-ts4.0/i18n/ru.d.ts +0 -18
- package/dist/types-ts4.0/i18n/sk.d.ts +0 -8
- package/dist/types-ts4.0/i18n/sv.d.ts +0 -18
- package/dist/types-ts4.0/i18n/th.d.ts +0 -18
- package/dist/types-ts4.0/i18n/tr.d.ts +0 -18
- package/dist/types-ts4.0/i18n/uk.d.ts +0 -18
- package/dist/types-ts4.0/i18n/vi.d.ts +0 -18
- package/dist/types-ts4.0/i18n/zh.d.ts +0 -18
- package/dist/types-ts4.0/i18n/zh_TW.d.ts +0 -18
- package/dist/types-ts4.0/i18n.d.ts +0 -47
- package/dist/types-ts4.0/index.d.ts +0 -5
- package/dist/types-ts4.0/service/constants.d.ts +0 -4
- package/dist/types-ts4.0/service/default-value-hydration-client.d.ts +0 -8
- package/dist/types-ts4.0/service/graphqlUtils.d.ts +0 -14
- package/dist/types-ts4.0/service/index.d.ts +0 -2
- package/dist/types-ts4.0/service/recommendation-client.d.ts +0 -5
- package/dist/types-ts4.0/service/teams-client.d.ts +0 -12
- package/dist/types-ts4.0/service/users-client.d.ts +0 -11
- package/dist/types-ts4.0/service/users-transformer.d.ts +0 -22
- package/dist/types-ts4.0/types.d.ts +0 -207
- package/dist/types-ts4.0/ufoExperiences.d.ts +0 -11
- package/dist/types-ts4.0/util/i18n-util.d.ts +0 -11
|
@@ -13,21 +13,23 @@ import MessagesIntlProvider from './MessagesIntlProvider';
|
|
|
13
13
|
import { getUserRecommendations, hydrateDefaultValues } from '../service';
|
|
14
14
|
import { smartUserPickerOptionsShownUfoExperience } from '../ufoExperiences';
|
|
15
15
|
const DEFAULT_DEBOUNCE_TIME_MS = 150;
|
|
16
|
-
|
|
16
|
+
const ufoEndStateConfig = fieldId => {
|
|
17
|
+
return {
|
|
18
|
+
metadata: {
|
|
19
|
+
contextType: fieldId
|
|
20
|
+
}
|
|
21
|
+
};
|
|
22
|
+
};
|
|
17
23
|
const hasContextChanged = (oldContext, newContext) => oldContext.siteId !== newContext.siteId || oldContext.orgId !== newContext.orgId || oldContext.productKey !== newContext.productKey || oldContext.principalId !== newContext.principalId || oldContext.containerId !== newContext.containerId || oldContext.objectId !== newContext.objectId || oldContext.childObjectId !== newContext.childObjectId;
|
|
18
|
-
|
|
19
24
|
const stringContains = (str, substr) => {
|
|
20
25
|
if (str === null || str === undefined) {
|
|
21
26
|
return false;
|
|
22
27
|
}
|
|
23
|
-
|
|
24
28
|
if (substr === null || substr === '' || substr === undefined) {
|
|
25
29
|
return true;
|
|
26
30
|
}
|
|
27
|
-
|
|
28
31
|
return str.toLowerCase().includes(substr.toLowerCase());
|
|
29
32
|
};
|
|
30
|
-
|
|
31
33
|
const getUsersForAnalytics = users => (users || []).map(({
|
|
32
34
|
id,
|
|
33
35
|
type
|
|
@@ -35,13 +37,10 @@ const getUsersForAnalytics = users => (users || []).map(({
|
|
|
35
37
|
id,
|
|
36
38
|
type
|
|
37
39
|
}));
|
|
38
|
-
|
|
39
40
|
export class SmartUserPickerWithoutAnalytics extends React.Component {
|
|
40
41
|
constructor(props) {
|
|
41
42
|
var _this$props$debounceT;
|
|
42
|
-
|
|
43
43
|
super(props);
|
|
44
|
-
|
|
45
44
|
_defineProperty(this, "state", {
|
|
46
45
|
users: [],
|
|
47
46
|
loading: false,
|
|
@@ -50,7 +49,6 @@ export class SmartUserPickerWithoutAnalytics extends React.Component {
|
|
|
50
49
|
defaultValue: [],
|
|
51
50
|
bootstrapOptions: []
|
|
52
51
|
});
|
|
53
|
-
|
|
54
52
|
_defineProperty(this, "abortOptionsShownUfoExperience", () => {
|
|
55
53
|
if (this.optionsShownUfoExperienceInstance.state.id === UFOExperienceState.STARTED.id) {
|
|
56
54
|
// There may be an existing UFO timing running from previous key entry or focus,
|
|
@@ -58,26 +56,20 @@ export class SmartUserPickerWithoutAnalytics extends React.Component {
|
|
|
58
56
|
this.optionsShownUfoExperienceInstance.abort();
|
|
59
57
|
}
|
|
60
58
|
});
|
|
61
|
-
|
|
62
59
|
_defineProperty(this, "startOptionsShownUfoExperience", () => {
|
|
63
60
|
this.abortOptionsShownUfoExperience();
|
|
64
61
|
this.optionsShownUfoExperienceInstance.start();
|
|
65
62
|
});
|
|
66
|
-
|
|
67
63
|
_defineProperty(this, "fireEvent", (eventCreator, ...args) => {
|
|
68
64
|
const {
|
|
69
65
|
createAnalyticsEvent
|
|
70
66
|
} = this.props;
|
|
71
|
-
|
|
72
67
|
if (createAnalyticsEvent) {
|
|
73
68
|
createAndFireEventInElementsChannel(eventCreator(this.props, this.state, ...args))(createAnalyticsEvent);
|
|
74
69
|
}
|
|
75
70
|
});
|
|
76
|
-
|
|
77
71
|
_defineProperty(this, "filterOptions", (users, query, propFilterOptions) => propFilterOptions ? propFilterOptions(users, query) : users);
|
|
78
|
-
|
|
79
72
|
_defineProperty(this, "memoizedFilterOptions", memoizeOne(this.filterOptions));
|
|
80
|
-
|
|
81
73
|
_defineProperty(this, "getUsers", debounce(async () => {
|
|
82
74
|
const {
|
|
83
75
|
query,
|
|
@@ -127,10 +119,8 @@ export class SmartUserPickerWithoutAnalytics extends React.Component {
|
|
|
127
119
|
query,
|
|
128
120
|
searchQueryFilter
|
|
129
121
|
};
|
|
130
|
-
|
|
131
122
|
try {
|
|
132
123
|
var _await$onEmpty;
|
|
133
|
-
|
|
134
124
|
this.fireEvent(requestUsersEvent);
|
|
135
125
|
const recommendedUsers = await getUserRecommendations(recommendationsRequest, intl);
|
|
136
126
|
const elapsedTimeMilli = window.performance.now() - startTime;
|
|
@@ -155,26 +145,22 @@ export class SmartUserPickerWithoutAnalytics extends React.Component {
|
|
|
155
145
|
if (!closed && !onError) {
|
|
156
146
|
// If the user lookup fails while the menu is open, and the consumer is not providing a
|
|
157
147
|
// fallback data source via the onError prop, then send UFO failure
|
|
158
|
-
this.optionsShownUfoExperienceInstance.failure();
|
|
148
|
+
this.optionsShownUfoExperienceInstance.failure(ufoEndStateConfig(this.props.fieldId));
|
|
159
149
|
}
|
|
160
|
-
|
|
161
150
|
this.setState({
|
|
162
151
|
users: []
|
|
163
152
|
});
|
|
164
153
|
let onErrorProducedError = false;
|
|
165
154
|
let defaultUsers = [];
|
|
166
|
-
|
|
167
155
|
try {
|
|
168
156
|
defaultUsers = onError ? (await onError(e, recommendationsRequest)) || [] : [];
|
|
169
157
|
} catch (error) {
|
|
170
158
|
onErrorProducedError = true;
|
|
171
159
|
}
|
|
172
|
-
|
|
173
160
|
if (onErrorProducedError) {
|
|
174
161
|
// Log error from fallback data source `onError` to UFO
|
|
175
|
-
this.optionsShownUfoExperienceInstance.failure();
|
|
162
|
+
this.optionsShownUfoExperienceInstance.failure(ufoEndStateConfig(this.props.fieldId));
|
|
176
163
|
}
|
|
177
|
-
|
|
178
164
|
this.setState({
|
|
179
165
|
users: defaultUsers,
|
|
180
166
|
loading: false
|
|
@@ -186,17 +172,14 @@ export class SmartUserPickerWithoutAnalytics extends React.Component {
|
|
|
186
172
|
});
|
|
187
173
|
}
|
|
188
174
|
}, (_this$props$debounceT = this.props.debounceTime) !== null && _this$props$debounceT !== void 0 ? _this$props$debounceT : 0));
|
|
189
|
-
|
|
190
175
|
_defineProperty(this, "onInputChange", (newQuery, sessionId) => {
|
|
191
176
|
const query = newQuery || '';
|
|
192
177
|
const {
|
|
193
178
|
closed
|
|
194
179
|
} = this.state;
|
|
195
|
-
|
|
196
180
|
if (query === this.state.query) {
|
|
197
181
|
return;
|
|
198
182
|
}
|
|
199
|
-
|
|
200
183
|
if (!closed) {
|
|
201
184
|
// If the input has been typed into and the dropdown has not been closed
|
|
202
185
|
// (i.e. input blurred) then start the UFO timer.
|
|
@@ -208,21 +191,19 @@ export class SmartUserPickerWithoutAnalytics extends React.Component {
|
|
|
208
191
|
query,
|
|
209
192
|
sessionId
|
|
210
193
|
});
|
|
211
|
-
|
|
212
194
|
if (this.props.onInputChange) {
|
|
213
195
|
this.props.onInputChange(query, sessionId);
|
|
214
196
|
}
|
|
215
197
|
}
|
|
216
198
|
});
|
|
217
|
-
|
|
218
199
|
_defineProperty(this, "filterUsers", () => {
|
|
219
200
|
const {
|
|
220
201
|
loading,
|
|
221
202
|
users,
|
|
222
203
|
query
|
|
223
204
|
} = this.state;
|
|
224
|
-
const filteredUsers = this.memoizedFilterOptions(users, query, this.props.filterOptions);
|
|
225
|
-
|
|
205
|
+
const filteredUsers = this.memoizedFilterOptions(users, query, this.props.filterOptions);
|
|
206
|
+
//If bootstrapOptions have been passed in and it is bootstrap
|
|
226
207
|
if (this.props.bootstrapOptions && this.props.bootstrapOptions.length !== 0 && query === '') {
|
|
227
208
|
const bootstrapFilteredUsers = this.memoizedFilterOptions(this.props.bootstrapOptions, query, this.props.filterOptions);
|
|
228
209
|
this.fireEvent(filterUsersEvent, {
|
|
@@ -230,29 +211,26 @@ export class SmartUserPickerWithoutAnalytics extends React.Component {
|
|
|
230
211
|
all: getUsersForAnalytics(this.props.bootstrapOptions)
|
|
231
212
|
});
|
|
232
213
|
return bootstrapFilteredUsers;
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
|
|
214
|
+
}
|
|
215
|
+
// while when not loading just return already filtered result from server.
|
|
236
216
|
if (!loading) {
|
|
237
217
|
return filteredUsers;
|
|
238
218
|
}
|
|
239
|
-
|
|
240
219
|
const queryFilteredUsers = filteredUsers.filter(user => stringContains(user.name, query));
|
|
241
220
|
this.fireEvent(filterUsersEvent, {
|
|
242
221
|
filtered: getUsersForAnalytics(queryFilteredUsers),
|
|
243
222
|
all: getUsersForAnalytics(users)
|
|
244
|
-
});
|
|
223
|
+
});
|
|
245
224
|
|
|
225
|
+
// when loading filter previous result.
|
|
246
226
|
return filteredUsers;
|
|
247
227
|
});
|
|
248
|
-
|
|
249
228
|
_defineProperty(this, "onFocus", sessionId => {
|
|
250
229
|
const state = {
|
|
251
230
|
query: '',
|
|
252
231
|
closed: false
|
|
253
232
|
};
|
|
254
233
|
this.startOptionsShownUfoExperience();
|
|
255
|
-
|
|
256
234
|
if (this.state.users.length === 0) {
|
|
257
235
|
state.sessionId = sessionId;
|
|
258
236
|
state.loading = true;
|
|
@@ -263,36 +241,32 @@ export class SmartUserPickerWithoutAnalytics extends React.Component {
|
|
|
263
241
|
sessionId
|
|
264
242
|
});
|
|
265
243
|
}
|
|
266
|
-
|
|
267
|
-
|
|
244
|
+
this.setState(currentState => ({
|
|
245
|
+
...currentState,
|
|
268
246
|
...state
|
|
269
247
|
}));
|
|
270
|
-
|
|
271
248
|
if (this.props.onFocus) {
|
|
272
249
|
this.props.onFocus(sessionId);
|
|
273
250
|
}
|
|
274
251
|
});
|
|
275
|
-
|
|
276
252
|
_defineProperty(this, "onBlur", sessionId => {
|
|
277
253
|
this.getUsers.cancel();
|
|
278
|
-
this.abortOptionsShownUfoExperience();
|
|
279
|
-
// the old list is not shown
|
|
254
|
+
this.abortOptionsShownUfoExperience();
|
|
280
255
|
|
|
256
|
+
// clear old users if query is populated so that on refocus,
|
|
257
|
+
// the old list is not shown
|
|
281
258
|
const users = this.state.query.length === 0 ? this.state.users : [];
|
|
282
259
|
this.setState({
|
|
283
260
|
loading: false,
|
|
284
261
|
closed: true,
|
|
285
262
|
users
|
|
286
263
|
});
|
|
287
|
-
|
|
288
264
|
if (this.props.onBlur) {
|
|
289
265
|
this.props.onBlur(sessionId);
|
|
290
266
|
}
|
|
291
267
|
});
|
|
292
|
-
|
|
293
268
|
this.optionsShownUfoExperienceInstance = smartUserPickerOptionsShownUfoExperience.getInstance(props.inputId || props.fieldId);
|
|
294
269
|
}
|
|
295
|
-
|
|
296
270
|
async componentDidMount() {
|
|
297
271
|
try {
|
|
298
272
|
const value = await hydrateDefaultValues(this.props.baseUrl, this.props.defaultValue, this.props.productKey);
|
|
@@ -305,11 +279,9 @@ export class SmartUserPickerWithoutAnalytics extends React.Component {
|
|
|
305
279
|
defaultValue: defaultValue
|
|
306
280
|
});
|
|
307
281
|
}
|
|
308
|
-
|
|
309
282
|
const {
|
|
310
283
|
prefetch
|
|
311
284
|
} = this.props;
|
|
312
|
-
|
|
313
285
|
if (prefetch) {
|
|
314
286
|
const sessionId = uuidV4();
|
|
315
287
|
this.fireEvent(mountedWithPrefetchEvent, {
|
|
@@ -320,25 +292,22 @@ export class SmartUserPickerWithoutAnalytics extends React.Component {
|
|
|
320
292
|
});
|
|
321
293
|
}
|
|
322
294
|
}
|
|
323
|
-
|
|
324
295
|
componentDidUpdate(prevProps, prevState) {
|
|
325
296
|
if (hasContextChanged(prevProps, this.props) || this.props.fieldId !== prevProps.fieldId) {
|
|
326
297
|
this.setState({
|
|
327
298
|
users: []
|
|
328
299
|
});
|
|
329
300
|
}
|
|
330
|
-
|
|
331
301
|
if ((this.state.sessionId !== prevState.sessionId || this.state.query !== prevState.query) && (this.state.query !== '' || !this.props.bootstrapOptions)) {
|
|
332
302
|
this.getUsers();
|
|
333
303
|
} else if (!this.state.closed && !this.state.loading) {
|
|
334
304
|
// If the component has rendered (including its dropdown list) and it
|
|
335
305
|
// is not loading anything further, send the success UFO event
|
|
336
306
|
if (![UFOExperienceState.FAILED.id, UFOExperienceState.SUCCEEDED.id].includes(this.optionsShownUfoExperienceInstance.state.id)) {
|
|
337
|
-
this.optionsShownUfoExperienceInstance.success();
|
|
307
|
+
this.optionsShownUfoExperienceInstance.success(ufoEndStateConfig(this.props.fieldId));
|
|
338
308
|
}
|
|
339
309
|
}
|
|
340
310
|
}
|
|
341
|
-
|
|
342
311
|
render() {
|
|
343
312
|
return /*#__PURE__*/React.createElement(MessagesIntlProvider, null, /*#__PURE__*/React.createElement(UserPicker, _extends({}, this.props, {
|
|
344
313
|
onInputChange: this.onInputChange,
|
|
@@ -349,9 +318,9 @@ export class SmartUserPickerWithoutAnalytics extends React.Component {
|
|
|
349
318
|
options: this.filterUsers()
|
|
350
319
|
})));
|
|
351
320
|
}
|
|
321
|
+
}
|
|
352
322
|
|
|
353
|
-
|
|
354
|
-
|
|
323
|
+
// TODO: Smart User picker team will have to add a type annotation here
|
|
355
324
|
_defineProperty(SmartUserPickerWithoutAnalytics, "defaultProps", {
|
|
356
325
|
baseUrl: '',
|
|
357
326
|
includeUsers: true,
|
|
@@ -361,5 +330,4 @@ _defineProperty(SmartUserPickerWithoutAnalytics, "defaultProps", {
|
|
|
361
330
|
principalId: 'Context',
|
|
362
331
|
debounceTime: DEFAULT_DEBOUNCE_TIME_MS
|
|
363
332
|
});
|
|
364
|
-
|
|
365
333
|
export const SmartUserPicker = withAnalyticsEvents()(injectIntl(SmartUserPickerWithoutAnalytics));
|
|
@@ -2,7 +2,6 @@ import React from 'react';
|
|
|
2
2
|
import { SmartUserPicker } from './SmartUserPicker';
|
|
3
3
|
import MessagesIntlProvider from './MessagesIntlProvider';
|
|
4
4
|
import { useUFOConcurrentExperience, smartUserPickerRenderedUfoExperience, UfoErrorBoundary } from '../ufoExperiences';
|
|
5
|
-
|
|
6
5
|
const SmartUserPickerWithIntlProvider = props => {
|
|
7
6
|
const ufoId = props.inputId || props.fieldId;
|
|
8
7
|
useUFOConcurrentExperience(smartUserPickerRenderedUfoExperience, ufoId);
|
|
@@ -10,5 +9,4 @@ const SmartUserPickerWithIntlProvider = props => {
|
|
|
10
9
|
id: ufoId
|
|
11
10
|
}, /*#__PURE__*/React.createElement(MessagesIntlProvider, null, /*#__PURE__*/React.createElement(SmartUserPicker, props)));
|
|
12
11
|
};
|
|
13
|
-
|
|
14
12
|
export default SmartUserPickerWithIntlProvider;
|
|
@@ -2,17 +2,13 @@ export const config = {
|
|
|
2
2
|
getRecommendationServiceUrl(baseUrl) {
|
|
3
3
|
return baseUrl ? `${baseUrl}/gateway/api/v1/recommendations` : '/gateway/api/v1/recommendations';
|
|
4
4
|
},
|
|
5
|
-
|
|
6
5
|
getUsersServiceUrl(productKey, baseUrl = '') {
|
|
7
6
|
return productKey === 'jira' ? `${baseUrl}/rest/api/3/user/bulk` : `${baseUrl}/wiki/rest/api/user/bulk`;
|
|
8
7
|
},
|
|
9
|
-
|
|
10
8
|
getGraphQLUrl(baseUrl) {
|
|
11
9
|
return baseUrl ? `${baseUrl}/gateway/api/graphql` : `/gateway/api/graphql`;
|
|
12
10
|
},
|
|
13
|
-
|
|
14
11
|
getTeamsUrl(baseUrl) {
|
|
15
12
|
return baseUrl ? `${baseUrl}/gateway/api/v3/teams` : `/gateway/api/v3/teams`;
|
|
16
13
|
}
|
|
17
|
-
|
|
18
14
|
};
|
package/dist/es2019/index.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
export { default } from './components';
|
|
2
2
|
export { getUserRecommendations, hydrateDefaultValues } from './service';
|
|
3
|
-
export {
|
|
4
|
-
|
|
3
|
+
export {
|
|
4
|
+
//Utils
|
|
5
|
+
isEmail, isTeam, isUser, isValidEmail,
|
|
6
|
+
// Constants
|
|
5
7
|
EmailType, GroupType, TeamType, UserType } from '@atlaskit/user-picker';
|
|
@@ -3,7 +3,6 @@ import { config } from '../config';
|
|
|
3
3
|
import getHydratedUsersFromPrs from './users-client';
|
|
4
4
|
import hydrateTeamFromLegion from './teams-client';
|
|
5
5
|
import { UNKNOWN } from './constants';
|
|
6
|
-
|
|
7
6
|
const getHydratedUsersFromProducts = request => {
|
|
8
7
|
const url = `${config.getUsersServiceUrl(request.productKey, request.baseUrl)}`;
|
|
9
8
|
let params = new URLSearchParams();
|
|
@@ -19,20 +18,16 @@ const getHydratedUsersFromProducts = request => {
|
|
|
19
18
|
if (response.status === 200) {
|
|
20
19
|
return response.json();
|
|
21
20
|
}
|
|
22
|
-
|
|
23
21
|
return Promise.reject({
|
|
24
22
|
message: `error calling users service, statusCode=${response.status}, statusText=${response.statusText}`
|
|
25
23
|
});
|
|
26
24
|
}).then(request.productKey === 'jira' ? transformJiraUsers : transformConfluenceUsers);
|
|
27
25
|
};
|
|
28
|
-
|
|
29
26
|
const transformJiraUsers = userResponse => userResponse.values.map(transformJiraUser).filter(user => !!user).map(user => user);
|
|
30
|
-
|
|
31
27
|
const transformJiraUser = item => {
|
|
32
28
|
if (!item) {
|
|
33
29
|
return null;
|
|
34
30
|
}
|
|
35
|
-
|
|
36
31
|
return {
|
|
37
32
|
id: item.accountId,
|
|
38
33
|
type: UserType,
|
|
@@ -41,14 +36,11 @@ const transformJiraUser = item => {
|
|
|
41
36
|
email: item.emailAddress
|
|
42
37
|
};
|
|
43
38
|
};
|
|
44
|
-
|
|
45
39
|
const transformConfluenceUsers = userResponse => userResponse.results.map(transformConfluenceUser).filter(user => !!user).map(user => user);
|
|
46
|
-
|
|
47
40
|
const transformConfluenceUser = item => {
|
|
48
41
|
if (!item) {
|
|
49
42
|
return null;
|
|
50
43
|
}
|
|
51
|
-
|
|
52
44
|
return {
|
|
53
45
|
id: item.accountId,
|
|
54
46
|
type: UserType,
|
|
@@ -57,16 +49,13 @@ const transformConfluenceUser = item => {
|
|
|
57
49
|
email: item.email
|
|
58
50
|
};
|
|
59
51
|
};
|
|
60
|
-
|
|
61
52
|
const sortResults = (options, sortIds) => {
|
|
62
53
|
const resultsMap = new Map(options.map(option => [option && option.id, option]));
|
|
63
54
|
return sortIds.map(option => {
|
|
64
55
|
const user = resultsMap.get(option.id);
|
|
65
|
-
|
|
66
56
|
if (user) {
|
|
67
57
|
return user;
|
|
68
58
|
}
|
|
69
|
-
|
|
70
59
|
return {
|
|
71
60
|
id: option.id,
|
|
72
61
|
type: option.type,
|
|
@@ -74,52 +63,45 @@ const sortResults = (options, sortIds) => {
|
|
|
74
63
|
};
|
|
75
64
|
});
|
|
76
65
|
};
|
|
77
|
-
|
|
78
66
|
const isOptionData = option => {
|
|
79
67
|
return option.name !== undefined;
|
|
80
68
|
};
|
|
81
|
-
|
|
82
69
|
const hydrateTeamIds = async (baseUrl, values) => {
|
|
83
70
|
if (values.length === 0) {
|
|
84
71
|
return [];
|
|
85
72
|
}
|
|
86
|
-
|
|
87
73
|
const legionPromises = values.map(value => hydrateTeamFromLegion({
|
|
88
74
|
baseUrl,
|
|
89
75
|
id: value.id
|
|
90
76
|
}));
|
|
91
77
|
return await Promise.all(legionPromises);
|
|
92
78
|
};
|
|
93
|
-
|
|
94
79
|
const hydrateAccountIds = async (baseUrl, productKey, values) => {
|
|
95
80
|
if (values.length === 0) {
|
|
96
81
|
return [];
|
|
97
82
|
}
|
|
83
|
+
const accountIds = values.map(val => val.id);
|
|
98
84
|
|
|
99
|
-
|
|
100
|
-
|
|
85
|
+
//if we are not jira or confluence then use PRS platform hydration
|
|
101
86
|
return productKey === 'jira' || productKey === 'confluence' ? await getHydratedUsersFromProducts({
|
|
102
87
|
baseUrl,
|
|
103
88
|
productKey,
|
|
104
89
|
accountIds
|
|
105
90
|
}) : await getHydratedUsersFromPrs(baseUrl, accountIds);
|
|
106
91
|
};
|
|
107
|
-
|
|
108
92
|
async function hydrateDefaultValues(baseUrl, value, productKey) {
|
|
109
93
|
//return if no value
|
|
110
94
|
if (!value || Array.isArray(value) && value.length === 0) {
|
|
111
95
|
return [];
|
|
112
96
|
}
|
|
97
|
+
const values = Array.isArray(value) ? value : [value];
|
|
113
98
|
|
|
114
|
-
|
|
115
|
-
|
|
99
|
+
// return if all hydrated
|
|
116
100
|
if (!values.some(val => !isOptionData(val))) {
|
|
117
101
|
return value;
|
|
118
102
|
}
|
|
119
|
-
|
|
120
103
|
const [hydratedUsers, hydratedTeams] = await Promise.all([hydrateAccountIds(baseUrl, productKey, values.filter(val => !isOptionData(val) && val.type === 'user')), hydrateTeamIds(baseUrl, values.filter(val => !isOptionData(val) && val.type === 'team'))]);
|
|
121
104
|
const hydratedOptions = values.filter(val => isOptionData(val)).map(val => val).concat(hydratedUsers).concat(hydratedTeams);
|
|
122
105
|
return sortResults(hydratedOptions, values);
|
|
123
106
|
}
|
|
124
|
-
|
|
125
107
|
export default hydrateDefaultValues;
|
|
@@ -3,7 +3,6 @@ const buildHeaders = () => {
|
|
|
3
3
|
headers.append('Content-Type', 'application/json');
|
|
4
4
|
return headers;
|
|
5
5
|
};
|
|
6
|
-
|
|
7
6
|
/**
|
|
8
7
|
* @param {string} serviceUrl - GraphQL service endpoint
|
|
9
8
|
* @param {Query} query - GraphQL query
|
|
@@ -23,17 +22,14 @@ export function graphqlQuery(serviceUrl, query) {
|
|
|
23
22
|
reason: response.statusText
|
|
24
23
|
});
|
|
25
24
|
}
|
|
26
|
-
|
|
27
25
|
return response;
|
|
28
26
|
}).then(response => response.json()).then(json => {
|
|
29
27
|
if (json.errors) {
|
|
30
28
|
var _json$errors$;
|
|
31
|
-
|
|
32
29
|
return Promise.reject({
|
|
33
30
|
reason: ((_json$errors$ = json.errors[0]) === null || _json$errors$ === void 0 ? void 0 : _json$errors$.category) || 'default'
|
|
34
31
|
});
|
|
35
32
|
}
|
|
36
|
-
|
|
37
33
|
return json.data;
|
|
38
34
|
});
|
|
39
35
|
}
|
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
import { transformUsers } from './users-transformer';
|
|
2
2
|
import { config } from '../config';
|
|
3
|
-
|
|
4
3
|
const getUserRecommendations = (request, intl) => {
|
|
5
4
|
var _request$context, _request$context$prod;
|
|
6
|
-
|
|
7
5
|
const url = config.getRecommendationServiceUrl(request.baseUrl || '');
|
|
8
6
|
return fetch(url, {
|
|
9
7
|
method: 'POST',
|
|
@@ -42,11 +40,9 @@ const getUserRecommendations = (request, intl) => {
|
|
|
42
40
|
if (response.status === 200) {
|
|
43
41
|
return response.json();
|
|
44
42
|
}
|
|
45
|
-
|
|
46
43
|
return Promise.reject({
|
|
47
44
|
message: `error calling smart service, statusCode=${response.status}, statusText=${response.statusText}`
|
|
48
45
|
});
|
|
49
46
|
}).then(response => transformUsers(response, intl));
|
|
50
47
|
};
|
|
51
|
-
|
|
52
48
|
export default getUserRecommendations;
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { config } from '../config';
|
|
2
2
|
import { UNKNOWN_TEAM } from './constants';
|
|
3
|
-
|
|
4
3
|
const transformTeam = (team, id) => {
|
|
5
4
|
return {
|
|
6
5
|
id,
|
|
@@ -9,7 +8,6 @@ const transformTeam = (team, id) => {
|
|
|
9
8
|
avatarUrl: team.smallAvatarImageUrl
|
|
10
9
|
};
|
|
11
10
|
};
|
|
12
|
-
|
|
13
11
|
const hydrateTeamFromLegion = request => {
|
|
14
12
|
const url = `${config.getTeamsUrl(request.baseUrl)}/${request.id}`;
|
|
15
13
|
return fetch(url, {
|
|
@@ -22,16 +20,15 @@ const hydrateTeamFromLegion = request => {
|
|
|
22
20
|
if (response.status === 200) {
|
|
23
21
|
return response.json();
|
|
24
22
|
}
|
|
25
|
-
|
|
26
23
|
return Promise.reject({
|
|
27
24
|
message: `error calling Legion, statusCode=${response.status}, statusText=${response.statusText}`
|
|
28
25
|
});
|
|
29
26
|
}).then(response => {
|
|
30
27
|
return transformTeam(response, request.id);
|
|
31
|
-
}).catch(() => ({
|
|
28
|
+
}).catch(() => ({
|
|
29
|
+
...UNKNOWN_TEAM,
|
|
32
30
|
// on network error, return original team with label 'Unknown'
|
|
33
31
|
id: request.id
|
|
34
32
|
}));
|
|
35
33
|
};
|
|
36
|
-
|
|
37
34
|
export default hydrateTeamFromLegion;
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { UNKNOWN_USER } from './constants';
|
|
2
2
|
import { graphqlQuery } from './graphqlUtils';
|
|
3
3
|
import { config } from '../config';
|
|
4
|
-
|
|
5
4
|
/**
|
|
6
5
|
* @param {string} accountIds ids to hydrate
|
|
7
6
|
* @return GraphQL Query
|
|
@@ -18,12 +17,10 @@ const buildUsersQuery = accountIds => ({
|
|
|
18
17
|
accountIds
|
|
19
18
|
}
|
|
20
19
|
});
|
|
21
|
-
|
|
22
20
|
const makeRequest = async (url, accountIds) => {
|
|
23
21
|
const query = buildUsersQuery(accountIds);
|
|
24
22
|
return await graphqlQuery(url, query);
|
|
25
23
|
};
|
|
26
|
-
|
|
27
24
|
const modifyResponse = users => users.map(({
|
|
28
25
|
accountId,
|
|
29
26
|
name,
|
|
@@ -34,7 +31,6 @@ const modifyResponse = users => users.map(({
|
|
|
34
31
|
name,
|
|
35
32
|
type: 'user'
|
|
36
33
|
}));
|
|
37
|
-
|
|
38
34
|
const getHydratedUsers = (baseUrl, userIds) => {
|
|
39
35
|
const url = config.getGraphQLUrl(baseUrl);
|
|
40
36
|
return new Promise(resolve => {
|
|
@@ -42,11 +38,11 @@ const getHydratedUsers = (baseUrl, userIds) => {
|
|
|
42
38
|
resolve(modifyResponse(data.users));
|
|
43
39
|
}).catch(() => {
|
|
44
40
|
// on network error, return original list with label 'Unknown'
|
|
45
|
-
resolve(userIds.map(id => ({
|
|
41
|
+
resolve(userIds.map(id => ({
|
|
42
|
+
...UNKNOWN_USER,
|
|
46
43
|
id
|
|
47
44
|
})));
|
|
48
45
|
});
|
|
49
46
|
});
|
|
50
47
|
};
|
|
51
|
-
|
|
52
48
|
export default getHydratedUsers;
|
|
@@ -1,20 +1,16 @@
|
|
|
1
1
|
import { TeamType, UserType, GroupType } from '@atlaskit/user-picker';
|
|
2
2
|
import { messages } from '../i18n';
|
|
3
3
|
var EntityType;
|
|
4
|
-
|
|
5
4
|
(function (EntityType) {
|
|
6
5
|
EntityType["USER"] = "USER";
|
|
7
6
|
EntityType["TEAM"] = "TEAM";
|
|
8
7
|
EntityType["GROUP"] = "GROUP";
|
|
9
8
|
})(EntityType || (EntityType = {}));
|
|
10
|
-
|
|
11
9
|
const getLozenzeProperties = (entity, intl) => {
|
|
12
10
|
var _entity$attributes, _entity$attributes2;
|
|
13
|
-
|
|
14
11
|
if ((_entity$attributes = entity.attributes) !== null && _entity$attributes !== void 0 && _entity$attributes.workspaceMember) {
|
|
15
12
|
return intl.formatMessage(messages.memberLozengeText);
|
|
16
13
|
}
|
|
17
|
-
|
|
18
14
|
if ((_entity$attributes2 = entity.attributes) !== null && _entity$attributes2 !== void 0 && _entity$attributes2.isConfluenceExternalCollaborator) {
|
|
19
15
|
const lozengeTooltipMessage = entity.entityType === EntityType.GROUP ? messages.guestGroupLozengeTooltip : messages.guestUserLozengeTooltip;
|
|
20
16
|
return {
|
|
@@ -23,13 +19,10 @@ const getLozenzeProperties = (entity, intl) => {
|
|
|
23
19
|
appearance: 'new'
|
|
24
20
|
};
|
|
25
21
|
}
|
|
26
|
-
|
|
27
22
|
return undefined;
|
|
28
23
|
};
|
|
29
|
-
|
|
30
24
|
const transformUser = (item, intl) => {
|
|
31
25
|
const type = item.entityType;
|
|
32
|
-
|
|
33
26
|
if (type === EntityType.USER) {
|
|
34
27
|
const user = item;
|
|
35
28
|
const lozenge = getLozenzeProperties(user, intl);
|
|
@@ -42,7 +35,6 @@ const transformUser = (item, intl) => {
|
|
|
42
35
|
lozenge: lozenge
|
|
43
36
|
};
|
|
44
37
|
}
|
|
45
|
-
|
|
46
38
|
if (type === EntityType.TEAM) {
|
|
47
39
|
const team = item;
|
|
48
40
|
return {
|
|
@@ -56,7 +48,6 @@ const transformUser = (item, intl) => {
|
|
|
56
48
|
avatarUrl: team.largeAvatarImageUrl || team.smallAvatarImageUrl
|
|
57
49
|
};
|
|
58
50
|
}
|
|
59
|
-
|
|
60
51
|
if (type === EntityType.GROUP) {
|
|
61
52
|
const group = item;
|
|
62
53
|
const lozenge = getLozenzeProperties(group, intl);
|
|
@@ -67,8 +58,6 @@ const transformUser = (item, intl) => {
|
|
|
67
58
|
lozenge: lozenge
|
|
68
59
|
};
|
|
69
60
|
}
|
|
70
|
-
|
|
71
61
|
return;
|
|
72
62
|
};
|
|
73
|
-
|
|
74
63
|
export const transformUsers = (serverResponse, intl) => (serverResponse.recommendedUsers || []).map(item => transformUser(item, intl)).filter(user => !!user).map(user => user);
|
package/dist/es2019/types.js
CHANGED
|
@@ -17,23 +17,26 @@ export const smartUserPickerOptionsShownUfoExperience = new ConcurrentExperience
|
|
|
17
17
|
performanceType: ExperiencePerformanceTypes.InlineResult
|
|
18
18
|
});
|
|
19
19
|
export const useUFOConcurrentExperience = (experience, id) => {
|
|
20
|
-
const experienceForId = experience.getInstance(id);
|
|
21
|
-
// useUFOComponentExperience when it supports ConcurrentExperience.
|
|
20
|
+
const experienceForId = experience.getInstance(id);
|
|
22
21
|
|
|
22
|
+
// Equivalent to componentWillMount - replace with @atlaskit/ufo's
|
|
23
|
+
// useUFOComponentExperience when it supports ConcurrentExperience.
|
|
23
24
|
useState(() => {
|
|
24
25
|
experienceForId.start();
|
|
25
|
-
});
|
|
26
|
+
});
|
|
26
27
|
|
|
28
|
+
// Replace with @atlaskit/ufo's <ExperienceSuccess> when it supports ConcurrentExperience
|
|
27
29
|
useEffect(() => {
|
|
28
30
|
if (experienceForId.state !== UFOExperienceState['FAILED']) {
|
|
29
31
|
experienceForId.success();
|
|
30
32
|
}
|
|
31
|
-
|
|
32
33
|
return () => {
|
|
33
34
|
if ([UFOExperienceState['STARTED'], UFOExperienceState['IN_PROGRESS']].includes(experienceForId.state)) {
|
|
34
35
|
experienceForId.abort();
|
|
35
36
|
}
|
|
36
|
-
};
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
// We only want this useEffect to run once after component mount, so no deps are needed.
|
|
37
40
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
38
41
|
}, []);
|
|
39
42
|
};
|
|
@@ -41,9 +44,7 @@ export class UfoErrorBoundary extends React.Component {
|
|
|
41
44
|
componentDidCatch() {
|
|
42
45
|
smartUserPickerRenderedUfoExperience.getInstance(this.props.id).failure();
|
|
43
46
|
}
|
|
44
|
-
|
|
45
47
|
render() {
|
|
46
48
|
return this.props.children;
|
|
47
49
|
}
|
|
48
|
-
|
|
49
50
|
}
|