@atlaskit/link-datasource 1.13.0 → 1.13.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +12 -0
- package/dist/cjs/analytics/constants.js +1 -1
- package/dist/cjs/services/useBasicFilterAGG.js +3 -10
- package/dist/cjs/ui/jira-issues-modal/basic-filters/hooks/useFilterOptions.js +34 -12
- package/dist/cjs/ui/jira-issues-modal/basic-filters/ui/async-popup-select/dropdownIndicator.js +39 -0
- package/dist/cjs/ui/jira-issues-modal/basic-filters/ui/async-popup-select/index.js +51 -20
- package/dist/cjs/ui/jira-issues-modal/basic-filters/ui/async-popup-select/trigger.js +2 -0
- package/dist/cjs/ui/jira-issues-modal/basic-filters/ui/index.js +1 -0
- package/dist/es2019/analytics/constants.js +1 -1
- package/dist/es2019/services/useBasicFilterAGG.js +4 -14
- package/dist/es2019/ui/jira-issues-modal/basic-filters/hooks/useFilterOptions.js +14 -2
- package/dist/es2019/ui/jira-issues-modal/basic-filters/ui/async-popup-select/dropdownIndicator.js +34 -0
- package/dist/es2019/ui/jira-issues-modal/basic-filters/ui/async-popup-select/index.js +25 -10
- package/dist/es2019/ui/jira-issues-modal/basic-filters/ui/async-popup-select/trigger.js +2 -0
- package/dist/es2019/ui/jira-issues-modal/basic-filters/ui/index.js +1 -0
- package/dist/esm/analytics/constants.js +1 -1
- package/dist/esm/services/useBasicFilterAGG.js +4 -11
- package/dist/esm/ui/jira-issues-modal/basic-filters/hooks/useFilterOptions.js +35 -13
- package/dist/esm/ui/jira-issues-modal/basic-filters/ui/async-popup-select/dropdownIndicator.js +32 -0
- package/dist/esm/ui/jira-issues-modal/basic-filters/ui/async-popup-select/index.js +52 -21
- package/dist/esm/ui/jira-issues-modal/basic-filters/ui/async-popup-select/trigger.js +2 -0
- package/dist/esm/ui/jira-issues-modal/basic-filters/ui/index.js +1 -0
- package/dist/types/ui/jira-issues-modal/basic-filters/ui/async-popup-select/dropdownIndicator.d.ts +5 -0
- package/dist/types/ui/jira-issues-modal/basic-filters/ui/async-popup-select/index.d.ts +2 -1
- package/dist/types/ui/jira-issues-modal/basic-filters/ui/async-popup-select/trigger.d.ts +1 -0
- package/dist/types-ts4.5/ui/jira-issues-modal/basic-filters/ui/async-popup-select/dropdownIndicator.d.ts +5 -0
- package/dist/types-ts4.5/ui/jira-issues-modal/basic-filters/ui/async-popup-select/index.d.ts +2 -1
- package/dist/types-ts4.5/ui/jira-issues-modal/basic-filters/ui/async-popup-select/trigger.d.ts +1 -0
- package/package.json +3 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# @atlaskit/link-datasource
|
|
2
2
|
|
|
3
|
+
## 1.13.2
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [#42785](https://bitbucket.org/atlassian/atlassian-frontend/pull-requests/42785) [`63e0adac24f`](https://bitbucket.org/atlassian/atlassian-frontend/commits/63e0adac24f) - Fix AGG base URL
|
|
8
|
+
|
|
9
|
+
## 1.13.1
|
|
10
|
+
|
|
11
|
+
### Patch Changes
|
|
12
|
+
|
|
13
|
+
- [#42684](https://bitbucket.org/atlassian/atlassian-frontend/pull-requests/42684) [`3752d98e7fd`](https://bitbucket.org/atlassian/atlassian-frontend/commits/3752d98e7fd) - Add search functionality to basic filter dropdowns.
|
|
14
|
+
|
|
3
15
|
## 1.13.0
|
|
4
16
|
|
|
5
17
|
### Minor Changes
|
|
@@ -8,23 +8,16 @@ exports.useBasicFilterAGG = void 0;
|
|
|
8
8
|
var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator"));
|
|
9
9
|
var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator"));
|
|
10
10
|
var _react = require("react");
|
|
11
|
-
var _linkProvider = require("@atlaskit/link-provider");
|
|
12
11
|
var _linkingCommon = require("@atlaskit/linking-common");
|
|
13
12
|
var _utils = require("./utils");
|
|
14
|
-
var
|
|
15
|
-
var baseUrl = baseUrlOverride || (0, _linkingCommon.getBaseUrl)(envKey);
|
|
16
|
-
return baseUrl ? "".concat(baseUrl, "/graphql") : '/gateway/api/graphql';
|
|
17
|
-
};
|
|
13
|
+
var AGG_BASE_URL = '/gateway/api/graphql';
|
|
18
14
|
var useBasicFilterAGG = exports.useBasicFilterAGG = function useBasicFilterAGG() {
|
|
19
|
-
var _useSmartLinkContext = (0, _linkProvider.useSmartLinkContext)(),
|
|
20
|
-
client = _useSmartLinkContext.connections.client;
|
|
21
|
-
var gatewayGraphqlUrl = getGraphqlUrl(client.envKey, client.baseUrlOverride);
|
|
22
15
|
var requestCall = (0, _react.useCallback)( /*#__PURE__*/function () {
|
|
23
16
|
var _ref = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee(body) {
|
|
24
17
|
return _regenerator.default.wrap(function _callee$(_context) {
|
|
25
18
|
while (1) switch (_context.prev = _context.next) {
|
|
26
19
|
case 0:
|
|
27
|
-
return _context.abrupt("return", (0, _linkingCommon.request)('post',
|
|
20
|
+
return _context.abrupt("return", (0, _linkingCommon.request)('post', AGG_BASE_URL, body, {
|
|
28
21
|
'X-ExperimentalApi': 'JiraJqlBuilder'
|
|
29
22
|
}, [200, 201, 202, 203, 204]));
|
|
30
23
|
case 1:
|
|
@@ -36,7 +29,7 @@ var useBasicFilterAGG = exports.useBasicFilterAGG = function useBasicFilterAGG()
|
|
|
36
29
|
return function (_x) {
|
|
37
30
|
return _ref.apply(this, arguments);
|
|
38
31
|
};
|
|
39
|
-
}(), [
|
|
32
|
+
}(), []);
|
|
40
33
|
var getHydratedJQL = (0, _react.useCallback)(function (cloudId, jql) {
|
|
41
34
|
return requestCall({
|
|
42
35
|
variables: {
|
|
@@ -31,12 +31,15 @@ var useFilterOptions = exports.useFilterOptions = function useFilterOptions(_ref
|
|
|
31
31
|
_useState8 = (0, _slicedToArray2.default)(_useState7, 2),
|
|
32
32
|
nextPageCursor = _useState8[0],
|
|
33
33
|
setNextPageCursor = _useState8[1];
|
|
34
|
+
var initialData = (0, _react.useRef)();
|
|
34
35
|
var _useBasicFilterAGG = (0, _useBasicFilterAGG2.useBasicFilterAGG)(),
|
|
35
36
|
getFieldValues = _useBasicFilterAGG.getFieldValues;
|
|
36
37
|
var fetchFilterOptions = (0, _react.useCallback)( /*#__PURE__*/(0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee() {
|
|
37
38
|
var _ref3,
|
|
38
39
|
pageCursor,
|
|
39
40
|
searchString,
|
|
41
|
+
isRequestLikeInitialSearch,
|
|
42
|
+
initialResponseData,
|
|
40
43
|
response,
|
|
41
44
|
isNewSearch,
|
|
42
45
|
_args = arguments;
|
|
@@ -45,8 +48,18 @@ var useFilterOptions = exports.useFilterOptions = function useFilterOptions(_ref
|
|
|
45
48
|
case 0:
|
|
46
49
|
_ref3 = _args.length > 0 && _args[0] !== undefined ? _args[0] : {}, pageCursor = _ref3.pageCursor, searchString = _ref3.searchString;
|
|
47
50
|
setStatus('loading');
|
|
48
|
-
|
|
49
|
-
|
|
51
|
+
isRequestLikeInitialSearch = !pageCursor && !searchString;
|
|
52
|
+
initialResponseData = initialData.current;
|
|
53
|
+
_context.prev = 4;
|
|
54
|
+
if (!(isRequestLikeInitialSearch && initialResponseData)) {
|
|
55
|
+
_context.next = 9;
|
|
56
|
+
break;
|
|
57
|
+
}
|
|
58
|
+
_context.t0 = initialResponseData;
|
|
59
|
+
_context.next = 12;
|
|
60
|
+
break;
|
|
61
|
+
case 9:
|
|
62
|
+
_context.next = 11;
|
|
50
63
|
return getFieldValues({
|
|
51
64
|
cloudId: cloudId,
|
|
52
65
|
jql: '',
|
|
@@ -54,35 +67,44 @@ var useFilterOptions = exports.useFilterOptions = function useFilterOptions(_ref
|
|
|
54
67
|
searchString: searchString,
|
|
55
68
|
pageCursor: pageCursor
|
|
56
69
|
});
|
|
57
|
-
case
|
|
58
|
-
|
|
70
|
+
case 11:
|
|
71
|
+
_context.t0 = _context.sent;
|
|
72
|
+
case 12:
|
|
73
|
+
response = _context.t0;
|
|
59
74
|
if (!(response.errors && response.errors.length > 0)) {
|
|
60
|
-
_context.next =
|
|
75
|
+
_context.next = 16;
|
|
61
76
|
break;
|
|
62
77
|
}
|
|
63
78
|
setStatus('rejected');
|
|
64
79
|
return _context.abrupt("return");
|
|
65
|
-
case
|
|
80
|
+
case 16:
|
|
66
81
|
isNewSearch = !pageCursor;
|
|
67
82
|
if (isNewSearch) {
|
|
68
83
|
setFilterOptions((0, _transformers.mapFieldValuesToFilterOptions)(response));
|
|
84
|
+
if (isRequestLikeInitialSearch) {
|
|
85
|
+
/**
|
|
86
|
+
* The initial dataset is used in couple of paths, eg: when a user searches and clears the search text.
|
|
87
|
+
* During these times, we dont want to fetch data again and again, hence a mini cache setup to store and provide the initial dataset
|
|
88
|
+
*/
|
|
89
|
+
initialData.current = response;
|
|
90
|
+
}
|
|
69
91
|
} else {
|
|
70
92
|
setFilterOptions([].concat((0, _toConsumableArray2.default)(filterOptions), (0, _toConsumableArray2.default)((0, _transformers.mapFieldValuesToFilterOptions)(response))));
|
|
71
93
|
}
|
|
72
94
|
setTotalCount((0, _transformers.mapFieldValuesToTotalCount)(response));
|
|
73
95
|
setNextPageCursor((0, _transformers.mapFieldValuesToPageCursor)(response));
|
|
74
96
|
setStatus('resolved');
|
|
75
|
-
_context.next =
|
|
97
|
+
_context.next = 26;
|
|
76
98
|
break;
|
|
77
|
-
case
|
|
78
|
-
_context.prev =
|
|
79
|
-
_context.
|
|
99
|
+
case 23:
|
|
100
|
+
_context.prev = 23;
|
|
101
|
+
_context.t1 = _context["catch"](4);
|
|
80
102
|
setStatus('rejected');
|
|
81
|
-
case
|
|
103
|
+
case 26:
|
|
82
104
|
case "end":
|
|
83
105
|
return _context.stop();
|
|
84
106
|
}
|
|
85
|
-
}, _callee, null, [[
|
|
107
|
+
}, _callee, null, [[4, 23]]);
|
|
86
108
|
})), [cloudId, filterOptions, filterType, getFieldValues]);
|
|
87
109
|
return {
|
|
88
110
|
filterOptions: filterOptions,
|
package/dist/cjs/ui/jira-issues-modal/basic-filters/ui/async-popup-select/dropdownIndicator.js
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
|
|
4
|
+
Object.defineProperty(exports, "__esModule", {
|
|
5
|
+
value: true
|
|
6
|
+
});
|
|
7
|
+
exports.default = void 0;
|
|
8
|
+
var _react = _interopRequireDefault(require("react"));
|
|
9
|
+
var _crossCircle = _interopRequireDefault(require("@atlaskit/icon/glyph/cross-circle"));
|
|
10
|
+
var _search = _interopRequireDefault(require("@atlaskit/icon/glyph/search"));
|
|
11
|
+
var _primitives = require("@atlaskit/primitives");
|
|
12
|
+
var _select = require("@atlaskit/select");
|
|
13
|
+
var customDropdownIndicatorStyles = (0, _primitives.xcss)({
|
|
14
|
+
display: 'flex',
|
|
15
|
+
cursor: 'pointer',
|
|
16
|
+
justifyContent: 'center',
|
|
17
|
+
width: "var(--ds-space-400, 32px)"
|
|
18
|
+
});
|
|
19
|
+
var CustomDropdownIndicator = function CustomDropdownIndicator(props) {
|
|
20
|
+
var selectProps = props.selectProps;
|
|
21
|
+
return /*#__PURE__*/_react.default.createElement(_select.components.DropdownIndicator, props, /*#__PURE__*/_react.default.createElement(_primitives.Box, {
|
|
22
|
+
xcss: customDropdownIndicatorStyles,
|
|
23
|
+
onClick: function onClick() {
|
|
24
|
+
if (selectProps.inputValue) {
|
|
25
|
+
selectProps.onInputChange && selectProps.onInputChange('', {
|
|
26
|
+
action: 'input-change',
|
|
27
|
+
prevInputValue: selectProps.inputValue
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}, selectProps.inputValue ? /*#__PURE__*/_react.default.createElement(_crossCircle.default, {
|
|
32
|
+
size: "small",
|
|
33
|
+
label: ""
|
|
34
|
+
}) : /*#__PURE__*/_react.default.createElement(_search.default, {
|
|
35
|
+
size: "small",
|
|
36
|
+
label: ""
|
|
37
|
+
})));
|
|
38
|
+
};
|
|
39
|
+
var _default = exports.default = CustomDropdownIndicator;
|
|
@@ -12,10 +12,12 @@ var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator"))
|
|
|
12
12
|
var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator"));
|
|
13
13
|
var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
|
|
14
14
|
var _react = _interopRequireWildcard(require("react"));
|
|
15
|
+
var _debounce = _interopRequireDefault(require("lodash/debounce"));
|
|
15
16
|
var _reactIntlNext = require("react-intl-next");
|
|
16
17
|
var _select = require("@atlaskit/select");
|
|
17
18
|
var _useFilterOptions2 = require("../../hooks/useFilterOptions");
|
|
18
19
|
var _control = _interopRequireDefault(require("./control"));
|
|
20
|
+
var _dropdownIndicator = _interopRequireDefault(require("./dropdownIndicator"));
|
|
19
21
|
var _footer = _interopRequireDefault(require("./footer"));
|
|
20
22
|
var _formatOptionLabel = _interopRequireDefault(require("./formatOptionLabel"));
|
|
21
23
|
var _messages = require("./messages");
|
|
@@ -27,12 +29,15 @@ function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj &&
|
|
|
27
29
|
var noFilterOptions = function noFilterOptions() {
|
|
28
30
|
return true;
|
|
29
31
|
};
|
|
32
|
+
var SEARCH_DEBOUNCE_MS = 350;
|
|
30
33
|
var AsyncPopupSelect = function AsyncPopupSelect(_ref) {
|
|
31
34
|
var filterType = _ref.filterType,
|
|
32
35
|
cloudId = _ref.cloudId,
|
|
33
36
|
selection = _ref.selection,
|
|
34
37
|
_ref$onSelectionChang = _ref.onSelectionChange,
|
|
35
|
-
onSelectionChange = _ref$onSelectionChang === void 0 ? function () {} : _ref$onSelectionChang
|
|
38
|
+
onSelectionChange = _ref$onSelectionChang === void 0 ? function () {} : _ref$onSelectionChang,
|
|
39
|
+
_ref$isDisabled = _ref.isDisabled,
|
|
40
|
+
isDisabled = _ref$isDisabled === void 0 ? false : _ref$isDisabled;
|
|
36
41
|
var _useIntl = (0, _reactIntlNext.useIntl)(),
|
|
37
42
|
formatMessage = _useIntl.formatMessage;
|
|
38
43
|
var pickerRef = (0, _react.useRef)(null);
|
|
@@ -52,30 +57,49 @@ var AsyncPopupSelect = function AsyncPopupSelect(_ref) {
|
|
|
52
57
|
fetchFilterOptions = _useFilterOptions.fetchFilterOptions,
|
|
53
58
|
totalCount = _useFilterOptions.totalCount,
|
|
54
59
|
status = _useFilterOptions.status;
|
|
55
|
-
var
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
+
var handleDebouncedFetchFilterOptions = (0, _react.useMemo)(function () {
|
|
61
|
+
return (0, _debounce.default)(fetchFilterOptions, SEARCH_DEBOUNCE_MS);
|
|
62
|
+
}, [fetchFilterOptions]);
|
|
63
|
+
var handleInputChange = (0, _react.useCallback)( /*#__PURE__*/function () {
|
|
64
|
+
var _ref2 = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee(newSearchTerm, actionMeta) {
|
|
65
|
+
return _regenerator.default.wrap(function _callee$(_context) {
|
|
66
|
+
while (1) switch (_context.prev = _context.next) {
|
|
67
|
+
case 0:
|
|
68
|
+
if (actionMeta.action === 'input-change' && newSearchTerm !== searchTerm) {
|
|
69
|
+
setSearchTerm(newSearchTerm);
|
|
70
|
+
handleDebouncedFetchFilterOptions({
|
|
71
|
+
searchString: newSearchTerm
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
case 1:
|
|
75
|
+
case "end":
|
|
76
|
+
return _context.stop();
|
|
77
|
+
}
|
|
78
|
+
}, _callee);
|
|
79
|
+
}));
|
|
80
|
+
return function (_x, _x2) {
|
|
81
|
+
return _ref2.apply(this, arguments);
|
|
82
|
+
};
|
|
83
|
+
}(), [handleDebouncedFetchFilterOptions, searchTerm]);
|
|
60
84
|
var handleOptionSelection = function handleOptionSelection(newValue) {
|
|
61
85
|
setSelectedOptions(newValue);
|
|
62
86
|
onSelectionChange(newValue);
|
|
63
87
|
};
|
|
64
|
-
var handleOpenPopup = (0, _react.useCallback)( /*#__PURE__*/(0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function
|
|
65
|
-
return _regenerator.default.wrap(function
|
|
66
|
-
while (1) switch (
|
|
88
|
+
var handleOpenPopup = (0, _react.useCallback)( /*#__PURE__*/(0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee2() {
|
|
89
|
+
return _regenerator.default.wrap(function _callee2$(_context2) {
|
|
90
|
+
while (1) switch (_context2.prev = _context2.next) {
|
|
67
91
|
case 0:
|
|
68
92
|
if (!(status === 'empty')) {
|
|
69
|
-
|
|
93
|
+
_context2.next = 3;
|
|
70
94
|
break;
|
|
71
95
|
}
|
|
72
|
-
|
|
96
|
+
_context2.next = 3;
|
|
73
97
|
return fetchFilterOptions();
|
|
74
98
|
case 3:
|
|
75
99
|
case "end":
|
|
76
|
-
return
|
|
100
|
+
return _context2.stop();
|
|
77
101
|
}
|
|
78
|
-
},
|
|
102
|
+
}, _callee2);
|
|
79
103
|
})), [fetchFilterOptions, status]);
|
|
80
104
|
(0, _react.useEffect)(function () {
|
|
81
105
|
if (status === 'resolved') {
|
|
@@ -85,6 +109,9 @@ var AsyncPopupSelect = function AsyncPopupSelect(_ref) {
|
|
|
85
109
|
}
|
|
86
110
|
}, [status]);
|
|
87
111
|
var isLoading = status === 'loading' || status === 'empty';
|
|
112
|
+
var shouldShowFooter = status === 'resolved' && filterOptions.length > 0;
|
|
113
|
+
var options = isLoading ? [] : filterOptions; // if not set to [], then on loading, no loading UI will be shown
|
|
114
|
+
|
|
88
115
|
return /*#__PURE__*/_react.default.createElement(_select.PopupSelect, {
|
|
89
116
|
isMulti: true,
|
|
90
117
|
maxMenuWidth: 300,
|
|
@@ -106,24 +133,28 @@ var AsyncPopupSelect = function AsyncPopupSelect(_ref) {
|
|
|
106
133
|
components: {
|
|
107
134
|
/* @ts-expect-error - This component has stricter OptionType, hence a temp setup untill its made generic */
|
|
108
135
|
Option: _select.CheckboxOption,
|
|
109
|
-
Control: _control.default
|
|
136
|
+
Control: _control.default,
|
|
137
|
+
LoadingIndicator: undefined,
|
|
138
|
+
// disables the three ... indicator in the searchbox when picker is loading
|
|
139
|
+
DropdownIndicator: _dropdownIndicator.default
|
|
110
140
|
},
|
|
111
|
-
options:
|
|
141
|
+
options: options,
|
|
112
142
|
value: selectedOptions,
|
|
113
143
|
filterOption: noFilterOptions,
|
|
114
144
|
formatOptionLabel: _formatOptionLabel.default,
|
|
115
145
|
onChange: handleOptionSelection,
|
|
116
146
|
onInputChange: handleInputChange,
|
|
117
|
-
target: function target(
|
|
118
|
-
var isOpen =
|
|
119
|
-
triggerProps = (0, _objectWithoutProperties2.default)(
|
|
147
|
+
target: function target(_ref4) {
|
|
148
|
+
var isOpen = _ref4.isOpen,
|
|
149
|
+
triggerProps = (0, _objectWithoutProperties2.default)(_ref4, _excluded);
|
|
120
150
|
return /*#__PURE__*/_react.default.createElement(_trigger.default, (0, _extends2.default)({}, triggerProps, {
|
|
121
151
|
filterType: filterType,
|
|
122
152
|
isSelected: isOpen,
|
|
123
|
-
onClick: handleOpenPopup
|
|
153
|
+
onClick: handleOpenPopup,
|
|
154
|
+
isDisabled: isDisabled
|
|
124
155
|
}));
|
|
125
156
|
},
|
|
126
|
-
footer: /*#__PURE__*/_react.default.createElement(_footer.default, {
|
|
157
|
+
footer: shouldShowFooter && /*#__PURE__*/_react.default.createElement(_footer.default, {
|
|
127
158
|
currentDisplayCount: filterOptions.length,
|
|
128
159
|
totalCount: totalCount
|
|
129
160
|
})
|
|
@@ -16,11 +16,13 @@ function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj &&
|
|
|
16
16
|
var PopupTrigger = /*#__PURE__*/(0, _react.forwardRef)(function (_ref, ref) {
|
|
17
17
|
var filterType = _ref.filterType,
|
|
18
18
|
isSelected = _ref.isSelected,
|
|
19
|
+
isDisabled = _ref.isDisabled,
|
|
19
20
|
onClick = _ref.onClick;
|
|
20
21
|
return /*#__PURE__*/_react.default.createElement(_standardButton.default, {
|
|
21
22
|
ref: ref,
|
|
22
23
|
appearance: "default",
|
|
23
24
|
isSelected: isSelected,
|
|
25
|
+
isDisabled: isDisabled,
|
|
24
26
|
onClick: onClick,
|
|
25
27
|
testId: "jlol-basic-filter-".concat(filterType, "-trigger"),
|
|
26
28
|
iconAfter: /*#__PURE__*/_react.default.createElement(_chevronDown.default, {
|
|
@@ -1,21 +1,11 @@
|
|
|
1
1
|
import { useCallback, useMemo } from 'react';
|
|
2
|
-
import {
|
|
3
|
-
import { getBaseUrl, request } from '@atlaskit/linking-common';
|
|
2
|
+
import { request } from '@atlaskit/linking-common';
|
|
4
3
|
import { fieldValuesQuery, hydrateJQLQuery } from './utils';
|
|
5
|
-
const
|
|
6
|
-
const baseUrl = baseUrlOverride || getBaseUrl(envKey);
|
|
7
|
-
return baseUrl ? `${baseUrl}/graphql` : '/gateway/api/graphql';
|
|
8
|
-
};
|
|
4
|
+
const AGG_BASE_URL = '/gateway/api/graphql';
|
|
9
5
|
export const useBasicFilterAGG = () => {
|
|
10
|
-
const {
|
|
11
|
-
connections: {
|
|
12
|
-
client
|
|
13
|
-
}
|
|
14
|
-
} = useSmartLinkContext();
|
|
15
|
-
const gatewayGraphqlUrl = getGraphqlUrl(client.envKey, client.baseUrlOverride);
|
|
16
|
-
const requestCall = useCallback(async body => request('post', gatewayGraphqlUrl, body, {
|
|
6
|
+
const requestCall = useCallback(async body => request('post', AGG_BASE_URL, body, {
|
|
17
7
|
'X-ExperimentalApi': 'JiraJqlBuilder'
|
|
18
|
-
}, [200, 201, 202, 203, 204]), [
|
|
8
|
+
}, [200, 201, 202, 203, 204]), []);
|
|
19
9
|
const getHydratedJQL = useCallback((cloudId, jql) => requestCall({
|
|
20
10
|
variables: {
|
|
21
11
|
cloudId,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { useCallback, useState } from 'react';
|
|
1
|
+
import { useCallback, useRef, useState } from 'react';
|
|
2
2
|
import { useBasicFilterAGG } from '../../../../services/useBasicFilterAGG';
|
|
3
3
|
import { mapFieldValuesToFilterOptions, mapFieldValuesToPageCursor, mapFieldValuesToTotalCount } from '../utils/transformers';
|
|
4
4
|
export const useFilterOptions = ({
|
|
@@ -9,6 +9,7 @@ export const useFilterOptions = ({
|
|
|
9
9
|
const [totalCount, setTotalCount] = useState(0);
|
|
10
10
|
const [status, setStatus] = useState('empty');
|
|
11
11
|
const [nextPageCursor, setNextPageCursor] = useState(undefined);
|
|
12
|
+
const initialData = useRef();
|
|
12
13
|
const {
|
|
13
14
|
getFieldValues
|
|
14
15
|
} = useBasicFilterAGG();
|
|
@@ -17,8 +18,12 @@ export const useFilterOptions = ({
|
|
|
17
18
|
searchString
|
|
18
19
|
} = {}) => {
|
|
19
20
|
setStatus('loading');
|
|
21
|
+
const isRequestLikeInitialSearch = !pageCursor && !searchString;
|
|
22
|
+
const {
|
|
23
|
+
current: initialResponseData
|
|
24
|
+
} = initialData;
|
|
20
25
|
try {
|
|
21
|
-
const response = await getFieldValues({
|
|
26
|
+
const response = isRequestLikeInitialSearch && initialResponseData ? initialResponseData : await getFieldValues({
|
|
22
27
|
cloudId,
|
|
23
28
|
jql: '',
|
|
24
29
|
jqlTerm: filterType,
|
|
@@ -32,6 +37,13 @@ export const useFilterOptions = ({
|
|
|
32
37
|
const isNewSearch = !pageCursor;
|
|
33
38
|
if (isNewSearch) {
|
|
34
39
|
setFilterOptions(mapFieldValuesToFilterOptions(response));
|
|
40
|
+
if (isRequestLikeInitialSearch) {
|
|
41
|
+
/**
|
|
42
|
+
* The initial dataset is used in couple of paths, eg: when a user searches and clears the search text.
|
|
43
|
+
* During these times, we dont want to fetch data again and again, hence a mini cache setup to store and provide the initial dataset
|
|
44
|
+
*/
|
|
45
|
+
initialData.current = response;
|
|
46
|
+
}
|
|
35
47
|
} else {
|
|
36
48
|
setFilterOptions([...filterOptions, ...mapFieldValuesToFilterOptions(response)]);
|
|
37
49
|
}
|
package/dist/es2019/ui/jira-issues-modal/basic-filters/ui/async-popup-select/dropdownIndicator.js
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import CloseIcon from '@atlaskit/icon/glyph/cross-circle';
|
|
3
|
+
import SearchIcon from '@atlaskit/icon/glyph/search';
|
|
4
|
+
import { Box, xcss } from '@atlaskit/primitives';
|
|
5
|
+
import { components } from '@atlaskit/select';
|
|
6
|
+
const customDropdownIndicatorStyles = xcss({
|
|
7
|
+
display: 'flex',
|
|
8
|
+
cursor: 'pointer',
|
|
9
|
+
justifyContent: 'center',
|
|
10
|
+
width: "var(--ds-space-400, 32px)"
|
|
11
|
+
});
|
|
12
|
+
const CustomDropdownIndicator = props => {
|
|
13
|
+
const {
|
|
14
|
+
selectProps
|
|
15
|
+
} = props;
|
|
16
|
+
return /*#__PURE__*/React.createElement(components.DropdownIndicator, props, /*#__PURE__*/React.createElement(Box, {
|
|
17
|
+
xcss: customDropdownIndicatorStyles,
|
|
18
|
+
onClick: () => {
|
|
19
|
+
if (selectProps.inputValue) {
|
|
20
|
+
selectProps.onInputChange && selectProps.onInputChange('', {
|
|
21
|
+
action: 'input-change',
|
|
22
|
+
prevInputValue: selectProps.inputValue
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}, selectProps.inputValue ? /*#__PURE__*/React.createElement(CloseIcon, {
|
|
27
|
+
size: "small",
|
|
28
|
+
label: ""
|
|
29
|
+
}) : /*#__PURE__*/React.createElement(SearchIcon, {
|
|
30
|
+
size: "small",
|
|
31
|
+
label: ""
|
|
32
|
+
})));
|
|
33
|
+
};
|
|
34
|
+
export default CustomDropdownIndicator;
|
|
@@ -1,20 +1,24 @@
|
|
|
1
1
|
import _extends from "@babel/runtime/helpers/extends";
|
|
2
|
-
import React, { useCallback, useEffect, useRef, useState } from 'react';
|
|
2
|
+
import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
|
3
|
+
import debounce from 'lodash/debounce';
|
|
3
4
|
import { useIntl } from 'react-intl-next';
|
|
4
5
|
import { CheckboxOption, PopupSelect } from '@atlaskit/select';
|
|
5
6
|
import { useFilterOptions } from '../../hooks/useFilterOptions';
|
|
6
7
|
import CustomControl from './control';
|
|
8
|
+
import CustomDropdownIndicator from './dropdownIndicator';
|
|
7
9
|
import PopupFooter from './footer';
|
|
8
10
|
import formatOptionLabel from './formatOptionLabel';
|
|
9
11
|
import { asyncPopupSelectMessages } from './messages';
|
|
10
12
|
import PopupTrigger from './trigger';
|
|
11
13
|
// Needed to disable filtering from react-select
|
|
12
14
|
const noFilterOptions = () => true;
|
|
15
|
+
const SEARCH_DEBOUNCE_MS = 350;
|
|
13
16
|
const AsyncPopupSelect = ({
|
|
14
17
|
filterType,
|
|
15
18
|
cloudId,
|
|
16
19
|
selection,
|
|
17
|
-
onSelectionChange = () => {}
|
|
20
|
+
onSelectionChange = () => {},
|
|
21
|
+
isDisabled = false
|
|
18
22
|
}) => {
|
|
19
23
|
const {
|
|
20
24
|
formatMessage
|
|
@@ -31,11 +35,15 @@ const AsyncPopupSelect = ({
|
|
|
31
35
|
filterType,
|
|
32
36
|
cloudId
|
|
33
37
|
});
|
|
34
|
-
const
|
|
35
|
-
|
|
36
|
-
|
|
38
|
+
const handleDebouncedFetchFilterOptions = useMemo(() => debounce(fetchFilterOptions, SEARCH_DEBOUNCE_MS), [fetchFilterOptions]);
|
|
39
|
+
const handleInputChange = useCallback(async (newSearchTerm, actionMeta) => {
|
|
40
|
+
if (actionMeta.action === 'input-change' && newSearchTerm !== searchTerm) {
|
|
41
|
+
setSearchTerm(newSearchTerm);
|
|
42
|
+
handleDebouncedFetchFilterOptions({
|
|
43
|
+
searchString: newSearchTerm
|
|
44
|
+
});
|
|
37
45
|
}
|
|
38
|
-
}, [searchTerm]);
|
|
46
|
+
}, [handleDebouncedFetchFilterOptions, searchTerm]);
|
|
39
47
|
const handleOptionSelection = newValue => {
|
|
40
48
|
setSelectedOptions(newValue);
|
|
41
49
|
onSelectionChange(newValue);
|
|
@@ -53,6 +61,9 @@ const AsyncPopupSelect = ({
|
|
|
53
61
|
}
|
|
54
62
|
}, [status]);
|
|
55
63
|
const isLoading = status === 'loading' || status === 'empty';
|
|
64
|
+
const shouldShowFooter = status === 'resolved' && filterOptions.length > 0;
|
|
65
|
+
const options = isLoading ? [] : filterOptions; // if not set to [], then on loading, no loading UI will be shown
|
|
66
|
+
|
|
56
67
|
return /*#__PURE__*/React.createElement(PopupSelect, {
|
|
57
68
|
isMulti: true,
|
|
58
69
|
maxMenuWidth: 300,
|
|
@@ -74,9 +85,12 @@ const AsyncPopupSelect = ({
|
|
|
74
85
|
components: {
|
|
75
86
|
/* @ts-expect-error - This component has stricter OptionType, hence a temp setup untill its made generic */
|
|
76
87
|
Option: CheckboxOption,
|
|
77
|
-
Control: CustomControl
|
|
88
|
+
Control: CustomControl,
|
|
89
|
+
LoadingIndicator: undefined,
|
|
90
|
+
// disables the three ... indicator in the searchbox when picker is loading
|
|
91
|
+
DropdownIndicator: CustomDropdownIndicator
|
|
78
92
|
},
|
|
79
|
-
options:
|
|
93
|
+
options: options,
|
|
80
94
|
value: selectedOptions,
|
|
81
95
|
filterOption: noFilterOptions,
|
|
82
96
|
formatOptionLabel: formatOptionLabel,
|
|
@@ -88,9 +102,10 @@ const AsyncPopupSelect = ({
|
|
|
88
102
|
}) => /*#__PURE__*/React.createElement(PopupTrigger, _extends({}, triggerProps, {
|
|
89
103
|
filterType: filterType,
|
|
90
104
|
isSelected: isOpen,
|
|
91
|
-
onClick: handleOpenPopup
|
|
105
|
+
onClick: handleOpenPopup,
|
|
106
|
+
isDisabled: isDisabled
|
|
92
107
|
})),
|
|
93
|
-
footer: /*#__PURE__*/React.createElement(PopupFooter, {
|
|
108
|
+
footer: shouldShowFooter && /*#__PURE__*/React.createElement(PopupFooter, {
|
|
94
109
|
currentDisplayCount: filterOptions.length,
|
|
95
110
|
totalCount: totalCount
|
|
96
111
|
})
|
|
@@ -6,12 +6,14 @@ import { asyncPopupSelectMessages } from './messages';
|
|
|
6
6
|
const PopupTrigger = /*#__PURE__*/forwardRef(({
|
|
7
7
|
filterType,
|
|
8
8
|
isSelected,
|
|
9
|
+
isDisabled,
|
|
9
10
|
onClick
|
|
10
11
|
}, ref) => {
|
|
11
12
|
return /*#__PURE__*/React.createElement(Button, {
|
|
12
13
|
ref: ref,
|
|
13
14
|
appearance: "default",
|
|
14
15
|
isSelected: isSelected,
|
|
16
|
+
isDisabled: isDisabled,
|
|
15
17
|
onClick: onClick,
|
|
16
18
|
testId: `jlol-basic-filter-${filterType}-trigger`,
|
|
17
19
|
iconAfter: /*#__PURE__*/React.createElement(ChevronDownIcon, {
|
|
@@ -1,23 +1,16 @@
|
|
|
1
1
|
import _asyncToGenerator from "@babel/runtime/helpers/asyncToGenerator";
|
|
2
2
|
import _regeneratorRuntime from "@babel/runtime/regenerator";
|
|
3
3
|
import { useCallback, useMemo } from 'react';
|
|
4
|
-
import {
|
|
5
|
-
import { getBaseUrl, request } from '@atlaskit/linking-common';
|
|
4
|
+
import { request } from '@atlaskit/linking-common';
|
|
6
5
|
import { fieldValuesQuery, hydrateJQLQuery } from './utils';
|
|
7
|
-
var
|
|
8
|
-
var baseUrl = baseUrlOverride || getBaseUrl(envKey);
|
|
9
|
-
return baseUrl ? "".concat(baseUrl, "/graphql") : '/gateway/api/graphql';
|
|
10
|
-
};
|
|
6
|
+
var AGG_BASE_URL = '/gateway/api/graphql';
|
|
11
7
|
export var useBasicFilterAGG = function useBasicFilterAGG() {
|
|
12
|
-
var _useSmartLinkContext = useSmartLinkContext(),
|
|
13
|
-
client = _useSmartLinkContext.connections.client;
|
|
14
|
-
var gatewayGraphqlUrl = getGraphqlUrl(client.envKey, client.baseUrlOverride);
|
|
15
8
|
var requestCall = useCallback( /*#__PURE__*/function () {
|
|
16
9
|
var _ref = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee(body) {
|
|
17
10
|
return _regeneratorRuntime.wrap(function _callee$(_context) {
|
|
18
11
|
while (1) switch (_context.prev = _context.next) {
|
|
19
12
|
case 0:
|
|
20
|
-
return _context.abrupt("return", request('post',
|
|
13
|
+
return _context.abrupt("return", request('post', AGG_BASE_URL, body, {
|
|
21
14
|
'X-ExperimentalApi': 'JiraJqlBuilder'
|
|
22
15
|
}, [200, 201, 202, 203, 204]));
|
|
23
16
|
case 1:
|
|
@@ -29,7 +22,7 @@ export var useBasicFilterAGG = function useBasicFilterAGG() {
|
|
|
29
22
|
return function (_x) {
|
|
30
23
|
return _ref.apply(this, arguments);
|
|
31
24
|
};
|
|
32
|
-
}(), [
|
|
25
|
+
}(), []);
|
|
33
26
|
var getHydratedJQL = useCallback(function (cloudId, jql) {
|
|
34
27
|
return requestCall({
|
|
35
28
|
variables: {
|
|
@@ -2,7 +2,7 @@ import _toConsumableArray from "@babel/runtime/helpers/toConsumableArray";
|
|
|
2
2
|
import _asyncToGenerator from "@babel/runtime/helpers/asyncToGenerator";
|
|
3
3
|
import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
|
|
4
4
|
import _regeneratorRuntime from "@babel/runtime/regenerator";
|
|
5
|
-
import { useCallback, useState } from 'react';
|
|
5
|
+
import { useCallback, useRef, useState } from 'react';
|
|
6
6
|
import { useBasicFilterAGG } from '../../../../services/useBasicFilterAGG';
|
|
7
7
|
import { mapFieldValuesToFilterOptions, mapFieldValuesToPageCursor, mapFieldValuesToTotalCount } from '../utils/transformers';
|
|
8
8
|
export var useFilterOptions = function useFilterOptions(_ref) {
|
|
@@ -24,12 +24,15 @@ export var useFilterOptions = function useFilterOptions(_ref) {
|
|
|
24
24
|
_useState8 = _slicedToArray(_useState7, 2),
|
|
25
25
|
nextPageCursor = _useState8[0],
|
|
26
26
|
setNextPageCursor = _useState8[1];
|
|
27
|
+
var initialData = useRef();
|
|
27
28
|
var _useBasicFilterAGG = useBasicFilterAGG(),
|
|
28
29
|
getFieldValues = _useBasicFilterAGG.getFieldValues;
|
|
29
30
|
var fetchFilterOptions = useCallback( /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee() {
|
|
30
31
|
var _ref3,
|
|
31
32
|
pageCursor,
|
|
32
33
|
searchString,
|
|
34
|
+
isRequestLikeInitialSearch,
|
|
35
|
+
initialResponseData,
|
|
33
36
|
response,
|
|
34
37
|
isNewSearch,
|
|
35
38
|
_args = arguments;
|
|
@@ -38,8 +41,18 @@ export var useFilterOptions = function useFilterOptions(_ref) {
|
|
|
38
41
|
case 0:
|
|
39
42
|
_ref3 = _args.length > 0 && _args[0] !== undefined ? _args[0] : {}, pageCursor = _ref3.pageCursor, searchString = _ref3.searchString;
|
|
40
43
|
setStatus('loading');
|
|
41
|
-
|
|
42
|
-
|
|
44
|
+
isRequestLikeInitialSearch = !pageCursor && !searchString;
|
|
45
|
+
initialResponseData = initialData.current;
|
|
46
|
+
_context.prev = 4;
|
|
47
|
+
if (!(isRequestLikeInitialSearch && initialResponseData)) {
|
|
48
|
+
_context.next = 9;
|
|
49
|
+
break;
|
|
50
|
+
}
|
|
51
|
+
_context.t0 = initialResponseData;
|
|
52
|
+
_context.next = 12;
|
|
53
|
+
break;
|
|
54
|
+
case 9:
|
|
55
|
+
_context.next = 11;
|
|
43
56
|
return getFieldValues({
|
|
44
57
|
cloudId: cloudId,
|
|
45
58
|
jql: '',
|
|
@@ -47,35 +60,44 @@ export var useFilterOptions = function useFilterOptions(_ref) {
|
|
|
47
60
|
searchString: searchString,
|
|
48
61
|
pageCursor: pageCursor
|
|
49
62
|
});
|
|
50
|
-
case
|
|
51
|
-
|
|
63
|
+
case 11:
|
|
64
|
+
_context.t0 = _context.sent;
|
|
65
|
+
case 12:
|
|
66
|
+
response = _context.t0;
|
|
52
67
|
if (!(response.errors && response.errors.length > 0)) {
|
|
53
|
-
_context.next =
|
|
68
|
+
_context.next = 16;
|
|
54
69
|
break;
|
|
55
70
|
}
|
|
56
71
|
setStatus('rejected');
|
|
57
72
|
return _context.abrupt("return");
|
|
58
|
-
case
|
|
73
|
+
case 16:
|
|
59
74
|
isNewSearch = !pageCursor;
|
|
60
75
|
if (isNewSearch) {
|
|
61
76
|
setFilterOptions(mapFieldValuesToFilterOptions(response));
|
|
77
|
+
if (isRequestLikeInitialSearch) {
|
|
78
|
+
/**
|
|
79
|
+
* The initial dataset is used in couple of paths, eg: when a user searches and clears the search text.
|
|
80
|
+
* During these times, we dont want to fetch data again and again, hence a mini cache setup to store and provide the initial dataset
|
|
81
|
+
*/
|
|
82
|
+
initialData.current = response;
|
|
83
|
+
}
|
|
62
84
|
} else {
|
|
63
85
|
setFilterOptions([].concat(_toConsumableArray(filterOptions), _toConsumableArray(mapFieldValuesToFilterOptions(response))));
|
|
64
86
|
}
|
|
65
87
|
setTotalCount(mapFieldValuesToTotalCount(response));
|
|
66
88
|
setNextPageCursor(mapFieldValuesToPageCursor(response));
|
|
67
89
|
setStatus('resolved');
|
|
68
|
-
_context.next =
|
|
90
|
+
_context.next = 26;
|
|
69
91
|
break;
|
|
70
|
-
case
|
|
71
|
-
_context.prev =
|
|
72
|
-
_context.
|
|
92
|
+
case 23:
|
|
93
|
+
_context.prev = 23;
|
|
94
|
+
_context.t1 = _context["catch"](4);
|
|
73
95
|
setStatus('rejected');
|
|
74
|
-
case
|
|
96
|
+
case 26:
|
|
75
97
|
case "end":
|
|
76
98
|
return _context.stop();
|
|
77
99
|
}
|
|
78
|
-
}, _callee, null, [[
|
|
100
|
+
}, _callee, null, [[4, 23]]);
|
|
79
101
|
})), [cloudId, filterOptions, filterType, getFieldValues]);
|
|
80
102
|
return {
|
|
81
103
|
filterOptions: filterOptions,
|
package/dist/esm/ui/jira-issues-modal/basic-filters/ui/async-popup-select/dropdownIndicator.js
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import CloseIcon from '@atlaskit/icon/glyph/cross-circle';
|
|
3
|
+
import SearchIcon from '@atlaskit/icon/glyph/search';
|
|
4
|
+
import { Box, xcss } from '@atlaskit/primitives';
|
|
5
|
+
import { components } from '@atlaskit/select';
|
|
6
|
+
var customDropdownIndicatorStyles = xcss({
|
|
7
|
+
display: 'flex',
|
|
8
|
+
cursor: 'pointer',
|
|
9
|
+
justifyContent: 'center',
|
|
10
|
+
width: "var(--ds-space-400, 32px)"
|
|
11
|
+
});
|
|
12
|
+
var CustomDropdownIndicator = function CustomDropdownIndicator(props) {
|
|
13
|
+
var selectProps = props.selectProps;
|
|
14
|
+
return /*#__PURE__*/React.createElement(components.DropdownIndicator, props, /*#__PURE__*/React.createElement(Box, {
|
|
15
|
+
xcss: customDropdownIndicatorStyles,
|
|
16
|
+
onClick: function onClick() {
|
|
17
|
+
if (selectProps.inputValue) {
|
|
18
|
+
selectProps.onInputChange && selectProps.onInputChange('', {
|
|
19
|
+
action: 'input-change',
|
|
20
|
+
prevInputValue: selectProps.inputValue
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
}, selectProps.inputValue ? /*#__PURE__*/React.createElement(CloseIcon, {
|
|
25
|
+
size: "small",
|
|
26
|
+
label: ""
|
|
27
|
+
}) : /*#__PURE__*/React.createElement(SearchIcon, {
|
|
28
|
+
size: "small",
|
|
29
|
+
label: ""
|
|
30
|
+
})));
|
|
31
|
+
};
|
|
32
|
+
export default CustomDropdownIndicator;
|
|
@@ -4,11 +4,13 @@ import _asyncToGenerator from "@babel/runtime/helpers/asyncToGenerator";
|
|
|
4
4
|
import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
|
|
5
5
|
var _excluded = ["isOpen"];
|
|
6
6
|
import _regeneratorRuntime from "@babel/runtime/regenerator";
|
|
7
|
-
import React, { useCallback, useEffect, useRef, useState } from 'react';
|
|
7
|
+
import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
|
8
|
+
import debounce from 'lodash/debounce';
|
|
8
9
|
import { useIntl } from 'react-intl-next';
|
|
9
10
|
import { CheckboxOption, PopupSelect } from '@atlaskit/select';
|
|
10
11
|
import { useFilterOptions } from '../../hooks/useFilterOptions';
|
|
11
12
|
import CustomControl from './control';
|
|
13
|
+
import CustomDropdownIndicator from './dropdownIndicator';
|
|
12
14
|
import PopupFooter from './footer';
|
|
13
15
|
import formatOptionLabel from './formatOptionLabel';
|
|
14
16
|
import { asyncPopupSelectMessages } from './messages';
|
|
@@ -17,12 +19,15 @@ import PopupTrigger from './trigger';
|
|
|
17
19
|
var noFilterOptions = function noFilterOptions() {
|
|
18
20
|
return true;
|
|
19
21
|
};
|
|
22
|
+
var SEARCH_DEBOUNCE_MS = 350;
|
|
20
23
|
var AsyncPopupSelect = function AsyncPopupSelect(_ref) {
|
|
21
24
|
var filterType = _ref.filterType,
|
|
22
25
|
cloudId = _ref.cloudId,
|
|
23
26
|
selection = _ref.selection,
|
|
24
27
|
_ref$onSelectionChang = _ref.onSelectionChange,
|
|
25
|
-
onSelectionChange = _ref$onSelectionChang === void 0 ? function () {} : _ref$onSelectionChang
|
|
28
|
+
onSelectionChange = _ref$onSelectionChang === void 0 ? function () {} : _ref$onSelectionChang,
|
|
29
|
+
_ref$isDisabled = _ref.isDisabled,
|
|
30
|
+
isDisabled = _ref$isDisabled === void 0 ? false : _ref$isDisabled;
|
|
26
31
|
var _useIntl = useIntl(),
|
|
27
32
|
formatMessage = _useIntl.formatMessage;
|
|
28
33
|
var pickerRef = useRef(null);
|
|
@@ -42,30 +47,49 @@ var AsyncPopupSelect = function AsyncPopupSelect(_ref) {
|
|
|
42
47
|
fetchFilterOptions = _useFilterOptions.fetchFilterOptions,
|
|
43
48
|
totalCount = _useFilterOptions.totalCount,
|
|
44
49
|
status = _useFilterOptions.status;
|
|
45
|
-
var
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
+
var handleDebouncedFetchFilterOptions = useMemo(function () {
|
|
51
|
+
return debounce(fetchFilterOptions, SEARCH_DEBOUNCE_MS);
|
|
52
|
+
}, [fetchFilterOptions]);
|
|
53
|
+
var handleInputChange = useCallback( /*#__PURE__*/function () {
|
|
54
|
+
var _ref2 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee(newSearchTerm, actionMeta) {
|
|
55
|
+
return _regeneratorRuntime.wrap(function _callee$(_context) {
|
|
56
|
+
while (1) switch (_context.prev = _context.next) {
|
|
57
|
+
case 0:
|
|
58
|
+
if (actionMeta.action === 'input-change' && newSearchTerm !== searchTerm) {
|
|
59
|
+
setSearchTerm(newSearchTerm);
|
|
60
|
+
handleDebouncedFetchFilterOptions({
|
|
61
|
+
searchString: newSearchTerm
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
case 1:
|
|
65
|
+
case "end":
|
|
66
|
+
return _context.stop();
|
|
67
|
+
}
|
|
68
|
+
}, _callee);
|
|
69
|
+
}));
|
|
70
|
+
return function (_x, _x2) {
|
|
71
|
+
return _ref2.apply(this, arguments);
|
|
72
|
+
};
|
|
73
|
+
}(), [handleDebouncedFetchFilterOptions, searchTerm]);
|
|
50
74
|
var handleOptionSelection = function handleOptionSelection(newValue) {
|
|
51
75
|
setSelectedOptions(newValue);
|
|
52
76
|
onSelectionChange(newValue);
|
|
53
77
|
};
|
|
54
|
-
var handleOpenPopup = useCallback( /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function
|
|
55
|
-
return _regeneratorRuntime.wrap(function
|
|
56
|
-
while (1) switch (
|
|
78
|
+
var handleOpenPopup = useCallback( /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee2() {
|
|
79
|
+
return _regeneratorRuntime.wrap(function _callee2$(_context2) {
|
|
80
|
+
while (1) switch (_context2.prev = _context2.next) {
|
|
57
81
|
case 0:
|
|
58
82
|
if (!(status === 'empty')) {
|
|
59
|
-
|
|
83
|
+
_context2.next = 3;
|
|
60
84
|
break;
|
|
61
85
|
}
|
|
62
|
-
|
|
86
|
+
_context2.next = 3;
|
|
63
87
|
return fetchFilterOptions();
|
|
64
88
|
case 3:
|
|
65
89
|
case "end":
|
|
66
|
-
return
|
|
90
|
+
return _context2.stop();
|
|
67
91
|
}
|
|
68
|
-
},
|
|
92
|
+
}, _callee2);
|
|
69
93
|
})), [fetchFilterOptions, status]);
|
|
70
94
|
useEffect(function () {
|
|
71
95
|
if (status === 'resolved') {
|
|
@@ -75,6 +99,9 @@ var AsyncPopupSelect = function AsyncPopupSelect(_ref) {
|
|
|
75
99
|
}
|
|
76
100
|
}, [status]);
|
|
77
101
|
var isLoading = status === 'loading' || status === 'empty';
|
|
102
|
+
var shouldShowFooter = status === 'resolved' && filterOptions.length > 0;
|
|
103
|
+
var options = isLoading ? [] : filterOptions; // if not set to [], then on loading, no loading UI will be shown
|
|
104
|
+
|
|
78
105
|
return /*#__PURE__*/React.createElement(PopupSelect, {
|
|
79
106
|
isMulti: true,
|
|
80
107
|
maxMenuWidth: 300,
|
|
@@ -96,24 +123,28 @@ var AsyncPopupSelect = function AsyncPopupSelect(_ref) {
|
|
|
96
123
|
components: {
|
|
97
124
|
/* @ts-expect-error - This component has stricter OptionType, hence a temp setup untill its made generic */
|
|
98
125
|
Option: CheckboxOption,
|
|
99
|
-
Control: CustomControl
|
|
126
|
+
Control: CustomControl,
|
|
127
|
+
LoadingIndicator: undefined,
|
|
128
|
+
// disables the three ... indicator in the searchbox when picker is loading
|
|
129
|
+
DropdownIndicator: CustomDropdownIndicator
|
|
100
130
|
},
|
|
101
|
-
options:
|
|
131
|
+
options: options,
|
|
102
132
|
value: selectedOptions,
|
|
103
133
|
filterOption: noFilterOptions,
|
|
104
134
|
formatOptionLabel: formatOptionLabel,
|
|
105
135
|
onChange: handleOptionSelection,
|
|
106
136
|
onInputChange: handleInputChange,
|
|
107
|
-
target: function target(
|
|
108
|
-
var isOpen =
|
|
109
|
-
triggerProps = _objectWithoutProperties(
|
|
137
|
+
target: function target(_ref4) {
|
|
138
|
+
var isOpen = _ref4.isOpen,
|
|
139
|
+
triggerProps = _objectWithoutProperties(_ref4, _excluded);
|
|
110
140
|
return /*#__PURE__*/React.createElement(PopupTrigger, _extends({}, triggerProps, {
|
|
111
141
|
filterType: filterType,
|
|
112
142
|
isSelected: isOpen,
|
|
113
|
-
onClick: handleOpenPopup
|
|
143
|
+
onClick: handleOpenPopup,
|
|
144
|
+
isDisabled: isDisabled
|
|
114
145
|
}));
|
|
115
146
|
},
|
|
116
|
-
footer: /*#__PURE__*/React.createElement(PopupFooter, {
|
|
147
|
+
footer: shouldShowFooter && /*#__PURE__*/React.createElement(PopupFooter, {
|
|
117
148
|
currentDisplayCount: filterOptions.length,
|
|
118
149
|
totalCount: totalCount
|
|
119
150
|
})
|
|
@@ -6,11 +6,13 @@ import { asyncPopupSelectMessages } from './messages';
|
|
|
6
6
|
var PopupTrigger = /*#__PURE__*/forwardRef(function (_ref, ref) {
|
|
7
7
|
var filterType = _ref.filterType,
|
|
8
8
|
isSelected = _ref.isSelected,
|
|
9
|
+
isDisabled = _ref.isDisabled,
|
|
9
10
|
onClick = _ref.onClick;
|
|
10
11
|
return /*#__PURE__*/React.createElement(Button, {
|
|
11
12
|
ref: ref,
|
|
12
13
|
appearance: "default",
|
|
13
14
|
isSelected: isSelected,
|
|
15
|
+
isDisabled: isDisabled,
|
|
14
16
|
onClick: onClick,
|
|
15
17
|
testId: "jlol-basic-filter-".concat(filterType, "-trigger"),
|
|
16
18
|
iconAfter: /*#__PURE__*/React.createElement(ChevronDownIcon, {
|
package/dist/types/ui/jira-issues-modal/basic-filters/ui/async-popup-select/dropdownIndicator.d.ts
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
/// <reference types="react" />
|
|
2
|
+
import { DropdownIndicatorProps } from '@atlaskit/select';
|
|
3
|
+
import { SelectOption } from '../../types';
|
|
4
|
+
declare const CustomDropdownIndicator: (props: DropdownIndicatorProps<SelectOption, true>) => JSX.Element;
|
|
5
|
+
export default CustomDropdownIndicator;
|
|
@@ -5,6 +5,7 @@ export interface AsyncPopupSelectProps {
|
|
|
5
5
|
cloudId: string;
|
|
6
6
|
selection: SelectOption[];
|
|
7
7
|
onSelectionChange?: (selection: SelectOption[]) => void;
|
|
8
|
+
isDisabled?: boolean;
|
|
8
9
|
}
|
|
9
|
-
declare const AsyncPopupSelect: ({ filterType, cloudId, selection, onSelectionChange, }: AsyncPopupSelectProps) => JSX.Element;
|
|
10
|
+
declare const AsyncPopupSelect: ({ filterType, cloudId, selection, onSelectionChange, isDisabled, }: AsyncPopupSelectProps) => JSX.Element;
|
|
10
11
|
export default AsyncPopupSelect;
|
|
@@ -3,6 +3,7 @@ import { BasicFilterFieldType } from '../../types';
|
|
|
3
3
|
export interface PopupTriggerProps {
|
|
4
4
|
filterType: BasicFilterFieldType;
|
|
5
5
|
isSelected?: boolean;
|
|
6
|
+
isDisabled?: boolean;
|
|
6
7
|
onClick?: () => void;
|
|
7
8
|
}
|
|
8
9
|
declare const PopupTrigger: React.ForwardRefExoticComponent<PopupTriggerProps & React.RefAttributes<HTMLElement>>;
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
/// <reference types="react" />
|
|
2
|
+
import { DropdownIndicatorProps } from '@atlaskit/select';
|
|
3
|
+
import { SelectOption } from '../../types';
|
|
4
|
+
declare const CustomDropdownIndicator: (props: DropdownIndicatorProps<SelectOption, true>) => JSX.Element;
|
|
5
|
+
export default CustomDropdownIndicator;
|
package/dist/types-ts4.5/ui/jira-issues-modal/basic-filters/ui/async-popup-select/index.d.ts
CHANGED
|
@@ -5,6 +5,7 @@ export interface AsyncPopupSelectProps {
|
|
|
5
5
|
cloudId: string;
|
|
6
6
|
selection: SelectOption[];
|
|
7
7
|
onSelectionChange?: (selection: SelectOption[]) => void;
|
|
8
|
+
isDisabled?: boolean;
|
|
8
9
|
}
|
|
9
|
-
declare const AsyncPopupSelect: ({ filterType, cloudId, selection, onSelectionChange, }: AsyncPopupSelectProps) => JSX.Element;
|
|
10
|
+
declare const AsyncPopupSelect: ({ filterType, cloudId, selection, onSelectionChange, isDisabled, }: AsyncPopupSelectProps) => JSX.Element;
|
|
10
11
|
export default AsyncPopupSelect;
|
package/dist/types-ts4.5/ui/jira-issues-modal/basic-filters/ui/async-popup-select/trigger.d.ts
CHANGED
|
@@ -3,6 +3,7 @@ import { BasicFilterFieldType } from '../../types';
|
|
|
3
3
|
export interface PopupTriggerProps {
|
|
4
4
|
filterType: BasicFilterFieldType;
|
|
5
5
|
isSelected?: boolean;
|
|
6
|
+
isDisabled?: boolean;
|
|
6
7
|
onClick?: () => void;
|
|
7
8
|
}
|
|
8
9
|
declare const PopupTrigger: React.ForwardRefExoticComponent<PopupTriggerProps & React.RefAttributes<HTMLElement>>;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@atlaskit/link-datasource",
|
|
3
|
-
"version": "1.13.
|
|
3
|
+
"version": "1.13.2",
|
|
4
4
|
"description": "UI Components to support linking platform dataset feature",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"registry": "https://registry.npmjs.org/"
|
|
@@ -45,8 +45,7 @@
|
|
|
45
45
|
"@atlaskit/jql-ast": "^3.0.0",
|
|
46
46
|
"@atlaskit/jql-editor-autocomplete-rest": "^2.0.0",
|
|
47
47
|
"@atlaskit/link-client-extension": "^1.8.0",
|
|
48
|
-
"@atlaskit/
|
|
49
|
-
"@atlaskit/linking-common": "^4.15.0",
|
|
48
|
+
"@atlaskit/linking-common": "^4.16.0",
|
|
50
49
|
"@atlaskit/linking-types": "^8.4.0",
|
|
51
50
|
"@atlaskit/lozenge": "^11.4.0",
|
|
52
51
|
"@atlaskit/modal-dialog": "^12.8.0",
|
|
@@ -82,6 +81,7 @@
|
|
|
82
81
|
"devDependencies": {
|
|
83
82
|
"@af/integration-testing": "*",
|
|
84
83
|
"@af/visual-regression": "*",
|
|
84
|
+
"@atlaskit/link-provider": "^1.6.12",
|
|
85
85
|
"@atlaskit/link-test-helpers": "^6.2.0",
|
|
86
86
|
"@atlaskit/ssr": "*",
|
|
87
87
|
"@atlaskit/visual-regression": "*",
|