@atlaskit/link-datasource 1.15.3 → 1.16.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.
Files changed (59) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/dist/cjs/analytics/constants.js +1 -1
  3. package/dist/cjs/hooks/useAssetsClient.js +71 -27
  4. package/dist/cjs/services/cmdbService.js +128 -28
  5. package/dist/cjs/services/cmdbService.utils.js +64 -0
  6. package/dist/cjs/ui/assets-modal/modal/index.js +73 -9
  7. package/dist/cjs/ui/assets-modal/modal/render-assets-content/index.js +25 -12
  8. package/dist/cjs/ui/assets-modal/search-container/index.js +2 -1
  9. package/dist/cjs/ui/assets-modal/search-container/object-schema-select/index.js +21 -63
  10. package/dist/cjs/ui/jira-issues-modal/basic-filters/hooks/useFilterOptions.js +14 -14
  11. package/dist/cjs/ui/jira-issues-modal/basic-filters/ui/async-popup-select/index.js +18 -3
  12. package/dist/cjs/ui/jira-issues-modal/basic-filters/ui/async-popup-select/messages.js +5 -0
  13. package/dist/cjs/ui/jira-issues-modal/basic-filters/ui/async-popup-select/showMoreButton.js +22 -0
  14. package/dist/cjs/ui/jira-issues-modal/basic-filters/ui/menu-list/index.js +21 -4
  15. package/dist/es2019/analytics/constants.js +1 -1
  16. package/dist/es2019/hooks/useAssetsClient.js +39 -15
  17. package/dist/es2019/services/cmdbService.js +60 -14
  18. package/dist/es2019/services/cmdbService.utils.js +39 -0
  19. package/dist/es2019/ui/assets-modal/modal/index.js +70 -9
  20. package/dist/es2019/ui/assets-modal/modal/render-assets-content/index.js +24 -9
  21. package/dist/es2019/ui/assets-modal/search-container/index.js +2 -1
  22. package/dist/es2019/ui/assets-modal/search-container/object-schema-select/index.js +2 -25
  23. package/dist/es2019/ui/jira-issues-modal/basic-filters/hooks/useFilterOptions.js +2 -2
  24. package/dist/es2019/ui/jira-issues-modal/basic-filters/ui/async-popup-select/index.js +18 -3
  25. package/dist/es2019/ui/jira-issues-modal/basic-filters/ui/async-popup-select/messages.js +5 -0
  26. package/dist/es2019/ui/jira-issues-modal/basic-filters/ui/async-popup-select/showMoreButton.js +17 -0
  27. package/dist/es2019/ui/jira-issues-modal/basic-filters/ui/menu-list/index.js +18 -3
  28. package/dist/esm/analytics/constants.js +1 -1
  29. package/dist/esm/hooks/useAssetsClient.js +72 -28
  30. package/dist/esm/services/cmdbService.js +128 -28
  31. package/dist/esm/services/cmdbService.utils.js +57 -0
  32. package/dist/esm/ui/assets-modal/modal/index.js +73 -9
  33. package/dist/esm/ui/assets-modal/modal/render-assets-content/index.js +24 -9
  34. package/dist/esm/ui/assets-modal/search-container/index.js +2 -1
  35. package/dist/esm/ui/assets-modal/search-container/object-schema-select/index.js +18 -60
  36. package/dist/esm/ui/jira-issues-modal/basic-filters/hooks/useFilterOptions.js +14 -14
  37. package/dist/esm/ui/jira-issues-modal/basic-filters/ui/async-popup-select/index.js +18 -3
  38. package/dist/esm/ui/jira-issues-modal/basic-filters/ui/async-popup-select/messages.js +5 -0
  39. package/dist/esm/ui/jira-issues-modal/basic-filters/ui/async-popup-select/showMoreButton.js +15 -0
  40. package/dist/esm/ui/jira-issues-modal/basic-filters/ui/menu-list/index.js +21 -4
  41. package/dist/types/hooks/useAssetsClient.d.ts +5 -1
  42. package/dist/types/services/cmdbService.utils.d.ts +9 -0
  43. package/dist/types/ui/assets-modal/modal/render-assets-content/index.d.ts +3 -2
  44. package/dist/types/ui/assets-modal/search-container/index.d.ts +1 -0
  45. package/dist/types/ui/assets-modal/search-container/object-schema-select/index.d.ts +2 -1
  46. package/dist/types/ui/jira-issues-modal/basic-filters/hooks/useFilterOptions.d.ts +1 -1
  47. package/dist/types/ui/jira-issues-modal/basic-filters/ui/async-popup-select/messages.d.ts +5 -0
  48. package/dist/types/ui/jira-issues-modal/basic-filters/ui/async-popup-select/showMoreButton.d.ts +6 -0
  49. package/dist/types/ui/jira-issues-modal/basic-filters/ui/menu-list/index.d.ts +4 -1
  50. package/dist/types-ts4.5/hooks/useAssetsClient.d.ts +5 -1
  51. package/dist/types-ts4.5/services/cmdbService.utils.d.ts +9 -0
  52. package/dist/types-ts4.5/ui/assets-modal/modal/render-assets-content/index.d.ts +3 -2
  53. package/dist/types-ts4.5/ui/assets-modal/search-container/index.d.ts +1 -0
  54. package/dist/types-ts4.5/ui/assets-modal/search-container/object-schema-select/index.d.ts +2 -1
  55. package/dist/types-ts4.5/ui/jira-issues-modal/basic-filters/hooks/useFilterOptions.d.ts +1 -1
  56. package/dist/types-ts4.5/ui/jira-issues-modal/basic-filters/ui/async-popup-select/messages.d.ts +5 -0
  57. package/dist/types-ts4.5/ui/jira-issues-modal/basic-filters/ui/async-popup-select/showMoreButton.d.ts +6 -0
  58. package/dist/types-ts4.5/ui/jira-issues-modal/basic-filters/ui/menu-list/index.d.ts +4 -1
  59. package/package.json +1 -1
@@ -18,6 +18,8 @@ import { fetchMessagesForLocale } from '../../../common/utils/locale/fetch-messa
18
18
  import { useAssetsClient } from '../../../hooks/useAssetsClient';
19
19
  import { useDatasourceTableState } from '../../../hooks/useDatasourceTableState';
20
20
  import i18nEN from '../../../i18n/en';
21
+ import { PermissionError } from '../../../services/cmdbService.utils';
22
+ import { AccessRequired } from '../../../ui/common/error-state/access-required';
21
23
  import { ModalLoadingError } from '../../common/error-state/modal-loading-error';
22
24
  import { AssetsSearchContainer } from '../search-container';
23
25
  import { AssetsSearchContainerLoading } from '../search-container/loading-state';
@@ -28,6 +30,9 @@ const modalBodyWrapperStyles = css({
28
30
  height: '420px',
29
31
  overflow: 'auto'
30
32
  });
33
+ const modalBodyErrorWrapperStyles = css({
34
+ alignItems: 'center'
35
+ });
31
36
  const AssetsModalTitle = jsx(ModalTitle, null, jsx(FormattedMessage, modalMessages.insertObjectsTitle));
32
37
  const PlainAssetsConfigModal = props => {
33
38
  const {
@@ -41,20 +46,53 @@ const PlainAssetsConfigModal = props => {
41
46
  const [schemaId, setSchemaId] = useState(initialParameters === null || initialParameters === void 0 ? void 0 : initialParameters.schemaId);
42
47
  const [visibleColumnKeys, setVisibleColumnKeys] = useState(initialVisibleColumnKeys);
43
48
  const [isNewSearch, setIsNewSearch] = useState(false);
49
+ const [errorState, setErrorState] = useState();
44
50
  const {
45
51
  fireEvent
46
52
  } = useDatasourceAnalyticsEvents();
47
53
  const {
48
54
  current: modalRenderInstanceId
49
55
  } = useRef(uuidv4());
50
-
51
- // If a workspaceError occurs this is a critical error
52
56
  const {
53
57
  workspaceId,
54
58
  workspaceError,
55
- objectSchema,
59
+ existingObjectSchema,
60
+ existingObjectSchemaError,
61
+ objectSchemas,
62
+ objectSchemasError,
63
+ totalObjectSchemas,
56
64
  assetsClientLoading
57
65
  } = useAssetsClient(initialParameters);
66
+
67
+ /* ------------------------------ PERMISSIONS ------------------------------ */
68
+ useEffect(() => {
69
+ if (workspaceError) {
70
+ // If a workspaceError occurs this is a critical error
71
+ if (workspaceError instanceof PermissionError) {
72
+ setErrorState('permission');
73
+ } else {
74
+ setErrorState('network');
75
+ }
76
+ }
77
+ }, [workspaceError]);
78
+ useEffect(() => {
79
+ if (objectSchemasError) {
80
+ // We only care about permission errors for objectSchemas fetching as the user can retry this action
81
+ if (objectSchemasError instanceof PermissionError) {
82
+ setErrorState('permission');
83
+ }
84
+ }
85
+ }, [objectSchemasError]);
86
+ useEffect(() => {
87
+ if (existingObjectSchemaError) {
88
+ // We only care about permission errors for existingObjectSchema fetching as the user can retry this action
89
+ if (existingObjectSchemaError instanceof PermissionError) {
90
+ setErrorState('permission');
91
+ }
92
+ }
93
+ }, [existingObjectSchemaError]);
94
+ /* ------------------------------ END PERMISSIONS ------------------------------ */
95
+
58
96
  const parameters = useMemo(() => ({
59
97
  aql: aql || '',
60
98
  schemaId: schemaId || '',
@@ -90,6 +128,15 @@ const PlainAssetsConfigModal = props => {
90
128
  destinationObjectTypes: destinationObjectTypes
91
129
  };
92
130
  }, [destinationObjectTypes, extensionKey]);
131
+ useEffect(() => {
132
+ // We only want to send modal ready event once after we've fetched the schema count
133
+ if (totalObjectSchemas !== undefined) {
134
+ fireEvent('ui.modal.ready.datasource', {
135
+ schemasCount: totalObjectSchemas,
136
+ instancesCount: null
137
+ });
138
+ }
139
+ }, [fireEvent, totalObjectSchemas]);
93
140
  useEffect(() => {
94
141
  fireEvent('screen.datasourceModalDialog.viewed', {});
95
142
  }, [fireEvent]);
@@ -144,7 +191,7 @@ const PlainAssetsConfigModal = props => {
144
191
  setVisibleColumnKeys(defaultVisibleColumnKeys);
145
192
  }
146
193
  }, [defaultVisibleColumnKeys, isNewSearch]);
147
- const isDisabled = !!workspaceError || status !== 'resolved' || assetsClientLoading || !aql || !schemaId;
194
+ const isDisabled = !!errorState || status !== 'resolved' || assetsClientLoading || !aql || !schemaId;
148
195
  const retrieveUrlForSmartCardRender = useCallback(() => {
149
196
  var _data$key, _data$key$data;
150
197
  const [data] = responseItems;
@@ -232,8 +279,20 @@ const PlainAssetsConfigModal = props => {
232
279
  setIsNewSearch(true);
233
280
  }
234
281
  }, [aql, reset, schemaId, status]);
282
+ const renderErrorState = useCallback(() => {
283
+ if (errorState) {
284
+ switch (errorState) {
285
+ case 'permission':
286
+ return jsx(AccessRequired, null);
287
+ case 'network':
288
+ return jsx(ModalLoadingError, null);
289
+ default:
290
+ return jsx(ModalLoadingError, null);
291
+ }
292
+ }
293
+ }, [errorState]);
235
294
  const renderModalTitleContent = useCallback(() => {
236
- if (workspaceError) {
295
+ if (errorState) {
237
296
  return undefined;
238
297
  } else {
239
298
  if (!workspaceId || assetsClientLoading) {
@@ -245,14 +304,15 @@ const PlainAssetsConfigModal = props => {
245
304
  workspaceId: workspaceId,
246
305
  initialSearchData: {
247
306
  aql,
248
- objectSchema
307
+ objectSchema: existingObjectSchema,
308
+ objectSchemas
249
309
  },
250
310
  onSearch: handleOnSearch,
251
311
  modalTitle: AssetsModalTitle,
252
312
  isSearching: status === 'loading'
253
313
  });
254
314
  }
255
- }, [aql, assetsClientLoading, handleOnSearch, objectSchema, status, workspaceError, workspaceId]);
315
+ }, [errorState, workspaceId, assetsClientLoading, aql, existingObjectSchema, objectSchemas, handleOnSearch, status]);
256
316
  return jsx(IntlMessagesProvider, {
257
317
  defaultMessages: i18nEN,
258
318
  loaderFn: fetchMessagesForLocale
@@ -263,8 +323,9 @@ const PlainAssetsConfigModal = props => {
263
323
  shouldScrollInViewport: true,
264
324
  shouldCloseOnOverlayClick: false
265
325
  }, jsx(ModalHeader, null, renderModalTitleContent()), jsx(ModalBody, null, jsx("div", {
266
- css: modalBodyWrapperStyles
267
- }, workspaceError ? jsx(ModalLoadingError, null) : jsx(RenderAssetsContent, {
326
+ css: [modalBodyWrapperStyles, errorState && modalBodyErrorWrapperStyles]
327
+ }, errorState ? renderErrorState() : jsx(RenderAssetsContent, {
328
+ isFetchingInitialData: assetsClientLoading,
268
329
  status: status,
269
330
  responseItems: responseItems,
270
331
  visibleColumnKeys: visibleColumnKeys,
@@ -1,9 +1,16 @@
1
- import React, { useMemo } from 'react';
1
+ /** @jsx jsx */
2
+ import { useMemo } from 'react';
3
+ import { css, jsx } from '@emotion/react';
2
4
  import { AccessRequired } from '../../../common/error-state/access-required';
3
5
  import { ModalLoadingError } from '../../../common/error-state/modal-loading-error';
4
6
  import { NoResults } from '../../../common/error-state/no-results';
5
7
  import { EmptyState, IssueLikeDataTableView } from '../../../issue-like-table';
6
8
  import { InitialStateView } from './initial-state-view';
9
+ // This is to prevent y scrollbar when initially fetching data
10
+ const emptyStateOverrideStyles = css({
11
+ height: '420px',
12
+ overflow: 'hidden'
13
+ });
7
14
  export const RenderAssetsContent = props => {
8
15
  const {
9
16
  status,
@@ -15,10 +22,11 @@ export const RenderAssetsContent = props => {
15
22
  columns,
16
23
  defaultVisibleColumnKeys,
17
24
  onVisibleColumnKeysChange,
18
- modalRenderInstanceId
25
+ modalRenderInstanceId,
26
+ isFetchingInitialData
19
27
  } = props;
20
28
  const resolvedWithNoResults = status === 'resolved' && !responseItems.length;
21
- const issueLikeDataTableView = useMemo(() => /*#__PURE__*/React.createElement(IssueLikeDataTableView, {
29
+ const issueLikeDataTableView = useMemo(() => jsx(IssueLikeDataTableView, {
22
30
  testId: "asset-datasource-table",
23
31
  status: status,
24
32
  columns: columns,
@@ -30,16 +38,23 @@ export const RenderAssetsContent = props => {
30
38
  onVisibleColumnKeysChange: onVisibleColumnKeysChange,
31
39
  parentContainerRenderInstanceId: modalRenderInstanceId
32
40
  }), [columns, defaultVisibleColumnKeys, hasNextPage, loadDatasourceDetails, onNextPage, onVisibleColumnKeysChange, responseItems, status, visibleColumnKeys, modalRenderInstanceId]);
33
- if (status === 'rejected') {
34
- return /*#__PURE__*/React.createElement(ModalLoadingError, null);
41
+ if (isFetchingInitialData) {
42
+ // Placing this check first as it's a priority before all others
43
+ return jsx("div", {
44
+ css: emptyStateOverrideStyles
45
+ }, jsx(EmptyState, {
46
+ testId: "assets-aql-datasource-modal--loading-state"
47
+ }));
48
+ } else if (status === 'rejected') {
49
+ return jsx(ModalLoadingError, null);
35
50
  } else if (status === 'unauthorized') {
36
- return /*#__PURE__*/React.createElement(AccessRequired, null);
51
+ return jsx(AccessRequired, null);
37
52
  } else if (status === 'empty') {
38
- return /*#__PURE__*/React.createElement(InitialStateView, null);
53
+ return jsx(InitialStateView, null);
39
54
  } else if (resolvedWithNoResults) {
40
- return /*#__PURE__*/React.createElement(NoResults, null);
55
+ return jsx(NoResults, null);
41
56
  } else if (status === 'loading' && !columns.length) {
42
- return /*#__PURE__*/React.createElement(EmptyState, {
57
+ return jsx(EmptyState, {
43
58
  testId: "assets-aql-datasource-modal--loading-state"
44
59
  });
45
60
  }
@@ -35,7 +35,7 @@ export const AssetsSearchContainer = props => {
35
35
  }, ({
36
36
  formProps
37
37
  }) => {
38
- var _initialSearchData$ob, _initialSearchData$aq;
38
+ var _initialSearchData$ob, _initialSearchData$ob2, _initialSearchData$aq;
39
39
  return jsx(FormContainer, _extends({}, formProps, {
40
40
  id: SEARCH_FORM_ID
41
41
  }), jsx(FormRowContainer, {
@@ -43,6 +43,7 @@ export const AssetsSearchContainer = props => {
43
43
  }, modalTitle, jsx(SchemaSelectContainer, null, jsx(AssetsObjectSchemaSelect, {
44
44
  value: (_initialSearchData$ob = initialSearchData.objectSchema) !== null && _initialSearchData$ob !== void 0 ? _initialSearchData$ob : undefined,
45
45
  workspaceId: workspaceId,
46
+ initialObjectSchemas: (_initialSearchData$ob2 = initialSearchData.objectSchemas) !== null && _initialSearchData$ob2 !== void 0 ? _initialSearchData$ob2 : undefined,
46
47
  classNamePrefix: "assets-datasource-modal--object-schema-select"
47
48
  }))), jsx(FormRowContainer, null, jsx(AqlSearchInput, {
48
49
  value: (_initialSearchData$aq = initialSearchData.aql) !== null && _initialSearchData$aq !== void 0 ? _initialSearchData$aq : DEFAULT_AQL_QUERY,
@@ -1,14 +1,12 @@
1
1
  import _extends from "@babel/runtime/helpers/extends";
2
2
  /** @jsx jsx */
3
3
 
4
- import { useEffect, useState } from 'react';
5
4
  import { jsx } from '@emotion/react';
6
5
  import debounce from 'debounce-promise';
7
6
  import { useIntl } from 'react-intl-next';
8
7
  import { Field } from '@atlaskit/form';
9
8
  import { AsyncSelect } from '@atlaskit/select';
10
9
  import { layers } from '@atlaskit/theme/constants';
11
- import { useDatasourceAnalyticsEvents } from '../../../../analytics';
12
10
  import { useObjectSchemas } from '../../../../hooks/useObjectSchemas';
13
11
  import { objectSchemaKey } from '../../../../types/assets/types';
14
12
  import { FieldContainer } from '../styled';
@@ -35,12 +33,9 @@ export const selectInAModalStyleFixProps = {
35
33
  export const AssetsObjectSchemaSelect = ({
36
34
  value,
37
35
  workspaceId,
36
+ initialObjectSchemas,
38
37
  classNamePrefix = 'assets-datasource-modal--object-schema-select'
39
38
  }) => {
40
- const [defaultOptions, setDefaultOptions] = useState(null);
41
- const {
42
- fireEvent
43
- } = useDatasourceAnalyticsEvents();
44
39
  const {
45
40
  formatMessage
46
41
  } = useIntl();
@@ -49,24 +44,6 @@ export const AssetsObjectSchemaSelect = ({
49
44
  objectSchemasLoading
50
45
  } = useObjectSchemas(workspaceId);
51
46
  const selectedObjectSchema = value ? objectSchemaToSelectOption(value) : undefined;
52
- useEffect(() => {
53
- const fetchInitialData = async () => {
54
- const {
55
- objectSchemas,
56
- totalObjectSchemas
57
- } = await fetchObjectSchemas('');
58
- // We only want to send modal ready event once after we've fetched the schema count
59
- fireEvent('ui.modal.ready.datasource', {
60
- schemasCount: totalObjectSchemas !== null && totalObjectSchemas !== void 0 ? totalObjectSchemas : 0,
61
- instancesCount: null
62
- });
63
- setDefaultOptions(mapObjectSchemasToOptions(objectSchemas));
64
- };
65
- if (defaultOptions === null) {
66
- fetchInitialData();
67
- }
68
- // eslint-disable-next-line react-hooks/exhaustive-deps
69
- }, []);
70
47
  const loadOptions = async inputValue => {
71
48
  const {
72
49
  objectSchemas
@@ -94,7 +71,7 @@ export const AssetsObjectSchemaSelect = ({
94
71
  autoFocus: true,
95
72
  classNamePrefix: classNamePrefix,
96
73
  isLoading: objectSchemasLoading,
97
- defaultOptions: defaultOptions !== null && defaultOptions !== void 0 ? defaultOptions : [],
74
+ defaultOptions: mapObjectSchemasToOptions(initialObjectSchemas),
98
75
  isSearchable: true,
99
76
  loadOptions: debouncedLoadOptions,
100
77
  placeholder: formatMessage(objectSchemaSelectMessages.placeholder),
@@ -17,7 +17,8 @@ export const useFilterOptions = ({
17
17
  pageCursor,
18
18
  searchString
19
19
  } = {}) => {
20
- setStatus('loading');
20
+ const isNewSearch = !pageCursor;
21
+ isNewSearch ? setStatus('loading') : setStatus('loadingMore');
21
22
  const isRequestLikeInitialSearch = !pageCursor && !searchString;
22
23
  const {
23
24
  current: initialResponseData
@@ -34,7 +35,6 @@ export const useFilterOptions = ({
34
35
  setStatus('rejected');
35
36
  return;
36
37
  }
37
- const isNewSearch = !pageCursor;
38
38
  if (isNewSearch) {
39
39
  setFilterOptions(mapFieldValuesToFilterOptions(response));
40
40
  if (isRequestLikeInitialSearch) {
@@ -31,7 +31,8 @@ const AsyncPopupSelect = ({
31
31
  filterOptions,
32
32
  fetchFilterOptions,
33
33
  totalCount,
34
- status
34
+ status,
35
+ pageCursor
35
36
  } = useFilterOptions({
36
37
  filterType,
37
38
  cloudId
@@ -59,6 +60,14 @@ const AsyncPopupSelect = ({
59
60
  });
60
61
  }
61
62
  }, [fetchFilterOptions, searchTerm, status]);
63
+ const handleShowMore = useCallback(() => {
64
+ if (pageCursor) {
65
+ fetchFilterOptions({
66
+ pageCursor,
67
+ searchString: searchTerm
68
+ });
69
+ }
70
+ }, [fetchFilterOptions, pageCursor, searchTerm]);
62
71
  useEffect(() => {
63
72
  if (status === 'resolved') {
64
73
  var _pickerRef$current, _pickerRef$current$se, _pickerRef$current$se2;
@@ -69,8 +78,11 @@ const AsyncPopupSelect = ({
69
78
  const filterOptionsLength = filterOptions.length;
70
79
  const isError = status === 'rejected';
71
80
  const isLoading = status === 'loading' || status === 'empty';
81
+ const isLoadingMore = status === 'loadingMore';
72
82
  const isEmpty = status === 'resolved' && filterOptionsLength === 0;
73
- const shouldShowFooter = status === 'resolved' && filterOptionsLength > 0;
83
+ const areAllResultsLoaded = filterOptions.length === totalCount;
84
+ const shouldShowFooter = (status === 'resolved' || isLoadingMore) && filterOptions.length > 0; // footer should not disappear when there is an inline spinner for loading more data
85
+ const shouldDisplayShowMoreButton = status === 'resolved' && !!pageCursor && !areAllResultsLoaded;
74
86
  const options = isLoading || isError ? [] : filterOptions; // if not set to [], for eg: on loading, no loading UI will be shown
75
87
 
76
88
  return /*#__PURE__*/React.createElement(PopupSelect, {
@@ -98,7 +110,10 @@ const AsyncPopupSelect = ({
98
110
  MenuList: props => /*#__PURE__*/React.createElement(CustomMenuList, _extends({}, props, {
99
111
  isError: isError,
100
112
  isEmpty: isEmpty,
101
- isLoading: isLoading
113
+ isLoading: isLoading,
114
+ isLoadingMore: isLoadingMore,
115
+ showMore: shouldDisplayShowMoreButton,
116
+ handleShowMore: handleShowMore
102
117
  })),
103
118
  DropdownIndicator: CustomDropdownIndicator,
104
119
  LoadingIndicator: undefined,
@@ -28,5 +28,10 @@ export const asyncPopupSelectMessages = {
28
28
  id: 'linkDataSource.basic-filter.assignee.label',
29
29
  description: 'Label to be displayed for assignee filter dropdown button.',
30
30
  defaultMessage: 'Assignee'
31
+ },
32
+ showMoreMessage: {
33
+ id: 'linkDataSource.basic-filter.showMoreButton',
34
+ defaultMessage: 'Show more',
35
+ description: 'The text to show more options in dropdown'
31
36
  }
32
37
  };
@@ -0,0 +1,17 @@
1
+ import React from 'react';
2
+ import { useIntl } from 'react-intl-next';
3
+ import Button from '@atlaskit/button';
4
+ import { asyncPopupSelectMessages } from './messages';
5
+ const ShowMoreButton = ({
6
+ onShowMore
7
+ }) => {
8
+ const {
9
+ formatMessage
10
+ } = useIntl();
11
+ return /*#__PURE__*/React.createElement(Button, {
12
+ onClick: onShowMore,
13
+ appearance: "link",
14
+ testId: "jlol-basic-filter-popup-select--show-more-button"
15
+ }, formatMessage(asyncPopupSelectMessages.showMoreMessage));
16
+ };
17
+ export default ShowMoreButton;
@@ -1,16 +1,29 @@
1
1
  import React from 'react';
2
+ import { Flex } from '@atlaskit/primitives';
2
3
  import { components } from '@atlaskit/select';
4
+ import Spinner from '@atlaskit/spinner';
5
+ import ShowMoreButton from '../async-popup-select/showMoreButton';
3
6
  import CustomErrorMessage from './errorMessage';
4
7
  import CustomDropdownLoadingMessage from './loadingMessage';
5
8
  import CustomNoOptionsMessage from './noOptionsMessage';
6
9
  const CustomMenuList = ({
7
10
  isLoading,
11
+ isLoadingMore,
8
12
  isError,
9
13
  isEmpty,
14
+ showMore,
15
+ handleShowMore,
10
16
  children,
11
17
  ...props
12
18
  }) => {
13
- const getChildComponent = () => {
19
+ const shouldDisplayShowMore = showMore && !isLoadingMore;
20
+ const isLoadingMoreData = !shouldDisplayShowMore && isLoadingMore;
21
+ const InlineSpinner = () => /*#__PURE__*/React.createElement(Flex, {
22
+ justifyContent: "center"
23
+ }, /*#__PURE__*/React.createElement(Spinner, {
24
+ size: "medium"
25
+ }));
26
+ const renderChildren = () => {
14
27
  if (isLoading) {
15
28
  return /*#__PURE__*/React.createElement(CustomDropdownLoadingMessage, null);
16
29
  }
@@ -20,8 +33,10 @@ const CustomMenuList = ({
20
33
  if (isEmpty) {
21
34
  return /*#__PURE__*/React.createElement(CustomNoOptionsMessage, null);
22
35
  }
23
- return children;
36
+ return /*#__PURE__*/React.createElement(React.Fragment, null, children, shouldDisplayShowMore && /*#__PURE__*/React.createElement(ShowMoreButton, {
37
+ onShowMore: handleShowMore
38
+ }), isLoadingMoreData && /*#__PURE__*/React.createElement(InlineSpinner, null));
24
39
  };
25
- return /*#__PURE__*/React.createElement(components.MenuList, props, getChildComponent());
40
+ return /*#__PURE__*/React.createElement(components.MenuList, props, renderChildren());
26
41
  };
27
42
  export default CustomMenuList;
@@ -1,5 +1,5 @@
1
1
  export var EVENT_CHANNEL = 'media';
2
2
  export var packageMetaData = {
3
3
  packageName: "@atlaskit/link-datasource",
4
- packageVersion: "1.15.3"
4
+ packageVersion: "1.16.0"
5
5
  };
@@ -2,7 +2,14 @@ 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
4
  import { useEffect, useState } from 'react';
5
- import { fetchObjectSchema, getWorkspaceId } from '../services/cmdbService';
5
+ import { fetchObjectSchema, fetchObjectSchemas, getWorkspaceId } from '../services/cmdbService';
6
+ var handleAssetsClientErrors = function handleAssetsClientErrors(errorSetter, error) {
7
+ if (error instanceof Error) {
8
+ errorSetter(error);
9
+ } else {
10
+ errorSetter(new Error('Unexpected error occured'));
11
+ }
12
+ };
6
13
  export var useAssetsClient = function useAssetsClient(initialParameters) {
7
14
  var _useState = useState(false),
8
15
  _useState2 = _slicedToArray(_useState, 2),
@@ -14,29 +21,51 @@ export var useAssetsClient = function useAssetsClient(initialParameters) {
14
21
  setWorkspaceId = _useState4[1];
15
22
  var _useState5 = useState(),
16
23
  _useState6 = _slicedToArray(_useState5, 2),
17
- objectSchema = _useState6[0],
18
- setObjectSchema = _useState6[1];
24
+ workspaceError = _useState6[0],
25
+ setWorkspaceError = _useState6[1];
19
26
  var _useState7 = useState(),
20
27
  _useState8 = _slicedToArray(_useState7, 2),
21
- error = _useState8[0],
22
- setError = _useState8[1];
28
+ existingObjectSchema = _useState8[0],
29
+ setExistingObjectSchema = _useState8[1];
30
+ var _useState9 = useState(),
31
+ _useState10 = _slicedToArray(_useState9, 2),
32
+ existingObjectSchemaError = _useState10[0],
33
+ setExistingObjectSchemaError = _useState10[1];
34
+ var _useState11 = useState(),
35
+ _useState12 = _slicedToArray(_useState11, 2),
36
+ objectSchemas = _useState12[0],
37
+ setObjectSchemas = _useState12[1];
38
+ var _useState13 = useState(),
39
+ _useState14 = _slicedToArray(_useState13, 2),
40
+ totalObjectSchemas = _useState14[0],
41
+ setTotalObjectSchemas = _useState14[1];
42
+ var _useState15 = useState(),
43
+ _useState16 = _slicedToArray(_useState15, 2),
44
+ objectSchemasError = _useState16[0],
45
+ setObjectSchemasError = _useState16[1];
46
+
47
+ /*
48
+ * We wrap this in nested try/catch blocks because we want to handle
49
+ * workspaceError/existingObjectSchemaError/objectSchemasError differently
50
+ * if we need to implement more initial data fetching/errors we should look at a store
51
+ */
23
52
  useEffect(function () {
24
53
  _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee() {
25
- var _workspaceId, fetchedObjectSchema;
54
+ var _workspaceId, fetchedObjectSchema, fetchedObjectSchemasResponse;
26
55
  return _regeneratorRuntime.wrap(function _callee$(_context) {
27
56
  while (1) switch (_context.prev = _context.next) {
28
57
  case 0:
29
58
  setLoading(true);
30
- setError(undefined);
59
+ setWorkspaceError(undefined);
31
60
  _context.prev = 2;
32
61
  _context.next = 5;
33
62
  return getWorkspaceId();
34
63
  case 5:
35
64
  _workspaceId = _context.sent;
36
65
  setWorkspaceId(_workspaceId);
37
- // Check schema from initial parameters still exists and fetch name for schema select
66
+ // Check schema from initial parameters still exists and fetch name/permissions for schema select
38
67
  if (!(initialParameters !== null && initialParameters !== void 0 && initialParameters.schemaId)) {
39
- _context.next = 17;
68
+ _context.next = 18;
40
69
  break;
41
70
  }
42
71
  _context.prev = 8;
@@ -44,38 +73,53 @@ export var useAssetsClient = function useAssetsClient(initialParameters) {
44
73
  return fetchObjectSchema(_workspaceId, initialParameters === null || initialParameters === void 0 ? void 0 : initialParameters.schemaId);
45
74
  case 11:
46
75
  fetchedObjectSchema = _context.sent;
47
- setObjectSchema(fetchedObjectSchema);
48
- _context.next = 17;
76
+ setExistingObjectSchema(fetchedObjectSchema);
77
+ _context.next = 18;
49
78
  break;
50
79
  case 15:
51
80
  _context.prev = 15;
52
81
  _context.t0 = _context["catch"](8);
53
- case 17:
54
- _context.next = 22;
82
+ handleAssetsClientErrors(setExistingObjectSchemaError, _context.t0);
83
+ case 18:
84
+ _context.prev = 18;
85
+ _context.next = 21;
86
+ return fetchObjectSchemas(_workspaceId);
87
+ case 21:
88
+ fetchedObjectSchemasResponse = _context.sent;
89
+ setObjectSchemas(fetchedObjectSchemasResponse.values);
90
+ setTotalObjectSchemas(fetchedObjectSchemasResponse.total);
91
+ _context.next = 29;
55
92
  break;
56
- case 19:
57
- _context.prev = 19;
58
- _context.t1 = _context["catch"](2);
59
- if (_context.t1 instanceof Error) {
60
- setError(_context.t1);
61
- } else {
62
- setError(new Error('Unexpected error occured'));
63
- }
64
- case 22:
65
- _context.prev = 22;
93
+ case 26:
94
+ _context.prev = 26;
95
+ _context.t1 = _context["catch"](18);
96
+ handleAssetsClientErrors(setObjectSchemasError, _context.t1);
97
+ case 29:
98
+ _context.next = 34;
99
+ break;
100
+ case 31:
101
+ _context.prev = 31;
102
+ _context.t2 = _context["catch"](2);
103
+ handleAssetsClientErrors(setWorkspaceError, _context.t2);
104
+ case 34:
105
+ _context.prev = 34;
66
106
  setLoading(false);
67
- return _context.finish(22);
68
- case 25:
107
+ return _context.finish(34);
108
+ case 37:
69
109
  case "end":
70
110
  return _context.stop();
71
111
  }
72
- }, _callee, null, [[2, 19, 22, 25], [8, 15]]);
112
+ }, _callee, null, [[2, 31, 34, 37], [8, 15], [18, 26]]);
73
113
  }))();
74
114
  }, [initialParameters]);
75
115
  return {
76
116
  workspaceId: workspaceId,
77
- workspaceError: error,
78
- objectSchema: objectSchema,
117
+ workspaceError: workspaceError,
118
+ existingObjectSchema: existingObjectSchema,
119
+ existingObjectSchemaError: existingObjectSchemaError,
120
+ objectSchemas: objectSchemas,
121
+ totalObjectSchemas: totalObjectSchemas,
122
+ objectSchemasError: objectSchemasError,
79
123
  assetsClientLoading: loading
80
124
  };
81
125
  };