@atlaskit/link-datasource 1.16.4 → 1.17.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +18 -0
- package/dist/cjs/analytics/constants.js +1 -1
- package/dist/cjs/hooks/useDatasourceTableState.js +83 -52
- package/dist/cjs/ui/jira-issues-modal/basic-filters/hooks/useFilterOptions.js +18 -11
- package/dist/cjs/ui/jira-issues-modal/basic-filters/ui/async-popup-select/index.js +62 -17
- package/dist/cjs/ui/jira-issues-modal/basic-filters/ui/async-popup-select/trigger.js +26 -3
- package/dist/cjs/ui/jira-issues-modal/basic-filters/ui/index.js +6 -3
- package/dist/cjs/ui/jira-issues-modal/basic-filters/ui/menu-list/errorMessage.js +39 -2
- package/dist/cjs/ui/jira-issues-modal/basic-filters/ui/menu-list/index.js +6 -2
- package/dist/es2019/analytics/constants.js +1 -1
- package/dist/es2019/hooks/useDatasourceTableState.js +40 -12
- package/dist/es2019/ui/jira-issues-modal/basic-filters/hooks/useFilterOptions.js +5 -1
- package/dist/es2019/ui/jira-issues-modal/basic-filters/ui/async-popup-select/index.js +45 -18
- package/dist/es2019/ui/jira-issues-modal/basic-filters/ui/async-popup-select/trigger.js +23 -3
- package/dist/es2019/ui/jira-issues-modal/basic-filters/ui/index.js +5 -3
- package/dist/es2019/ui/jira-issues-modal/basic-filters/ui/menu-list/errorMessage.js +33 -2
- package/dist/es2019/ui/jira-issues-modal/basic-filters/ui/menu-list/index.js +5 -1
- package/dist/esm/analytics/constants.js +1 -1
- package/dist/esm/hooks/useDatasourceTableState.js +83 -52
- package/dist/esm/ui/jira-issues-modal/basic-filters/hooks/useFilterOptions.js +18 -11
- package/dist/esm/ui/jira-issues-modal/basic-filters/ui/async-popup-select/index.js +63 -18
- package/dist/esm/ui/jira-issues-modal/basic-filters/ui/async-popup-select/trigger.js +26 -3
- package/dist/esm/ui/jira-issues-modal/basic-filters/ui/index.js +7 -4
- package/dist/esm/ui/jira-issues-modal/basic-filters/ui/menu-list/errorMessage.js +36 -2
- package/dist/esm/ui/jira-issues-modal/basic-filters/ui/menu-list/index.js +6 -2
- package/dist/types/analytics/generated/analytics.types.d.ts +8 -1
- package/dist/types/services/cmdbService.utils.d.ts +1 -1
- package/dist/types/ui/jira-issues-modal/basic-filters/hooks/useFilterOptions.d.ts +1 -0
- package/dist/types/ui/jira-issues-modal/basic-filters/ui/async-popup-select/trigger.d.ts +2 -1
- package/dist/types/ui/jira-issues-modal/basic-filters/ui/menu-list/errorMessage.d.ts +6 -1
- package/dist/types/ui/jira-issues-modal/basic-filters/ui/menu-list/index.d.ts +3 -1
- package/dist/types-ts4.5/analytics/generated/analytics.types.d.ts +8 -1
- package/dist/types-ts4.5/services/cmdbService.utils.d.ts +1 -1
- package/dist/types-ts4.5/ui/jira-issues-modal/basic-filters/hooks/useFilterOptions.d.ts +1 -0
- package/dist/types-ts4.5/ui/jira-issues-modal/basic-filters/ui/async-popup-select/trigger.d.ts +2 -1
- package/dist/types-ts4.5/ui/jira-issues-modal/basic-filters/ui/menu-list/errorMessage.d.ts +6 -1
- package/dist/types-ts4.5/ui/jira-issues-modal/basic-filters/ui/menu-list/index.d.ts +3 -1
- package/package.json +3 -2
|
@@ -10,8 +10,13 @@ export const useDatasourceTableState = ({
|
|
|
10
10
|
const {
|
|
11
11
|
fireEvent
|
|
12
12
|
} = useDatasourceAnalyticsEvents();
|
|
13
|
+
const idFieldCount = 1;
|
|
14
|
+
const keyFieldCount = 1;
|
|
13
15
|
const [defaultVisibleColumnKeys, setDefaultVisibleColumnKeys] = useState([]);
|
|
14
16
|
const [lastRequestedFieldKeys, setLastRequestedFieldKeys] = useState([]);
|
|
17
|
+
const [fullSchema, setFullSchema] = useState({
|
|
18
|
+
properties: []
|
|
19
|
+
});
|
|
15
20
|
const [status, setStatus] = useState('empty');
|
|
16
21
|
const [responseItems, setResponseItems] = useState([]);
|
|
17
22
|
const [hasNextPage, setHasNextPage] = useState(true);
|
|
@@ -56,19 +61,38 @@ export const useDatasourceTableState = ({
|
|
|
56
61
|
setStatus('rejected');
|
|
57
62
|
}
|
|
58
63
|
}, [columns, datasourceId, getDatasourceDetails, parameters]);
|
|
59
|
-
const applySchemaProperties = useCallback(
|
|
60
|
-
|
|
61
|
-
|
|
64
|
+
const applySchemaProperties = useCallback((schema, fieldKeys) => {
|
|
65
|
+
let {
|
|
66
|
+
properties,
|
|
67
|
+
defaultProperties = []
|
|
68
|
+
} = schema;
|
|
69
|
+
let propertiesToBeUsed = properties;
|
|
70
|
+
const propertyKeysToBeUsed = Array.isArray(fieldKeys) && fieldKeys.length > 0 ? fieldKeys : defaultProperties;
|
|
71
|
+
if (fieldKeys.length > 0 || defaultProperties.length > 0) {
|
|
72
|
+
propertiesToBeUsed = properties.filter(property => {
|
|
73
|
+
return propertyKeysToBeUsed.includes(property.key);
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/*Jira adds identifier fields like id and key to all data responses
|
|
78
|
+
Since defaultProperties already send back the keyField, we are accounting only
|
|
79
|
+
for the idField when we are using defaulProperties
|
|
80
|
+
*/
|
|
81
|
+
if (properties.length > fieldKeys.length + idFieldCount + keyFieldCount && properties.length > defaultProperties.length + idFieldCount) {
|
|
82
|
+
setFullSchema(schema);
|
|
83
|
+
}
|
|
84
|
+
if (!isEqual(columns, propertiesToBeUsed)) {
|
|
85
|
+
setColumns(propertiesToBeUsed);
|
|
62
86
|
}
|
|
63
|
-
const
|
|
87
|
+
const newProperties = propertiesToBeUsed.map(prop => prop.key);
|
|
64
88
|
|
|
65
89
|
// when loading for the first time, we will need to set default visible props as /data does not give you that info
|
|
66
90
|
// also, since we dont pass any fields, we will need to set this info as lastRequestedFieldKeys
|
|
67
|
-
if (!isEqual(defaultVisibleColumnKeys,
|
|
68
|
-
setDefaultVisibleColumnKeys(
|
|
91
|
+
if (!isEqual(defaultVisibleColumnKeys, newProperties)) {
|
|
92
|
+
setDefaultVisibleColumnKeys(newProperties);
|
|
69
93
|
}
|
|
70
|
-
if (!isEqual(lastRequestedFieldKeys,
|
|
71
|
-
setLastRequestedFieldKeys(
|
|
94
|
+
if (!isEqual(lastRequestedFieldKeys, newProperties)) {
|
|
95
|
+
setLastRequestedFieldKeys(newProperties);
|
|
72
96
|
}
|
|
73
97
|
}, [columns, defaultVisibleColumnKeys, lastRequestedFieldKeys]);
|
|
74
98
|
const onNextPage = useCallback(async (requestInfo = {}) => {
|
|
@@ -80,12 +104,13 @@ export const useDatasourceTableState = ({
|
|
|
80
104
|
shouldRequestFirstPage,
|
|
81
105
|
shouldForceRequest = false
|
|
82
106
|
} = requestInfo;
|
|
107
|
+
const isFullSchemaLoaded = fullSchema.properties.length > 0;
|
|
83
108
|
const datasourceDataRequest = {
|
|
84
109
|
parameters,
|
|
85
110
|
pageSize: DEFAULT_GET_DATASOURCE_DATA_PAGE_SIZE,
|
|
86
111
|
pageCursor: shouldRequestFirstPage ? undefined : nextCursor,
|
|
87
112
|
fields: fieldKeys,
|
|
88
|
-
includeSchema: isSchemaFromData
|
|
113
|
+
includeSchema: isFullSchemaLoaded ? false : isSchemaFromData
|
|
89
114
|
};
|
|
90
115
|
setStatus('loading');
|
|
91
116
|
try {
|
|
@@ -120,8 +145,8 @@ export const useDatasourceTableState = ({
|
|
|
120
145
|
if (fieldKeys.length > 0) {
|
|
121
146
|
setLastRequestedFieldKeys(fieldKeys);
|
|
122
147
|
}
|
|
123
|
-
if (isSchemaFromData && schema && items.length > 0) {
|
|
124
|
-
applySchemaProperties(schema
|
|
148
|
+
if ((isSchemaFromData && schema || fullSchema.properties.length > 0) && items.length > 0) {
|
|
149
|
+
applySchemaProperties(schema || fullSchema, fieldKeys);
|
|
125
150
|
}
|
|
126
151
|
const isUserLoadingNextPage = (responseItems === null || responseItems === void 0 ? void 0 : responseItems.length) !== 0 && !shouldRequestFirstPage;
|
|
127
152
|
if (isUserLoadingNextPage) {
|
|
@@ -141,7 +166,7 @@ export const useDatasourceTableState = ({
|
|
|
141
166
|
}
|
|
142
167
|
setStatus('rejected');
|
|
143
168
|
}
|
|
144
|
-
}, [parameters, fieldKeys, nextCursor, getDatasourceData, datasourceId, responseItems === null || responseItems === void 0 ? void 0 : responseItems.length, applySchemaProperties, fireEvent]);
|
|
169
|
+
}, [parameters, fieldKeys, nextCursor, getDatasourceData, datasourceId, responseItems === null || responseItems === void 0 ? void 0 : responseItems.length, applySchemaProperties, fireEvent, fullSchema]);
|
|
145
170
|
const reset = useCallback(options => {
|
|
146
171
|
setStatus('empty');
|
|
147
172
|
setResponseItems([]);
|
|
@@ -149,6 +174,9 @@ export const useDatasourceTableState = ({
|
|
|
149
174
|
setNextCursor(undefined);
|
|
150
175
|
setTotalCount(undefined);
|
|
151
176
|
setLastRequestedFieldKeys([]);
|
|
177
|
+
setFullSchema({
|
|
178
|
+
properties: []
|
|
179
|
+
});
|
|
152
180
|
setShouldForceRequest((options === null || options === void 0 ? void 0 : options.shouldForceRequest) || false);
|
|
153
181
|
if (options !== null && options !== void 0 && options.shouldResetColumns) {
|
|
154
182
|
setColumns([]);
|
|
@@ -8,6 +8,7 @@ export const useFilterOptions = ({
|
|
|
8
8
|
const [filterOptions, setFilterOptions] = useState([]);
|
|
9
9
|
const [totalCount, setTotalCount] = useState(0);
|
|
10
10
|
const [status, setStatus] = useState('empty');
|
|
11
|
+
const [errors, setErrors] = useState([]);
|
|
11
12
|
const [nextPageCursor, setNextPageCursor] = useState(undefined);
|
|
12
13
|
const initialData = useRef();
|
|
13
14
|
const {
|
|
@@ -33,6 +34,7 @@ export const useFilterOptions = ({
|
|
|
33
34
|
});
|
|
34
35
|
if (response.errors && response.errors.length > 0) {
|
|
35
36
|
setStatus('rejected');
|
|
37
|
+
setErrors(response.errors);
|
|
36
38
|
return;
|
|
37
39
|
}
|
|
38
40
|
if (isNewSearch) {
|
|
@@ -51,6 +53,7 @@ export const useFilterOptions = ({
|
|
|
51
53
|
setNextPageCursor(mapFieldValuesToPageCursor(response));
|
|
52
54
|
setStatus('resolved');
|
|
53
55
|
} catch (error) {
|
|
56
|
+
setErrors([error]);
|
|
54
57
|
setStatus('rejected');
|
|
55
58
|
}
|
|
56
59
|
}, [cloudId, filterOptions, filterType, getFieldValues]);
|
|
@@ -59,6 +62,7 @@ export const useFilterOptions = ({
|
|
|
59
62
|
fetchFilterOptions,
|
|
60
63
|
totalCount,
|
|
61
64
|
pageCursor: nextPageCursor,
|
|
62
|
-
status
|
|
65
|
+
status,
|
|
66
|
+
errors: status === 'rejected' ? errors : []
|
|
63
67
|
};
|
|
64
68
|
};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import _extends from "@babel/runtime/helpers/extends";
|
|
2
|
-
import React, { useCallback, useEffect,
|
|
2
|
+
import React, { useCallback, useEffect, useState } from 'react';
|
|
3
3
|
import { useIntl } from 'react-intl-next';
|
|
4
4
|
import { useDebouncedCallback } from 'use-debounce';
|
|
5
5
|
import { CheckboxOption, PopupSelect } from '@atlaskit/select';
|
|
@@ -24,15 +24,16 @@ const AsyncPopupSelect = ({
|
|
|
24
24
|
const {
|
|
25
25
|
formatMessage
|
|
26
26
|
} = useIntl();
|
|
27
|
-
const pickerRef = useRef(null);
|
|
28
27
|
const [searchTerm, setSearchTerm] = useState('');
|
|
29
28
|
const [selectedOptions, setSelectedOptions] = useState(selection);
|
|
29
|
+
const [sortedOptions, setSortedOptions] = useState(selectedOptions);
|
|
30
30
|
const {
|
|
31
31
|
filterOptions,
|
|
32
32
|
fetchFilterOptions,
|
|
33
33
|
totalCount,
|
|
34
34
|
status,
|
|
35
|
-
pageCursor
|
|
35
|
+
pageCursor,
|
|
36
|
+
errors
|
|
36
37
|
} = useFilterOptions({
|
|
37
38
|
filterType,
|
|
38
39
|
cloudId
|
|
@@ -52,14 +53,32 @@ const AsyncPopupSelect = ({
|
|
|
52
53
|
setSelectedOptions(newValue);
|
|
53
54
|
onSelectionChange(newValue);
|
|
54
55
|
};
|
|
55
|
-
const
|
|
56
|
-
if (
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
56
|
+
const sortOptionsOnPopupOpen = useCallback(() => {
|
|
57
|
+
if (selectedOptions.length === 0) {
|
|
58
|
+
setSortedOptions(filterOptions);
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
const nonSelectedOptions = filterOptions.filter(option => !selectedOptions.find(selectedOption => selectedOption.value === option.value));
|
|
62
|
+
const newOptions = [...selectedOptions, ...nonSelectedOptions];
|
|
63
|
+
setSortedOptions(newOptions);
|
|
64
|
+
}, [selectedOptions, filterOptions]);
|
|
65
|
+
const sortOptionsOnResolve = useCallback(() => {
|
|
66
|
+
const newOptions = filterOptions.filter(option => !sortedOptions.find(sortedOption => sortedOption.value === option.value));
|
|
67
|
+
let shouldSetSortOptions = false;
|
|
68
|
+
if (sortedOptions.length !== filterOptions.length) {
|
|
69
|
+
shouldSetSortOptions = true;
|
|
70
|
+
} else {
|
|
71
|
+
sortedOptions.forEach(sortedOption => {
|
|
72
|
+
if (!filterOptions.some(filterOption => filterOption.value === sortedOption.value)) {
|
|
73
|
+
shouldSetSortOptions = true;
|
|
74
|
+
}
|
|
60
75
|
});
|
|
61
76
|
}
|
|
62
|
-
|
|
77
|
+
if (shouldSetSortOptions) {
|
|
78
|
+
const sortedOptionsFiltered = sortedOptions.filter(sortedOption => filterOptions.some(filterOption => filterOption.value === sortedOption.value));
|
|
79
|
+
setSortedOptions([...sortedOptionsFiltered, ...newOptions]);
|
|
80
|
+
}
|
|
81
|
+
}, [filterOptions, sortedOptions]);
|
|
63
82
|
const handleShowMore = useCallback(() => {
|
|
64
83
|
if (pageCursor) {
|
|
65
84
|
fetchFilterOptions({
|
|
@@ -68,28 +87,34 @@ const AsyncPopupSelect = ({
|
|
|
68
87
|
});
|
|
69
88
|
}
|
|
70
89
|
}, [fetchFilterOptions, pageCursor, searchTerm]);
|
|
90
|
+
const handleOpenPopup = useCallback(() => {
|
|
91
|
+
if (status === 'empty' || status === 'rejected') {
|
|
92
|
+
// 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
|
|
93
|
+
fetchFilterOptions({
|
|
94
|
+
searchString: searchTerm
|
|
95
|
+
});
|
|
96
|
+
} else if (status === 'resolved') {
|
|
97
|
+
sortOptionsOnPopupOpen();
|
|
98
|
+
}
|
|
99
|
+
}, [fetchFilterOptions, searchTerm, sortOptionsOnPopupOpen, status]);
|
|
71
100
|
useEffect(() => {
|
|
72
101
|
if (status === 'resolved') {
|
|
73
|
-
|
|
74
|
-
// necessary to refocus the search input after the loading state
|
|
75
|
-
pickerRef === null || pickerRef === void 0 ? void 0 : (_pickerRef$current = pickerRef.current) === null || _pickerRef$current === void 0 ? void 0 : (_pickerRef$current$se = _pickerRef$current.selectRef) === null || _pickerRef$current$se === void 0 ? void 0 : (_pickerRef$current$se2 = _pickerRef$current$se.inputRef) === null || _pickerRef$current$se2 === void 0 ? void 0 : _pickerRef$current$se2.focus();
|
|
102
|
+
sortOptionsOnResolve();
|
|
76
103
|
}
|
|
77
|
-
}, [status]);
|
|
104
|
+
}, [sortOptionsOnResolve, status]);
|
|
78
105
|
const filterOptionsLength = filterOptions.length;
|
|
79
106
|
const isError = status === 'rejected';
|
|
80
107
|
const isLoading = status === 'loading' || status === 'empty';
|
|
81
108
|
const isLoadingMore = status === 'loadingMore';
|
|
82
109
|
const isEmpty = status === 'resolved' && filterOptionsLength === 0;
|
|
110
|
+
const popupSelectOptions = isLoading || isError ? [] : sortedOptions; // if not set to [], then on loading, no loading UI will be shown
|
|
83
111
|
const areAllResultsLoaded = filterOptions.length === totalCount;
|
|
84
112
|
const shouldShowFooter = (status === 'resolved' || isLoadingMore) && filterOptions.length > 0; // footer should not disappear when there is an inline spinner for loading more data
|
|
85
113
|
const shouldDisplayShowMoreButton = status === 'resolved' && !!pageCursor && !areAllResultsLoaded;
|
|
86
|
-
const options = isLoading || isError ? [] : filterOptions; // if not set to [], for eg: on loading, no loading UI will be shown
|
|
87
|
-
|
|
88
114
|
return /*#__PURE__*/React.createElement(PopupSelect, {
|
|
89
115
|
isMulti: true,
|
|
90
116
|
maxMenuWidth: 300,
|
|
91
117
|
minMenuWidth: 300,
|
|
92
|
-
ref: pickerRef,
|
|
93
118
|
testId: "jlol-basic-filter-popup-select",
|
|
94
119
|
inputId: "jlol-basic-filter-popup-select--input"
|
|
95
120
|
/*
|
|
@@ -114,7 +139,8 @@ const AsyncPopupSelect = ({
|
|
|
114
139
|
isLoading: isLoading,
|
|
115
140
|
isLoadingMore: isLoadingMore,
|
|
116
141
|
showMore: shouldDisplayShowMoreButton,
|
|
117
|
-
handleShowMore: handleShowMore
|
|
142
|
+
handleShowMore: handleShowMore,
|
|
143
|
+
errors: errors
|
|
118
144
|
})),
|
|
119
145
|
DropdownIndicator: CustomDropdownIndicator,
|
|
120
146
|
LoadingIndicator: undefined,
|
|
@@ -122,7 +148,7 @@ const AsyncPopupSelect = ({
|
|
|
122
148
|
IndicatorSeparator: undefined // disables the | separator between search input and icon
|
|
123
149
|
},
|
|
124
150
|
|
|
125
|
-
options:
|
|
151
|
+
options: popupSelectOptions,
|
|
126
152
|
value: selectedOptions,
|
|
127
153
|
filterOption: noFilterOptions,
|
|
128
154
|
formatOptionLabel: formatOptionLabel,
|
|
@@ -133,6 +159,7 @@ const AsyncPopupSelect = ({
|
|
|
133
159
|
...triggerProps
|
|
134
160
|
}) => /*#__PURE__*/React.createElement(PopupTrigger, _extends({}, triggerProps, {
|
|
135
161
|
filterType: filterType,
|
|
162
|
+
selectedOptions: selectedOptions,
|
|
136
163
|
isSelected: isOpen,
|
|
137
164
|
onClick: handleOpenPopup,
|
|
138
165
|
isDisabled: isDisabled
|
|
@@ -1,24 +1,44 @@
|
|
|
1
1
|
import React, { forwardRef } from 'react';
|
|
2
2
|
import { FormattedMessage } from 'react-intl-next';
|
|
3
|
+
import Badge from '@atlaskit/badge';
|
|
3
4
|
import Button from '@atlaskit/button/standard-button';
|
|
4
5
|
import ChevronDownIcon from '@atlaskit/icon/glyph/chevron-down';
|
|
6
|
+
import { Box, Flex, xcss } from '@atlaskit/primitives';
|
|
5
7
|
import { asyncPopupSelectMessages } from './messages';
|
|
8
|
+
const triggerButtonLabelStyles = xcss({
|
|
9
|
+
textOverflow: 'ellipsis',
|
|
10
|
+
overflow: 'hidden',
|
|
11
|
+
maxWidth: '150px'
|
|
12
|
+
});
|
|
13
|
+
const badgeStyles = xcss({
|
|
14
|
+
marginLeft: 'space.050'
|
|
15
|
+
});
|
|
6
16
|
const PopupTrigger = /*#__PURE__*/forwardRef(({
|
|
7
17
|
filterType,
|
|
8
18
|
isSelected,
|
|
9
19
|
isDisabled,
|
|
10
|
-
onClick
|
|
20
|
+
onClick,
|
|
21
|
+
selectedOptions
|
|
11
22
|
}, ref) => {
|
|
23
|
+
const [firstOption] = selectedOptions || [];
|
|
24
|
+
const hasOptions = selectedOptions && selectedOptions.length > 0;
|
|
12
25
|
return /*#__PURE__*/React.createElement(Button, {
|
|
13
26
|
ref: ref,
|
|
14
27
|
appearance: "default",
|
|
15
|
-
isSelected: isSelected,
|
|
28
|
+
isSelected: isSelected || hasOptions,
|
|
16
29
|
isDisabled: isDisabled,
|
|
17
30
|
onClick: onClick,
|
|
18
31
|
testId: `jlol-basic-filter-${filterType}-trigger`,
|
|
19
32
|
iconAfter: /*#__PURE__*/React.createElement(ChevronDownIcon, {
|
|
20
33
|
label: ""
|
|
21
34
|
})
|
|
22
|
-
}, /*#__PURE__*/React.createElement(
|
|
35
|
+
}, /*#__PURE__*/React.createElement(Flex, null, /*#__PURE__*/React.createElement(Box, {
|
|
36
|
+
xcss: triggerButtonLabelStyles
|
|
37
|
+
}, /*#__PURE__*/React.createElement(FormattedMessage, asyncPopupSelectMessages[`${filterType}Label`]), firstOption && /*#__PURE__*/React.createElement(React.Fragment, null, ": ", firstOption.label)), selectedOptions && selectedOptions.length > 1 && /*#__PURE__*/React.createElement(Flex, {
|
|
38
|
+
xcss: badgeStyles,
|
|
39
|
+
alignItems: "center"
|
|
40
|
+
}, /*#__PURE__*/React.createElement(Badge, {
|
|
41
|
+
appearance: "primary"
|
|
42
|
+
}, "+", selectedOptions.length - 1))));
|
|
23
43
|
});
|
|
24
44
|
export default PopupTrigger;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React, { useEffect, useState } from 'react';
|
|
1
|
+
import React, { useCallback, useEffect, useState } from 'react';
|
|
2
2
|
import { Flex, xcss } from '@atlaskit/primitives';
|
|
3
3
|
import { isValidJql } from '../utils';
|
|
4
4
|
import AsyncPopupSelect from './async-popup-select';
|
|
@@ -10,13 +10,15 @@ const BasicFilterContainer = ({
|
|
|
10
10
|
jql,
|
|
11
11
|
cloudId
|
|
12
12
|
}) => {
|
|
13
|
-
const [selection] = useState([]);
|
|
13
|
+
const [selection, setSelection] = useState([]);
|
|
14
14
|
useEffect(() => {
|
|
15
15
|
if (isValidJql(jql)) {
|
|
16
16
|
// hydrate hook call goes in here
|
|
17
17
|
}
|
|
18
18
|
}, [jql]);
|
|
19
|
-
const handleSelectionChange = (
|
|
19
|
+
const handleSelectionChange = useCallback(options => {
|
|
20
|
+
setSelection(options);
|
|
21
|
+
}, [setSelection]);
|
|
20
22
|
return /*#__PURE__*/React.createElement(Flex, {
|
|
21
23
|
xcss: basicFilterContainerStyles,
|
|
22
24
|
gap: "space.100",
|
|
@@ -1,9 +1,40 @@
|
|
|
1
|
-
import React from 'react';
|
|
1
|
+
import React, { useEffect } from 'react';
|
|
2
|
+
import { useDebouncedCallback } from 'use-debounce';
|
|
2
3
|
import ErrorIcon from '@atlaskit/icon/glyph/error';
|
|
3
4
|
import { N500 } from '@atlaskit/theme/colors';
|
|
5
|
+
import { useDatasourceAnalyticsEvents } from '../../../../../analytics';
|
|
6
|
+
import { SEARCH_DEBOUNCE_MS } from '../async-popup-select';
|
|
4
7
|
import { asyncPopupSelectMessages } from './messages';
|
|
5
8
|
import CustomSelectMessage from './selectMessage';
|
|
6
|
-
const
|
|
9
|
+
const getErrorReasonType = errors => {
|
|
10
|
+
const [error] = errors || [];
|
|
11
|
+
if (error instanceof Error) {
|
|
12
|
+
return 'network';
|
|
13
|
+
}
|
|
14
|
+
if (errors && errors.length > 0) {
|
|
15
|
+
return 'agg';
|
|
16
|
+
}
|
|
17
|
+
return 'unknown';
|
|
18
|
+
};
|
|
19
|
+
const CustomErrorMessage = ({
|
|
20
|
+
filterType,
|
|
21
|
+
errors
|
|
22
|
+
}) => {
|
|
23
|
+
const {
|
|
24
|
+
fireEvent
|
|
25
|
+
} = useDatasourceAnalyticsEvents();
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Debounce is required because our search is debounced
|
|
29
|
+
* ref: ./noOptionsMessage.tsx
|
|
30
|
+
*/
|
|
31
|
+
const [debouncedAnalyticsCallback] = useDebouncedCallback(() => {
|
|
32
|
+
fireEvent('ui.error.shown.basicSearchDropdown', {
|
|
33
|
+
filterType,
|
|
34
|
+
reason: getErrorReasonType(errors)
|
|
35
|
+
});
|
|
36
|
+
}, SEARCH_DEBOUNCE_MS);
|
|
37
|
+
useEffect(debouncedAnalyticsCallback, [debouncedAnalyticsCallback]);
|
|
7
38
|
return /*#__PURE__*/React.createElement(CustomSelectMessage, {
|
|
8
39
|
icon: /*#__PURE__*/React.createElement(ErrorIcon, {
|
|
9
40
|
primaryColor: `var(--ds-icon, ${N500})`,
|
|
@@ -12,6 +12,7 @@ const CustomMenuList = ({
|
|
|
12
12
|
isLoadingMore,
|
|
13
13
|
isError,
|
|
14
14
|
isEmpty,
|
|
15
|
+
errors,
|
|
15
16
|
showMore,
|
|
16
17
|
handleShowMore,
|
|
17
18
|
children,
|
|
@@ -29,7 +30,10 @@ const CustomMenuList = ({
|
|
|
29
30
|
return /*#__PURE__*/React.createElement(CustomDropdownLoadingMessage, null);
|
|
30
31
|
}
|
|
31
32
|
if (isError) {
|
|
32
|
-
return /*#__PURE__*/React.createElement(CustomErrorMessage,
|
|
33
|
+
return /*#__PURE__*/React.createElement(CustomErrorMessage, {
|
|
34
|
+
filterType: filterType,
|
|
35
|
+
errors: errors
|
|
36
|
+
});
|
|
33
37
|
}
|
|
34
38
|
if (isEmpty) {
|
|
35
39
|
return /*#__PURE__*/React.createElement(CustomNoOptionsMessage, {
|
|
@@ -13,6 +13,8 @@ export var useDatasourceTableState = function useDatasourceTableState(_ref) {
|
|
|
13
13
|
fieldKeys = _ref$fieldKeys === void 0 ? [] : _ref$fieldKeys;
|
|
14
14
|
var _useDatasourceAnalyti = useDatasourceAnalyticsEvents(),
|
|
15
15
|
fireEvent = _useDatasourceAnalyti.fireEvent;
|
|
16
|
+
var idFieldCount = 1;
|
|
17
|
+
var keyFieldCount = 1;
|
|
16
18
|
var _useState = useState([]),
|
|
17
19
|
_useState2 = _slicedToArray(_useState, 2),
|
|
18
20
|
defaultVisibleColumnKeys = _useState2[0],
|
|
@@ -21,42 +23,48 @@ export var useDatasourceTableState = function useDatasourceTableState(_ref) {
|
|
|
21
23
|
_useState4 = _slicedToArray(_useState3, 2),
|
|
22
24
|
lastRequestedFieldKeys = _useState4[0],
|
|
23
25
|
setLastRequestedFieldKeys = _useState4[1];
|
|
24
|
-
var _useState5 = useState(
|
|
26
|
+
var _useState5 = useState({
|
|
27
|
+
properties: []
|
|
28
|
+
}),
|
|
25
29
|
_useState6 = _slicedToArray(_useState5, 2),
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
var _useState7 = useState(
|
|
30
|
+
fullSchema = _useState6[0],
|
|
31
|
+
setFullSchema = _useState6[1];
|
|
32
|
+
var _useState7 = useState('empty'),
|
|
29
33
|
_useState8 = _slicedToArray(_useState7, 2),
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
var _useState9 = useState(
|
|
34
|
+
status = _useState8[0],
|
|
35
|
+
setStatus = _useState8[1];
|
|
36
|
+
var _useState9 = useState([]),
|
|
33
37
|
_useState10 = _slicedToArray(_useState9, 2),
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
var _useState11 = useState(
|
|
38
|
+
responseItems = _useState10[0],
|
|
39
|
+
setResponseItems = _useState10[1];
|
|
40
|
+
var _useState11 = useState(true),
|
|
37
41
|
_useState12 = _slicedToArray(_useState11, 2),
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
var _useState13 = useState(
|
|
42
|
+
hasNextPage = _useState12[0],
|
|
43
|
+
setHasNextPage = _useState12[1];
|
|
44
|
+
var _useState13 = useState(undefined),
|
|
41
45
|
_useState14 = _slicedToArray(_useState13, 2),
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
var _useState15 = useState(
|
|
46
|
+
nextCursor = _useState14[0],
|
|
47
|
+
setNextCursor = _useState14[1];
|
|
48
|
+
var _useState15 = useState([]),
|
|
45
49
|
_useState16 = _slicedToArray(_useState15, 2),
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
var _useState17 = useState(
|
|
50
|
+
columns = _useState16[0],
|
|
51
|
+
setColumns = _useState16[1];
|
|
52
|
+
var _useState17 = useState(undefined),
|
|
49
53
|
_useState18 = _slicedToArray(_useState17, 2),
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
var _useState19 = useState(
|
|
54
|
+
totalCount = _useState18[0],
|
|
55
|
+
setTotalCount = _useState18[1];
|
|
56
|
+
var _useState19 = useState(false),
|
|
53
57
|
_useState20 = _slicedToArray(_useState19, 2),
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
var _useState21 = useState(),
|
|
58
|
+
shouldForceRequest = _useState20[0],
|
|
59
|
+
setShouldForceRequest = _useState20[1];
|
|
60
|
+
var _useState21 = useState([]),
|
|
57
61
|
_useState22 = _slicedToArray(_useState21, 2),
|
|
58
|
-
|
|
59
|
-
|
|
62
|
+
destinationObjectTypes = _useState22[0],
|
|
63
|
+
setDestinationObjectTypes = _useState22[1];
|
|
64
|
+
var _useState23 = useState(),
|
|
65
|
+
_useState24 = _slicedToArray(_useState23, 2),
|
|
66
|
+
extensionKey = _useState24[0],
|
|
67
|
+
setExtensionKey = _useState24[1];
|
|
60
68
|
var _useDatasourceClientE = useDatasourceClientExtension(),
|
|
61
69
|
getDatasourceData = _useDatasourceClientE.getDatasourceData,
|
|
62
70
|
getDatasourceDetails = _useDatasourceClientE.getDatasourceDetails;
|
|
@@ -114,21 +122,39 @@ export var useDatasourceTableState = function useDatasourceTableState(_ref) {
|
|
|
114
122
|
}
|
|
115
123
|
}, _callee, null, [[2, 17]]);
|
|
116
124
|
})), [columns, datasourceId, getDatasourceDetails, parameters]);
|
|
117
|
-
var applySchemaProperties = useCallback(function (
|
|
118
|
-
|
|
119
|
-
|
|
125
|
+
var applySchemaProperties = useCallback(function (schema, fieldKeys) {
|
|
126
|
+
var properties = schema.properties,
|
|
127
|
+
_schema$defaultProper = schema.defaultProperties,
|
|
128
|
+
defaultProperties = _schema$defaultProper === void 0 ? [] : _schema$defaultProper;
|
|
129
|
+
var propertiesToBeUsed = properties;
|
|
130
|
+
var propertyKeysToBeUsed = Array.isArray(fieldKeys) && fieldKeys.length > 0 ? fieldKeys : defaultProperties;
|
|
131
|
+
if (fieldKeys.length > 0 || defaultProperties.length > 0) {
|
|
132
|
+
propertiesToBeUsed = properties.filter(function (property) {
|
|
133
|
+
return propertyKeysToBeUsed.includes(property.key);
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/*Jira adds identifier fields like id and key to all data responses
|
|
138
|
+
Since defaultProperties already send back the keyField, we are accounting only
|
|
139
|
+
for the idField when we are using defaulProperties
|
|
140
|
+
*/
|
|
141
|
+
if (properties.length > fieldKeys.length + idFieldCount + keyFieldCount && properties.length > defaultProperties.length + idFieldCount) {
|
|
142
|
+
setFullSchema(schema);
|
|
120
143
|
}
|
|
121
|
-
|
|
144
|
+
if (!isEqual(columns, propertiesToBeUsed)) {
|
|
145
|
+
setColumns(propertiesToBeUsed);
|
|
146
|
+
}
|
|
147
|
+
var newProperties = propertiesToBeUsed.map(function (prop) {
|
|
122
148
|
return prop.key;
|
|
123
149
|
});
|
|
124
150
|
|
|
125
151
|
// when loading for the first time, we will need to set default visible props as /data does not give you that info
|
|
126
152
|
// also, since we dont pass any fields, we will need to set this info as lastRequestedFieldKeys
|
|
127
|
-
if (!isEqual(defaultVisibleColumnKeys,
|
|
128
|
-
setDefaultVisibleColumnKeys(
|
|
153
|
+
if (!isEqual(defaultVisibleColumnKeys, newProperties)) {
|
|
154
|
+
setDefaultVisibleColumnKeys(newProperties);
|
|
129
155
|
}
|
|
130
|
-
if (!isEqual(lastRequestedFieldKeys,
|
|
131
|
-
setLastRequestedFieldKeys(
|
|
156
|
+
if (!isEqual(lastRequestedFieldKeys, newProperties)) {
|
|
157
|
+
setLastRequestedFieldKeys(newProperties);
|
|
132
158
|
}
|
|
133
159
|
}, [columns, defaultVisibleColumnKeys, lastRequestedFieldKeys]);
|
|
134
160
|
var onNextPage = useCallback( /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee2() {
|
|
@@ -138,6 +164,7 @@ export var useDatasourceTableState = function useDatasourceTableState(_ref) {
|
|
|
138
164
|
shouldRequestFirstPage,
|
|
139
165
|
_requestInfo$shouldFo,
|
|
140
166
|
shouldForceRequest,
|
|
167
|
+
isFullSchemaLoaded,
|
|
141
168
|
datasourceDataRequest,
|
|
142
169
|
_yield$getDatasourceD2,
|
|
143
170
|
_yield$getDatasourceD3,
|
|
@@ -164,18 +191,19 @@ export var useDatasourceTableState = function useDatasourceTableState(_ref) {
|
|
|
164
191
|
return _context2.abrupt("return");
|
|
165
192
|
case 3:
|
|
166
193
|
_requestInfo$isSchema = requestInfo.isSchemaFromData, isSchemaFromData = _requestInfo$isSchema === void 0 ? true : _requestInfo$isSchema, shouldRequestFirstPage = requestInfo.shouldRequestFirstPage, _requestInfo$shouldFo = requestInfo.shouldForceRequest, shouldForceRequest = _requestInfo$shouldFo === void 0 ? false : _requestInfo$shouldFo;
|
|
194
|
+
isFullSchemaLoaded = fullSchema.properties.length > 0;
|
|
167
195
|
datasourceDataRequest = {
|
|
168
196
|
parameters: parameters,
|
|
169
197
|
pageSize: DEFAULT_GET_DATASOURCE_DATA_PAGE_SIZE,
|
|
170
198
|
pageCursor: shouldRequestFirstPage ? undefined : nextCursor,
|
|
171
199
|
fields: fieldKeys,
|
|
172
|
-
includeSchema: isSchemaFromData
|
|
200
|
+
includeSchema: isFullSchemaLoaded ? false : isSchemaFromData
|
|
173
201
|
};
|
|
174
202
|
setStatus('loading');
|
|
175
|
-
_context2.prev =
|
|
176
|
-
_context2.next =
|
|
203
|
+
_context2.prev = 7;
|
|
204
|
+
_context2.next = 10;
|
|
177
205
|
return getDatasourceData(datasourceId, datasourceDataRequest, shouldForceRequest);
|
|
178
|
-
case
|
|
206
|
+
case 10:
|
|
179
207
|
_yield$getDatasourceD2 = _context2.sent;
|
|
180
208
|
_yield$getDatasourceD3 = _yield$getDatasourceD2.meta;
|
|
181
209
|
access = _yield$getDatasourceD3.access;
|
|
@@ -187,12 +215,12 @@ export var useDatasourceTableState = function useDatasourceTableState(_ref) {
|
|
|
187
215
|
_totalCount = _yield$getDatasourceD4.totalCount;
|
|
188
216
|
schema = _yield$getDatasourceD4.schema;
|
|
189
217
|
if (!(access === 'forbidden' || access === 'unauthorized')) {
|
|
190
|
-
_context2.next =
|
|
218
|
+
_context2.next = 23;
|
|
191
219
|
break;
|
|
192
220
|
}
|
|
193
221
|
setStatus('unauthorized');
|
|
194
222
|
return _context2.abrupt("return");
|
|
195
|
-
case
|
|
223
|
+
case 23:
|
|
196
224
|
setExtensionKey(_extensionKey);
|
|
197
225
|
setDestinationObjectTypes(_destinationObjectTypes);
|
|
198
226
|
setTotalCount(_totalCount);
|
|
@@ -207,8 +235,8 @@ export var useDatasourceTableState = function useDatasourceTableState(_ref) {
|
|
|
207
235
|
if (fieldKeys.length > 0) {
|
|
208
236
|
setLastRequestedFieldKeys(fieldKeys);
|
|
209
237
|
}
|
|
210
|
-
if (isSchemaFromData && schema && items.length > 0) {
|
|
211
|
-
applySchemaProperties(schema
|
|
238
|
+
if ((isSchemaFromData && schema || fullSchema.properties.length > 0) && items.length > 0) {
|
|
239
|
+
applySchemaProperties(schema || fullSchema, fieldKeys);
|
|
212
240
|
}
|
|
213
241
|
isUserLoadingNextPage = (responseItems === null || responseItems === void 0 ? void 0 : responseItems.length) !== 0 && !shouldRequestFirstPage;
|
|
214
242
|
if (isUserLoadingNextPage) {
|
|
@@ -221,25 +249,25 @@ export var useDatasourceTableState = function useDatasourceTableState(_ref) {
|
|
|
221
249
|
});
|
|
222
250
|
}
|
|
223
251
|
setStatus('resolved');
|
|
224
|
-
_context2.next =
|
|
252
|
+
_context2.next = 42;
|
|
225
253
|
break;
|
|
226
|
-
case
|
|
227
|
-
_context2.prev =
|
|
228
|
-
_context2.t0 = _context2["catch"](
|
|
254
|
+
case 36:
|
|
255
|
+
_context2.prev = 36;
|
|
256
|
+
_context2.t0 = _context2["catch"](7);
|
|
229
257
|
if (!(_context2.t0 instanceof Response && (_context2.t0.status === 401 || _context2.t0.status === 403))) {
|
|
230
|
-
_context2.next =
|
|
258
|
+
_context2.next = 41;
|
|
231
259
|
break;
|
|
232
260
|
}
|
|
233
261
|
setStatus('unauthorized');
|
|
234
262
|
return _context2.abrupt("return");
|
|
235
|
-
case 40:
|
|
236
|
-
setStatus('rejected');
|
|
237
263
|
case 41:
|
|
264
|
+
setStatus('rejected');
|
|
265
|
+
case 42:
|
|
238
266
|
case "end":
|
|
239
267
|
return _context2.stop();
|
|
240
268
|
}
|
|
241
|
-
}, _callee2, null, [[
|
|
242
|
-
})), [parameters, fieldKeys, nextCursor, getDatasourceData, datasourceId, responseItems === null || responseItems === void 0 ? void 0 : responseItems.length, applySchemaProperties, fireEvent]);
|
|
269
|
+
}, _callee2, null, [[7, 36]]);
|
|
270
|
+
})), [parameters, fieldKeys, nextCursor, getDatasourceData, datasourceId, responseItems === null || responseItems === void 0 ? void 0 : responseItems.length, applySchemaProperties, fireEvent, fullSchema]);
|
|
243
271
|
var reset = useCallback(function (options) {
|
|
244
272
|
setStatus('empty');
|
|
245
273
|
setResponseItems([]);
|
|
@@ -247,6 +275,9 @@ export var useDatasourceTableState = function useDatasourceTableState(_ref) {
|
|
|
247
275
|
setNextCursor(undefined);
|
|
248
276
|
setTotalCount(undefined);
|
|
249
277
|
setLastRequestedFieldKeys([]);
|
|
278
|
+
setFullSchema({
|
|
279
|
+
properties: []
|
|
280
|
+
});
|
|
250
281
|
setShouldForceRequest((options === null || options === void 0 ? void 0 : options.shouldForceRequest) || false);
|
|
251
282
|
if (options !== null && options !== void 0 && options.shouldResetColumns) {
|
|
252
283
|
setColumns([]);
|