@atlaskit/smart-user-picker 8.9.3 → 9.0.0
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 +8 -0
- package/dist/cjs/analytics.js +1 -1
- package/dist/cjs/components/SmartUserPicker.js +23 -6
- package/dist/cjs/service/recommendation-client.js +3 -1
- package/dist/cjs/service/users-transformer.js +3 -1
- package/dist/es2019/analytics.js +1 -1
- package/dist/es2019/components/SmartUserPicker.js +20 -3
- package/dist/es2019/service/recommendation-client.js +3 -0
- package/dist/es2019/service/users-transformer.js +3 -1
- package/dist/esm/analytics.js +1 -1
- package/dist/esm/components/SmartUserPicker.js +23 -6
- package/dist/esm/service/recommendation-client.js +3 -1
- package/dist/esm/service/users-transformer.js +3 -1
- package/dist/types/types.d.ts +15 -1
- package/dist/types-ts4.5/types.d.ts +15 -1
- package/package.json +7 -4
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
# @atlassian/smart-user-picker
|
|
2
2
|
|
|
3
|
+
## 9.0.0
|
|
4
|
+
|
|
5
|
+
### Major Changes
|
|
6
|
+
|
|
7
|
+
- [`fe65ecbc97c01`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/fe65ecbc97c01) -
|
|
8
|
+
Filter team results to directory-synced teams only, so only supported teams can be selected and
|
|
9
|
+
unsynced teams do not cause errors.
|
|
10
|
+
|
|
3
11
|
## 8.9.3
|
|
4
12
|
|
|
5
13
|
### 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; } // eslint-disable-next-line @atlaskit/platform/prefer-crypto-random-uuid -- Use crypto.randomUUID instead
|
|
13
13
|
var packageName = "@atlaskit/smart-user-picker";
|
|
14
|
-
var packageVersion = "
|
|
14
|
+
var packageVersion = "0.0.0-development";
|
|
15
15
|
var startSession = exports.startSession = function startSession() {
|
|
16
16
|
return {
|
|
17
17
|
// eslint-disable-next-line @atlaskit/platform/prefer-crypto-random-uuid -- Use crypto.randomUUID instead
|
|
@@ -118,16 +118,16 @@ var SmartUserPickerWithoutAnalytics = exports.SmartUserPickerWithoutAnalytics =
|
|
|
118
118
|
});
|
|
119
119
|
(0, _defineProperty2.default)(_this, "memoizedFilterOptions", (0, _memoizeOne.default)(_this.filterOptions));
|
|
120
120
|
(0, _defineProperty2.default)(_this, "getUsers", (0, _debounce.default)( /*#__PURE__*/(0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee() {
|
|
121
|
-
var _this$state, query, sessionId, closed, _this$props, baseUrl, childObjectId, containerId, fieldId, includeGroups, includeTeams, includeTeamsUpdates, includeUsers, includeNonLicensedUsers, intl, fetchOptions, maxOptions, objectId, onEmpty, onError, overrideByline, displayEmailInByline, verifiedTeams, orgId, principalId, productAttributes, productKey, restrictTo, 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, _iterator3, _step3, _option2, elapsedTimeMilli, transformedOptions, displayedUsers, is5xxEvent, onErrorProducedError, defaultUsers, _elapsedTimeMilli;
|
|
121
|
+
var _this$state, query, sessionId, closed, _this$props, baseUrl, childObjectId, containerId, fieldId, includeGroups, includeTeams, includeTeamsUpdates, includeUsers, includeNonLicensedUsers, intl, fetchOptions, maxOptions, objectId, onEmpty, onError, overrideByline, displayEmailInByline, verifiedTeams, orgId, principalId, productAttributes, productKey, restrictTo, searchQueryFilter, siteId, isTeamSyncedToGroupDirectoryFilter, 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, _iterator3, _step3, _option2, userMatches, elapsedTimeMilli, transformedOptions, displayedUsers, is5xxEvent, onErrorProducedError, defaultUsers, _elapsedTimeMilli;
|
|
122
122
|
return _regenerator.default.wrap(function _callee$(_context) {
|
|
123
123
|
while (1) switch (_context.prev = _context.next) {
|
|
124
124
|
case 0:
|
|
125
125
|
_this$state = _this.state, query = _this$state.query, sessionId = _this$state.sessionId, closed = _this$state.closed;
|
|
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, includeTeamsUpdates = _this$props.includeTeamsUpdates, includeUsers = _this$props.includeUsers, includeNonLicensedUsers = _this$props.includeNonLicensedUsers, intl = _this$props.intl, fetchOptions = _this$props.fetchOptions, maxOptions = _this$props.maxOptions, objectId = _this$props.objectId, onEmpty = _this$props.onEmpty, onError = _this$props.onError, overrideByline = _this$props.overrideByline, displayEmailInByline = _this$props.displayEmailInByline, verifiedTeams = _this$props.verifiedTeams, orgId = _this$props.orgId, principalId = _this$props.principalId, productAttributes = _this$props.productAttributes, productKey = _this$props.productKey, restrictTo = _this$props.restrictTo, searchQueryFilter = _this$props.searchQueryFilter, siteId = _this$props.siteId, transformOptions = _this$props.transformOptions, userResolvers = _this$props.userResolvers, enableEmailSearch = _this$props.enableEmailSearch;
|
|
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, includeTeamsUpdates = _this$props.includeTeamsUpdates, includeUsers = _this$props.includeUsers, includeNonLicensedUsers = _this$props.includeNonLicensedUsers, intl = _this$props.intl, fetchOptions = _this$props.fetchOptions, maxOptions = _this$props.maxOptions, objectId = _this$props.objectId, onEmpty = _this$props.onEmpty, onError = _this$props.onError, overrideByline = _this$props.overrideByline, displayEmailInByline = _this$props.displayEmailInByline, verifiedTeams = _this$props.verifiedTeams, orgId = _this$props.orgId, principalId = _this$props.principalId, productAttributes = _this$props.productAttributes, productKey = _this$props.productKey, restrictTo = _this$props.restrictTo, searchQueryFilter = _this$props.searchQueryFilter, siteId = _this$props.siteId, isTeamSyncedToGroupDirectoryFilter = _this$props.isTeamSyncedToGroupDirectoryFilter, transformOptions = _this$props.transformOptions, userResolvers = _this$props.userResolvers, enableEmailSearch = _this$props.enableEmailSearch;
|
|
127
127
|
maxNumberOfResults = maxOptions || 100;
|
|
128
128
|
startTime = window.performance.now(); // Check if this is an email search
|
|
129
129
|
isEmail = enableEmailSearch && isEmailQuery(query);
|
|
130
|
-
recommendationsRequest = _objectSpread(_objectSpread({
|
|
130
|
+
recommendationsRequest = _objectSpread(_objectSpread(_objectSpread({
|
|
131
131
|
baseUrl: baseUrl,
|
|
132
132
|
context: {
|
|
133
133
|
containerId: containerId,
|
|
@@ -161,6 +161,8 @@ var SmartUserPickerWithoutAnalytics = exports.SmartUserPickerWithoutAnalytics =
|
|
|
161
161
|
searchQueryFilter: isEmail && !searchQueryFilter ? '(NOT not_mentionable:true) AND (account_status:active) AND (NOT account_type:app)' : searchQueryFilter
|
|
162
162
|
}, restrictTo && (0, _platformFeatureFlags.fg)('smart-user-picker-restrict-to-gate') && {
|
|
163
163
|
restrictTo: restrictTo
|
|
164
|
+
}), isTeamSyncedToGroupDirectoryFilter === true && {
|
|
165
|
+
isTeamSyncedToGroupDirectoryFilter: true
|
|
164
166
|
});
|
|
165
167
|
_context.prev = 6;
|
|
166
168
|
_query = _this.state.query;
|
|
@@ -259,7 +261,15 @@ var SmartUserPickerWithoutAnalytics = exports.SmartUserPickerWithoutAnalytics =
|
|
|
259
261
|
|
|
260
262
|
// Track if email search found matches for conditional allowEmail logic
|
|
261
263
|
if (isEmail) {
|
|
262
|
-
|
|
264
|
+
if ((0, _platformFeatureFlags.fg)('smart_user_picker_allow_email_if_team_is_found')) {
|
|
265
|
+
// Only count user/external user matches, not teams or groups
|
|
266
|
+
userMatches = recommendedUsers.filter(function (user) {
|
|
267
|
+
return (0, _userPicker.isUser)(user) || (0, _userPicker.isExternalUser)(user);
|
|
268
|
+
});
|
|
269
|
+
_this.lastEmailSearchFoundMatches = userMatches.length > 0;
|
|
270
|
+
} else {
|
|
271
|
+
_this.lastEmailSearchFoundMatches = recommendedUsers.length > 0;
|
|
272
|
+
}
|
|
263
273
|
} else {
|
|
264
274
|
_this.lastEmailSearchFoundMatches = false;
|
|
265
275
|
}
|
|
@@ -572,9 +582,16 @@ var SmartUserPickerWithoutAnalytics = exports.SmartUserPickerWithoutAnalytics =
|
|
|
572
582
|
// Determine whether to allow email selection based on allowEmailSelectionWhenEmailMatched, if needed
|
|
573
583
|
var shouldAllowEmail = allowEmail;
|
|
574
584
|
if (allowEmail && enableEmailSearch && !allowEmailSelectionWhenEmailMatched) {
|
|
575
|
-
// Only allow email selection if we're in an email search that found no matches
|
|
576
585
|
var isCurrentQueryEmail = isEmailQuery(this.state.query);
|
|
577
|
-
|
|
586
|
+
if ((0, _platformFeatureFlags.fg)('smart_user_picker_allow_email_if_team_is_found')) {
|
|
587
|
+
// Only allow email selection when:
|
|
588
|
+
// 1. The query matches email format (validated by regex)
|
|
589
|
+
// 2. No user/external user matches were found (only teams/groups suggested)
|
|
590
|
+
shouldAllowEmail = isCurrentQueryEmail && !this.lastEmailSearchFoundMatches;
|
|
591
|
+
} else {
|
|
592
|
+
// Only allow email selection if we're in an email search that found no matches
|
|
593
|
+
shouldAllowEmail = !isCurrentQueryEmail || !this.lastEmailSearchFoundMatches;
|
|
594
|
+
}
|
|
578
595
|
}
|
|
579
596
|
return /*#__PURE__*/_react.default.createElement(_MessagesIntlProvider.default, null, /*#__PURE__*/_react.default.createElement(_userPicker.default, (0, _extends2.default)({}, restProps, {
|
|
580
597
|
allowEmail: shouldAllowEmail,
|
|
@@ -27,8 +27,10 @@ var getUserRecommendations = function getUserRecommendations(request, intl) {
|
|
|
27
27
|
includeNonLicensedUsers: request.includeNonLicensedUsers,
|
|
28
28
|
maxNumberOfResults: request.maxNumberOfResults,
|
|
29
29
|
performSearchQueryOnly: false,
|
|
30
|
-
searchQuery: _objectSpread(_objectSpread(_objectSpread({}, request.verifiedTeams === true && {
|
|
30
|
+
searchQuery: _objectSpread(_objectSpread(_objectSpread(_objectSpread({}, request.verifiedTeams === true && {
|
|
31
31
|
isVerifiedTeamFilter: true
|
|
32
|
+
}), request.isTeamSyncedToGroupDirectoryFilter === true && {
|
|
33
|
+
isTeamSyncedToGroupDirectoryFilter: true
|
|
32
34
|
}), {}, {
|
|
33
35
|
cpusQueryHighlights: {
|
|
34
36
|
query: '',
|
|
@@ -42,6 +42,7 @@ var transformUser = function transformUser(item, intl) {
|
|
|
42
42
|
};
|
|
43
43
|
}
|
|
44
44
|
if (type === _types.EntityType.TEAM) {
|
|
45
|
+
var _team$type;
|
|
45
46
|
var team = item;
|
|
46
47
|
return {
|
|
47
48
|
id: team.id,
|
|
@@ -53,7 +54,8 @@ var transformUser = function transformUser(item, intl) {
|
|
|
53
54
|
includesYou: team.includesYou,
|
|
54
55
|
avatarUrl: team.largeAvatarImageUrl || team.smallAvatarImageUrl,
|
|
55
56
|
tooltip: team.displayName,
|
|
56
|
-
verified: team.verified
|
|
57
|
+
verified: team.verified,
|
|
58
|
+
teamTypeName: (_team$type = team.type) === null || _team$type === void 0 ? void 0 : _team$type.name
|
|
57
59
|
};
|
|
58
60
|
}
|
|
59
61
|
if (type === _types.EntityType.GROUP) {
|
package/dist/es2019/analytics.js
CHANGED
|
@@ -2,7 +2,7 @@ import { createAndFireEvent } from '@atlaskit/analytics-next';
|
|
|
2
2
|
// eslint-disable-next-line @atlaskit/platform/prefer-crypto-random-uuid -- Use crypto.randomUUID instead
|
|
3
3
|
import { v4 as uuid } from 'uuid';
|
|
4
4
|
const packageName = "@atlaskit/smart-user-picker";
|
|
5
|
-
const packageVersion = "
|
|
5
|
+
const packageVersion = "0.0.0-development";
|
|
6
6
|
export const startSession = () => ({
|
|
7
7
|
// eslint-disable-next-line @atlaskit/platform/prefer-crypto-random-uuid -- Use crypto.randomUUID instead
|
|
8
8
|
id: uuid(),
|
|
@@ -111,6 +111,7 @@ export class SmartUserPickerWithoutAnalytics extends React.Component {
|
|
|
111
111
|
restrictTo,
|
|
112
112
|
searchQueryFilter,
|
|
113
113
|
siteId,
|
|
114
|
+
isTeamSyncedToGroupDirectoryFilter,
|
|
114
115
|
transformOptions,
|
|
115
116
|
userResolvers,
|
|
116
117
|
enableEmailSearch
|
|
@@ -154,6 +155,9 @@ export class SmartUserPickerWithoutAnalytics extends React.Component {
|
|
|
154
155
|
searchQueryFilter: isEmail && !searchQueryFilter ? '(NOT not_mentionable:true) AND (account_status:active) AND (NOT account_type:app)' : searchQueryFilter,
|
|
155
156
|
...(restrictTo && fg('smart-user-picker-restrict-to-gate') && {
|
|
156
157
|
restrictTo
|
|
158
|
+
}),
|
|
159
|
+
...(isTeamSyncedToGroupDirectoryFilter === true && {
|
|
160
|
+
isTeamSyncedToGroupDirectoryFilter: true
|
|
157
161
|
})
|
|
158
162
|
};
|
|
159
163
|
try {
|
|
@@ -208,7 +212,13 @@ export class SmartUserPickerWithoutAnalytics extends React.Component {
|
|
|
208
212
|
|
|
209
213
|
// Track if email search found matches for conditional allowEmail logic
|
|
210
214
|
if (isEmail) {
|
|
211
|
-
|
|
215
|
+
if (fg('smart_user_picker_allow_email_if_team_is_found')) {
|
|
216
|
+
// Only count user/external user matches, not teams or groups
|
|
217
|
+
const userMatches = recommendedUsers.filter(user => isUser(user) || isExternalUser(user));
|
|
218
|
+
this.lastEmailSearchFoundMatches = userMatches.length > 0;
|
|
219
|
+
} else {
|
|
220
|
+
this.lastEmailSearchFoundMatches = recommendedUsers.length > 0;
|
|
221
|
+
}
|
|
212
222
|
} else {
|
|
213
223
|
this.lastEmailSearchFoundMatches = false;
|
|
214
224
|
}
|
|
@@ -416,9 +426,16 @@ export class SmartUserPickerWithoutAnalytics extends React.Component {
|
|
|
416
426
|
// Determine whether to allow email selection based on allowEmailSelectionWhenEmailMatched, if needed
|
|
417
427
|
let shouldAllowEmail = allowEmail;
|
|
418
428
|
if (allowEmail && enableEmailSearch && !allowEmailSelectionWhenEmailMatched) {
|
|
419
|
-
// Only allow email selection if we're in an email search that found no matches
|
|
420
429
|
const isCurrentQueryEmail = isEmailQuery(this.state.query);
|
|
421
|
-
|
|
430
|
+
if (fg('smart_user_picker_allow_email_if_team_is_found')) {
|
|
431
|
+
// Only allow email selection when:
|
|
432
|
+
// 1. The query matches email format (validated by regex)
|
|
433
|
+
// 2. No user/external user matches were found (only teams/groups suggested)
|
|
434
|
+
shouldAllowEmail = isCurrentQueryEmail && !this.lastEmailSearchFoundMatches;
|
|
435
|
+
} else {
|
|
436
|
+
// Only allow email selection if we're in an email search that found no matches
|
|
437
|
+
shouldAllowEmail = !isCurrentQueryEmail || !this.lastEmailSearchFoundMatches;
|
|
438
|
+
}
|
|
422
439
|
}
|
|
423
440
|
return /*#__PURE__*/React.createElement(MessagesIntlProvider, null, /*#__PURE__*/React.createElement(UserPicker, _extends({}, restProps, {
|
|
424
441
|
allowEmail: shouldAllowEmail,
|
|
@@ -21,6 +21,9 @@ const getUserRecommendations = (request, intl) => {
|
|
|
21
21
|
...(request.verifiedTeams === true && {
|
|
22
22
|
isVerifiedTeamFilter: true
|
|
23
23
|
}),
|
|
24
|
+
...(request.isTeamSyncedToGroupDirectoryFilter === true && {
|
|
25
|
+
isTeamSyncedToGroupDirectoryFilter: true
|
|
26
|
+
}),
|
|
24
27
|
cpusQueryHighlights: {
|
|
25
28
|
query: '',
|
|
26
29
|
field: ''
|
|
@@ -36,6 +36,7 @@ const transformUser = (item, intl) => {
|
|
|
36
36
|
};
|
|
37
37
|
}
|
|
38
38
|
if (type === EntityType.TEAM) {
|
|
39
|
+
var _team$type;
|
|
39
40
|
const team = item;
|
|
40
41
|
return {
|
|
41
42
|
id: team.id,
|
|
@@ -47,7 +48,8 @@ const transformUser = (item, intl) => {
|
|
|
47
48
|
includesYou: team.includesYou,
|
|
48
49
|
avatarUrl: team.largeAvatarImageUrl || team.smallAvatarImageUrl,
|
|
49
50
|
tooltip: team.displayName,
|
|
50
|
-
verified: team.verified
|
|
51
|
+
verified: team.verified,
|
|
52
|
+
teamTypeName: (_team$type = team.type) === null || _team$type === void 0 ? void 0 : _team$type.name
|
|
51
53
|
};
|
|
52
54
|
}
|
|
53
55
|
if (type === EntityType.GROUP) {
|
package/dist/esm/analytics.js
CHANGED
|
@@ -5,7 +5,7 @@ import { createAndFireEvent } from '@atlaskit/analytics-next';
|
|
|
5
5
|
// eslint-disable-next-line @atlaskit/platform/prefer-crypto-random-uuid -- Use crypto.randomUUID instead
|
|
6
6
|
import { v4 as uuid } from 'uuid';
|
|
7
7
|
var packageName = "@atlaskit/smart-user-picker";
|
|
8
|
-
var packageVersion = "
|
|
8
|
+
var packageVersion = "0.0.0-development";
|
|
9
9
|
export var startSession = function startSession() {
|
|
10
10
|
return {
|
|
11
11
|
// eslint-disable-next-line @atlaskit/platform/prefer-crypto-random-uuid -- Use crypto.randomUUID instead
|
|
@@ -110,16 +110,16 @@ export var SmartUserPickerWithoutAnalytics = /*#__PURE__*/function (_React$Compo
|
|
|
110
110
|
});
|
|
111
111
|
_defineProperty(_this, "memoizedFilterOptions", memoizeOne(_this.filterOptions));
|
|
112
112
|
_defineProperty(_this, "getUsers", debounce( /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee() {
|
|
113
|
-
var _this$state, query, sessionId, closed, _this$props, baseUrl, childObjectId, containerId, fieldId, includeGroups, includeTeams, includeTeamsUpdates, includeUsers, includeNonLicensedUsers, intl, fetchOptions, maxOptions, objectId, onEmpty, onError, overrideByline, displayEmailInByline, verifiedTeams, orgId, principalId, productAttributes, productKey, restrictTo, 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, _iterator3, _step3, _option2, elapsedTimeMilli, transformedOptions, displayedUsers, is5xxEvent, onErrorProducedError, defaultUsers, _elapsedTimeMilli;
|
|
113
|
+
var _this$state, query, sessionId, closed, _this$props, baseUrl, childObjectId, containerId, fieldId, includeGroups, includeTeams, includeTeamsUpdates, includeUsers, includeNonLicensedUsers, intl, fetchOptions, maxOptions, objectId, onEmpty, onError, overrideByline, displayEmailInByline, verifiedTeams, orgId, principalId, productAttributes, productKey, restrictTo, searchQueryFilter, siteId, isTeamSyncedToGroupDirectoryFilter, 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, _iterator3, _step3, _option2, userMatches, elapsedTimeMilli, transformedOptions, displayedUsers, is5xxEvent, onErrorProducedError, defaultUsers, _elapsedTimeMilli;
|
|
114
114
|
return _regeneratorRuntime.wrap(function _callee$(_context) {
|
|
115
115
|
while (1) switch (_context.prev = _context.next) {
|
|
116
116
|
case 0:
|
|
117
117
|
_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, includeTeamsUpdates = _this$props.includeTeamsUpdates, includeUsers = _this$props.includeUsers, includeNonLicensedUsers = _this$props.includeNonLicensedUsers, intl = _this$props.intl, fetchOptions = _this$props.fetchOptions, maxOptions = _this$props.maxOptions, objectId = _this$props.objectId, onEmpty = _this$props.onEmpty, onError = _this$props.onError, overrideByline = _this$props.overrideByline, displayEmailInByline = _this$props.displayEmailInByline, verifiedTeams = _this$props.verifiedTeams, orgId = _this$props.orgId, principalId = _this$props.principalId, productAttributes = _this$props.productAttributes, productKey = _this$props.productKey, restrictTo = _this$props.restrictTo, searchQueryFilter = _this$props.searchQueryFilter, siteId = _this$props.siteId, transformOptions = _this$props.transformOptions, userResolvers = _this$props.userResolvers, enableEmailSearch = _this$props.enableEmailSearch;
|
|
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, includeTeamsUpdates = _this$props.includeTeamsUpdates, includeUsers = _this$props.includeUsers, includeNonLicensedUsers = _this$props.includeNonLicensedUsers, intl = _this$props.intl, fetchOptions = _this$props.fetchOptions, maxOptions = _this$props.maxOptions, objectId = _this$props.objectId, onEmpty = _this$props.onEmpty, onError = _this$props.onError, overrideByline = _this$props.overrideByline, displayEmailInByline = _this$props.displayEmailInByline, verifiedTeams = _this$props.verifiedTeams, orgId = _this$props.orgId, principalId = _this$props.principalId, productAttributes = _this$props.productAttributes, productKey = _this$props.productKey, restrictTo = _this$props.restrictTo, searchQueryFilter = _this$props.searchQueryFilter, siteId = _this$props.siteId, isTeamSyncedToGroupDirectoryFilter = _this$props.isTeamSyncedToGroupDirectoryFilter, transformOptions = _this$props.transformOptions, userResolvers = _this$props.userResolvers, enableEmailSearch = _this$props.enableEmailSearch;
|
|
119
119
|
maxNumberOfResults = maxOptions || 100;
|
|
120
120
|
startTime = window.performance.now(); // Check if this is an email search
|
|
121
121
|
isEmail = enableEmailSearch && isEmailQuery(query);
|
|
122
|
-
recommendationsRequest = _objectSpread(_objectSpread({
|
|
122
|
+
recommendationsRequest = _objectSpread(_objectSpread(_objectSpread({
|
|
123
123
|
baseUrl: baseUrl,
|
|
124
124
|
context: {
|
|
125
125
|
containerId: containerId,
|
|
@@ -153,6 +153,8 @@ export var SmartUserPickerWithoutAnalytics = /*#__PURE__*/function (_React$Compo
|
|
|
153
153
|
searchQueryFilter: isEmail && !searchQueryFilter ? '(NOT not_mentionable:true) AND (account_status:active) AND (NOT account_type:app)' : searchQueryFilter
|
|
154
154
|
}, restrictTo && fg('smart-user-picker-restrict-to-gate') && {
|
|
155
155
|
restrictTo: restrictTo
|
|
156
|
+
}), isTeamSyncedToGroupDirectoryFilter === true && {
|
|
157
|
+
isTeamSyncedToGroupDirectoryFilter: true
|
|
156
158
|
});
|
|
157
159
|
_context.prev = 6;
|
|
158
160
|
_query = _this.state.query;
|
|
@@ -251,7 +253,15 @@ export var SmartUserPickerWithoutAnalytics = /*#__PURE__*/function (_React$Compo
|
|
|
251
253
|
|
|
252
254
|
// Track if email search found matches for conditional allowEmail logic
|
|
253
255
|
if (isEmail) {
|
|
254
|
-
|
|
256
|
+
if (fg('smart_user_picker_allow_email_if_team_is_found')) {
|
|
257
|
+
// Only count user/external user matches, not teams or groups
|
|
258
|
+
userMatches = recommendedUsers.filter(function (user) {
|
|
259
|
+
return isUser(user) || isExternalUser(user);
|
|
260
|
+
});
|
|
261
|
+
_this.lastEmailSearchFoundMatches = userMatches.length > 0;
|
|
262
|
+
} else {
|
|
263
|
+
_this.lastEmailSearchFoundMatches = recommendedUsers.length > 0;
|
|
264
|
+
}
|
|
255
265
|
} else {
|
|
256
266
|
_this.lastEmailSearchFoundMatches = false;
|
|
257
267
|
}
|
|
@@ -564,9 +574,16 @@ export var SmartUserPickerWithoutAnalytics = /*#__PURE__*/function (_React$Compo
|
|
|
564
574
|
// Determine whether to allow email selection based on allowEmailSelectionWhenEmailMatched, if needed
|
|
565
575
|
var shouldAllowEmail = allowEmail;
|
|
566
576
|
if (allowEmail && enableEmailSearch && !allowEmailSelectionWhenEmailMatched) {
|
|
567
|
-
// Only allow email selection if we're in an email search that found no matches
|
|
568
577
|
var isCurrentQueryEmail = isEmailQuery(this.state.query);
|
|
569
|
-
|
|
578
|
+
if (fg('smart_user_picker_allow_email_if_team_is_found')) {
|
|
579
|
+
// Only allow email selection when:
|
|
580
|
+
// 1. The query matches email format (validated by regex)
|
|
581
|
+
// 2. No user/external user matches were found (only teams/groups suggested)
|
|
582
|
+
shouldAllowEmail = isCurrentQueryEmail && !this.lastEmailSearchFoundMatches;
|
|
583
|
+
} else {
|
|
584
|
+
// Only allow email selection if we're in an email search that found no matches
|
|
585
|
+
shouldAllowEmail = !isCurrentQueryEmail || !this.lastEmailSearchFoundMatches;
|
|
586
|
+
}
|
|
570
587
|
}
|
|
571
588
|
return /*#__PURE__*/React.createElement(MessagesIntlProvider, null, /*#__PURE__*/React.createElement(UserPicker, _extends({}, restProps, {
|
|
572
589
|
allowEmail: shouldAllowEmail,
|
|
@@ -20,8 +20,10 @@ var getUserRecommendations = function getUserRecommendations(request, intl) {
|
|
|
20
20
|
includeNonLicensedUsers: request.includeNonLicensedUsers,
|
|
21
21
|
maxNumberOfResults: request.maxNumberOfResults,
|
|
22
22
|
performSearchQueryOnly: false,
|
|
23
|
-
searchQuery: _objectSpread(_objectSpread(_objectSpread({}, request.verifiedTeams === true && {
|
|
23
|
+
searchQuery: _objectSpread(_objectSpread(_objectSpread(_objectSpread({}, request.verifiedTeams === true && {
|
|
24
24
|
isVerifiedTeamFilter: true
|
|
25
|
+
}), request.isTeamSyncedToGroupDirectoryFilter === true && {
|
|
26
|
+
isTeamSyncedToGroupDirectoryFilter: true
|
|
25
27
|
}), {}, {
|
|
26
28
|
cpusQueryHighlights: {
|
|
27
29
|
query: '',
|
|
@@ -36,6 +36,7 @@ var transformUser = function transformUser(item, intl) {
|
|
|
36
36
|
};
|
|
37
37
|
}
|
|
38
38
|
if (type === EntityType.TEAM) {
|
|
39
|
+
var _team$type;
|
|
39
40
|
var team = item;
|
|
40
41
|
return {
|
|
41
42
|
id: team.id,
|
|
@@ -47,7 +48,8 @@ var transformUser = function transformUser(item, intl) {
|
|
|
47
48
|
includesYou: team.includesYou,
|
|
48
49
|
avatarUrl: team.largeAvatarImageUrl || team.smallAvatarImageUrl,
|
|
49
50
|
tooltip: team.displayName,
|
|
50
|
-
verified: team.verified
|
|
51
|
+
verified: team.verified,
|
|
52
|
+
teamTypeName: (_team$type = team.type) === null || _team$type === void 0 ? void 0 : _team$type.name
|
|
51
53
|
};
|
|
52
54
|
}
|
|
53
55
|
if (type === EntityType.GROUP) {
|
package/dist/types/types.d.ts
CHANGED
|
@@ -29,6 +29,12 @@ export interface RecommendationRequest {
|
|
|
29
29
|
searchEmail?: boolean;
|
|
30
30
|
verifiedTeams?: boolean;
|
|
31
31
|
restrictTo?: RestrictionFilter;
|
|
32
|
+
/**
|
|
33
|
+
* When true, URS returns only userbase-aligned teams (teams synced to Identity).
|
|
34
|
+
* Confluence uses this for teams-as-principals to avoid errors when users select teams
|
|
35
|
+
* that are not yet mirrored to Identity (e.g. old org-scoped teams in NonVortex orgs).
|
|
36
|
+
*/
|
|
37
|
+
isTeamSyncedToGroupDirectoryFilter?: boolean;
|
|
32
38
|
}
|
|
33
39
|
type OnError = (error: any, request: RecommendationRequest) => Promise<OptionData[]> | void;
|
|
34
40
|
type OnValueError = (error: any, defaultValue: DefaultValue) => Promise<OptionData[]> | void;
|
|
@@ -211,7 +217,9 @@ export interface SmartProps {
|
|
|
211
217
|
/**
|
|
212
218
|
* When both allowEmail and enableEmailSearch are true, this controls whether both email entry
|
|
213
219
|
* and matched user entries can be selected simultaneously.
|
|
214
|
-
* If false, only allows email selection when
|
|
220
|
+
* If false, only allows email selection when:
|
|
221
|
+
* 1. The query matches email format (validated by regex)
|
|
222
|
+
* 2. No user/external user matches are found (teams/groups don't suppress email entry)
|
|
215
223
|
* @default true
|
|
216
224
|
*/
|
|
217
225
|
allowEmailSelectionWhenEmailMatched?: boolean;
|
|
@@ -258,6 +266,12 @@ export interface SmartProps {
|
|
|
258
266
|
* @example { userIds: ["123", "456"], groupIds: ["789"] }
|
|
259
267
|
*/
|
|
260
268
|
restrictTo?: RestrictionFilter;
|
|
269
|
+
/**
|
|
270
|
+
* When true, URS returns only userbase-aligned teams (teams synced to Identity).
|
|
271
|
+
* Confluence uses this for teams-as-principals to avoid errors when users select teams
|
|
272
|
+
* that are not yet mirrored to Identity (e.g. old org-scoped teams in NonVortex orgs).
|
|
273
|
+
*/
|
|
274
|
+
isTeamSyncedToGroupDirectoryFilter?: boolean;
|
|
261
275
|
}
|
|
262
276
|
export interface Props extends SmartProps, UserPickerProps, WithAnalyticsEventsProps {
|
|
263
277
|
/**
|
|
@@ -29,6 +29,12 @@ export interface RecommendationRequest {
|
|
|
29
29
|
searchEmail?: boolean;
|
|
30
30
|
verifiedTeams?: boolean;
|
|
31
31
|
restrictTo?: RestrictionFilter;
|
|
32
|
+
/**
|
|
33
|
+
* When true, URS returns only userbase-aligned teams (teams synced to Identity).
|
|
34
|
+
* Confluence uses this for teams-as-principals to avoid errors when users select teams
|
|
35
|
+
* that are not yet mirrored to Identity (e.g. old org-scoped teams in NonVortex orgs).
|
|
36
|
+
*/
|
|
37
|
+
isTeamSyncedToGroupDirectoryFilter?: boolean;
|
|
32
38
|
}
|
|
33
39
|
type OnError = (error: any, request: RecommendationRequest) => Promise<OptionData[]> | void;
|
|
34
40
|
type OnValueError = (error: any, defaultValue: DefaultValue) => Promise<OptionData[]> | void;
|
|
@@ -211,7 +217,9 @@ export interface SmartProps {
|
|
|
211
217
|
/**
|
|
212
218
|
* When both allowEmail and enableEmailSearch are true, this controls whether both email entry
|
|
213
219
|
* and matched user entries can be selected simultaneously.
|
|
214
|
-
* If false, only allows email selection when
|
|
220
|
+
* If false, only allows email selection when:
|
|
221
|
+
* 1. The query matches email format (validated by regex)
|
|
222
|
+
* 2. No user/external user matches are found (teams/groups don't suppress email entry)
|
|
215
223
|
* @default true
|
|
216
224
|
*/
|
|
217
225
|
allowEmailSelectionWhenEmailMatched?: boolean;
|
|
@@ -258,6 +266,12 @@ export interface SmartProps {
|
|
|
258
266
|
* @example { userIds: ["123", "456"], groupIds: ["789"] }
|
|
259
267
|
*/
|
|
260
268
|
restrictTo?: RestrictionFilter;
|
|
269
|
+
/**
|
|
270
|
+
* When true, URS returns only userbase-aligned teams (teams synced to Identity).
|
|
271
|
+
* Confluence uses this for teams-as-principals to avoid errors when users select teams
|
|
272
|
+
* that are not yet mirrored to Identity (e.g. old org-scoped teams in NonVortex orgs).
|
|
273
|
+
*/
|
|
274
|
+
isTeamSyncedToGroupDirectoryFilter?: boolean;
|
|
261
275
|
}
|
|
262
276
|
export interface Props extends SmartProps, UserPickerProps, WithAnalyticsEventsProps {
|
|
263
277
|
/**
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@atlaskit/smart-user-picker",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "9.0.0",
|
|
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.22.0",
|
|
42
42
|
"@babel/runtime": "^7.0.0",
|
|
43
43
|
"lodash": "^4.17.21",
|
|
44
44
|
"memoize-one": "^6.0.0",
|
|
@@ -51,8 +51,8 @@
|
|
|
51
51
|
},
|
|
52
52
|
"devDependencies": {
|
|
53
53
|
"@atlaskit/select": "^21.7.0",
|
|
54
|
-
"@atlaskit/util-data-test": "^18.
|
|
55
|
-
"@atlassian/a11y-jest-testing": "^0.
|
|
54
|
+
"@atlaskit/util-data-test": "^18.5.0",
|
|
55
|
+
"@atlassian/a11y-jest-testing": "^0.10.0",
|
|
56
56
|
"@testing-library/dom": "^10.1.0",
|
|
57
57
|
"@testing-library/react": "^16.3.0",
|
|
58
58
|
"@testing-library/user-event": "^14.4.3",
|
|
@@ -73,6 +73,9 @@
|
|
|
73
73
|
},
|
|
74
74
|
"smart-user-picker-restrict-to-gate": {
|
|
75
75
|
"type": "boolean"
|
|
76
|
+
},
|
|
77
|
+
"smart_user_picker_allow_email_if_team_is_found": {
|
|
78
|
+
"type": "boolean"
|
|
76
79
|
}
|
|
77
80
|
}
|
|
78
81
|
}
|