@atlaskit/link-datasource 1.28.0 → 1.28.2

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.
Files changed (59) hide show
  1. package/CHANGELOG.md +13 -0
  2. package/dist/cjs/services/mocks.js +152 -1
  3. package/dist/cjs/services/useBasicFilterAGG.js +9 -2
  4. package/dist/cjs/services/utils.js +3 -2
  5. package/dist/cjs/ui/common/modal/popup-select/formatOptionLabel.js +7 -10
  6. package/dist/cjs/ui/common/modal/popup-select/index.js +2 -1
  7. package/dist/cjs/ui/common/modal/popup-select/trigger.js +7 -8
  8. package/dist/cjs/ui/confluence-search-modal/basic-filters/filters/edited-or-created-by/index.js +110 -0
  9. package/dist/cjs/ui/confluence-search-modal/basic-filters/filters/edited-or-created-by/messages.js +14 -0
  10. package/dist/cjs/ui/confluence-search-modal/basic-filters/hooks/useCurrentUserInfo.js +48 -0
  11. package/dist/cjs/ui/confluence-search-modal/basic-filters/hooks/useRecommendation.js +120 -0
  12. package/dist/cjs/ui/confluence-search-modal/basic-filters/index.js +12 -3
  13. package/dist/cjs/ui/confluence-search-modal/confluence-search-container/index.js +15 -6
  14. package/dist/cjs/ui/confluence-search-modal/modal/index.js +35 -17
  15. package/dist/es2019/services/mocks.js +151 -0
  16. package/dist/es2019/services/useBasicFilterAGG.js +8 -3
  17. package/dist/es2019/services/utils.js +8 -0
  18. package/dist/es2019/ui/common/modal/popup-select/formatOptionLabel.js +7 -7
  19. package/dist/es2019/ui/common/modal/popup-select/index.js +1 -1
  20. package/dist/es2019/ui/common/modal/popup-select/trigger.js +7 -8
  21. package/dist/es2019/ui/confluence-search-modal/basic-filters/filters/edited-or-created-by/index.js +82 -0
  22. package/dist/es2019/ui/confluence-search-modal/basic-filters/filters/edited-or-created-by/messages.js +8 -0
  23. package/dist/es2019/ui/confluence-search-modal/basic-filters/hooks/useCurrentUserInfo.js +25 -0
  24. package/dist/es2019/ui/confluence-search-modal/basic-filters/hooks/useRecommendation.js +74 -0
  25. package/dist/es2019/ui/confluence-search-modal/basic-filters/index.js +13 -3
  26. package/dist/es2019/ui/confluence-search-modal/confluence-search-container/index.js +16 -9
  27. package/dist/es2019/ui/confluence-search-modal/modal/index.js +22 -6
  28. package/dist/esm/services/mocks.js +151 -0
  29. package/dist/esm/services/useBasicFilterAGG.js +10 -3
  30. package/dist/esm/services/utils.js +2 -1
  31. package/dist/esm/ui/common/modal/popup-select/formatOptionLabel.js +7 -7
  32. package/dist/esm/ui/common/modal/popup-select/index.js +2 -1
  33. package/dist/esm/ui/common/modal/popup-select/trigger.js +7 -8
  34. package/dist/esm/ui/confluence-search-modal/basic-filters/filters/edited-or-created-by/index.js +100 -0
  35. package/dist/esm/ui/confluence-search-modal/basic-filters/filters/edited-or-created-by/messages.js +8 -0
  36. package/dist/esm/ui/confluence-search-modal/basic-filters/hooks/useCurrentUserInfo.js +41 -0
  37. package/dist/esm/ui/confluence-search-modal/basic-filters/hooks/useRecommendation.js +113 -0
  38. package/dist/esm/ui/confluence-search-modal/basic-filters/index.js +12 -3
  39. package/dist/esm/ui/confluence-search-modal/confluence-search-container/index.js +15 -6
  40. package/dist/esm/ui/confluence-search-modal/modal/index.js +35 -17
  41. package/dist/types/services/mocks.d.ts +51 -0
  42. package/dist/types/services/useBasicFilterAGG.d.ts +2 -0
  43. package/dist/types/services/utils.d.ts +1 -0
  44. package/dist/types/ui/common/modal/popup-select/index.d.ts +1 -1
  45. package/dist/types/ui/confluence-search-modal/basic-filters/filters/edited-or-created-by/index.d.ts +10 -0
  46. package/dist/types/ui/confluence-search-modal/basic-filters/filters/edited-or-created-by/messages.d.ts +7 -0
  47. package/dist/types/ui/confluence-search-modal/basic-filters/hooks/useCurrentUserInfo.d.ts +7 -0
  48. package/dist/types/ui/confluence-search-modal/basic-filters/hooks/useRecommendation.d.ts +16 -0
  49. package/dist/types/ui/confluence-search-modal/basic-filters/index.d.ts +4 -2
  50. package/dist/types-ts4.5/services/mocks.d.ts +51 -0
  51. package/dist/types-ts4.5/services/useBasicFilterAGG.d.ts +2 -0
  52. package/dist/types-ts4.5/services/utils.d.ts +1 -0
  53. package/dist/types-ts4.5/ui/common/modal/popup-select/index.d.ts +1 -1
  54. package/dist/types-ts4.5/ui/confluence-search-modal/basic-filters/filters/edited-or-created-by/index.d.ts +10 -0
  55. package/dist/types-ts4.5/ui/confluence-search-modal/basic-filters/filters/edited-or-created-by/messages.d.ts +7 -0
  56. package/dist/types-ts4.5/ui/confluence-search-modal/basic-filters/hooks/useCurrentUserInfo.d.ts +7 -0
  57. package/dist/types-ts4.5/ui/confluence-search-modal/basic-filters/hooks/useRecommendation.d.ts +16 -0
  58. package/dist/types-ts4.5/ui/confluence-search-modal/basic-filters/index.d.ts +4 -2
  59. package/package.json +7 -6
@@ -9,9 +9,11 @@ exports.default = void 0;
9
9
  var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
10
10
  var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
11
11
  var _react = _interopRequireWildcard(require("react"));
12
+ var _useDebounce = require("use-debounce");
12
13
  var _platformFeatureFlags = require("@atlaskit/platform-feature-flags");
13
14
  var _primitives = require("@atlaskit/primitives");
14
15
  var _basicSearchInput = require("../../common/modal/basic-search-input");
16
+ var _constants = require("../../common/modal/popup-select/constants");
15
17
  var _basicFilters = _interopRequireDefault(require("../basic-filters"));
16
18
  var _messages = require("./messages");
17
19
  function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(e) { return e ? t : r; })(e); }
@@ -39,21 +41,26 @@ var ConfluenceSearchContainer = function ConfluenceSearchContainer(_ref) {
39
41
  var rawSearch = e.currentTarget.value;
40
42
  setSearchBarSearchString(rawSearch);
41
43
  }, []);
44
+ var _useDebouncedCallback = (0, _useDebounce.useDebouncedCallback)(function (filterValues) {
45
+ onSearch(searchBarSearchString, filterValues);
46
+ }, _constants.FILTER_SELECTION_DEBOUNCE_MS),
47
+ _useDebouncedCallback2 = (0, _slicedToArray2.default)(_useDebouncedCallback, 1),
48
+ debouncedBasicFilterSelectionChange = _useDebouncedCallback2[0];
49
+ var handleBasicFilterSelectionChange = (0, _react.useCallback)(function (filterType, options) {
50
+ var updatedSelection = _objectSpread(_objectSpread({}, filterSelections), {}, (0, _defineProperty2.default)({}, filterType, options));
51
+ setFilterSelections(updatedSelection);
52
+ debouncedBasicFilterSelectionChange(updatedSelection);
53
+ }, [debouncedBasicFilterSelectionChange, filterSelections]);
42
54
 
43
55
  // TODO: further refactoring in EDM-9573
44
56
  // https://stash.atlassian.com/projects/ATLASSIAN/repos/atlassian-frontend-monorepo/pull-requests/82725/overview?commentId=6827913
45
57
  (0, _react.useEffect)(function () {
46
58
  if (currentCloudId.current !== cloudId) {
47
59
  setSearchBarSearchString('');
60
+ setFilterSelections({});
48
61
  currentCloudId.current = cloudId;
49
62
  }
50
63
  }, [cloudId]);
51
- var handleBasicFilterSelectionChange = (0, _react.useCallback)(function (filterType, options) {
52
- var updatedSelection = _objectSpread(_objectSpread({}, filterSelections), {}, (0, _defineProperty2.default)({}, filterType, options));
53
- setFilterSelections(updatedSelection);
54
- //TODO: move to debounce fn in https://product-fabric.atlassian.net/browse/EDM-9485
55
- onSearch(searchBarSearchString, updatedSelection);
56
- }, [filterSelections, onSearch, searchBarSearchString]);
57
64
  var showBasicFilters = (0, _react.useMemo)(function () {
58
65
  if ((0, _platformFeatureFlags.getBooleanFF)('platform.linking-platform.datasource.show-clol-basic-filters')) {
59
66
  return true;
@@ -72,6 +79,8 @@ var ConfluenceSearchContainer = function ConfluenceSearchContainer(_ref) {
72
79
  placeholder: _messages.searchMessages.searchLabel,
73
80
  fullWidth: !showBasicFilters
74
81
  }), showBasicFilters && /*#__PURE__*/_react.default.createElement(_basicFilters.default, {
82
+ cloudId: cloudId,
83
+ selections: filterSelections,
75
84
  onChange: handleBasicFilterSelectionChange
76
85
  }));
77
86
  };
@@ -108,10 +108,14 @@ var PlainConfluenceSearchConfigModal = exports.PlainConfluenceSearchConfigModal
108
108
  _useState10 = (0, _slicedToArray2.default)(_useState9, 2),
109
109
  visibleColumnKeys = _useState10[0],
110
110
  setVisibleColumnKeys = _useState10[1];
111
- var _useState11 = (0, _react.useState)(),
111
+ var _useState11 = (0, _react.useState)(initialParameters === null || initialParameters === void 0 ? void 0 : initialParameters.lastModified),
112
112
  _useState12 = (0, _slicedToArray2.default)(_useState11, 2),
113
113
  lastModified = _useState12[0],
114
114
  setLastModified = _useState12[1];
115
+ var _useState13 = (0, _react.useState)((initialParameters === null || initialParameters === void 0 ? void 0 : initialParameters.contributorAccountIds) || []),
116
+ _useState14 = (0, _slicedToArray2.default)(_useState13, 2),
117
+ contributorAccountIds = _useState14[0],
118
+ setContributorAccountIds = _useState14[1];
115
119
 
116
120
  // analytics related parameters
117
121
  var searchCount = (0, _react.useRef)(0);
@@ -121,13 +125,15 @@ var PlainConfluenceSearchConfigModal = exports.PlainConfluenceSearchConfigModal
121
125
  // TODO: further refactoring in EDM-9573
122
126
  // https://stash.atlassian.com/projects/ATLASSIAN/repos/atlassian-frontend-monorepo/pull-requests/82725/overview?commentId=6829210
123
127
  var parameters = (0, _react.useMemo)(function () {
124
- return _objectSpread(_objectSpread({}, initialParameters), {}, {
128
+ return _objectSpread(_objectSpread(_objectSpread({}, initialParameters), {}, {
125
129
  cloudId: cloudId,
126
130
  searchString: searchString
127
- }, lastModified && {
131
+ }, ((initialParameters === null || initialParameters === void 0 ? void 0 : initialParameters.lastModified) || lastModified) && {
128
132
  lastModified: lastModified
133
+ }), ((initialParameters === null || initialParameters === void 0 ? void 0 : initialParameters.contributorAccountIds) || (contributorAccountIds === null || contributorAccountIds === void 0 ? void 0 : contributorAccountIds.length) > 0) && {
134
+ contributorAccountIds: contributorAccountIds
129
135
  });
130
- }, [cloudId, lastModified, initialParameters, searchString /** Add more parameters when more filters are added */]);
136
+ }, [cloudId, lastModified, contributorAccountIds, initialParameters, searchString /** Add more parameters when more filters are added */]);
131
137
  var isParametersSet = (0, _react.useMemo)(function () {
132
138
  return !!cloudId && Object.values(parameters !== null && parameters !== void 0 ? parameters : {}).filter(function (v) {
133
139
  return v !== undefined;
@@ -191,6 +197,8 @@ var PlainConfluenceSearchConfigModal = exports.PlainConfluenceSearchConfigModal
191
197
  var onSiteSelection = (0, _react.useCallback)(function (site) {
192
198
  userInteractionActions.current.add(_types.DatasourceAction.INSTANCE_UPDATED);
193
199
  setSearchString(undefined);
200
+ setLastModified(undefined);
201
+ setContributorAccountIds([]);
194
202
  setCloudId(site.cloudId);
195
203
  reset({
196
204
  shouldForceRequest: true
@@ -233,17 +241,17 @@ var PlainConfluenceSearchConfigModal = exports.PlainConfluenceSearchConfigModal
233
241
  setVisibleColumnKeys(newVisibleColumnKeys);
234
242
  }, [initialVisibleColumnKeys, defaultVisibleColumnKeys]);
235
243
  var siteSelectorLabel = availableSites && availableSites.length > 1 ? _messages.confluenceSearchModalMessages.insertIssuesTitleManySites : _messages.confluenceSearchModalMessages.insertIssuesTitle;
236
- var _useState13 = (0, _react.useState)(initialColumnCustomSizes),
237
- _useState14 = (0, _slicedToArray2.default)(_useState13, 2),
238
- columnCustomSizes = _useState14[0],
239
- setColumnCustomSizes = _useState14[1];
244
+ var _useState15 = (0, _react.useState)(initialColumnCustomSizes),
245
+ _useState16 = (0, _slicedToArray2.default)(_useState15, 2),
246
+ columnCustomSizes = _useState16[0],
247
+ setColumnCustomSizes = _useState16[1];
240
248
  var onColumnResize = (0, _react.useCallback)(function (key, width) {
241
249
  setColumnCustomSizes(_objectSpread(_objectSpread({}, columnCustomSizes), {}, (0, _defineProperty2.default)({}, key, width)));
242
250
  }, [columnCustomSizes]);
243
- var _useState15 = (0, _react.useState)(initialWrappedColumnKeys),
244
- _useState16 = (0, _slicedToArray2.default)(_useState15, 2),
245
- wrappedColumnKeys = _useState16[0],
246
- setWrappedColumnKeys = _useState16[1];
251
+ var _useState17 = (0, _react.useState)(initialWrappedColumnKeys),
252
+ _useState18 = (0, _slicedToArray2.default)(_useState17, 2),
253
+ wrappedColumnKeys = _useState18[0],
254
+ setWrappedColumnKeys = _useState18[1];
247
255
  var onWrappedColumnChange = (0, _react.useCallback)(function (key, isWrapped) {
248
256
  var set = new Set(wrappedColumnKeys);
249
257
  if (isWrapped) {
@@ -425,11 +433,21 @@ var PlainConfluenceSearchConfigModal = exports.PlainConfluenceSearchConfigModal
425
433
  var onSearch = (0, _react.useCallback)(function (newSearchString, filters) {
426
434
  searchCount.current++;
427
435
  userInteractionActions.current.add(_types.DatasourceAction.QUERY_UPDATED);
428
- if (filters !== null && filters !== void 0 && filters.lastModified) {
429
- var lastModifiedValue = filters.lastModified.find(function (range) {
430
- return range.value;
431
- });
432
- setLastModified(lastModifiedValue === null || lastModifiedValue === void 0 ? void 0 : lastModifiedValue.value);
436
+ if (filters) {
437
+ var editedOrCreatedBy = filters.editedOrCreatedBy,
438
+ _lastModified = filters.lastModified;
439
+ if (_lastModified) {
440
+ var lastModifiedValue = _lastModified.find(function (range) {
441
+ return range.value;
442
+ });
443
+ setLastModified(lastModifiedValue === null || lastModifiedValue === void 0 ? void 0 : lastModifiedValue.value);
444
+ }
445
+ if (editedOrCreatedBy) {
446
+ var accountIds = editedOrCreatedBy.map(function (user) {
447
+ return user.value;
448
+ });
449
+ setContributorAccountIds(accountIds);
450
+ }
433
451
  }
434
452
  setSearchString(newSearchString);
435
453
  reset({
@@ -125,4 +125,155 @@ export const mockFieldValuesResponse = {
125
125
  }
126
126
  }
127
127
  }
128
+ };
129
+ export const mockUserRecommendationsResponse = {
130
+ recommendedUsers: [{
131
+ entityType: 'USER',
132
+ id: '5ffe1efc34847e0069446bf8',
133
+ name: 'Atlassian Assist (staging)',
134
+ avatarUrl: '',
135
+ nickname: 'Atlassian Assist (staging)',
136
+ matchPositions: {},
137
+ accessLevel: 'CONTAINER',
138
+ accountStatus: 'ACTIVE',
139
+ notMentionable: false,
140
+ userType: 'APP',
141
+ attributes: {
142
+ isConfluenceExternalCollaborator: false
143
+ }
144
+ }, {
145
+ entityType: 'USER',
146
+ id: '62df272c3aaeedcae755c533',
147
+ name: 'Atlas for Jira (staging)',
148
+ avatarUrl: '',
149
+ nickname: 'Atlas for Jira (staging)',
150
+ matchPositions: {},
151
+ accessLevel: 'CONTAINER',
152
+ accountStatus: 'ACTIVE',
153
+ notMentionable: false,
154
+ userType: 'APP',
155
+ attributes: {
156
+ isConfluenceExternalCollaborator: false
157
+ }
158
+ }, {
159
+ entityType: 'USER',
160
+ id: '6232be743eacc50071fe13ba',
161
+ name: 'Stephen',
162
+ email: 'sdemontfort+10@atlassian.com',
163
+ avatarUrl: '',
164
+ nickname: 'Stephen',
165
+ matchPositions: {},
166
+ accessLevel: 'CONTAINER',
167
+ accountStatus: 'ACTIVE',
168
+ notMentionable: false,
169
+ locale: 'en-GB',
170
+ userType: 'DEFAULT',
171
+ attributes: {
172
+ isConfluenceExternalCollaborator: false
173
+ }
174
+ }, {
175
+ entityType: 'USER',
176
+ id: '608b253e2911000071b6e6d6',
177
+ name: 'Pranay Test 1773',
178
+ email: 'pmarella+1773@atlassian.com',
179
+ avatarUrl: '',
180
+ nickname: 'Pranay Test 1773',
181
+ matchPositions: {},
182
+ accessLevel: 'CONTAINER',
183
+ accountStatus: 'ACTIVE',
184
+ notMentionable: false,
185
+ locale: 'en-US',
186
+ userType: 'DEFAULT',
187
+ attributes: {
188
+ isConfluenceExternalCollaborator: false
189
+ }
190
+ }, {
191
+ entityType: 'USER',
192
+ id: '6202a8cfc4e2c9006ae620b1',
193
+ name: 'Jacob Test3',
194
+ email: 'jbrunson+test3@atlassian.com',
195
+ avatarUrl: '',
196
+ nickname: 'Jacob Test3',
197
+ matchPositions: {},
198
+ accessLevel: 'CONTAINER',
199
+ accountStatus: 'ACTIVE',
200
+ notMentionable: false,
201
+ locale: 'en-US',
202
+ userType: 'DEFAULT',
203
+ attributes: {
204
+ isConfluenceExternalCollaborator: false
205
+ }
206
+ }, {
207
+ entityType: 'USER',
208
+ id: '61428180ff23ba00717b7d78',
209
+ name: 'Test Themes',
210
+ avatarUrl: '',
211
+ nickname: 'Test Themes',
212
+ matchPositions: {},
213
+ accessLevel: 'CONTAINER',
214
+ accountStatus: 'ACTIVE',
215
+ notMentionable: false,
216
+ userType: 'APP',
217
+ attributes: {
218
+ isConfluenceExternalCollaborator: false
219
+ }
220
+ }, {
221
+ entityType: 'USER',
222
+ id: '5d9e2c300d44fc0dca5428bb',
223
+ name: 'Confluence Connect Test - AP methods',
224
+ avatarUrl: '',
225
+ nickname: 'Confluence Connect Test - AP methods',
226
+ matchPositions: {},
227
+ accessLevel: 'CONTAINER',
228
+ accountStatus: 'ACTIVE',
229
+ notMentionable: false,
230
+ userType: 'APP',
231
+ attributes: {
232
+ isConfluenceExternalCollaborator: false
233
+ }
234
+ }, {
235
+ entityType: 'USER',
236
+ id: '655363:1276a696-f0d0-4f3a-a022-636723eb5148',
237
+ name: 'Confluence Google Drive',
238
+ avatarUrl: '',
239
+ nickname: 'Confluence Google Drive',
240
+ matchPositions: {},
241
+ accessLevel: 'CONTAINER',
242
+ accountStatus: 'ACTIVE',
243
+ notMentionable: false,
244
+ userType: 'APP',
245
+ attributes: {
246
+ isConfluenceExternalCollaborator: false
247
+ }
248
+ }, {
249
+ entityType: 'USER',
250
+ id: '712020:413e43c0-7202-4016-a318-a004892e7f8c',
251
+ name: 'arthur chen nth user',
252
+ avatarUrl: '',
253
+ nickname: 'arthur chen nth user',
254
+ matchPositions: {},
255
+ accessLevel: 'CONTAINER',
256
+ accountStatus: 'ACTIVE',
257
+ notMentionable: false,
258
+ locale: 'en-US',
259
+ userType: 'DEFAULT',
260
+ attributes: {
261
+ isConfluenceExternalCollaborator: false
262
+ }
263
+ }, {
264
+ entityType: 'USER',
265
+ id: '712020:9219bf5f-0358-4782-99dc-bc73258b2ddc',
266
+ name: 'jeff mellis',
267
+ avatarUrl: '',
268
+ nickname: 'jeff mellis',
269
+ matchPositions: {},
270
+ accessLevel: 'CONTAINER',
271
+ accountStatus: 'ACTIVE',
272
+ notMentionable: false,
273
+ locale: 'en-US',
274
+ userType: 'DEFAULT',
275
+ attributes: {
276
+ isConfluenceExternalCollaborator: false
277
+ }
278
+ }]
128
279
  };
@@ -1,6 +1,6 @@
1
1
  import { useCallback, useMemo } from 'react';
2
2
  import { request } from '@atlaskit/linking-common';
3
- import { fieldValuesQuery, hydrateJQLQuery } from './utils';
3
+ import { fieldValuesQuery, hydrateJQLQuery, userQuery } from './utils';
4
4
  const AGG_BASE_URL = '/gateway/api/graphql';
5
5
  export const useBasicFilterAGG = () => {
6
6
  const requestCall = useCallback(async body => request('post', AGG_BASE_URL, body, {
@@ -32,8 +32,13 @@ export const useBasicFilterAGG = () => {
32
32
  operationName: 'fieldValues',
33
33
  query: fieldValuesQuery
34
34
  }), [requestCall]);
35
+ const getCurrentUserInfo = useCallback(() => requestCall({
36
+ operationName: 'userQuery',
37
+ query: userQuery
38
+ }), [requestCall]);
35
39
  return useMemo(() => ({
36
40
  getHydratedJQL,
37
- getFieldValues
38
- }), [getHydratedJQL, getFieldValues]);
41
+ getFieldValues,
42
+ getCurrentUserInfo
43
+ }), [getHydratedJQL, getFieldValues, getCurrentUserInfo]);
39
44
  };
@@ -117,4 +117,12 @@ export const fieldValuesQuery = `query fieldValues($cloudId: ID!, $first: Int =
117
117
  }
118
118
  }
119
119
  }
120
+ }`;
121
+ export const userQuery = `query userQuery {
122
+ me {
123
+ user {
124
+ id
125
+ accountId
126
+ }
127
+ }
120
128
  }`;
@@ -1,4 +1,4 @@
1
- import React, { Fragment } from 'react';
1
+ import React from 'react';
2
2
  import Avatar from '@atlaskit/avatar';
3
3
  import PeopleGroupIcon from '@atlaskit/icon/glyph/people-group';
4
4
  import Lozenge from '@atlaskit/lozenge';
@@ -68,9 +68,6 @@ const AvatarOptionLabel = ({
68
68
  }, data.label));
69
69
  };
70
70
  const formatOptionLabel = data => {
71
- if (data.optionType === 'defaultOption') {
72
- return /*#__PURE__*/React.createElement(Fragment, null);
73
- }
74
71
  if (data.optionType === 'lozengeLabel') {
75
72
  return /*#__PURE__*/React.createElement(LozengeOptionLabel, {
76
73
  data: data
@@ -81,8 +78,11 @@ const formatOptionLabel = data => {
81
78
  data: data
82
79
  });
83
80
  }
84
- return /*#__PURE__*/React.createElement(IconOptionLabel, {
85
- data: data
86
- });
81
+ if (data.optionType === 'iconLabel') {
82
+ return /*#__PURE__*/React.createElement(IconOptionLabel, {
83
+ data: data
84
+ });
85
+ }
86
+ return /*#__PURE__*/React.createElement(React.Fragment, null);
87
87
  };
88
88
  export default formatOptionLabel;
@@ -15,7 +15,7 @@ import PopupTrigger from './trigger';
15
15
  const noFilterOptions = () => true;
16
16
  export const FilterPopupSelect = ({
17
17
  filterName,
18
- totalCount,
18
+ totalCount = 0,
19
19
  status,
20
20
  buttonLabel,
21
21
  showLoading = false,
@@ -7,8 +7,7 @@ import { Box, Flex, xcss } from '@atlaskit/primitives';
7
7
  import Spinner from '@atlaskit/spinner';
8
8
  const triggerButtonLabelStyles = xcss({
9
9
  textOverflow: 'ellipsis',
10
- overflow: 'hidden',
11
- maxWidth: '150px'
10
+ overflow: 'hidden'
12
11
  });
13
12
  const badgeStyles = xcss({
14
13
  marginLeft: 'space.050'
@@ -39,13 +38,13 @@ const PopupTrigger = /*#__PURE__*/forwardRef(({
39
38
  const [firstOption] = selectedOptions || [];
40
39
  const hasOptions = selectedOptions && selectedOptions.length > 0;
41
40
  const showButtonLoading = !isDisabled && isLoading;
42
- const tiggerButtonTestId = `${testId}-trigger`;
41
+ const triggerButtonTestId = `${testId}-trigger`;
43
42
  const LoadingButton = useCallback(() => /*#__PURE__*/React.createElement(LoadingStateAnimationWrapper, null, /*#__PURE__*/React.createElement(Button, {
44
43
  iconAfter: /*#__PURE__*/React.createElement(Spinner, {
45
44
  size: 'xsmall'
46
45
  }),
47
- testId: `${tiggerButtonTestId}--loading-button`
48
- }, label)), [label, tiggerButtonTestId]);
46
+ testId: `${triggerButtonTestId}--loading-button`
47
+ }, label)), [label, triggerButtonTestId]);
49
48
  const DefaultButton = useCallback(() => /*#__PURE__*/React.createElement(Button, {
50
49
  appearance: "default",
51
50
  isSelected: isSelected || hasOptions,
@@ -53,7 +52,7 @@ const PopupTrigger = /*#__PURE__*/forwardRef(({
53
52
  iconAfter: /*#__PURE__*/React.createElement(ChevronDownIcon, {
54
53
  label: ""
55
54
  }),
56
- testId: `${tiggerButtonTestId}--button`
55
+ testId: `${triggerButtonTestId}--button`
57
56
  }, /*#__PURE__*/React.createElement(Flex, null, /*#__PURE__*/React.createElement(Box, {
58
57
  xcss: triggerButtonLabelStyles
59
58
  }, label, firstOption && /*#__PURE__*/React.createElement(React.Fragment, null, ": ", firstOption.label)), selectedOptions && selectedOptions.length > 1 && /*#__PURE__*/React.createElement(Flex, {
@@ -61,7 +60,7 @@ const PopupTrigger = /*#__PURE__*/forwardRef(({
61
60
  alignItems: "center"
62
61
  }, /*#__PURE__*/React.createElement(Badge, {
63
62
  appearance: "primary"
64
- }, "+", selectedOptions.length - 1)))), [firstOption, hasOptions, isDisabled, isSelected, label, selectedOptions, tiggerButtonTestId]);
63
+ }, "+", selectedOptions.length - 1)))), [firstOption, hasOptions, isDisabled, isSelected, label, selectedOptions, triggerButtonTestId]);
65
64
 
66
65
  /**
67
66
  * We had an issue with the popup component referencing a stale DOM ref for the trigger button.
@@ -69,7 +68,7 @@ const PopupTrigger = /*#__PURE__*/forwardRef(({
69
68
  */
70
69
  return /*#__PURE__*/React.createElement(Box, {
71
70
  ref: ref,
72
- testId: tiggerButtonTestId
71
+ testId: triggerButtonTestId
73
72
  }, showButtonLoading ? /*#__PURE__*/React.createElement(LoadingButton, null) : /*#__PURE__*/React.createElement(DefaultButton, null));
74
73
  });
75
74
  export default PopupTrigger;
@@ -0,0 +1,82 @@
1
+ import React, { useCallback, useState } from 'react';
2
+ import { useIntl } from 'react-intl-next';
3
+ import { useDebouncedCallback } from 'use-debounce';
4
+ import { FilterPopupSelect } from '../../../../common/modal/popup-select';
5
+ import { SEARCH_DEBOUNCE_MS } from '../../../../common/modal/popup-select/constants';
6
+ import { useCurrentUserInfo } from '../../hooks/useCurrentUserInfo';
7
+ import useRecommendation from '../../hooks/useRecommendation';
8
+ import { CLOLBasicFilters } from '../../types';
9
+ import { editedOrCreatedByMessage } from './messages';
10
+ const filterName = `clol-basic-filter-${CLOLBasicFilters.editedOrCreatedBy}`;
11
+ const EditedOrCreatedByFilter = ({
12
+ cloudId,
13
+ onSelectionChange,
14
+ selection = []
15
+ }) => {
16
+ const {
17
+ user
18
+ } = useCurrentUserInfo();
19
+ const {
20
+ formatMessage
21
+ } = useIntl();
22
+ const {
23
+ status,
24
+ filterOptions,
25
+ fetchFilterOptions,
26
+ errors
27
+ } = useRecommendation();
28
+ const [searchTerm, setSearchTerm] = useState('');
29
+ const [handleDebouncedFetchFilterOptions] = useDebouncedCallback(searchTerm => {
30
+ if (cloudId && user !== null && user !== void 0 && user.accountId) {
31
+ fetchFilterOptions({
32
+ searchTerm,
33
+ cloudId,
34
+ userId: user.accountId
35
+ });
36
+ }
37
+ }, SEARCH_DEBOUNCE_MS);
38
+ const handleInputChange = useCallback(async newSearchTerm => {
39
+ setSearchTerm(newSearchTerm);
40
+ handleDebouncedFetchFilterOptions(newSearchTerm);
41
+ }, [handleDebouncedFetchFilterOptions]);
42
+ const handleOptionSelection = useCallback(newValue => {
43
+ onSelectionChange(CLOLBasicFilters.editedOrCreatedBy, newValue);
44
+ }, [onSelectionChange]);
45
+ const handleMenuOpen = useCallback(() => {
46
+ if ((status === 'empty' || status === 'rejected') && cloudId && user !== null && user !== void 0 && user.accountId) {
47
+ // if user searches and gets status as rejected, we want the dropdown to try load the request with searchString when the user reopens the dropdown
48
+ fetchFilterOptions({
49
+ cloudId,
50
+ userId: user.accountId,
51
+ searchTerm
52
+ });
53
+ }
54
+ }, [fetchFilterOptions, status, cloudId, user === null || user === void 0 ? void 0 : user.accountId, searchTerm]);
55
+ const filterOptionsLength = filterOptions.length;
56
+ const isError = status === 'rejected';
57
+ const isLoading = status === 'loading' || status === 'empty';
58
+ const isEmpty = status === 'resolved' && filterOptionsLength === 0;
59
+ const isDisabled = !cloudId || !(user !== null && user !== void 0 && user.accountId);
60
+ return /*#__PURE__*/React.createElement(FilterPopupSelect, {
61
+ buttonLabel: formatMessage(editedOrCreatedByMessage.buttonLabel),
62
+ filterName: filterName,
63
+ isDisabled: isDisabled,
64
+ options: filterOptions,
65
+ showLoading: isLoading,
66
+ selectedOptions: selection,
67
+ onSelectionChange: handleOptionSelection,
68
+ onInputChange: handleInputChange,
69
+ showHydrating: false,
70
+ shouldShowFooter: false,
71
+ status: status,
72
+ onMenuOpen: handleMenuOpen,
73
+ menuListProps: {
74
+ filterName: filterName,
75
+ errors,
76
+ isLoading,
77
+ isError,
78
+ isEmpty
79
+ }
80
+ });
81
+ };
82
+ export default EditedOrCreatedByFilter;
@@ -0,0 +1,8 @@
1
+ import { defineMessages } from 'react-intl-next';
2
+ export const editedOrCreatedByMessage = defineMessages({
3
+ buttonLabel: {
4
+ id: 'linkDataSource.clol-basic-filter.editedOrCreatedBy.label',
5
+ description: 'Label to be displayed for "Edited or created by" filter dropdown button.',
6
+ defaultMessage: 'Edited or created by'
7
+ }
8
+ });
@@ -0,0 +1,25 @@
1
+ import { useCallback, useEffect, useState } from 'react';
2
+ import { useBasicFilterAGG } from '../../../../services/useBasicFilterAGG';
3
+ export const useCurrentUserInfo = () => {
4
+ const [user, setUser] = useState();
5
+ const {
6
+ getCurrentUserInfo: getCurrentUserInfoFromAGG
7
+ } = useBasicFilterAGG();
8
+ const getCurrentUserInfo = useCallback(async () => {
9
+ var _user$data;
10
+ const user = await getCurrentUserInfoFromAGG();
11
+ if (user !== null && user !== void 0 && (_user$data = user.data) !== null && _user$data !== void 0 && _user$data.me.user) {
12
+ var _user$data2;
13
+ setUser((_user$data2 = user.data) === null || _user$data2 === void 0 ? void 0 : _user$data2.me.user);
14
+ } else {
15
+ setUser(undefined);
16
+ }
17
+ }, [getCurrentUserInfoFromAGG]);
18
+ useEffect(() => {
19
+ getCurrentUserInfo();
20
+ }, [getCurrentUserInfo]);
21
+ return {
22
+ user,
23
+ getCurrentUserInfo
24
+ };
25
+ };
@@ -0,0 +1,74 @@
1
+ import { useCallback, useRef, useState } from 'react';
2
+ import { useIntl } from 'react-intl-next';
3
+ import { getUserRecommendations } from '@atlaskit/smart-user-picker';
4
+ const useRecommendation = () => {
5
+ const intl = useIntl();
6
+ const [filterOptions, setFilterOptions] = useState([]);
7
+ const [status, setStatus] = useState('empty');
8
+ const [errors, setErrors] = useState([]);
9
+ const initialData = useRef();
10
+ const convertRecommendationsToFilterOptions = recommendations => {
11
+ return recommendations.map(item => ({
12
+ optionType: 'avatarLabel',
13
+ label: item.name,
14
+ value: item.id,
15
+ avatar: item.avatarUrl
16
+ }));
17
+ };
18
+ const fetchFilterOptions = useCallback(async ({
19
+ userId,
20
+ cloudId,
21
+ searchTerm
22
+ }) => {
23
+ setStatus('loading');
24
+ const requestParams = {
25
+ context: {
26
+ contextType: 'contributors',
27
+ principalId: userId || '',
28
+ productAttributes: {
29
+ isEntitledConfluenceExternalCollaborator: true
30
+ },
31
+ productKey: 'confluence',
32
+ siteId: cloudId
33
+ },
34
+ includeGroups: false,
35
+ includeTeams: false,
36
+ includeUsers: true,
37
+ maxNumberOfResults: 10,
38
+ performSearchQueryOnly: false,
39
+ query: searchTerm
40
+ };
41
+ const {
42
+ current: initialResponseData
43
+ } = initialData;
44
+ const isRequestLikeInitialSearch = !searchTerm;
45
+ try {
46
+ const recommendations = isRequestLikeInitialSearch && initialResponseData ? initialResponseData : await getUserRecommendations(requestParams, intl);
47
+ setFilterOptions(convertRecommendationsToFilterOptions(recommendations));
48
+ setStatus('resolved');
49
+ if (!searchTerm) {
50
+ /**
51
+ * The initial dataset is used in couple of paths, eg: when a user searches and clears the search text.
52
+ * During these times, we dont want to fetch data again and again, hence a mini cache setup to store and provide the initial dataset
53
+ */
54
+ initialData.current = recommendations;
55
+ }
56
+ } catch (error) {
57
+ setStatus('rejected');
58
+ setErrors([error]);
59
+ }
60
+ }, [intl]);
61
+ const reset = useCallback(() => {
62
+ setStatus('empty');
63
+ setFilterOptions([]);
64
+ setErrors([]);
65
+ }, []);
66
+ return {
67
+ status,
68
+ errors,
69
+ filterOptions,
70
+ reset,
71
+ fetchFilterOptions
72
+ };
73
+ };
74
+ export default useRecommendation;
@@ -1,18 +1,28 @@
1
1
  import React from 'react';
2
2
  import { Flex, xcss } from '@atlaskit/primitives';
3
3
  import { DateRangePicker } from './filters/date-range-picker';
4
+ import EditedOrCreatedByFilter from './filters/edited-or-created-by';
4
5
  const basicFilterContainerStyles = xcss({
5
6
  paddingLeft: 'space.100'
6
7
  });
7
8
  const BasicFilterContainer = ({
8
- onChange
9
+ cloudId,
10
+ onChange,
11
+ selections = {}
9
12
  }) => {
13
+ const {
14
+ editedOrCreatedBy
15
+ } = selections;
10
16
  return /*#__PURE__*/React.createElement(Flex, {
11
17
  xcss: basicFilterContainerStyles,
12
18
  gap: "space.100",
13
19
  testId: "clol-basic-filter-container"
14
- }, /*#__PURE__*/React.createElement(DateRangePicker, {
20
+ }, /*#__PURE__*/React.createElement(EditedOrCreatedByFilter, {
21
+ cloudId: cloudId,
22
+ onSelectionChange: onChange,
23
+ selection: editedOrCreatedBy || []
24
+ }), /*#__PURE__*/React.createElement(DateRangePicker, {
15
25
  onSelectionChange: onChange
16
- }), /*#__PURE__*/React.createElement(React.Fragment, null));
26
+ }));
17
27
  };
18
28
  export default BasicFilterContainer;