@atlaskit/link-datasource 1.29.2 → 1.29.4

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 (53) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/LICENSE.md +13 -0
  3. package/dist/cjs/services/mocks.js +44 -2
  4. package/dist/cjs/services/useBasicFilterAGG.js +19 -7
  5. package/dist/cjs/services/utils.js +3 -2
  6. package/dist/cjs/ui/confluence-search-modal/basic-filters/filters/edited-or-created-by/index.js +15 -3
  7. package/dist/cjs/ui/confluence-search-modal/basic-filters/hooks/useBasicFilterHydration.js +79 -0
  8. package/dist/cjs/ui/confluence-search-modal/basic-filters/hooks/useCurrentUserInfo.js +2 -6
  9. package/dist/cjs/ui/confluence-search-modal/basic-filters/hooks/useRecommendation.js +1 -0
  10. package/dist/cjs/ui/confluence-search-modal/basic-filters/index.js +4 -2
  11. package/dist/cjs/ui/confluence-search-modal/confluence-search-container/index.js +23 -1
  12. package/dist/cjs/ui/confluence-search-modal/modal/index.js +19 -2
  13. package/dist/es2019/services/mocks.js +43 -1
  14. package/dist/es2019/services/useBasicFilterAGG.js +16 -6
  15. package/dist/es2019/services/utils.js +7 -0
  16. package/dist/es2019/ui/confluence-search-modal/basic-filters/filters/edited-or-created-by/index.js +15 -4
  17. package/dist/es2019/ui/confluence-search-modal/basic-filters/hooks/useBasicFilterHydration.js +39 -0
  18. package/dist/es2019/ui/confluence-search-modal/basic-filters/hooks/useCurrentUserInfo.js +2 -7
  19. package/dist/es2019/ui/confluence-search-modal/basic-filters/hooks/useRecommendation.js +1 -0
  20. package/dist/es2019/ui/confluence-search-modal/basic-filters/index.js +4 -2
  21. package/dist/es2019/ui/confluence-search-modal/confluence-search-container/index.js +24 -1
  22. package/dist/es2019/ui/confluence-search-modal/modal/index.js +17 -2
  23. package/dist/esm/services/mocks.js +43 -1
  24. package/dist/esm/services/useBasicFilterAGG.js +20 -8
  25. package/dist/esm/services/utils.js +2 -1
  26. package/dist/esm/ui/confluence-search-modal/basic-filters/filters/edited-or-created-by/index.js +16 -4
  27. package/dist/esm/ui/confluence-search-modal/basic-filters/hooks/useBasicFilterHydration.js +72 -0
  28. package/dist/esm/ui/confluence-search-modal/basic-filters/hooks/useCurrentUserInfo.js +2 -6
  29. package/dist/esm/ui/confluence-search-modal/basic-filters/hooks/useRecommendation.js +1 -0
  30. package/dist/esm/ui/confluence-search-modal/basic-filters/index.js +4 -2
  31. package/dist/esm/ui/confluence-search-modal/confluence-search-container/index.js +23 -1
  32. package/dist/esm/ui/confluence-search-modal/modal/index.js +19 -2
  33. package/dist/types/services/mocks.d.ts +11 -0
  34. package/dist/types/services/useBasicFilterAGG.d.ts +2 -1
  35. package/dist/types/services/utils.d.ts +1 -0
  36. package/dist/types/ui/common/modal/popup-select/types.d.ts +4 -0
  37. package/dist/types/ui/confluence-search-modal/basic-filters/filters/edited-or-created-by/index.d.ts +2 -1
  38. package/dist/types/ui/confluence-search-modal/basic-filters/hooks/useBasicFilterHydration.d.ts +6 -0
  39. package/dist/types/ui/confluence-search-modal/basic-filters/index.d.ts +2 -1
  40. package/dist/types/ui/confluence-search-modal/basic-filters/types.d.ts +8 -0
  41. package/dist/types/ui/confluence-search-modal/confluence-search-container/index.d.ts +6 -2
  42. package/dist/types/ui/jira-issues-modal/basic-filters/hooks/useHydrateJqlQuery.d.ts +2 -3
  43. package/dist/types-ts4.5/services/mocks.d.ts +11 -0
  44. package/dist/types-ts4.5/services/useBasicFilterAGG.d.ts +2 -1
  45. package/dist/types-ts4.5/services/utils.d.ts +1 -0
  46. package/dist/types-ts4.5/ui/common/modal/popup-select/types.d.ts +4 -0
  47. package/dist/types-ts4.5/ui/confluence-search-modal/basic-filters/filters/edited-or-created-by/index.d.ts +2 -1
  48. package/dist/types-ts4.5/ui/confluence-search-modal/basic-filters/hooks/useBasicFilterHydration.d.ts +6 -0
  49. package/dist/types-ts4.5/ui/confluence-search-modal/basic-filters/index.d.ts +2 -1
  50. package/dist/types-ts4.5/ui/confluence-search-modal/basic-filters/types.d.ts +8 -0
  51. package/dist/types-ts4.5/ui/confluence-search-modal/confluence-search-container/index.d.ts +6 -2
  52. package/dist/types-ts4.5/ui/jira-issues-modal/basic-filters/hooks/useHydrateJqlQuery.d.ts +2 -3
  53. package/package.json +3 -2
@@ -6,14 +6,9 @@ export const useCurrentUserInfo = () => {
6
6
  getCurrentUserInfo: getCurrentUserInfoFromAGG
7
7
  } = useBasicFilterAGG();
8
8
  const getCurrentUserInfo = useCallback(async () => {
9
- var _user$data;
9
+ var _user$data, _user$data$me;
10
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
- }
11
+ setUser((_user$data = user.data) === null || _user$data === void 0 ? void 0 : (_user$data$me = _user$data.me) === null || _user$data$me === void 0 ? void 0 : _user$data$me.user);
17
12
  }, [getCurrentUserInfoFromAGG]);
18
13
  useEffect(() => {
19
14
  getCurrentUserInfo();
@@ -62,6 +62,7 @@ const useRecommendation = () => {
62
62
  setStatus('empty');
63
63
  setFilterOptions([]);
64
64
  setErrors([]);
65
+ initialData.current = undefined;
65
66
  }, []);
66
67
  return {
67
68
  status,
@@ -8,7 +8,8 @@ const basicFilterContainerStyles = xcss({
8
8
  const BasicFilterContainer = ({
9
9
  cloudId,
10
10
  onChange,
11
- selections = {}
11
+ selections = {},
12
+ isHydrating
12
13
  }) => {
13
14
  const {
14
15
  editedOrCreatedBy
@@ -20,7 +21,8 @@ const BasicFilterContainer = ({
20
21
  }, /*#__PURE__*/React.createElement(EditedOrCreatedByFilter, {
21
22
  cloudId: cloudId,
22
23
  onSelectionChange: onChange,
23
- selection: editedOrCreatedBy || []
24
+ selection: editedOrCreatedBy || [],
25
+ isHydrating: isHydrating
24
26
  }), /*#__PURE__*/React.createElement(DateRangePicker, {
25
27
  onSelectionChange: onChange
26
28
  }));
@@ -5,6 +5,8 @@ import { Flex, xcss } from '@atlaskit/primitives';
5
5
  import { BasicSearchInput } from '../../common/modal/basic-search-input';
6
6
  import { FILTER_SELECTION_DEBOUNCE_MS } from '../../common/modal/popup-select/constants';
7
7
  import BasicFilters from '../basic-filters';
8
+ import { useBasicFilterHydration } from '../basic-filters/hooks/useBasicFilterHydration';
9
+ import { CLOLBasicFilters } from '../basic-filters/types';
8
10
  import { searchMessages } from './messages';
9
11
  const basicSearchInputContainerStyles = xcss({
10
12
  flexGrow: 1
@@ -12,9 +14,15 @@ const basicSearchInputContainerStyles = xcss({
12
14
  const ConfluenceSearchContainer = ({
13
15
  cloudId,
14
16
  initialSearchValue,
17
+ initialFilterSelection,
15
18
  isSearching,
16
19
  onSearch
17
20
  }) => {
21
+ const {
22
+ hydrateUsersFromAccountIds,
23
+ users,
24
+ status
25
+ } = useBasicFilterHydration();
18
26
  const currentCloudId = useRef(cloudId);
19
27
  const [searchBarSearchString, setSearchBarSearchString] = useState(initialSearchValue !== null && initialSearchValue !== void 0 ? initialSearchValue : '');
20
28
  const [filterSelections, setFilterSelections] = useState({});
@@ -49,6 +57,20 @@ const ConfluenceSearchContainer = ({
49
57
  }
50
58
  return false;
51
59
  }, []);
60
+ useEffect(() => {
61
+ const accountIds = initialFilterSelection === null || initialFilterSelection === void 0 ? void 0 : initialFilterSelection[CLOLBasicFilters.editedOrCreatedBy];
62
+ const hasAccountIds = accountIds && accountIds.length > 0;
63
+ if (hasAccountIds && status === 'empty' && showBasicFilters) {
64
+ hydrateUsersFromAccountIds(accountIds);
65
+ }
66
+ }, [hydrateUsersFromAccountIds, initialFilterSelection, showBasicFilters, status]);
67
+ useEffect(() => {
68
+ if (status === 'resolved') {
69
+ setFilterSelections({
70
+ editedOrCreatedBy: users
71
+ });
72
+ }
73
+ }, [users, status]);
52
74
  return /*#__PURE__*/React.createElement(Flex, {
53
75
  alignItems: "center",
54
76
  xcss: basicSearchInputContainerStyles
@@ -63,7 +85,8 @@ const ConfluenceSearchContainer = ({
63
85
  }), showBasicFilters && /*#__PURE__*/React.createElement(BasicFilters, {
64
86
  cloudId: cloudId,
65
87
  selections: filterSelections,
66
- onChange: handleBasicFilterSelectionChange
88
+ onChange: handleBasicFilterSelectionChange,
89
+ isHydrating: status === 'loading'
67
90
  }));
68
91
  };
69
92
  export default ConfluenceSearchContainer;
@@ -99,6 +99,9 @@ export const PlainConfluenceSearchConfigModal = props => {
99
99
  contributorAccountIds
100
100
  })
101
101
  }), [cloudId, lastModified, contributorAccountIds, initialParameters, searchString /** Add more parameters when more filters are added */]);
102
+ const initialFilterSelection = useMemo(() => ({
103
+ editedOrCreatedBy: (initialParameters === null || initialParameters === void 0 ? void 0 : initialParameters.contributorAccountIds) || []
104
+ }), [initialParameters === null || initialParameters === void 0 ? void 0 : initialParameters.contributorAccountIds]);
102
105
  const isParametersSet = useMemo(() => !!cloudId && Object.values(parameters !== null && parameters !== void 0 ? parameters : {}).filter(v => v !== undefined).length > 1, [cloudId, parameters]);
103
106
  const parametersToSend = useMemo(() => {
104
107
  if (!isParametersSet) {
@@ -233,7 +236,18 @@ export const PlainConfluenceSearchConfigModal = props => {
233
236
  const resolvedWithNoResults = status === 'resolved' && !responseItems.length;
234
237
  const hasConfluenceSearchParams = selectedConfluenceSite && searchString;
235
238
  const selectedConfluenceSiteUrl = selectedConfluenceSite === null || selectedConfluenceSite === void 0 ? void 0 : selectedConfluenceSite.url;
236
- const confluenceSearchUrl = selectedConfluenceSiteUrl && searchString !== undefined && `${selectedConfluenceSiteUrl}/wiki/search?text=${encodeURI(searchString)}`;
239
+ const confluenceSearchUrl = useMemo(() => {
240
+ if (!selectedConfluenceSiteUrl || searchString === undefined) {
241
+ return undefined;
242
+ }
243
+ const params = new URLSearchParams();
244
+ // we are appending "text" without checking searchString as we need the url to have "text" when a user does an empty search
245
+ params.append('text', searchString);
246
+ if (contributorAccountIds.length > 0) {
247
+ params.append('contributors', contributorAccountIds.join(','));
248
+ }
249
+ return `${selectedConfluenceSiteUrl}/wiki/search?${params.toString()}`;
250
+ }, [contributorAccountIds, searchString, selectedConfluenceSiteUrl]);
237
251
  const analyticsPayload = useMemo(() => ({
238
252
  extensionKey,
239
253
  destinationObjectTypes,
@@ -424,7 +438,8 @@ export const PlainConfluenceSearchConfigModal = props => {
424
438
  cloudId: cloudId,
425
439
  isSearching: status === 'loading',
426
440
  onSearch: onSearch,
427
- initialSearchValue: initialParameters === null || initialParameters === void 0 ? void 0 : initialParameters.searchString
441
+ initialSearchValue: initialParameters === null || initialParameters === void 0 ? void 0 : initialParameters.searchString,
442
+ initialFilterSelection: initialFilterSelection
428
443
  })), currentViewMode === 'inline' ? renderInlineLinkModalContent() : renderTableModalContent()) : jsx(NoInstancesView, {
429
444
  title: confluenceSearchModalMessages.noAccessToConfluenceSitesTitle,
430
445
  description: confluenceSearchModalMessages.noAccessToConfluenceSitesDescription,
@@ -276,4 +276,46 @@ export var mockUserRecommendationsResponse = {
276
276
  isConfluenceExternalCollaborator: false
277
277
  }
278
278
  }]
279
- };
279
+ };
280
+ export var mockUserHydrationResponse = {
281
+ data: {
282
+ users: [{
283
+ accountId: '655363:d8dff7fe-efb7-4073-a3cd-12463ac79e1c',
284
+ name: 'Peter Grasevski',
285
+ picture: 'https://secure.gravatar.com/avatar/f4bb2f6eef1621e67cd136c0be9af81c?d=https%3A%2F%2Favatar-management--avatars.us-west-2.staging.public.atl-paas.net%2Finitials%2FPG-5.png'
286
+ }, {
287
+ accountId: '62cf07378afb5805e5d46454',
288
+ name: 'Richard Wang',
289
+ picture: 'https://avatar-management--avatars.us-west-2.staging.public.atl-paas.net/62cf07378afb5805e5d46454/5d1719ab-8717-4837-9ae7-a3761c3b6604/128'
290
+ }, {
291
+ accountId: '62f3ed1ee50f2f2a39573e7f',
292
+ name: 'Luke Muller',
293
+ picture: 'https://avatar-management--avatars.us-west-2.staging.public.atl-paas.net/62f3ed1ee50f2f2a39573e7f/1bd99ace-ea01-4d41-b0ab-3e1ebc353914/128'
294
+ }, {
295
+ accountId: '6232212a62dc1e006802dea8',
296
+ name: 'Nidhin Joseph',
297
+ picture: 'https://secure.gravatar.com/avatar/815c1ee3e8e2839ef94bf90b134d1c68?d=https%3A%2F%2Favatar-management--avatars.us-west-2.staging.public.atl-paas.net%2Finitials%2FNJ-2.png'
298
+ }]
299
+ }
300
+ };
301
+ export var mockTransformedUserHydrationResponse = [{
302
+ optionType: 'avatarLabel',
303
+ label: 'Peter Grasevski',
304
+ value: '655363:d8dff7fe-efb7-4073-a3cd-12463ac79e1c',
305
+ avatar: 'https://secure.gravatar.com/avatar/f4bb2f6eef1621e67cd136c0be9af81c?d=https%3A%2F%2Favatar-management--avatars.us-west-2.staging.public.atl-paas.net%2Finitials%2FPG-5.png'
306
+ }, {
307
+ optionType: 'avatarLabel',
308
+ label: 'Richard Wang',
309
+ value: '62cf07378afb5805e5d46454',
310
+ avatar: 'https://avatar-management--avatars.us-west-2.staging.public.atl-paas.net/62cf07378afb5805e5d46454/5d1719ab-8717-4837-9ae7-a3761c3b6604/128'
311
+ }, {
312
+ optionType: 'avatarLabel',
313
+ label: 'Luke Muller',
314
+ value: '62f3ed1ee50f2f2a39573e7f',
315
+ avatar: 'https://avatar-management--avatars.us-west-2.staging.public.atl-paas.net/62f3ed1ee50f2f2a39573e7f/1bd99ace-ea01-4d41-b0ab-3e1ebc353914/128'
316
+ }, {
317
+ optionType: 'avatarLabel',
318
+ label: 'Nidhin Joseph',
319
+ value: '6232212a62dc1e006802dea8',
320
+ avatar: 'https://secure.gravatar.com/avatar/815c1ee3e8e2839ef94bf90b134d1c68?d=https%3A%2F%2Favatar-management--avatars.us-west-2.staging.public.atl-paas.net%2Finitials%2FNJ-2.png'
321
+ }];
@@ -2,24 +2,22 @@ import _asyncToGenerator from "@babel/runtime/helpers/asyncToGenerator";
2
2
  import _regeneratorRuntime from "@babel/runtime/regenerator";
3
3
  import { useCallback, useMemo } from 'react';
4
4
  import { request } from '@atlaskit/linking-common';
5
- import { fieldValuesQuery, hydrateJQLQuery, userQuery } from './utils';
5
+ import { fieldValuesQuery, hydrateJQLQuery, userHydration, userQuery } from './utils';
6
6
  var AGG_BASE_URL = '/gateway/api/graphql';
7
7
  export var useBasicFilterAGG = function useBasicFilterAGG() {
8
8
  var requestCall = useCallback( /*#__PURE__*/function () {
9
- var _ref = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee(body) {
9
+ var _ref = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee(body, headers) {
10
10
  return _regeneratorRuntime.wrap(function _callee$(_context) {
11
11
  while (1) switch (_context.prev = _context.next) {
12
12
  case 0:
13
- return _context.abrupt("return", request('post', AGG_BASE_URL, body, {
14
- 'X-ExperimentalApi': 'JiraJqlBuilder'
15
- }, [200, 201, 202, 203, 204]));
13
+ return _context.abrupt("return", request('post', AGG_BASE_URL, body, headers, [200, 201, 202, 203, 204]));
16
14
  case 1:
17
15
  case "end":
18
16
  return _context.stop();
19
17
  }
20
18
  }, _callee);
21
19
  }));
22
- return function (_x) {
20
+ return function (_x, _x2) {
23
21
  return _ref.apply(this, arguments);
24
22
  };
25
23
  }(), []);
@@ -31,6 +29,8 @@ export var useBasicFilterAGG = function useBasicFilterAGG() {
31
29
  },
32
30
  operationName: 'hydrate',
33
31
  query: hydrateJQLQuery
32
+ }, {
33
+ 'X-ExperimentalApi': 'JiraJqlBuilder'
34
34
  });
35
35
  }, [requestCall]);
36
36
  var getFieldValues = useCallback(function (_ref2) {
@@ -52,6 +52,8 @@ export var useBasicFilterAGG = function useBasicFilterAGG() {
52
52
  },
53
53
  operationName: 'fieldValues',
54
54
  query: fieldValuesQuery
55
+ }, {
56
+ 'X-ExperimentalApi': 'JiraJqlBuilder'
55
57
  });
56
58
  }, [requestCall]);
57
59
  var getCurrentUserInfo = useCallback(function () {
@@ -60,11 +62,21 @@ export var useBasicFilterAGG = function useBasicFilterAGG() {
60
62
  query: userQuery
61
63
  });
62
64
  }, [requestCall]);
65
+ var getUsersFromAccountIDs = useCallback(function (accountIds) {
66
+ return requestCall({
67
+ variables: {
68
+ accountIds: accountIds
69
+ },
70
+ operationName: 'userHydration',
71
+ query: userHydration
72
+ });
73
+ }, [requestCall]);
63
74
  return useMemo(function () {
64
75
  return {
65
76
  getHydratedJQL: getHydratedJQL,
66
77
  getFieldValues: getFieldValues,
67
- getCurrentUserInfo: getCurrentUserInfo
78
+ getCurrentUserInfo: getCurrentUserInfo,
79
+ getUsersFromAccountIDs: getUsersFromAccountIDs
68
80
  };
69
- }, [getHydratedJQL, getFieldValues, getCurrentUserInfo]);
81
+ }, [getHydratedJQL, getFieldValues, getCurrentUserInfo, getUsersFromAccountIDs]);
70
82
  };
@@ -7,4 +7,5 @@
7
7
 
8
8
  export var hydrateJQLQuery = "query hydrate($cloudId: ID!, $jql: String!) {\n jira {\n jqlBuilder(cloudId: $cloudId) {\n hydrateJqlQuery(query: $jql) {\n ... on JiraJqlHydratedQuery {\n fields {\n ... on JiraJqlQueryHydratedField {\n jqlTerm\n values {\n ... on JiraJqlQueryHydratedValue {\n values {\n ... on JiraJqlProjectFieldValue {\n jqlTerm\n displayName\n project {\n avatar {\n small\n }\n }\n }\n ... on JiraJqlStatusFieldValue {\n jqlTerm\n displayName\n statusCategory {\n colorName\n }\n }\n ... on JiraJqlIssueTypeFieldValue {\n jqlTerm\n displayName\n issueTypes {\n avatar {\n small\n }\n }\n }\n ... on JiraJqlUserFieldValue {\n jqlTerm\n displayName\n user {\n picture\n }\n }\n ... on JiraJqlGroupFieldValue {\n jqlTerm\n displayName\n group {\n name\n }\n }\n }\n }\n }\n }\n }\n }\n }\n }\n }\n}";
9
9
  export var fieldValuesQuery = "query fieldValues($cloudId: ID!, $first: Int = 10, $jqlTerm: String!, $jql: String!, $searchString: String!, $after: String) {\n jira {\n jqlBuilder(cloudId: $cloudId) {\n fieldValues(\n first: $first\n jqlTerm: $jqlTerm\n jqlContext: $jql\n searchString: $searchString\n after: $after\n ) {\n totalCount\n pageInfo {\n endCursor\n }\n edges {\n node {\n jqlTerm\n displayName\n ... on JiraJqlProjectFieldValue {\n project {\n avatar {\n small\n }\n }\n }\n ... on JiraJqlIssueTypeFieldValue {\n issueTypes {\n avatar {\n small\n }\n }\n }\n ... on JiraJqlStatusFieldValue {\n statusCategory {\n colorName\n }\n }\n ... on JiraJqlUserFieldValue {\n user {\n picture\n }\n }\n ... on JiraJqlGroupFieldValue {\n group {\n name\n }\n }\n }\n }\n }\n }\n }\n}";
10
- export var userQuery = "query userQuery {\n me {\n user {\n id\n accountId\n }\n }\n}";
10
+ export var userQuery = "query userQuery {\n me {\n user {\n id\n accountId\n }\n }\n}";
11
+ export var userHydration = "query userHydration($accountIds: [ID!]!) {\n users(accountIds: $accountIds) {\n accountId\n name\n picture\n }\n}";
@@ -1,7 +1,7 @@
1
1
  import _asyncToGenerator from "@babel/runtime/helpers/asyncToGenerator";
2
2
  import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
3
3
  import _regeneratorRuntime from "@babel/runtime/regenerator";
4
- import React, { useCallback, useState } from 'react';
4
+ import React, { useCallback, useEffect, useRef, useState } from 'react';
5
5
  import { useIntl } from 'react-intl-next';
6
6
  import { useDebouncedCallback } from 'use-debounce';
7
7
  import { FilterPopupSelect } from '../../../../common/modal/popup-select';
@@ -15,7 +15,9 @@ var EditedOrCreatedByFilter = function EditedOrCreatedByFilter(_ref) {
15
15
  var cloudId = _ref.cloudId,
16
16
  onSelectionChange = _ref.onSelectionChange,
17
17
  _ref$selection = _ref.selection,
18
- selection = _ref$selection === void 0 ? [] : _ref$selection;
18
+ selection = _ref$selection === void 0 ? [] : _ref$selection,
19
+ _ref$isHydrating = _ref.isHydrating,
20
+ isHydrating = _ref$isHydrating === void 0 ? false : _ref$isHydrating;
19
21
  var _useCurrentUserInfo = useCurrentUserInfo(),
20
22
  user = _useCurrentUserInfo.user;
21
23
  var _useIntl = useIntl(),
@@ -24,7 +26,9 @@ var EditedOrCreatedByFilter = function EditedOrCreatedByFilter(_ref) {
24
26
  status = _useRecommendation.status,
25
27
  filterOptions = _useRecommendation.filterOptions,
26
28
  fetchFilterOptions = _useRecommendation.fetchFilterOptions,
27
- errors = _useRecommendation.errors;
29
+ errors = _useRecommendation.errors,
30
+ resetHook = _useRecommendation.reset;
31
+ var currentSiteCloudId = useRef(cloudId || '');
28
32
  var _useState = useState(''),
29
33
  _useState2 = _slicedToArray(_useState, 2),
30
34
  searchTerm = _useState2[0],
@@ -75,6 +79,14 @@ var EditedOrCreatedByFilter = function EditedOrCreatedByFilter(_ref) {
75
79
  var isLoading = status === 'loading' || status === 'empty';
76
80
  var isEmpty = status === 'resolved' && filterOptionsLength === 0;
77
81
  var isDisabled = !cloudId || !(user !== null && user !== void 0 && user.accountId);
82
+ useEffect(function () {
83
+ if (cloudId && currentSiteCloudId.current !== cloudId) {
84
+ currentSiteCloudId.current = cloudId;
85
+ if (status === 'resolved') {
86
+ resetHook();
87
+ }
88
+ }
89
+ }, [cloudId, resetHook, status]);
78
90
  return /*#__PURE__*/React.createElement(FilterPopupSelect, {
79
91
  buttonLabel: formatMessage(editedOrCreatedByMessage.buttonLabel),
80
92
  filterName: filterName,
@@ -84,7 +96,7 @@ var EditedOrCreatedByFilter = function EditedOrCreatedByFilter(_ref) {
84
96
  selectedOptions: selection,
85
97
  onSelectionChange: handleOptionSelection,
86
98
  onInputChange: handleInputChange,
87
- showHydrating: false,
99
+ showHydrating: isHydrating,
88
100
  shouldShowFooter: false,
89
101
  status: status,
90
102
  onMenuOpen: handleMenuOpen,
@@ -0,0 +1,72 @@
1
+ import _asyncToGenerator from "@babel/runtime/helpers/asyncToGenerator";
2
+ import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
3
+ import _regeneratorRuntime from "@babel/runtime/regenerator";
4
+ import { useCallback, useState } from 'react';
5
+ import { useBasicFilterAGG } from '../../../../services/useBasicFilterAGG';
6
+ export var useBasicFilterHydration = function useBasicFilterHydration() {
7
+ var _useState = useState('empty'),
8
+ _useState2 = _slicedToArray(_useState, 2),
9
+ status = _useState2[0],
10
+ setStatus = _useState2[1];
11
+ var _useBasicFilterAGG = useBasicFilterAGG(),
12
+ getUsersFromAccountIDs = _useBasicFilterAGG.getUsersFromAccountIDs;
13
+ var _useState3 = useState([]),
14
+ _useState4 = _slicedToArray(_useState3, 2),
15
+ users = _useState4[0],
16
+ setUsers = _useState4[1];
17
+ var convertUserHydrationResponseToFilterOptions = function convertUserHydrationResponseToFilterOptions(response) {
18
+ var _response$data, _response$data2;
19
+ if (!((_response$data = response.data) !== null && _response$data !== void 0 && _response$data.users)) {
20
+ return [];
21
+ }
22
+ return (_response$data2 = response.data) === null || _response$data2 === void 0 ? void 0 : _response$data2.users.map(function (item) {
23
+ return {
24
+ optionType: 'avatarLabel',
25
+ label: item.name,
26
+ value: item.accountId,
27
+ avatar: item.picture
28
+ };
29
+ });
30
+ };
31
+ var hydrateUsersFromAccountIds = useCallback( /*#__PURE__*/function () {
32
+ var _ref = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee(accountIds) {
33
+ var response;
34
+ return _regeneratorRuntime.wrap(function _callee$(_context) {
35
+ while (1) switch (_context.prev = _context.next) {
36
+ case 0:
37
+ _context.prev = 0;
38
+ setStatus('loading');
39
+ _context.next = 4;
40
+ return getUsersFromAccountIDs(accountIds);
41
+ case 4:
42
+ response = _context.sent;
43
+ if (!(response.errors && response.errors.length > 0)) {
44
+ _context.next = 7;
45
+ break;
46
+ }
47
+ throw new Error(JSON.stringify(response.errors));
48
+ case 7:
49
+ setUsers(convertUserHydrationResponseToFilterOptions(response));
50
+ setStatus('resolved');
51
+ _context.next = 14;
52
+ break;
53
+ case 11:
54
+ _context.prev = 11;
55
+ _context.t0 = _context["catch"](0);
56
+ setStatus('rejected');
57
+ case 14:
58
+ case "end":
59
+ return _context.stop();
60
+ }
61
+ }, _callee, null, [[0, 11]]);
62
+ }));
63
+ return function (_x) {
64
+ return _ref.apply(this, arguments);
65
+ };
66
+ }(), [getUsersFromAccountIDs]);
67
+ return {
68
+ hydrateUsersFromAccountIds: hydrateUsersFromAccountIds,
69
+ status: status,
70
+ users: users
71
+ };
72
+ };
@@ -12,7 +12,7 @@ export var useCurrentUserInfo = function useCurrentUserInfo() {
12
12
  getCurrentUserInfoFromAGG = _useBasicFilterAGG.getCurrentUserInfo;
13
13
  var getCurrentUserInfo = useCallback( /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee() {
14
14
  var _user$data;
15
- var user, _user$data2;
15
+ var user;
16
16
  return _regeneratorRuntime.wrap(function _callee$(_context) {
17
17
  while (1) switch (_context.prev = _context.next) {
18
18
  case 0:
@@ -20,11 +20,7 @@ export var useCurrentUserInfo = function useCurrentUserInfo() {
20
20
  return getCurrentUserInfoFromAGG();
21
21
  case 2:
22
22
  user = _context.sent;
23
- if (user !== null && user !== void 0 && (_user$data = user.data) !== null && _user$data !== void 0 && _user$data.me.user) {
24
- setUser((_user$data2 = user.data) === null || _user$data2 === void 0 ? void 0 : _user$data2.me.user);
25
- } else {
26
- setUser(undefined);
27
- }
23
+ setUser((_user$data = user.data) === null || _user$data === void 0 || (_user$data = _user$data.me) === null || _user$data === void 0 ? void 0 : _user$data.user);
28
24
  case 4:
29
25
  case "end":
30
26
  return _context.stop();
@@ -101,6 +101,7 @@ var useRecommendation = function useRecommendation() {
101
101
  setStatus('empty');
102
102
  setFilterOptions([]);
103
103
  setErrors([]);
104
+ initialData.current = undefined;
104
105
  }, []);
105
106
  return {
106
107
  status: status,
@@ -9,7 +9,8 @@ var BasicFilterContainer = function BasicFilterContainer(_ref) {
9
9
  var cloudId = _ref.cloudId,
10
10
  onChange = _ref.onChange,
11
11
  _ref$selections = _ref.selections,
12
- selections = _ref$selections === void 0 ? {} : _ref$selections;
12
+ selections = _ref$selections === void 0 ? {} : _ref$selections,
13
+ isHydrating = _ref.isHydrating;
13
14
  var editedOrCreatedBy = selections.editedOrCreatedBy;
14
15
  return /*#__PURE__*/React.createElement(Flex, {
15
16
  xcss: basicFilterContainerStyles,
@@ -18,7 +19,8 @@ var BasicFilterContainer = function BasicFilterContainer(_ref) {
18
19
  }, /*#__PURE__*/React.createElement(EditedOrCreatedByFilter, {
19
20
  cloudId: cloudId,
20
21
  onSelectionChange: onChange,
21
- selection: editedOrCreatedBy || []
22
+ selection: editedOrCreatedBy || [],
23
+ isHydrating: isHydrating
22
24
  }), /*#__PURE__*/React.createElement(DateRangePicker, {
23
25
  onSelectionChange: onChange
24
26
  }));
@@ -9,6 +9,8 @@ import { Flex, xcss } from '@atlaskit/primitives';
9
9
  import { BasicSearchInput } from '../../common/modal/basic-search-input';
10
10
  import { FILTER_SELECTION_DEBOUNCE_MS } from '../../common/modal/popup-select/constants';
11
11
  import BasicFilters from '../basic-filters';
12
+ import { useBasicFilterHydration } from '../basic-filters/hooks/useBasicFilterHydration';
13
+ import { CLOLBasicFilters } from '../basic-filters/types';
12
14
  import { searchMessages } from './messages';
13
15
  var basicSearchInputContainerStyles = xcss({
14
16
  flexGrow: 1
@@ -16,8 +18,13 @@ var basicSearchInputContainerStyles = xcss({
16
18
  var ConfluenceSearchContainer = function ConfluenceSearchContainer(_ref) {
17
19
  var cloudId = _ref.cloudId,
18
20
  initialSearchValue = _ref.initialSearchValue,
21
+ initialFilterSelection = _ref.initialFilterSelection,
19
22
  isSearching = _ref.isSearching,
20
23
  onSearch = _ref.onSearch;
24
+ var _useBasicFilterHydrat = useBasicFilterHydration(),
25
+ hydrateUsersFromAccountIds = _useBasicFilterHydrat.hydrateUsersFromAccountIds,
26
+ users = _useBasicFilterHydrat.users,
27
+ status = _useBasicFilterHydrat.status;
21
28
  var currentCloudId = useRef(cloudId);
22
29
  var _useState = useState(initialSearchValue !== null && initialSearchValue !== void 0 ? initialSearchValue : ''),
23
30
  _useState2 = _slicedToArray(_useState, 2),
@@ -57,6 +64,20 @@ var ConfluenceSearchContainer = function ConfluenceSearchContainer(_ref) {
57
64
  }
58
65
  return false;
59
66
  }, []);
67
+ useEffect(function () {
68
+ var accountIds = initialFilterSelection === null || initialFilterSelection === void 0 ? void 0 : initialFilterSelection[CLOLBasicFilters.editedOrCreatedBy];
69
+ var hasAccountIds = accountIds && accountIds.length > 0;
70
+ if (hasAccountIds && status === 'empty' && showBasicFilters) {
71
+ hydrateUsersFromAccountIds(accountIds);
72
+ }
73
+ }, [hydrateUsersFromAccountIds, initialFilterSelection, showBasicFilters, status]);
74
+ useEffect(function () {
75
+ if (status === 'resolved') {
76
+ setFilterSelections({
77
+ editedOrCreatedBy: users
78
+ });
79
+ }
80
+ }, [users, status]);
60
81
  return /*#__PURE__*/React.createElement(Flex, {
61
82
  alignItems: "center",
62
83
  xcss: basicSearchInputContainerStyles
@@ -71,7 +92,8 @@ var ConfluenceSearchContainer = function ConfluenceSearchContainer(_ref) {
71
92
  }), showBasicFilters && /*#__PURE__*/React.createElement(BasicFilters, {
72
93
  cloudId: cloudId,
73
94
  selections: filterSelections,
74
- onChange: handleBasicFilterSelectionChange
95
+ onChange: handleBasicFilterSelectionChange,
96
+ isHydrating: status === 'loading'
75
97
  }));
76
98
  };
77
99
  export default ConfluenceSearchContainer;
@@ -125,6 +125,11 @@ export var PlainConfluenceSearchConfigModal = function PlainConfluenceSearchConf
125
125
  contributorAccountIds: contributorAccountIds
126
126
  });
127
127
  }, [cloudId, lastModified, contributorAccountIds, initialParameters, searchString /** Add more parameters when more filters are added */]);
128
+ var initialFilterSelection = useMemo(function () {
129
+ return {
130
+ editedOrCreatedBy: (initialParameters === null || initialParameters === void 0 ? void 0 : initialParameters.contributorAccountIds) || []
131
+ };
132
+ }, [initialParameters === null || initialParameters === void 0 ? void 0 : initialParameters.contributorAccountIds]);
128
133
  var isParametersSet = useMemo(function () {
129
134
  return !!cloudId && Object.values(parameters !== null && parameters !== void 0 ? parameters : {}).filter(function (v) {
130
135
  return v !== undefined;
@@ -288,7 +293,18 @@ export var PlainConfluenceSearchConfigModal = function PlainConfluenceSearchConf
288
293
  var resolvedWithNoResults = status === 'resolved' && !responseItems.length;
289
294
  var hasConfluenceSearchParams = selectedConfluenceSite && searchString;
290
295
  var selectedConfluenceSiteUrl = selectedConfluenceSite === null || selectedConfluenceSite === void 0 ? void 0 : selectedConfluenceSite.url;
291
- var confluenceSearchUrl = selectedConfluenceSiteUrl && searchString !== undefined && "".concat(selectedConfluenceSiteUrl, "/wiki/search?text=").concat(encodeURI(searchString));
296
+ var confluenceSearchUrl = useMemo(function () {
297
+ if (!selectedConfluenceSiteUrl || searchString === undefined) {
298
+ return undefined;
299
+ }
300
+ var params = new URLSearchParams();
301
+ // we are appending "text" without checking searchString as we need the url to have "text" when a user does an empty search
302
+ params.append('text', searchString);
303
+ if (contributorAccountIds.length > 0) {
304
+ params.append('contributors', contributorAccountIds.join(','));
305
+ }
306
+ return "".concat(selectedConfluenceSiteUrl, "/wiki/search?").concat(params.toString());
307
+ }, [contributorAccountIds, searchString, selectedConfluenceSiteUrl]);
292
308
  var analyticsPayload = useMemo(function () {
293
309
  return {
294
310
  extensionKey: extensionKey,
@@ -477,7 +493,8 @@ export var PlainConfluenceSearchConfigModal = function PlainConfluenceSearchConf
477
493
  cloudId: cloudId,
478
494
  isSearching: status === 'loading',
479
495
  onSearch: onSearch,
480
- initialSearchValue: initialParameters === null || initialParameters === void 0 ? void 0 : initialParameters.searchString
496
+ initialSearchValue: initialParameters === null || initialParameters === void 0 ? void 0 : initialParameters.searchString,
497
+ initialFilterSelection: initialFilterSelection
481
498
  })), currentViewMode === 'inline' ? renderInlineLinkModalContent() : renderTableModalContent()) : jsx(NoInstancesView, {
482
499
  title: confluenceSearchModalMessages.noAccessToConfluenceSitesTitle,
483
500
  description: confluenceSearchModalMessages.noAccessToConfluenceSitesDescription,
@@ -1,3 +1,4 @@
1
+ import { SelectOption } from '../ui/common/modal/popup-select/types';
1
2
  import { FieldValuesResponse, HydrateResponse } from '../ui/jira-issues-modal/basic-filters/types';
2
3
  export declare const mockHydrateJqlResponse: HydrateResponse;
3
4
  export declare const mockFieldValuesResponse: FieldValuesResponse;
@@ -52,3 +53,13 @@ export declare const mockUserRecommendationsResponse: {
52
53
  email?: undefined;
53
54
  })[];
54
55
  };
56
+ export declare const mockUserHydrationResponse: {
57
+ data: {
58
+ users: {
59
+ accountId: string;
60
+ name: string;
61
+ picture: string;
62
+ }[];
63
+ };
64
+ };
65
+ export declare const mockTransformedUserHydrationResponse: SelectOption[];
@@ -1,4 +1,4 @@
1
- import { UserInfoAGGResponse } from '../ui/confluence-search-modal/basic-filters/types';
1
+ import { UserHydrationAGGResponse, UserInfoAGGResponse } from '../ui/confluence-search-modal/basic-filters/types';
2
2
  import { BasicFilterFieldType, FieldValuesResponse, HydrateResponse } from '../ui/jira-issues-modal/basic-filters/types';
3
3
  interface GetFieldValuesProps {
4
4
  cloudId: string;
@@ -11,5 +11,6 @@ export declare const useBasicFilterAGG: () => {
11
11
  getHydratedJQL: (cloudId: string, jql: string) => Promise<HydrateResponse>;
12
12
  getFieldValues: ({ cloudId, jql, jqlTerm, searchString, pageCursor, }: GetFieldValuesProps) => Promise<FieldValuesResponse>;
13
13
  getCurrentUserInfo: () => Promise<UserInfoAGGResponse>;
14
+ getUsersFromAccountIDs: (accountIds: string[]) => Promise<UserHydrationAGGResponse>;
14
15
  };
15
16
  export {};
@@ -7,3 +7,4 @@
7
7
  export declare const hydrateJQLQuery = "query hydrate($cloudId: ID!, $jql: String!) {\n jira {\n jqlBuilder(cloudId: $cloudId) {\n hydrateJqlQuery(query: $jql) {\n ... on JiraJqlHydratedQuery {\n fields {\n ... on JiraJqlQueryHydratedField {\n jqlTerm\n values {\n ... on JiraJqlQueryHydratedValue {\n values {\n ... on JiraJqlProjectFieldValue {\n jqlTerm\n displayName\n project {\n avatar {\n small\n }\n }\n }\n ... on JiraJqlStatusFieldValue {\n jqlTerm\n displayName\n statusCategory {\n colorName\n }\n }\n ... on JiraJqlIssueTypeFieldValue {\n jqlTerm\n displayName\n issueTypes {\n avatar {\n small\n }\n }\n }\n ... on JiraJqlUserFieldValue {\n jqlTerm\n displayName\n user {\n picture\n }\n }\n ... on JiraJqlGroupFieldValue {\n jqlTerm\n displayName\n group {\n name\n }\n }\n }\n }\n }\n }\n }\n }\n }\n }\n }\n}";
8
8
  export declare const fieldValuesQuery = "query fieldValues($cloudId: ID!, $first: Int = 10, $jqlTerm: String!, $jql: String!, $searchString: String!, $after: String) {\n jira {\n jqlBuilder(cloudId: $cloudId) {\n fieldValues(\n first: $first\n jqlTerm: $jqlTerm\n jqlContext: $jql\n searchString: $searchString\n after: $after\n ) {\n totalCount\n pageInfo {\n endCursor\n }\n edges {\n node {\n jqlTerm\n displayName\n ... on JiraJqlProjectFieldValue {\n project {\n avatar {\n small\n }\n }\n }\n ... on JiraJqlIssueTypeFieldValue {\n issueTypes {\n avatar {\n small\n }\n }\n }\n ... on JiraJqlStatusFieldValue {\n statusCategory {\n colorName\n }\n }\n ... on JiraJqlUserFieldValue {\n user {\n picture\n }\n }\n ... on JiraJqlGroupFieldValue {\n group {\n name\n }\n }\n }\n }\n }\n }\n }\n}";
9
9
  export declare const userQuery = "query userQuery {\n me {\n user {\n id\n accountId\n }\n }\n}";
10
+ export declare const userHydration = "query userHydration($accountIds: [ID!]!) {\n users(accountIds: $accountIds) {\n accountId\n name\n picture\n }\n}";
@@ -25,3 +25,7 @@ export type DateRangeOption = OptionBase & {
25
25
  };
26
26
  export type SelectOption = IconLabelOption | LozengeLabelOption | AvatarLabelOption | DateRangeOption;
27
27
  export type FormatOptionLabel = (option: SelectOption) => ReactElement;
28
+ export interface CommonBasicFilterHookState {
29
+ status: 'empty' | 'loading' | 'resolved' | 'rejected';
30
+ errors: unknown[];
31
+ }
@@ -4,7 +4,8 @@ import { CLOLBasicFilters } from '../../types';
4
4
  interface EditedOrCreatedByFilterProps {
5
5
  cloudId?: string;
6
6
  selection: SelectOption[];
7
+ isHydrating?: boolean;
7
8
  onSelectionChange: (filterType: CLOLBasicFilters, selection: SelectOption[]) => void;
8
9
  }
9
- declare const EditedOrCreatedByFilter: ({ cloudId, onSelectionChange, selection, }: EditedOrCreatedByFilterProps) => JSX.Element;
10
+ declare const EditedOrCreatedByFilter: ({ cloudId, onSelectionChange, selection, isHydrating, }: EditedOrCreatedByFilterProps) => JSX.Element;
10
11
  export default EditedOrCreatedByFilter;
@@ -0,0 +1,6 @@
1
+ import { CommonBasicFilterHookState, SelectOption } from '../../../common/modal/popup-select/types';
2
+ export interface BasicFilterHydrationState extends Omit<CommonBasicFilterHookState, 'errors'> {
3
+ hydrateUsersFromAccountIds: (accountIds: string[]) => void;
4
+ users: SelectOption[];
5
+ }
6
+ export declare const useBasicFilterHydration: () => BasicFilterHydrationState;
@@ -5,6 +5,7 @@ export interface BasicFilterContainerProps {
5
5
  cloudId?: string;
6
6
  selections: SelectedOptionsMap;
7
7
  onChange: (filterType: CLOLBasicFilters, options: SelectOption[]) => void;
8
+ isHydrating?: boolean;
8
9
  }
9
- declare const BasicFilterContainer: ({ cloudId, onChange, selections, }: BasicFilterContainerProps) => JSX.Element;
10
+ declare const BasicFilterContainer: ({ cloudId, onChange, selections, isHydrating, }: BasicFilterContainerProps) => JSX.Element;
10
11
  export default BasicFilterContainer;