@atlaskit/smart-user-picker 8.2.1 → 8.3.1
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 +19 -0
- package/dist/cjs/analytics.js +1 -1
- package/dist/cjs/components/SmartUserPicker.js +119 -58
- package/dist/cjs/service/recommendation-client.js +1 -1
- package/dist/cjs/service/users-transformer.js +1 -0
- package/dist/cjs/types.js +8 -1
- package/dist/es2019/analytics.js +1 -1
- package/dist/es2019/components/SmartUserPicker.js +65 -9
- package/dist/es2019/service/recommendation-client.js +1 -1
- package/dist/es2019/service/users-transformer.js +1 -0
- package/dist/es2019/types.js +7 -0
- package/dist/esm/analytics.js +1 -1
- package/dist/esm/components/SmartUserPicker.js +119 -58
- package/dist/esm/service/recommendation-client.js +1 -1
- package/dist/esm/service/users-transformer.js +1 -0
- package/dist/esm/types.js +7 -0
- package/dist/types/components/SmartUserPicker.d.ts +4 -0
- package/dist/types/types.d.ts +29 -0
- package/dist/types-ts4.5/components/SmartUserPicker.d.ts +4 -0
- package/dist/types-ts4.5/types.d.ts +29 -0
- package/package.json +3 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,24 @@
|
|
|
1
1
|
# @atlassian/smart-user-picker
|
|
2
2
|
|
|
3
|
+
## 8.3.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [`56ac0cf74b37d`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/56ac0cf74b37d) -
|
|
8
|
+
Migrated teams assets to new service
|
|
9
|
+
|
|
10
|
+
## 8.3.0
|
|
11
|
+
|
|
12
|
+
### Minor Changes
|
|
13
|
+
|
|
14
|
+
- [`be2f98085fa9f`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/be2f98085fa9f) -
|
|
15
|
+
[ux] Introduce additional email props to smart user picker (displayEmailInByline,
|
|
16
|
+
enableEmailSearch, allowEmailSelectionWhenEmailMatched) and one type adjustment to user picker
|
|
17
|
+
|
|
18
|
+
### Patch Changes
|
|
19
|
+
|
|
20
|
+
- Updated dependencies
|
|
21
|
+
|
|
3
22
|
## 8.2.1
|
|
4
23
|
|
|
5
24
|
### Patch Changes
|
package/dist/cjs/analytics.js
CHANGED
|
@@ -11,7 +11,7 @@ var _uuid = require("uuid");
|
|
|
11
11
|
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
|
|
12
12
|
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { (0, _defineProperty2.default)(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
|
|
13
13
|
var packageName = "@atlaskit/smart-user-picker";
|
|
14
|
-
var packageVersion = "
|
|
14
|
+
var packageVersion = "8.3.0";
|
|
15
15
|
var startSession = exports.startSession = function startSession() {
|
|
16
16
|
return {
|
|
17
17
|
id: (0, _uuid.v4)(),
|
|
@@ -6,8 +6,9 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
6
6
|
value: true
|
|
7
7
|
});
|
|
8
8
|
exports.SmartUserPickerWithoutAnalytics = exports.SmartUserPicker = void 0;
|
|
9
|
-
var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator"));
|
|
10
9
|
var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));
|
|
10
|
+
var _objectWithoutProperties2 = _interopRequireDefault(require("@babel/runtime/helpers/objectWithoutProperties"));
|
|
11
|
+
var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator"));
|
|
11
12
|
var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
|
|
12
13
|
var _toArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toArray"));
|
|
13
14
|
var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator"));
|
|
@@ -28,8 +29,10 @@ var _userPicker = _interopRequireWildcard(require("@atlaskit/user-picker"));
|
|
|
28
29
|
var _platformFeatureFlags = require("@atlaskit/platform-feature-flags");
|
|
29
30
|
var _analytics = require("../analytics");
|
|
30
31
|
var _MessagesIntlProvider = _interopRequireDefault(require("./MessagesIntlProvider"));
|
|
32
|
+
var _types = require("../types");
|
|
31
33
|
var _service = require("../service");
|
|
32
34
|
var _ufoExperiences = require("../ufoExperiences");
|
|
35
|
+
var _excluded = ["allowEmail", "enableEmailSearch", "allowEmailSelectionWhenEmailMatched"];
|
|
33
36
|
function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function _interopRequireWildcard(e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != _typeof(e) && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (var _t in e) "default" !== _t && {}.hasOwnProperty.call(e, _t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, _t)) && (i.get || i.set) ? o(f, _t, i) : f[_t] = e[_t]); return f; })(e, t); }
|
|
34
37
|
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
|
|
35
38
|
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { (0, _defineProperty2.default)(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
|
|
@@ -71,6 +74,9 @@ var getUsersForAnalytics = function getUsersForAnalytics(users) {
|
|
|
71
74
|
var checkIf500Event = function checkIf500Event(statusCode) {
|
|
72
75
|
return 500 <= statusCode && statusCode < 600;
|
|
73
76
|
};
|
|
77
|
+
var isEmailQuery = function isEmailQuery(query) {
|
|
78
|
+
return (0, _userPicker.isValidEmail)(query.trim()) === 'VALID';
|
|
79
|
+
};
|
|
74
80
|
var SmartUserPickerWithoutAnalytics = exports.SmartUserPickerWithoutAnalytics = /*#__PURE__*/function (_React$Component) {
|
|
75
81
|
function SmartUserPickerWithoutAnalytics(props) {
|
|
76
82
|
var _this$props$debounceT;
|
|
@@ -85,6 +91,8 @@ var SmartUserPickerWithoutAnalytics = exports.SmartUserPickerWithoutAnalytics =
|
|
|
85
91
|
defaultValue: [],
|
|
86
92
|
bootstrapOptions: []
|
|
87
93
|
});
|
|
94
|
+
// Track if the last search was an email search that found matches
|
|
95
|
+
(0, _defineProperty2.default)(_this, "lastEmailSearchFoundMatches", false);
|
|
88
96
|
(0, _defineProperty2.default)(_this, "abortOptionsShownUfoExperience", function () {
|
|
89
97
|
if (_this.optionsShownUfoExperienceInstance.state.id === _ufo.UFOExperienceState.STARTED.id) {
|
|
90
98
|
// There may be an existing UFO timing running from previous key entry or focus,
|
|
@@ -110,14 +118,15 @@ var SmartUserPickerWithoutAnalytics = exports.SmartUserPickerWithoutAnalytics =
|
|
|
110
118
|
});
|
|
111
119
|
(0, _defineProperty2.default)(_this, "memoizedFilterOptions", (0, _memoizeOne.default)(_this.filterOptions));
|
|
112
120
|
(0, _defineProperty2.default)(_this, "getUsers", (0, _debounce.default)( /*#__PURE__*/(0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee() {
|
|
113
|
-
var _this$state, query, sessionId, closed, _this$props, baseUrl, childObjectId, containerId, fieldId, includeGroups, includeTeams, includeUsers, includeNonLicensedUsers, intl, maxOptions, objectId, onEmpty, onError, overrideByline, orgId, principalId, productAttributes, productKey, searchQueryFilter, siteId, transformOptions, userResolvers, maxNumberOfResults, startTime, recommendationsRequest, _yield$onEmpty, _query, recommendedUsers, userRecommendationsPromise, userResolversPromises, _yield$Promise$all, _yield$Promise$all2, mainRecommendations, userResolverResults, _iterator, _step, option, elapsedTimeMilli, transformedOptions, displayedUsers, is5xxEvent, onErrorProducedError, defaultUsers, _elapsedTimeMilli;
|
|
121
|
+
var _this$state, query, sessionId, closed, _this$props, baseUrl, childObjectId, containerId, fieldId, includeGroups, includeTeams, includeUsers, includeNonLicensedUsers, intl, maxOptions, objectId, onEmpty, onError, overrideByline, displayEmailInByline, orgId, principalId, productAttributes, productKey, searchQueryFilter, siteId, transformOptions, userResolvers, enableEmailSearch, maxNumberOfResults, startTime, isEmail, recommendationsRequest, _yield$onEmpty, _query, recommendedUsers, userRecommendationsPromise, userResolversPromises, _yield$Promise$all, _yield$Promise$all2, mainRecommendations, userResolverResults, _iterator, _step, option, _iterator2, _step2, _option, elapsedTimeMilli, transformedOptions, displayedUsers, is5xxEvent, onErrorProducedError, defaultUsers, _elapsedTimeMilli;
|
|
114
122
|
return _regenerator.default.wrap(function _callee$(_context) {
|
|
115
123
|
while (1) switch (_context.prev = _context.next) {
|
|
116
124
|
case 0:
|
|
117
125
|
_this$state = _this.state, query = _this$state.query, sessionId = _this$state.sessionId, closed = _this$state.closed;
|
|
118
|
-
_this$props = _this.props, baseUrl = _this$props.baseUrl, childObjectId = _this$props.childObjectId, containerId = _this$props.containerId, fieldId = _this$props.fieldId, includeGroups = _this$props.includeGroups, includeTeams = _this$props.includeTeams, includeUsers = _this$props.includeUsers, includeNonLicensedUsers = _this$props.includeNonLicensedUsers, intl = _this$props.intl, maxOptions = _this$props.maxOptions, objectId = _this$props.objectId, onEmpty = _this$props.onEmpty, onError = _this$props.onError, overrideByline = _this$props.overrideByline, orgId = _this$props.orgId, principalId = _this$props.principalId, productAttributes = _this$props.productAttributes, productKey = _this$props.productKey, searchQueryFilter = _this$props.searchQueryFilter, siteId = _this$props.siteId, transformOptions = _this$props.transformOptions, userResolvers = _this$props.userResolvers;
|
|
126
|
+
_this$props = _this.props, baseUrl = _this$props.baseUrl, childObjectId = _this$props.childObjectId, containerId = _this$props.containerId, fieldId = _this$props.fieldId, includeGroups = _this$props.includeGroups, includeTeams = _this$props.includeTeams, includeUsers = _this$props.includeUsers, includeNonLicensedUsers = _this$props.includeNonLicensedUsers, intl = _this$props.intl, maxOptions = _this$props.maxOptions, objectId = _this$props.objectId, onEmpty = _this$props.onEmpty, onError = _this$props.onError, overrideByline = _this$props.overrideByline, displayEmailInByline = _this$props.displayEmailInByline, orgId = _this$props.orgId, principalId = _this$props.principalId, productAttributes = _this$props.productAttributes, productKey = _this$props.productKey, searchQueryFilter = _this$props.searchQueryFilter, siteId = _this$props.siteId, transformOptions = _this$props.transformOptions, userResolvers = _this$props.userResolvers, enableEmailSearch = _this$props.enableEmailSearch;
|
|
119
127
|
maxNumberOfResults = maxOptions || 100;
|
|
120
|
-
startTime = window.performance.now();
|
|
128
|
+
startTime = window.performance.now(); // Check if this is an email search
|
|
129
|
+
isEmail = enableEmailSearch && isEmailQuery(query);
|
|
121
130
|
recommendationsRequest = {
|
|
122
131
|
baseUrl: baseUrl,
|
|
123
132
|
context: {
|
|
@@ -133,18 +142,27 @@ var SmartUserPickerWithoutAnalytics = exports.SmartUserPickerWithoutAnalytics =
|
|
|
133
142
|
productAttributes: productAttributes
|
|
134
143
|
},
|
|
135
144
|
includeUsers: includeUsers,
|
|
136
|
-
|
|
137
|
-
|
|
145
|
+
// For email searches, disable groups and teams
|
|
146
|
+
includeGroups: isEmail ? false : includeGroups,
|
|
147
|
+
includeTeams: isEmail ? false : includeTeams,
|
|
138
148
|
includeNonLicensedUsers: includeNonLicensedUsers,
|
|
139
149
|
maxNumberOfResults: maxNumberOfResults,
|
|
140
|
-
|
|
141
|
-
|
|
150
|
+
// For email searches, leverage customQuery instead of queryString
|
|
151
|
+
query: isEmail ? '' : query,
|
|
152
|
+
customQuery: isEmail ? "(email:\"".concat(query.trim(), "\")") : '',
|
|
153
|
+
/*
|
|
154
|
+
For email-based searches, we have decided to filter out apps.
|
|
155
|
+
Also - because the other 2 filters ((NOT not_mentionable:true) AND (account_status:active)) are included
|
|
156
|
+
when filter is empty, they have been added here to maintain consistency.
|
|
157
|
+
Further ref: https://developer.atlassian.com/platform/user-recommendations/guides/frequently-asked-questions/#filter-behavior
|
|
158
|
+
*/
|
|
159
|
+
searchQueryFilter: isEmail && !searchQueryFilter ? '(NOT not_mentionable:true) AND (account_status:active) AND (NOT account_type:app)' : searchQueryFilter
|
|
142
160
|
};
|
|
143
|
-
_context.prev =
|
|
161
|
+
_context.prev = 6;
|
|
144
162
|
_query = _this.state.query;
|
|
145
163
|
_this.fireEvent(_analytics.requestUsersEvent);
|
|
146
164
|
if (!(0, _platformFeatureFlags.fg)('twcg-444-invite-usd-improvements-m2-gate')) {
|
|
147
|
-
_context.next =
|
|
165
|
+
_context.next = 21;
|
|
148
166
|
break;
|
|
149
167
|
}
|
|
150
168
|
userRecommendationsPromise = (0, _service.getUserRecommendations)(recommendationsRequest, intl);
|
|
@@ -157,22 +175,22 @@ var SmartUserPickerWithoutAnalytics = exports.SmartUserPickerWithoutAnalytics =
|
|
|
157
175
|
return [];
|
|
158
176
|
});
|
|
159
177
|
});
|
|
160
|
-
_context.next =
|
|
178
|
+
_context.next = 14;
|
|
161
179
|
return Promise.all([userRecommendationsPromise].concat((0, _toConsumableArray2.default)(userResolversPromises)));
|
|
162
|
-
case
|
|
180
|
+
case 14:
|
|
163
181
|
_yield$Promise$all = _context.sent;
|
|
164
182
|
_yield$Promise$all2 = (0, _toArray2.default)(_yield$Promise$all);
|
|
165
183
|
mainRecommendations = _yield$Promise$all2[0];
|
|
166
184
|
userResolverResults = _yield$Promise$all2.slice(1);
|
|
167
185
|
recommendedUsers = [mainRecommendations].concat((0, _toConsumableArray2.default)(userResolverResults)).flat();
|
|
168
|
-
_context.next =
|
|
186
|
+
_context.next = 24;
|
|
169
187
|
break;
|
|
170
|
-
case
|
|
171
|
-
_context.next =
|
|
188
|
+
case 21:
|
|
189
|
+
_context.next = 23;
|
|
172
190
|
return (0, _service.getUserRecommendations)(recommendationsRequest, intl);
|
|
173
|
-
case 22:
|
|
174
|
-
recommendedUsers = _context.sent;
|
|
175
191
|
case 23:
|
|
192
|
+
recommendedUsers = _context.sent;
|
|
193
|
+
case 24:
|
|
176
194
|
if (overrideByline) {
|
|
177
195
|
_iterator = _createForOfIteratorHelper(recommendedUsers);
|
|
178
196
|
try {
|
|
@@ -188,52 +206,79 @@ var SmartUserPickerWithoutAnalytics = exports.SmartUserPickerWithoutAnalytics =
|
|
|
188
206
|
_iterator.f();
|
|
189
207
|
}
|
|
190
208
|
}
|
|
209
|
+
if (displayEmailInByline) {
|
|
210
|
+
_iterator2 = _createForOfIteratorHelper(recommendedUsers);
|
|
211
|
+
try {
|
|
212
|
+
for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
|
|
213
|
+
_option = _step2.value;
|
|
214
|
+
if ((0, _userPicker.isUser)(_option) || (0, _userPicker.isExternalUser)(_option)) {
|
|
215
|
+
if (_option.userType === _types.UserEntityType.DEFAULT || _option.userType === _types.UserEntityType.CUSTOMER) {
|
|
216
|
+
// Respect existing byline if present
|
|
217
|
+
if (_option.email && !_option.byline) {
|
|
218
|
+
_option.byline = _option.email;
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
} catch (err) {
|
|
224
|
+
_iterator2.e(err);
|
|
225
|
+
} finally {
|
|
226
|
+
_iterator2.f();
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
// Track if email search found matches for conditional allowEmail logic
|
|
231
|
+
if (isEmail) {
|
|
232
|
+
_this.lastEmailSearchFoundMatches = recommendedUsers.length > 0;
|
|
233
|
+
} else {
|
|
234
|
+
_this.lastEmailSearchFoundMatches = false;
|
|
235
|
+
}
|
|
191
236
|
elapsedTimeMilli = window.performance.now() - startTime;
|
|
192
237
|
if (!transformOptions) {
|
|
193
|
-
_context.next =
|
|
238
|
+
_context.next = 34;
|
|
194
239
|
break;
|
|
195
240
|
}
|
|
196
|
-
_context.next =
|
|
241
|
+
_context.next = 31;
|
|
197
242
|
return transformOptions(recommendedUsers, _query);
|
|
198
|
-
case
|
|
243
|
+
case 31:
|
|
199
244
|
_context.t0 = _context.sent;
|
|
200
|
-
_context.next =
|
|
245
|
+
_context.next = 35;
|
|
201
246
|
break;
|
|
202
|
-
case
|
|
247
|
+
case 34:
|
|
203
248
|
_context.t0 = recommendedUsers;
|
|
204
|
-
case
|
|
249
|
+
case 35:
|
|
205
250
|
transformedOptions = _context.t0;
|
|
206
251
|
if (!(transformedOptions.length === 0 && onEmpty)) {
|
|
207
|
-
_context.next =
|
|
252
|
+
_context.next = 51;
|
|
208
253
|
break;
|
|
209
254
|
}
|
|
210
|
-
_context.next =
|
|
255
|
+
_context.next = 39;
|
|
211
256
|
return onEmpty(_query);
|
|
212
|
-
case
|
|
257
|
+
case 39:
|
|
213
258
|
_context.t3 = _yield$onEmpty = _context.sent;
|
|
214
259
|
_context.t2 = _context.t3 !== null;
|
|
215
260
|
if (!_context.t2) {
|
|
216
|
-
_context.next =
|
|
261
|
+
_context.next = 43;
|
|
217
262
|
break;
|
|
218
263
|
}
|
|
219
264
|
_context.t2 = _yield$onEmpty !== void 0;
|
|
220
|
-
case
|
|
265
|
+
case 43:
|
|
221
266
|
if (!_context.t2) {
|
|
222
|
-
_context.next =
|
|
267
|
+
_context.next = 47;
|
|
223
268
|
break;
|
|
224
269
|
}
|
|
225
270
|
_context.t4 = _yield$onEmpty;
|
|
226
|
-
_context.next =
|
|
271
|
+
_context.next = 48;
|
|
227
272
|
break;
|
|
228
|
-
case
|
|
273
|
+
case 47:
|
|
229
274
|
_context.t4 = [];
|
|
230
|
-
case
|
|
275
|
+
case 48:
|
|
231
276
|
_context.t1 = _context.t4;
|
|
232
|
-
_context.next =
|
|
277
|
+
_context.next = 52;
|
|
233
278
|
break;
|
|
234
|
-
case
|
|
279
|
+
case 51:
|
|
235
280
|
_context.t1 = transformedOptions;
|
|
236
|
-
case
|
|
281
|
+
case 52:
|
|
237
282
|
displayedUsers = _context.t1;
|
|
238
283
|
_this.setState(function (state) {
|
|
239
284
|
var applicable = state.query === _query;
|
|
@@ -255,11 +300,11 @@ var SmartUserPickerWithoutAnalytics = exports.SmartUserPickerWithoutAnalytics =
|
|
|
255
300
|
loading: loading
|
|
256
301
|
};
|
|
257
302
|
});
|
|
258
|
-
_context.next =
|
|
303
|
+
_context.next = 85;
|
|
259
304
|
break;
|
|
260
|
-
case
|
|
261
|
-
_context.prev =
|
|
262
|
-
_context.t5 = _context["catch"](
|
|
305
|
+
case 56:
|
|
306
|
+
_context.prev = 56;
|
|
307
|
+
_context.t5 = _context["catch"](6);
|
|
263
308
|
is5xxEvent = checkIf500Event(_context.t5.statusCode);
|
|
264
309
|
if (!closed && !onError && is5xxEvent) {
|
|
265
310
|
// If the user lookup fails while the menu is open, and the consumer is not providing a
|
|
@@ -271,35 +316,35 @@ var SmartUserPickerWithoutAnalytics = exports.SmartUserPickerWithoutAnalytics =
|
|
|
271
316
|
});
|
|
272
317
|
onErrorProducedError = false;
|
|
273
318
|
defaultUsers = [];
|
|
274
|
-
_context.prev =
|
|
319
|
+
_context.prev = 63;
|
|
275
320
|
if (!onError) {
|
|
276
|
-
_context.next =
|
|
321
|
+
_context.next = 73;
|
|
277
322
|
break;
|
|
278
323
|
}
|
|
279
|
-
_context.next =
|
|
324
|
+
_context.next = 67;
|
|
280
325
|
return onError(_context.t5, recommendationsRequest);
|
|
281
|
-
case
|
|
326
|
+
case 67:
|
|
282
327
|
_context.t7 = _context.sent;
|
|
283
328
|
if (_context.t7) {
|
|
284
|
-
_context.next =
|
|
329
|
+
_context.next = 70;
|
|
285
330
|
break;
|
|
286
331
|
}
|
|
287
332
|
_context.t7 = [];
|
|
288
|
-
case
|
|
333
|
+
case 70:
|
|
289
334
|
_context.t6 = _context.t7;
|
|
290
|
-
_context.next =
|
|
335
|
+
_context.next = 74;
|
|
291
336
|
break;
|
|
292
|
-
case
|
|
337
|
+
case 73:
|
|
293
338
|
_context.t6 = [];
|
|
294
|
-
case
|
|
339
|
+
case 74:
|
|
295
340
|
defaultUsers = _context.t6;
|
|
296
|
-
_context.next =
|
|
341
|
+
_context.next = 80;
|
|
297
342
|
break;
|
|
298
|
-
case 74:
|
|
299
|
-
_context.prev = 74;
|
|
300
|
-
_context.t8 = _context["catch"](60);
|
|
301
|
-
onErrorProducedError = true;
|
|
302
343
|
case 77:
|
|
344
|
+
_context.prev = 77;
|
|
345
|
+
_context.t8 = _context["catch"](63);
|
|
346
|
+
onErrorProducedError = true;
|
|
347
|
+
case 80:
|
|
303
348
|
if (onErrorProducedError && is5xxEvent) {
|
|
304
349
|
// Log error from fallback data source `onError` to UFO
|
|
305
350
|
_this.optionsShownUfoExperienceInstance.failure(ufoEndStateConfig(_this.props.fieldId));
|
|
@@ -316,11 +361,11 @@ var SmartUserPickerWithoutAnalytics = exports.SmartUserPickerWithoutAnalytics =
|
|
|
316
361
|
elapsedTimeMilli: _elapsedTimeMilli,
|
|
317
362
|
productAttributes: productAttributes
|
|
318
363
|
});
|
|
319
|
-
case
|
|
364
|
+
case 85:
|
|
320
365
|
case "end":
|
|
321
366
|
return _context.stop();
|
|
322
367
|
}
|
|
323
|
-
}, _callee, null, [[
|
|
368
|
+
}, _callee, null, [[6, 56], [63, 77]]);
|
|
324
369
|
})), (_this$props$debounceT = _this.props.debounceTime) !== null && _this$props$debounceT !== void 0 ? _this$props$debounceT : 0));
|
|
325
370
|
(0, _defineProperty2.default)(_this, "onInputChange", function (newQuery, sessionId) {
|
|
326
371
|
var query = newQuery || '';
|
|
@@ -376,7 +421,6 @@ var SmartUserPickerWithoutAnalytics = exports.SmartUserPickerWithoutAnalytics =
|
|
|
376
421
|
});
|
|
377
422
|
(0, _defineProperty2.default)(_this, "onFocus", function (sessionId) {
|
|
378
423
|
var state = {
|
|
379
|
-
query: '',
|
|
380
424
|
closed: false
|
|
381
425
|
};
|
|
382
426
|
_this.startOptionsShownUfoExperience();
|
|
@@ -488,7 +532,21 @@ var SmartUserPickerWithoutAnalytics = exports.SmartUserPickerWithoutAnalytics =
|
|
|
488
532
|
}, {
|
|
489
533
|
key: "render",
|
|
490
534
|
value: function render() {
|
|
491
|
-
|
|
535
|
+
var _this$props2 = this.props,
|
|
536
|
+
allowEmail = _this$props2.allowEmail,
|
|
537
|
+
enableEmailSearch = _this$props2.enableEmailSearch,
|
|
538
|
+
allowEmailSelectionWhenEmailMatched = _this$props2.allowEmailSelectionWhenEmailMatched,
|
|
539
|
+
restProps = (0, _objectWithoutProperties2.default)(_this$props2, _excluded);
|
|
540
|
+
|
|
541
|
+
// Determine whether to allow email selection based on allowEmailSelectionWhenEmailMatched, if needed
|
|
542
|
+
var shouldAllowEmail = allowEmail;
|
|
543
|
+
if (allowEmail && enableEmailSearch && !allowEmailSelectionWhenEmailMatched) {
|
|
544
|
+
// Only allow email selection if we're in an email search that found no matches
|
|
545
|
+
var isCurrentQueryEmail = isEmailQuery(this.state.query);
|
|
546
|
+
shouldAllowEmail = !isCurrentQueryEmail || !this.lastEmailSearchFoundMatches;
|
|
547
|
+
}
|
|
548
|
+
return /*#__PURE__*/_react.default.createElement(_MessagesIntlProvider.default, null, /*#__PURE__*/_react.default.createElement(_userPicker.default, (0, _extends2.default)({}, restProps, {
|
|
549
|
+
allowEmail: shouldAllowEmail,
|
|
492
550
|
onInputChange: this.onInputChange,
|
|
493
551
|
onBlur: this.onBlur,
|
|
494
552
|
onFocus: this.onFocus,
|
|
@@ -505,9 +563,12 @@ var SmartUserPickerWithoutAnalytics = exports.SmartUserPickerWithoutAnalytics =
|
|
|
505
563
|
includeGroups: false,
|
|
506
564
|
includeTeams: false,
|
|
507
565
|
includeNonLicensedUsers: false,
|
|
566
|
+
displayEmailInByline: false,
|
|
508
567
|
prefetch: false,
|
|
509
568
|
principalId: 'Context',
|
|
510
569
|
debounceTime: DEFAULT_DEBOUNCE_TIME_MS,
|
|
511
|
-
userResolvers: []
|
|
570
|
+
userResolvers: [],
|
|
571
|
+
enableEmailSearch: false,
|
|
572
|
+
allowEmailSelectionWhenEmailMatched: true
|
|
512
573
|
});
|
|
513
574
|
var SmartUserPicker = exports.SmartUserPicker = (0, _analyticsNext.withAnalyticsEvents)()((0, _reactIntlNext.injectIntl)(SmartUserPickerWithoutAnalytics));
|
|
@@ -35,7 +35,7 @@ var getUserRecommendations = function getUserRecommendations(request, intl) {
|
|
|
35
35
|
}, ((_request$context = request.context) === null || _request$context === void 0 || (_request$context = _request$context.productAttributes) === null || _request$context === void 0 ? void 0 : _request$context.isEntitledConfluenceExternalCollaborator) && {
|
|
36
36
|
productAccessPermissionIds: ['write', 'external-collaborator-write']
|
|
37
37
|
}), {}, {
|
|
38
|
-
customQuery: '',
|
|
38
|
+
customQuery: request.customQuery || '',
|
|
39
39
|
customerDirectoryId: '',
|
|
40
40
|
filter: request.searchQueryFilter || '',
|
|
41
41
|
minimumAccessLevel: 'APPLICATION',
|
|
@@ -30,6 +30,7 @@ var transformUser = function transformUser(item, intl) {
|
|
|
30
30
|
return {
|
|
31
31
|
id: user.id,
|
|
32
32
|
type: user.nonLicensedUser ? _userPicker.ExternalUserType : _userPicker.UserType,
|
|
33
|
+
userType: user.userType,
|
|
33
34
|
avatarUrl: user.avatarUrl,
|
|
34
35
|
name: user.name,
|
|
35
36
|
email: user.email,
|
package/dist/cjs/types.js
CHANGED
|
@@ -3,10 +3,17 @@
|
|
|
3
3
|
Object.defineProperty(exports, "__esModule", {
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
|
-
exports.EntityType = void 0;
|
|
6
|
+
exports.UserEntityType = exports.EntityType = void 0;
|
|
7
7
|
var EntityType = exports.EntityType = /*#__PURE__*/function (EntityType) {
|
|
8
8
|
EntityType["USER"] = "USER";
|
|
9
9
|
EntityType["TEAM"] = "TEAM";
|
|
10
10
|
EntityType["GROUP"] = "GROUP";
|
|
11
11
|
return EntityType;
|
|
12
|
+
}({});
|
|
13
|
+
var UserEntityType = exports.UserEntityType = /*#__PURE__*/function (UserEntityType) {
|
|
14
|
+
UserEntityType["DEFAULT"] = "DEFAULT";
|
|
15
|
+
UserEntityType["APP"] = "APP";
|
|
16
|
+
UserEntityType["CUSTOMER"] = "CUSTOMER";
|
|
17
|
+
UserEntityType["SYSTEM"] = "SYSTEM";
|
|
18
|
+
return UserEntityType;
|
|
12
19
|
}({}); // Override UserPickerProps below with replacement documentation
|
package/dist/es2019/analytics.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { createAndFireEvent } from '@atlaskit/analytics-next';
|
|
2
2
|
import { v4 as uuid } from 'uuid';
|
|
3
3
|
const packageName = "@atlaskit/smart-user-picker";
|
|
4
|
-
const packageVersion = "
|
|
4
|
+
const packageVersion = "8.3.0";
|
|
5
5
|
export const startSession = () => ({
|
|
6
6
|
id: uuid(),
|
|
7
7
|
start: Date.now(),
|
|
@@ -7,10 +7,11 @@ import { withAnalyticsEvents } from '@atlaskit/analytics-next';
|
|
|
7
7
|
import memoizeOne from 'memoize-one';
|
|
8
8
|
import { injectIntl } from 'react-intl-next';
|
|
9
9
|
import { UFOExperienceState } from '@atlaskit/ufo';
|
|
10
|
-
import UserPicker, { isExternalUser, isTeam, isUser } from '@atlaskit/user-picker';
|
|
10
|
+
import UserPicker, { isExternalUser, isTeam, isUser, isValidEmail } from '@atlaskit/user-picker';
|
|
11
11
|
import { fg } from '@atlaskit/platform-feature-flags';
|
|
12
12
|
import { requestUsersEvent, filterUsersEvent, preparedUsersLoadedEvent, successfulRequestUsersEvent, failedRequestUsersEvent, mountedWithPrefetchEvent, createAndFireEventInElementsChannel, failedUserResolversEvent } from '../analytics';
|
|
13
13
|
import MessagesIntlProvider from './MessagesIntlProvider';
|
|
14
|
+
import { UserEntityType } from '../types';
|
|
14
15
|
import { getUserRecommendations, hydrateDefaultValues } from '../service';
|
|
15
16
|
import { smartUserPickerOptionsShownUfoExperience } from '../ufoExperiences';
|
|
16
17
|
const DEFAULT_DEBOUNCE_TIME_MS = 150;
|
|
@@ -39,6 +40,9 @@ const getUsersForAnalytics = users => (users || []).map(({
|
|
|
39
40
|
type
|
|
40
41
|
}));
|
|
41
42
|
const checkIf500Event = statusCode => 500 <= statusCode && statusCode < 600;
|
|
43
|
+
const isEmailQuery = query => {
|
|
44
|
+
return isValidEmail(query.trim()) === 'VALID';
|
|
45
|
+
};
|
|
42
46
|
export class SmartUserPickerWithoutAnalytics extends React.Component {
|
|
43
47
|
constructor(props) {
|
|
44
48
|
var _this$props$debounceT;
|
|
@@ -51,6 +55,8 @@ export class SmartUserPickerWithoutAnalytics extends React.Component {
|
|
|
51
55
|
defaultValue: [],
|
|
52
56
|
bootstrapOptions: []
|
|
53
57
|
});
|
|
58
|
+
// Track if the last search was an email search that found matches
|
|
59
|
+
_defineProperty(this, "lastEmailSearchFoundMatches", false);
|
|
54
60
|
_defineProperty(this, "abortOptionsShownUfoExperience", () => {
|
|
55
61
|
if (this.optionsShownUfoExperienceInstance.state.id === UFOExperienceState.STARTED.id) {
|
|
56
62
|
// There may be an existing UFO timing running from previous key entry or focus,
|
|
@@ -93,6 +99,7 @@ export class SmartUserPickerWithoutAnalytics extends React.Component {
|
|
|
93
99
|
onEmpty,
|
|
94
100
|
onError,
|
|
95
101
|
overrideByline,
|
|
102
|
+
displayEmailInByline,
|
|
96
103
|
orgId,
|
|
97
104
|
principalId,
|
|
98
105
|
productAttributes,
|
|
@@ -100,10 +107,14 @@ export class SmartUserPickerWithoutAnalytics extends React.Component {
|
|
|
100
107
|
searchQueryFilter,
|
|
101
108
|
siteId,
|
|
102
109
|
transformOptions,
|
|
103
|
-
userResolvers
|
|
110
|
+
userResolvers,
|
|
111
|
+
enableEmailSearch
|
|
104
112
|
} = this.props;
|
|
105
113
|
const maxNumberOfResults = maxOptions || 100;
|
|
106
114
|
const startTime = window.performance.now();
|
|
115
|
+
|
|
116
|
+
// Check if this is an email search
|
|
117
|
+
const isEmail = enableEmailSearch && isEmailQuery(query);
|
|
107
118
|
const recommendationsRequest = {
|
|
108
119
|
baseUrl,
|
|
109
120
|
context: {
|
|
@@ -119,12 +130,21 @@ export class SmartUserPickerWithoutAnalytics extends React.Component {
|
|
|
119
130
|
productAttributes
|
|
120
131
|
},
|
|
121
132
|
includeUsers,
|
|
122
|
-
|
|
123
|
-
|
|
133
|
+
// For email searches, disable groups and teams
|
|
134
|
+
includeGroups: isEmail ? false : includeGroups,
|
|
135
|
+
includeTeams: isEmail ? false : includeTeams,
|
|
124
136
|
includeNonLicensedUsers,
|
|
125
137
|
maxNumberOfResults,
|
|
126
|
-
|
|
127
|
-
|
|
138
|
+
// For email searches, leverage customQuery instead of queryString
|
|
139
|
+
query: isEmail ? '' : query,
|
|
140
|
+
customQuery: isEmail ? `(email:"${query.trim()}")` : '',
|
|
141
|
+
/*
|
|
142
|
+
For email-based searches, we have decided to filter out apps.
|
|
143
|
+
Also - because the other 2 filters ((NOT not_mentionable:true) AND (account_status:active)) are included
|
|
144
|
+
when filter is empty, they have been added here to maintain consistency.
|
|
145
|
+
Further ref: https://developer.atlassian.com/platform/user-recommendations/guides/frequently-asked-questions/#filter-behavior
|
|
146
|
+
*/
|
|
147
|
+
searchQueryFilter: isEmail && !searchQueryFilter ? '(NOT not_mentionable:true) AND (account_status:active) AND (NOT account_type:app)' : searchQueryFilter
|
|
128
148
|
};
|
|
129
149
|
try {
|
|
130
150
|
var _await$onEmpty;
|
|
@@ -154,6 +174,25 @@ export class SmartUserPickerWithoutAnalytics extends React.Component {
|
|
|
154
174
|
}
|
|
155
175
|
}
|
|
156
176
|
}
|
|
177
|
+
if (displayEmailInByline) {
|
|
178
|
+
for (let option of recommendedUsers) {
|
|
179
|
+
if (isUser(option) || isExternalUser(option)) {
|
|
180
|
+
if (option.userType === UserEntityType.DEFAULT || option.userType === UserEntityType.CUSTOMER) {
|
|
181
|
+
// Respect existing byline if present
|
|
182
|
+
if (option.email && !option.byline) {
|
|
183
|
+
option.byline = option.email;
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
// Track if email search found matches for conditional allowEmail logic
|
|
191
|
+
if (isEmail) {
|
|
192
|
+
this.lastEmailSearchFoundMatches = recommendedUsers.length > 0;
|
|
193
|
+
} else {
|
|
194
|
+
this.lastEmailSearchFoundMatches = false;
|
|
195
|
+
}
|
|
157
196
|
const elapsedTimeMilli = window.performance.now() - startTime;
|
|
158
197
|
const transformedOptions = transformOptions ? await transformOptions(recommendedUsers, query) : recommendedUsers;
|
|
159
198
|
const displayedUsers = transformedOptions.length === 0 && onEmpty ? (_await$onEmpty = await onEmpty(query)) !== null && _await$onEmpty !== void 0 ? _await$onEmpty : [] : transformedOptions;
|
|
@@ -266,7 +305,6 @@ export class SmartUserPickerWithoutAnalytics extends React.Component {
|
|
|
266
305
|
});
|
|
267
306
|
_defineProperty(this, "onFocus", sessionId => {
|
|
268
307
|
const state = {
|
|
269
|
-
query: '',
|
|
270
308
|
closed: false
|
|
271
309
|
};
|
|
272
310
|
this.startOptionsShownUfoExperience();
|
|
@@ -348,7 +386,22 @@ export class SmartUserPickerWithoutAnalytics extends React.Component {
|
|
|
348
386
|
}
|
|
349
387
|
}
|
|
350
388
|
render() {
|
|
351
|
-
|
|
389
|
+
const {
|
|
390
|
+
allowEmail,
|
|
391
|
+
enableEmailSearch,
|
|
392
|
+
allowEmailSelectionWhenEmailMatched,
|
|
393
|
+
...restProps
|
|
394
|
+
} = this.props;
|
|
395
|
+
|
|
396
|
+
// Determine whether to allow email selection based on allowEmailSelectionWhenEmailMatched, if needed
|
|
397
|
+
let shouldAllowEmail = allowEmail;
|
|
398
|
+
if (allowEmail && enableEmailSearch && !allowEmailSelectionWhenEmailMatched) {
|
|
399
|
+
// Only allow email selection if we're in an email search that found no matches
|
|
400
|
+
const isCurrentQueryEmail = isEmailQuery(this.state.query);
|
|
401
|
+
shouldAllowEmail = !isCurrentQueryEmail || !this.lastEmailSearchFoundMatches;
|
|
402
|
+
}
|
|
403
|
+
return /*#__PURE__*/React.createElement(MessagesIntlProvider, null, /*#__PURE__*/React.createElement(UserPicker, _extends({}, restProps, {
|
|
404
|
+
allowEmail: shouldAllowEmail,
|
|
352
405
|
onInputChange: this.onInputChange,
|
|
353
406
|
onBlur: this.onBlur,
|
|
354
407
|
onFocus: this.onFocus,
|
|
@@ -366,9 +419,12 @@ _defineProperty(SmartUserPickerWithoutAnalytics, "defaultProps", {
|
|
|
366
419
|
includeGroups: false,
|
|
367
420
|
includeTeams: false,
|
|
368
421
|
includeNonLicensedUsers: false,
|
|
422
|
+
displayEmailInByline: false,
|
|
369
423
|
prefetch: false,
|
|
370
424
|
principalId: 'Context',
|
|
371
425
|
debounceTime: DEFAULT_DEBOUNCE_TIME_MS,
|
|
372
|
-
userResolvers: []
|
|
426
|
+
userResolvers: [],
|
|
427
|
+
enableEmailSearch: false,
|
|
428
|
+
allowEmailSelectionWhenEmailMatched: true
|
|
373
429
|
});
|
|
374
430
|
export const SmartUserPicker = withAnalyticsEvents()(injectIntl(SmartUserPickerWithoutAnalytics));
|
|
@@ -25,7 +25,7 @@ const getUserRecommendations = (request, intl) => {
|
|
|
25
25
|
...(((_request$context = request.context) === null || _request$context === void 0 ? void 0 : (_request$context$prod = _request$context.productAttributes) === null || _request$context$prod === void 0 ? void 0 : _request$context$prod.isEntitledConfluenceExternalCollaborator) && {
|
|
26
26
|
productAccessPermissionIds: ['write', 'external-collaborator-write']
|
|
27
27
|
}),
|
|
28
|
-
customQuery: '',
|
|
28
|
+
customQuery: request.customQuery || '',
|
|
29
29
|
customerDirectoryId: '',
|
|
30
30
|
filter: request.searchQueryFilter || '',
|
|
31
31
|
minimumAccessLevel: 'APPLICATION',
|
package/dist/es2019/types.js
CHANGED
|
@@ -4,5 +4,12 @@ export let EntityType = /*#__PURE__*/function (EntityType) {
|
|
|
4
4
|
EntityType["GROUP"] = "GROUP";
|
|
5
5
|
return EntityType;
|
|
6
6
|
}({});
|
|
7
|
+
export let UserEntityType = /*#__PURE__*/function (UserEntityType) {
|
|
8
|
+
UserEntityType["DEFAULT"] = "DEFAULT";
|
|
9
|
+
UserEntityType["APP"] = "APP";
|
|
10
|
+
UserEntityType["CUSTOMER"] = "CUSTOMER";
|
|
11
|
+
UserEntityType["SYSTEM"] = "SYSTEM";
|
|
12
|
+
return UserEntityType;
|
|
13
|
+
}({});
|
|
7
14
|
|
|
8
15
|
// Override UserPickerProps below with replacement documentation
|
package/dist/esm/analytics.js
CHANGED
|
@@ -4,7 +4,7 @@ function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t =
|
|
|
4
4
|
import { createAndFireEvent } from '@atlaskit/analytics-next';
|
|
5
5
|
import { v4 as uuid } from 'uuid';
|
|
6
6
|
var packageName = "@atlaskit/smart-user-picker";
|
|
7
|
-
var packageVersion = "
|
|
7
|
+
var packageVersion = "8.3.0";
|
|
8
8
|
export var startSession = function startSession() {
|
|
9
9
|
return {
|
|
10
10
|
id: uuid(),
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import _extends from "@babel/runtime/helpers/extends";
|
|
2
|
+
import _objectWithoutProperties from "@babel/runtime/helpers/objectWithoutProperties";
|
|
2
3
|
import _toConsumableArray from "@babel/runtime/helpers/toConsumableArray";
|
|
3
4
|
import _toArray from "@babel/runtime/helpers/toArray";
|
|
4
5
|
import _asyncToGenerator from "@babel/runtime/helpers/asyncToGenerator";
|
|
@@ -8,6 +9,7 @@ import _possibleConstructorReturn from "@babel/runtime/helpers/possibleConstruct
|
|
|
8
9
|
import _getPrototypeOf from "@babel/runtime/helpers/getPrototypeOf";
|
|
9
10
|
import _inherits from "@babel/runtime/helpers/inherits";
|
|
10
11
|
import _defineProperty from "@babel/runtime/helpers/defineProperty";
|
|
12
|
+
var _excluded = ["allowEmail", "enableEmailSearch", "allowEmailSelectionWhenEmailMatched"];
|
|
11
13
|
import _regeneratorRuntime from "@babel/runtime/regenerator";
|
|
12
14
|
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
|
|
13
15
|
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
|
|
@@ -23,10 +25,11 @@ import { withAnalyticsEvents } from '@atlaskit/analytics-next';
|
|
|
23
25
|
import memoizeOne from 'memoize-one';
|
|
24
26
|
import { injectIntl } from 'react-intl-next';
|
|
25
27
|
import { UFOExperienceState } from '@atlaskit/ufo';
|
|
26
|
-
import UserPicker, { isExternalUser, isTeam, isUser } from '@atlaskit/user-picker';
|
|
28
|
+
import UserPicker, { isExternalUser, isTeam, isUser, isValidEmail } from '@atlaskit/user-picker';
|
|
27
29
|
import { fg } from '@atlaskit/platform-feature-flags';
|
|
28
30
|
import { requestUsersEvent, filterUsersEvent, preparedUsersLoadedEvent, successfulRequestUsersEvent, failedRequestUsersEvent, mountedWithPrefetchEvent, createAndFireEventInElementsChannel, failedUserResolversEvent } from '../analytics';
|
|
29
31
|
import MessagesIntlProvider from './MessagesIntlProvider';
|
|
32
|
+
import { UserEntityType } from '../types';
|
|
30
33
|
import { getUserRecommendations, hydrateDefaultValues } from '../service';
|
|
31
34
|
import { smartUserPickerOptionsShownUfoExperience } from '../ufoExperiences';
|
|
32
35
|
var DEFAULT_DEBOUNCE_TIME_MS = 150;
|
|
@@ -62,6 +65,9 @@ var getUsersForAnalytics = function getUsersForAnalytics(users) {
|
|
|
62
65
|
var checkIf500Event = function checkIf500Event(statusCode) {
|
|
63
66
|
return 500 <= statusCode && statusCode < 600;
|
|
64
67
|
};
|
|
68
|
+
var isEmailQuery = function isEmailQuery(query) {
|
|
69
|
+
return isValidEmail(query.trim()) === 'VALID';
|
|
70
|
+
};
|
|
65
71
|
export var SmartUserPickerWithoutAnalytics = /*#__PURE__*/function (_React$Component) {
|
|
66
72
|
function SmartUserPickerWithoutAnalytics(props) {
|
|
67
73
|
var _this$props$debounceT;
|
|
@@ -76,6 +82,8 @@ export var SmartUserPickerWithoutAnalytics = /*#__PURE__*/function (_React$Compo
|
|
|
76
82
|
defaultValue: [],
|
|
77
83
|
bootstrapOptions: []
|
|
78
84
|
});
|
|
85
|
+
// Track if the last search was an email search that found matches
|
|
86
|
+
_defineProperty(_this, "lastEmailSearchFoundMatches", false);
|
|
79
87
|
_defineProperty(_this, "abortOptionsShownUfoExperience", function () {
|
|
80
88
|
if (_this.optionsShownUfoExperienceInstance.state.id === UFOExperienceState.STARTED.id) {
|
|
81
89
|
// There may be an existing UFO timing running from previous key entry or focus,
|
|
@@ -101,14 +109,15 @@ export var SmartUserPickerWithoutAnalytics = /*#__PURE__*/function (_React$Compo
|
|
|
101
109
|
});
|
|
102
110
|
_defineProperty(_this, "memoizedFilterOptions", memoizeOne(_this.filterOptions));
|
|
103
111
|
_defineProperty(_this, "getUsers", debounce( /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee() {
|
|
104
|
-
var _this$state, query, sessionId, closed, _this$props, baseUrl, childObjectId, containerId, fieldId, includeGroups, includeTeams, includeUsers, includeNonLicensedUsers, intl, maxOptions, objectId, onEmpty, onError, overrideByline, orgId, principalId, productAttributes, productKey, searchQueryFilter, siteId, transformOptions, userResolvers, maxNumberOfResults, startTime, recommendationsRequest, _yield$onEmpty, _query, recommendedUsers, userRecommendationsPromise, userResolversPromises, _yield$Promise$all, _yield$Promise$all2, mainRecommendations, userResolverResults, _iterator, _step, option, elapsedTimeMilli, transformedOptions, displayedUsers, is5xxEvent, onErrorProducedError, defaultUsers, _elapsedTimeMilli;
|
|
112
|
+
var _this$state, query, sessionId, closed, _this$props, baseUrl, childObjectId, containerId, fieldId, includeGroups, includeTeams, includeUsers, includeNonLicensedUsers, intl, maxOptions, objectId, onEmpty, onError, overrideByline, displayEmailInByline, orgId, principalId, productAttributes, productKey, searchQueryFilter, siteId, transformOptions, userResolvers, enableEmailSearch, maxNumberOfResults, startTime, isEmail, recommendationsRequest, _yield$onEmpty, _query, recommendedUsers, userRecommendationsPromise, userResolversPromises, _yield$Promise$all, _yield$Promise$all2, mainRecommendations, userResolverResults, _iterator, _step, option, _iterator2, _step2, _option, elapsedTimeMilli, transformedOptions, displayedUsers, is5xxEvent, onErrorProducedError, defaultUsers, _elapsedTimeMilli;
|
|
105
113
|
return _regeneratorRuntime.wrap(function _callee$(_context) {
|
|
106
114
|
while (1) switch (_context.prev = _context.next) {
|
|
107
115
|
case 0:
|
|
108
116
|
_this$state = _this.state, query = _this$state.query, sessionId = _this$state.sessionId, closed = _this$state.closed;
|
|
109
|
-
_this$props = _this.props, baseUrl = _this$props.baseUrl, childObjectId = _this$props.childObjectId, containerId = _this$props.containerId, fieldId = _this$props.fieldId, includeGroups = _this$props.includeGroups, includeTeams = _this$props.includeTeams, includeUsers = _this$props.includeUsers, includeNonLicensedUsers = _this$props.includeNonLicensedUsers, intl = _this$props.intl, maxOptions = _this$props.maxOptions, objectId = _this$props.objectId, onEmpty = _this$props.onEmpty, onError = _this$props.onError, overrideByline = _this$props.overrideByline, orgId = _this$props.orgId, principalId = _this$props.principalId, productAttributes = _this$props.productAttributes, productKey = _this$props.productKey, searchQueryFilter = _this$props.searchQueryFilter, siteId = _this$props.siteId, transformOptions = _this$props.transformOptions, userResolvers = _this$props.userResolvers;
|
|
117
|
+
_this$props = _this.props, baseUrl = _this$props.baseUrl, childObjectId = _this$props.childObjectId, containerId = _this$props.containerId, fieldId = _this$props.fieldId, includeGroups = _this$props.includeGroups, includeTeams = _this$props.includeTeams, includeUsers = _this$props.includeUsers, includeNonLicensedUsers = _this$props.includeNonLicensedUsers, intl = _this$props.intl, maxOptions = _this$props.maxOptions, objectId = _this$props.objectId, onEmpty = _this$props.onEmpty, onError = _this$props.onError, overrideByline = _this$props.overrideByline, displayEmailInByline = _this$props.displayEmailInByline, orgId = _this$props.orgId, principalId = _this$props.principalId, productAttributes = _this$props.productAttributes, productKey = _this$props.productKey, searchQueryFilter = _this$props.searchQueryFilter, siteId = _this$props.siteId, transformOptions = _this$props.transformOptions, userResolvers = _this$props.userResolvers, enableEmailSearch = _this$props.enableEmailSearch;
|
|
110
118
|
maxNumberOfResults = maxOptions || 100;
|
|
111
|
-
startTime = window.performance.now();
|
|
119
|
+
startTime = window.performance.now(); // Check if this is an email search
|
|
120
|
+
isEmail = enableEmailSearch && isEmailQuery(query);
|
|
112
121
|
recommendationsRequest = {
|
|
113
122
|
baseUrl: baseUrl,
|
|
114
123
|
context: {
|
|
@@ -124,18 +133,27 @@ export var SmartUserPickerWithoutAnalytics = /*#__PURE__*/function (_React$Compo
|
|
|
124
133
|
productAttributes: productAttributes
|
|
125
134
|
},
|
|
126
135
|
includeUsers: includeUsers,
|
|
127
|
-
|
|
128
|
-
|
|
136
|
+
// For email searches, disable groups and teams
|
|
137
|
+
includeGroups: isEmail ? false : includeGroups,
|
|
138
|
+
includeTeams: isEmail ? false : includeTeams,
|
|
129
139
|
includeNonLicensedUsers: includeNonLicensedUsers,
|
|
130
140
|
maxNumberOfResults: maxNumberOfResults,
|
|
131
|
-
|
|
132
|
-
|
|
141
|
+
// For email searches, leverage customQuery instead of queryString
|
|
142
|
+
query: isEmail ? '' : query,
|
|
143
|
+
customQuery: isEmail ? "(email:\"".concat(query.trim(), "\")") : '',
|
|
144
|
+
/*
|
|
145
|
+
For email-based searches, we have decided to filter out apps.
|
|
146
|
+
Also - because the other 2 filters ((NOT not_mentionable:true) AND (account_status:active)) are included
|
|
147
|
+
when filter is empty, they have been added here to maintain consistency.
|
|
148
|
+
Further ref: https://developer.atlassian.com/platform/user-recommendations/guides/frequently-asked-questions/#filter-behavior
|
|
149
|
+
*/
|
|
150
|
+
searchQueryFilter: isEmail && !searchQueryFilter ? '(NOT not_mentionable:true) AND (account_status:active) AND (NOT account_type:app)' : searchQueryFilter
|
|
133
151
|
};
|
|
134
|
-
_context.prev =
|
|
152
|
+
_context.prev = 6;
|
|
135
153
|
_query = _this.state.query;
|
|
136
154
|
_this.fireEvent(requestUsersEvent);
|
|
137
155
|
if (!fg('twcg-444-invite-usd-improvements-m2-gate')) {
|
|
138
|
-
_context.next =
|
|
156
|
+
_context.next = 21;
|
|
139
157
|
break;
|
|
140
158
|
}
|
|
141
159
|
userRecommendationsPromise = getUserRecommendations(recommendationsRequest, intl);
|
|
@@ -148,22 +166,22 @@ export var SmartUserPickerWithoutAnalytics = /*#__PURE__*/function (_React$Compo
|
|
|
148
166
|
return [];
|
|
149
167
|
});
|
|
150
168
|
});
|
|
151
|
-
_context.next =
|
|
169
|
+
_context.next = 14;
|
|
152
170
|
return Promise.all([userRecommendationsPromise].concat(_toConsumableArray(userResolversPromises)));
|
|
153
|
-
case
|
|
171
|
+
case 14:
|
|
154
172
|
_yield$Promise$all = _context.sent;
|
|
155
173
|
_yield$Promise$all2 = _toArray(_yield$Promise$all);
|
|
156
174
|
mainRecommendations = _yield$Promise$all2[0];
|
|
157
175
|
userResolverResults = _yield$Promise$all2.slice(1);
|
|
158
176
|
recommendedUsers = [mainRecommendations].concat(_toConsumableArray(userResolverResults)).flat();
|
|
159
|
-
_context.next =
|
|
177
|
+
_context.next = 24;
|
|
160
178
|
break;
|
|
161
|
-
case
|
|
162
|
-
_context.next =
|
|
179
|
+
case 21:
|
|
180
|
+
_context.next = 23;
|
|
163
181
|
return getUserRecommendations(recommendationsRequest, intl);
|
|
164
|
-
case 22:
|
|
165
|
-
recommendedUsers = _context.sent;
|
|
166
182
|
case 23:
|
|
183
|
+
recommendedUsers = _context.sent;
|
|
184
|
+
case 24:
|
|
167
185
|
if (overrideByline) {
|
|
168
186
|
_iterator = _createForOfIteratorHelper(recommendedUsers);
|
|
169
187
|
try {
|
|
@@ -179,52 +197,79 @@ export var SmartUserPickerWithoutAnalytics = /*#__PURE__*/function (_React$Compo
|
|
|
179
197
|
_iterator.f();
|
|
180
198
|
}
|
|
181
199
|
}
|
|
200
|
+
if (displayEmailInByline) {
|
|
201
|
+
_iterator2 = _createForOfIteratorHelper(recommendedUsers);
|
|
202
|
+
try {
|
|
203
|
+
for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
|
|
204
|
+
_option = _step2.value;
|
|
205
|
+
if (isUser(_option) || isExternalUser(_option)) {
|
|
206
|
+
if (_option.userType === UserEntityType.DEFAULT || _option.userType === UserEntityType.CUSTOMER) {
|
|
207
|
+
// Respect existing byline if present
|
|
208
|
+
if (_option.email && !_option.byline) {
|
|
209
|
+
_option.byline = _option.email;
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
} catch (err) {
|
|
215
|
+
_iterator2.e(err);
|
|
216
|
+
} finally {
|
|
217
|
+
_iterator2.f();
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
// Track if email search found matches for conditional allowEmail logic
|
|
222
|
+
if (isEmail) {
|
|
223
|
+
_this.lastEmailSearchFoundMatches = recommendedUsers.length > 0;
|
|
224
|
+
} else {
|
|
225
|
+
_this.lastEmailSearchFoundMatches = false;
|
|
226
|
+
}
|
|
182
227
|
elapsedTimeMilli = window.performance.now() - startTime;
|
|
183
228
|
if (!transformOptions) {
|
|
184
|
-
_context.next =
|
|
229
|
+
_context.next = 34;
|
|
185
230
|
break;
|
|
186
231
|
}
|
|
187
|
-
_context.next =
|
|
232
|
+
_context.next = 31;
|
|
188
233
|
return transformOptions(recommendedUsers, _query);
|
|
189
|
-
case
|
|
234
|
+
case 31:
|
|
190
235
|
_context.t0 = _context.sent;
|
|
191
|
-
_context.next =
|
|
236
|
+
_context.next = 35;
|
|
192
237
|
break;
|
|
193
|
-
case
|
|
238
|
+
case 34:
|
|
194
239
|
_context.t0 = recommendedUsers;
|
|
195
|
-
case
|
|
240
|
+
case 35:
|
|
196
241
|
transformedOptions = _context.t0;
|
|
197
242
|
if (!(transformedOptions.length === 0 && onEmpty)) {
|
|
198
|
-
_context.next =
|
|
243
|
+
_context.next = 51;
|
|
199
244
|
break;
|
|
200
245
|
}
|
|
201
|
-
_context.next =
|
|
246
|
+
_context.next = 39;
|
|
202
247
|
return onEmpty(_query);
|
|
203
|
-
case
|
|
248
|
+
case 39:
|
|
204
249
|
_context.t3 = _yield$onEmpty = _context.sent;
|
|
205
250
|
_context.t2 = _context.t3 !== null;
|
|
206
251
|
if (!_context.t2) {
|
|
207
|
-
_context.next =
|
|
252
|
+
_context.next = 43;
|
|
208
253
|
break;
|
|
209
254
|
}
|
|
210
255
|
_context.t2 = _yield$onEmpty !== void 0;
|
|
211
|
-
case
|
|
256
|
+
case 43:
|
|
212
257
|
if (!_context.t2) {
|
|
213
|
-
_context.next =
|
|
258
|
+
_context.next = 47;
|
|
214
259
|
break;
|
|
215
260
|
}
|
|
216
261
|
_context.t4 = _yield$onEmpty;
|
|
217
|
-
_context.next =
|
|
262
|
+
_context.next = 48;
|
|
218
263
|
break;
|
|
219
|
-
case
|
|
264
|
+
case 47:
|
|
220
265
|
_context.t4 = [];
|
|
221
|
-
case
|
|
266
|
+
case 48:
|
|
222
267
|
_context.t1 = _context.t4;
|
|
223
|
-
_context.next =
|
|
268
|
+
_context.next = 52;
|
|
224
269
|
break;
|
|
225
|
-
case
|
|
270
|
+
case 51:
|
|
226
271
|
_context.t1 = transformedOptions;
|
|
227
|
-
case
|
|
272
|
+
case 52:
|
|
228
273
|
displayedUsers = _context.t1;
|
|
229
274
|
_this.setState(function (state) {
|
|
230
275
|
var applicable = state.query === _query;
|
|
@@ -246,11 +291,11 @@ export var SmartUserPickerWithoutAnalytics = /*#__PURE__*/function (_React$Compo
|
|
|
246
291
|
loading: loading
|
|
247
292
|
};
|
|
248
293
|
});
|
|
249
|
-
_context.next =
|
|
294
|
+
_context.next = 85;
|
|
250
295
|
break;
|
|
251
|
-
case
|
|
252
|
-
_context.prev =
|
|
253
|
-
_context.t5 = _context["catch"](
|
|
296
|
+
case 56:
|
|
297
|
+
_context.prev = 56;
|
|
298
|
+
_context.t5 = _context["catch"](6);
|
|
254
299
|
is5xxEvent = checkIf500Event(_context.t5.statusCode);
|
|
255
300
|
if (!closed && !onError && is5xxEvent) {
|
|
256
301
|
// If the user lookup fails while the menu is open, and the consumer is not providing a
|
|
@@ -262,35 +307,35 @@ export var SmartUserPickerWithoutAnalytics = /*#__PURE__*/function (_React$Compo
|
|
|
262
307
|
});
|
|
263
308
|
onErrorProducedError = false;
|
|
264
309
|
defaultUsers = [];
|
|
265
|
-
_context.prev =
|
|
310
|
+
_context.prev = 63;
|
|
266
311
|
if (!onError) {
|
|
267
|
-
_context.next =
|
|
312
|
+
_context.next = 73;
|
|
268
313
|
break;
|
|
269
314
|
}
|
|
270
|
-
_context.next =
|
|
315
|
+
_context.next = 67;
|
|
271
316
|
return onError(_context.t5, recommendationsRequest);
|
|
272
|
-
case
|
|
317
|
+
case 67:
|
|
273
318
|
_context.t7 = _context.sent;
|
|
274
319
|
if (_context.t7) {
|
|
275
|
-
_context.next =
|
|
320
|
+
_context.next = 70;
|
|
276
321
|
break;
|
|
277
322
|
}
|
|
278
323
|
_context.t7 = [];
|
|
279
|
-
case
|
|
324
|
+
case 70:
|
|
280
325
|
_context.t6 = _context.t7;
|
|
281
|
-
_context.next =
|
|
326
|
+
_context.next = 74;
|
|
282
327
|
break;
|
|
283
|
-
case
|
|
328
|
+
case 73:
|
|
284
329
|
_context.t6 = [];
|
|
285
|
-
case
|
|
330
|
+
case 74:
|
|
286
331
|
defaultUsers = _context.t6;
|
|
287
|
-
_context.next =
|
|
332
|
+
_context.next = 80;
|
|
288
333
|
break;
|
|
289
|
-
case 74:
|
|
290
|
-
_context.prev = 74;
|
|
291
|
-
_context.t8 = _context["catch"](60);
|
|
292
|
-
onErrorProducedError = true;
|
|
293
334
|
case 77:
|
|
335
|
+
_context.prev = 77;
|
|
336
|
+
_context.t8 = _context["catch"](63);
|
|
337
|
+
onErrorProducedError = true;
|
|
338
|
+
case 80:
|
|
294
339
|
if (onErrorProducedError && is5xxEvent) {
|
|
295
340
|
// Log error from fallback data source `onError` to UFO
|
|
296
341
|
_this.optionsShownUfoExperienceInstance.failure(ufoEndStateConfig(_this.props.fieldId));
|
|
@@ -307,11 +352,11 @@ export var SmartUserPickerWithoutAnalytics = /*#__PURE__*/function (_React$Compo
|
|
|
307
352
|
elapsedTimeMilli: _elapsedTimeMilli,
|
|
308
353
|
productAttributes: productAttributes
|
|
309
354
|
});
|
|
310
|
-
case
|
|
355
|
+
case 85:
|
|
311
356
|
case "end":
|
|
312
357
|
return _context.stop();
|
|
313
358
|
}
|
|
314
|
-
}, _callee, null, [[
|
|
359
|
+
}, _callee, null, [[6, 56], [63, 77]]);
|
|
315
360
|
})), (_this$props$debounceT = _this.props.debounceTime) !== null && _this$props$debounceT !== void 0 ? _this$props$debounceT : 0));
|
|
316
361
|
_defineProperty(_this, "onInputChange", function (newQuery, sessionId) {
|
|
317
362
|
var query = newQuery || '';
|
|
@@ -367,7 +412,6 @@ export var SmartUserPickerWithoutAnalytics = /*#__PURE__*/function (_React$Compo
|
|
|
367
412
|
});
|
|
368
413
|
_defineProperty(_this, "onFocus", function (sessionId) {
|
|
369
414
|
var state = {
|
|
370
|
-
query: '',
|
|
371
415
|
closed: false
|
|
372
416
|
};
|
|
373
417
|
_this.startOptionsShownUfoExperience();
|
|
@@ -479,7 +523,21 @@ export var SmartUserPickerWithoutAnalytics = /*#__PURE__*/function (_React$Compo
|
|
|
479
523
|
}, {
|
|
480
524
|
key: "render",
|
|
481
525
|
value: function render() {
|
|
482
|
-
|
|
526
|
+
var _this$props2 = this.props,
|
|
527
|
+
allowEmail = _this$props2.allowEmail,
|
|
528
|
+
enableEmailSearch = _this$props2.enableEmailSearch,
|
|
529
|
+
allowEmailSelectionWhenEmailMatched = _this$props2.allowEmailSelectionWhenEmailMatched,
|
|
530
|
+
restProps = _objectWithoutProperties(_this$props2, _excluded);
|
|
531
|
+
|
|
532
|
+
// Determine whether to allow email selection based on allowEmailSelectionWhenEmailMatched, if needed
|
|
533
|
+
var shouldAllowEmail = allowEmail;
|
|
534
|
+
if (allowEmail && enableEmailSearch && !allowEmailSelectionWhenEmailMatched) {
|
|
535
|
+
// Only allow email selection if we're in an email search that found no matches
|
|
536
|
+
var isCurrentQueryEmail = isEmailQuery(this.state.query);
|
|
537
|
+
shouldAllowEmail = !isCurrentQueryEmail || !this.lastEmailSearchFoundMatches;
|
|
538
|
+
}
|
|
539
|
+
return /*#__PURE__*/React.createElement(MessagesIntlProvider, null, /*#__PURE__*/React.createElement(UserPicker, _extends({}, restProps, {
|
|
540
|
+
allowEmail: shouldAllowEmail,
|
|
483
541
|
onInputChange: this.onInputChange,
|
|
484
542
|
onBlur: this.onBlur,
|
|
485
543
|
onFocus: this.onFocus,
|
|
@@ -498,9 +556,12 @@ _defineProperty(SmartUserPickerWithoutAnalytics, "defaultProps", {
|
|
|
498
556
|
includeGroups: false,
|
|
499
557
|
includeTeams: false,
|
|
500
558
|
includeNonLicensedUsers: false,
|
|
559
|
+
displayEmailInByline: false,
|
|
501
560
|
prefetch: false,
|
|
502
561
|
principalId: 'Context',
|
|
503
562
|
debounceTime: DEFAULT_DEBOUNCE_TIME_MS,
|
|
504
|
-
userResolvers: []
|
|
563
|
+
userResolvers: [],
|
|
564
|
+
enableEmailSearch: false,
|
|
565
|
+
allowEmailSelectionWhenEmailMatched: true
|
|
505
566
|
});
|
|
506
567
|
export var SmartUserPicker = withAnalyticsEvents()(injectIntl(SmartUserPickerWithoutAnalytics));
|
|
@@ -28,7 +28,7 @@ var getUserRecommendations = function getUserRecommendations(request, intl) {
|
|
|
28
28
|
}, ((_request$context = request.context) === null || _request$context === void 0 || (_request$context = _request$context.productAttributes) === null || _request$context === void 0 ? void 0 : _request$context.isEntitledConfluenceExternalCollaborator) && {
|
|
29
29
|
productAccessPermissionIds: ['write', 'external-collaborator-write']
|
|
30
30
|
}), {}, {
|
|
31
|
-
customQuery: '',
|
|
31
|
+
customQuery: request.customQuery || '',
|
|
32
32
|
customerDirectoryId: '',
|
|
33
33
|
filter: request.searchQueryFilter || '',
|
|
34
34
|
minimumAccessLevel: 'APPLICATION',
|
package/dist/esm/types.js
CHANGED
|
@@ -4,5 +4,12 @@ export var EntityType = /*#__PURE__*/function (EntityType) {
|
|
|
4
4
|
EntityType["GROUP"] = "GROUP";
|
|
5
5
|
return EntityType;
|
|
6
6
|
}({});
|
|
7
|
+
export var UserEntityType = /*#__PURE__*/function (UserEntityType) {
|
|
8
|
+
UserEntityType["DEFAULT"] = "DEFAULT";
|
|
9
|
+
UserEntityType["APP"] = "APP";
|
|
10
|
+
UserEntityType["CUSTOMER"] = "CUSTOMER";
|
|
11
|
+
UserEntityType["SYSTEM"] = "SYSTEM";
|
|
12
|
+
return UserEntityType;
|
|
13
|
+
}({});
|
|
7
14
|
|
|
8
15
|
// Override UserPickerProps below with replacement documentation
|
|
@@ -5,6 +5,7 @@ import { type OptionData } from '@atlaskit/user-picker';
|
|
|
5
5
|
import { type Props, type State, type FilterOptions } from '../types';
|
|
6
6
|
export declare class SmartUserPickerWithoutAnalytics extends React.Component<Props & WrappedComponentProps, State> {
|
|
7
7
|
state: State;
|
|
8
|
+
private lastEmailSearchFoundMatches;
|
|
8
9
|
optionsShownUfoExperienceInstance: UFOExperience;
|
|
9
10
|
static defaultProps: {
|
|
10
11
|
baseUrl: string;
|
|
@@ -12,10 +13,13 @@ export declare class SmartUserPickerWithoutAnalytics extends React.Component<Pro
|
|
|
12
13
|
includeGroups: boolean;
|
|
13
14
|
includeTeams: boolean;
|
|
14
15
|
includeNonLicensedUsers: boolean;
|
|
16
|
+
displayEmailInByline: boolean;
|
|
15
17
|
prefetch: boolean;
|
|
16
18
|
principalId: string;
|
|
17
19
|
debounceTime: number;
|
|
18
20
|
userResolvers: never[];
|
|
21
|
+
enableEmailSearch: boolean;
|
|
22
|
+
allowEmailSelectionWhenEmailMatched: boolean;
|
|
19
23
|
};
|
|
20
24
|
constructor(props: Props & WrappedComponentProps);
|
|
21
25
|
componentDidMount(): Promise<void>;
|
package/dist/types/types.d.ts
CHANGED
|
@@ -17,6 +17,7 @@ export interface RecommendationRequest {
|
|
|
17
17
|
context: Context;
|
|
18
18
|
maxNumberOfResults: number;
|
|
19
19
|
query?: string;
|
|
20
|
+
customQuery?: string;
|
|
20
21
|
searchQueryFilter?: string;
|
|
21
22
|
includeUsers?: boolean;
|
|
22
23
|
includeGroups?: boolean;
|
|
@@ -63,10 +64,18 @@ export declare enum EntityType {
|
|
|
63
64
|
TEAM = "TEAM",
|
|
64
65
|
GROUP = "GROUP"
|
|
65
66
|
}
|
|
67
|
+
export declare enum UserEntityType {
|
|
68
|
+
DEFAULT = "DEFAULT",
|
|
69
|
+
APP = "APP",
|
|
70
|
+
CUSTOMER = "CUSTOMER",
|
|
71
|
+
SYSTEM = "SYSTEM"
|
|
72
|
+
}
|
|
66
73
|
export interface RecommendationItem {
|
|
67
74
|
id: string;
|
|
68
75
|
name?: string;
|
|
76
|
+
email?: string;
|
|
69
77
|
entityType: EntityType;
|
|
78
|
+
userType?: UserEntityType;
|
|
70
79
|
avatarUrl: string;
|
|
71
80
|
description?: string;
|
|
72
81
|
teamAri?: string;
|
|
@@ -153,6 +162,13 @@ export interface SmartProps {
|
|
|
153
162
|
* provided as an argument to the function.
|
|
154
163
|
*/
|
|
155
164
|
overrideByline?: OverrideByline;
|
|
165
|
+
/**
|
|
166
|
+
* When enabled, displays email addresses for users in the byline of each option, if available.
|
|
167
|
+
* Note - overrideByline will take precedent over displayEmailInByline.
|
|
168
|
+
* Note - only certain user types will have their email displayed.
|
|
169
|
+
* @default false
|
|
170
|
+
*/
|
|
171
|
+
displayEmailInByline?: boolean;
|
|
156
172
|
/**
|
|
157
173
|
* Prefetch the list of suggested assignees before the user picker is focused.
|
|
158
174
|
* WARNING: please consider carefully before deciding to prefetch your suggestions
|
|
@@ -177,6 +193,19 @@ export interface SmartProps {
|
|
|
177
193
|
* If you are still waiting for CPUS, you can use the `people` productKey in the interim.
|
|
178
194
|
*/
|
|
179
195
|
productKey: string;
|
|
196
|
+
/**
|
|
197
|
+
* When enabled, allows searching for users by email address.
|
|
198
|
+
* Email searches will use customQuery instead of queryString and will set includeGroups and includeTeams to false.
|
|
199
|
+
* @default false
|
|
200
|
+
*/
|
|
201
|
+
enableEmailSearch?: boolean;
|
|
202
|
+
/**
|
|
203
|
+
* When both allowEmail and enableEmailSearch are true, this controls whether both email entry
|
|
204
|
+
* and matched user entries can be selected simultaneously.
|
|
205
|
+
* If false, only allows email selection when no users are found.
|
|
206
|
+
* @default true
|
|
207
|
+
*/
|
|
208
|
+
allowEmailSelectionWhenEmailMatched?: boolean;
|
|
180
209
|
/**
|
|
181
210
|
* Filter to be applied to the eventual query to CPUS for user suggestions.
|
|
182
211
|
* Example:`account_status:"active" AND (NOT email_domain:"connect.atlassian.com")`
|
|
@@ -5,6 +5,7 @@ import { type OptionData } from '@atlaskit/user-picker';
|
|
|
5
5
|
import { type Props, type State, type FilterOptions } from '../types';
|
|
6
6
|
export declare class SmartUserPickerWithoutAnalytics extends React.Component<Props & WrappedComponentProps, State> {
|
|
7
7
|
state: State;
|
|
8
|
+
private lastEmailSearchFoundMatches;
|
|
8
9
|
optionsShownUfoExperienceInstance: UFOExperience;
|
|
9
10
|
static defaultProps: {
|
|
10
11
|
baseUrl: string;
|
|
@@ -12,10 +13,13 @@ export declare class SmartUserPickerWithoutAnalytics extends React.Component<Pro
|
|
|
12
13
|
includeGroups: boolean;
|
|
13
14
|
includeTeams: boolean;
|
|
14
15
|
includeNonLicensedUsers: boolean;
|
|
16
|
+
displayEmailInByline: boolean;
|
|
15
17
|
prefetch: boolean;
|
|
16
18
|
principalId: string;
|
|
17
19
|
debounceTime: number;
|
|
18
20
|
userResolvers: never[];
|
|
21
|
+
enableEmailSearch: boolean;
|
|
22
|
+
allowEmailSelectionWhenEmailMatched: boolean;
|
|
19
23
|
};
|
|
20
24
|
constructor(props: Props & WrappedComponentProps);
|
|
21
25
|
componentDidMount(): Promise<void>;
|
|
@@ -17,6 +17,7 @@ export interface RecommendationRequest {
|
|
|
17
17
|
context: Context;
|
|
18
18
|
maxNumberOfResults: number;
|
|
19
19
|
query?: string;
|
|
20
|
+
customQuery?: string;
|
|
20
21
|
searchQueryFilter?: string;
|
|
21
22
|
includeUsers?: boolean;
|
|
22
23
|
includeGroups?: boolean;
|
|
@@ -63,10 +64,18 @@ export declare enum EntityType {
|
|
|
63
64
|
TEAM = "TEAM",
|
|
64
65
|
GROUP = "GROUP"
|
|
65
66
|
}
|
|
67
|
+
export declare enum UserEntityType {
|
|
68
|
+
DEFAULT = "DEFAULT",
|
|
69
|
+
APP = "APP",
|
|
70
|
+
CUSTOMER = "CUSTOMER",
|
|
71
|
+
SYSTEM = "SYSTEM"
|
|
72
|
+
}
|
|
66
73
|
export interface RecommendationItem {
|
|
67
74
|
id: string;
|
|
68
75
|
name?: string;
|
|
76
|
+
email?: string;
|
|
69
77
|
entityType: EntityType;
|
|
78
|
+
userType?: UserEntityType;
|
|
70
79
|
avatarUrl: string;
|
|
71
80
|
description?: string;
|
|
72
81
|
teamAri?: string;
|
|
@@ -153,6 +162,13 @@ export interface SmartProps {
|
|
|
153
162
|
* provided as an argument to the function.
|
|
154
163
|
*/
|
|
155
164
|
overrideByline?: OverrideByline;
|
|
165
|
+
/**
|
|
166
|
+
* When enabled, displays email addresses for users in the byline of each option, if available.
|
|
167
|
+
* Note - overrideByline will take precedent over displayEmailInByline.
|
|
168
|
+
* Note - only certain user types will have their email displayed.
|
|
169
|
+
* @default false
|
|
170
|
+
*/
|
|
171
|
+
displayEmailInByline?: boolean;
|
|
156
172
|
/**
|
|
157
173
|
* Prefetch the list of suggested assignees before the user picker is focused.
|
|
158
174
|
* WARNING: please consider carefully before deciding to prefetch your suggestions
|
|
@@ -177,6 +193,19 @@ export interface SmartProps {
|
|
|
177
193
|
* If you are still waiting for CPUS, you can use the `people` productKey in the interim.
|
|
178
194
|
*/
|
|
179
195
|
productKey: string;
|
|
196
|
+
/**
|
|
197
|
+
* When enabled, allows searching for users by email address.
|
|
198
|
+
* Email searches will use customQuery instead of queryString and will set includeGroups and includeTeams to false.
|
|
199
|
+
* @default false
|
|
200
|
+
*/
|
|
201
|
+
enableEmailSearch?: boolean;
|
|
202
|
+
/**
|
|
203
|
+
* When both allowEmail and enableEmailSearch are true, this controls whether both email entry
|
|
204
|
+
* and matched user entries can be selected simultaneously.
|
|
205
|
+
* If false, only allows email selection when no users are found.
|
|
206
|
+
* @default true
|
|
207
|
+
*/
|
|
208
|
+
allowEmailSelectionWhenEmailMatched?: boolean;
|
|
180
209
|
/**
|
|
181
210
|
* Filter to be applied to the eventual query to CPUS for user suggestions.
|
|
182
211
|
* Example:`account_status:"active" AND (NOT email_domain:"connect.atlassian.com")`
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@atlaskit/smart-user-picker",
|
|
3
|
-
"version": "8.
|
|
3
|
+
"version": "8.3.1",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"registry": "https://registry.npmjs.org/"
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
"@atlaskit/analytics-next": "^11.1.0",
|
|
39
39
|
"@atlaskit/platform-feature-flags": "^1.1.0",
|
|
40
40
|
"@atlaskit/ufo": "^0.4.0",
|
|
41
|
-
"@atlaskit/user-picker": "^11.
|
|
41
|
+
"@atlaskit/user-picker": "^11.7.0",
|
|
42
42
|
"@babel/runtime": "^7.0.0",
|
|
43
43
|
"lodash": "^4.17.21",
|
|
44
44
|
"memoize-one": "^6.0.0",
|
|
@@ -51,7 +51,7 @@
|
|
|
51
51
|
},
|
|
52
52
|
"devDependencies": {
|
|
53
53
|
"@atlaskit/select": "^21.3.0",
|
|
54
|
-
"@atlaskit/util-data-test": "^18.
|
|
54
|
+
"@atlaskit/util-data-test": "^18.3.0",
|
|
55
55
|
"@testing-library/dom": "^10.1.0",
|
|
56
56
|
"@testing-library/react": "^13.4.0",
|
|
57
57
|
"@testing-library/user-event": "^14.4.3",
|