@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.
Files changed (38) hide show
  1. package/CHANGELOG.md +18 -0
  2. package/dist/cjs/analytics/constants.js +1 -1
  3. package/dist/cjs/hooks/useDatasourceTableState.js +83 -52
  4. package/dist/cjs/ui/jira-issues-modal/basic-filters/hooks/useFilterOptions.js +18 -11
  5. package/dist/cjs/ui/jira-issues-modal/basic-filters/ui/async-popup-select/index.js +62 -17
  6. package/dist/cjs/ui/jira-issues-modal/basic-filters/ui/async-popup-select/trigger.js +26 -3
  7. package/dist/cjs/ui/jira-issues-modal/basic-filters/ui/index.js +6 -3
  8. package/dist/cjs/ui/jira-issues-modal/basic-filters/ui/menu-list/errorMessage.js +39 -2
  9. package/dist/cjs/ui/jira-issues-modal/basic-filters/ui/menu-list/index.js +6 -2
  10. package/dist/es2019/analytics/constants.js +1 -1
  11. package/dist/es2019/hooks/useDatasourceTableState.js +40 -12
  12. package/dist/es2019/ui/jira-issues-modal/basic-filters/hooks/useFilterOptions.js +5 -1
  13. package/dist/es2019/ui/jira-issues-modal/basic-filters/ui/async-popup-select/index.js +45 -18
  14. package/dist/es2019/ui/jira-issues-modal/basic-filters/ui/async-popup-select/trigger.js +23 -3
  15. package/dist/es2019/ui/jira-issues-modal/basic-filters/ui/index.js +5 -3
  16. package/dist/es2019/ui/jira-issues-modal/basic-filters/ui/menu-list/errorMessage.js +33 -2
  17. package/dist/es2019/ui/jira-issues-modal/basic-filters/ui/menu-list/index.js +5 -1
  18. package/dist/esm/analytics/constants.js +1 -1
  19. package/dist/esm/hooks/useDatasourceTableState.js +83 -52
  20. package/dist/esm/ui/jira-issues-modal/basic-filters/hooks/useFilterOptions.js +18 -11
  21. package/dist/esm/ui/jira-issues-modal/basic-filters/ui/async-popup-select/index.js +63 -18
  22. package/dist/esm/ui/jira-issues-modal/basic-filters/ui/async-popup-select/trigger.js +26 -3
  23. package/dist/esm/ui/jira-issues-modal/basic-filters/ui/index.js +7 -4
  24. package/dist/esm/ui/jira-issues-modal/basic-filters/ui/menu-list/errorMessage.js +36 -2
  25. package/dist/esm/ui/jira-issues-modal/basic-filters/ui/menu-list/index.js +6 -2
  26. package/dist/types/analytics/generated/analytics.types.d.ts +8 -1
  27. package/dist/types/services/cmdbService.utils.d.ts +1 -1
  28. package/dist/types/ui/jira-issues-modal/basic-filters/hooks/useFilterOptions.d.ts +1 -0
  29. package/dist/types/ui/jira-issues-modal/basic-filters/ui/async-popup-select/trigger.d.ts +2 -1
  30. package/dist/types/ui/jira-issues-modal/basic-filters/ui/menu-list/errorMessage.d.ts +6 -1
  31. package/dist/types/ui/jira-issues-modal/basic-filters/ui/menu-list/index.d.ts +3 -1
  32. package/dist/types-ts4.5/analytics/generated/analytics.types.d.ts +8 -1
  33. package/dist/types-ts4.5/services/cmdbService.utils.d.ts +1 -1
  34. package/dist/types-ts4.5/ui/jira-issues-modal/basic-filters/hooks/useFilterOptions.d.ts +1 -0
  35. package/dist/types-ts4.5/ui/jira-issues-modal/basic-filters/ui/async-popup-select/trigger.d.ts +2 -1
  36. package/dist/types-ts4.5/ui/jira-issues-modal/basic-filters/ui/menu-list/errorMessage.d.ts +6 -1
  37. package/dist/types-ts4.5/ui/jira-issues-modal/basic-filters/ui/menu-list/index.d.ts +3 -1
  38. package/package.json +3 -2
package/CHANGELOG.md CHANGED
@@ -1,5 +1,23 @@
1
1
  # @atlaskit/link-datasource
2
2
 
3
+ ## 1.17.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [#43023](https://bitbucket.org/atlassian/atlassian-frontend/pull-requests/43023) [`312be02e858`](https://bitbucket.org/atlassian/atlassian-frontend/commits/312be02e858) - [ux] Basic filter dropdown button label now includes first selected item's name. If multiple items are selected then a badge now indicates the remaining number of items. Selected options are also reordered to the top of the select list.
8
+
9
+ ### Patch Changes
10
+
11
+ - [#42504](https://bitbucket.org/atlassian/atlassian-frontend/pull-requests/42504) [`8ee7afb2d85`](https://bitbucket.org/atlassian/atlassian-frontend/commits/8ee7afb2d85) - Added DatasourceDataSchema model.
12
+ Used fields in the request for applying schema.
13
+ - Updated dependencies
14
+
15
+ ## 1.16.5
16
+
17
+ ### Patch Changes
18
+
19
+ - [#43103](https://bitbucket.org/atlassian/atlassian-frontend/pull-requests/43103) [`effb3f0234c`](https://bitbucket.org/atlassian/atlassian-frontend/commits/effb3f0234c) - Add ui analytics event when error UI is displayed for basic filter search.
20
+
3
21
  ## 1.16.4
4
22
 
5
23
  ### Patch Changes
@@ -7,5 +7,5 @@ exports.packageMetaData = exports.EVENT_CHANNEL = void 0;
7
7
  var EVENT_CHANNEL = exports.EVENT_CHANNEL = 'media';
8
8
  var packageMetaData = exports.packageMetaData = {
9
9
  packageName: "@atlaskit/link-datasource",
10
- packageVersion: "1.16.4"
10
+ packageVersion: "1.17.0"
11
11
  };
@@ -20,6 +20,8 @@ var useDatasourceTableState = exports.useDatasourceTableState = function useData
20
20
  fieldKeys = _ref$fieldKeys === void 0 ? [] : _ref$fieldKeys;
21
21
  var _useDatasourceAnalyti = (0, _analytics.useDatasourceAnalyticsEvents)(),
22
22
  fireEvent = _useDatasourceAnalyti.fireEvent;
23
+ var idFieldCount = 1;
24
+ var keyFieldCount = 1;
23
25
  var _useState = (0, _react.useState)([]),
24
26
  _useState2 = (0, _slicedToArray2.default)(_useState, 2),
25
27
  defaultVisibleColumnKeys = _useState2[0],
@@ -28,42 +30,48 @@ var useDatasourceTableState = exports.useDatasourceTableState = function useData
28
30
  _useState4 = (0, _slicedToArray2.default)(_useState3, 2),
29
31
  lastRequestedFieldKeys = _useState4[0],
30
32
  setLastRequestedFieldKeys = _useState4[1];
31
- var _useState5 = (0, _react.useState)('empty'),
33
+ var _useState5 = (0, _react.useState)({
34
+ properties: []
35
+ }),
32
36
  _useState6 = (0, _slicedToArray2.default)(_useState5, 2),
33
- status = _useState6[0],
34
- setStatus = _useState6[1];
35
- var _useState7 = (0, _react.useState)([]),
37
+ fullSchema = _useState6[0],
38
+ setFullSchema = _useState6[1];
39
+ var _useState7 = (0, _react.useState)('empty'),
36
40
  _useState8 = (0, _slicedToArray2.default)(_useState7, 2),
37
- responseItems = _useState8[0],
38
- setResponseItems = _useState8[1];
39
- var _useState9 = (0, _react.useState)(true),
41
+ status = _useState8[0],
42
+ setStatus = _useState8[1];
43
+ var _useState9 = (0, _react.useState)([]),
40
44
  _useState10 = (0, _slicedToArray2.default)(_useState9, 2),
41
- hasNextPage = _useState10[0],
42
- setHasNextPage = _useState10[1];
43
- var _useState11 = (0, _react.useState)(undefined),
45
+ responseItems = _useState10[0],
46
+ setResponseItems = _useState10[1];
47
+ var _useState11 = (0, _react.useState)(true),
44
48
  _useState12 = (0, _slicedToArray2.default)(_useState11, 2),
45
- nextCursor = _useState12[0],
46
- setNextCursor = _useState12[1];
47
- var _useState13 = (0, _react.useState)([]),
49
+ hasNextPage = _useState12[0],
50
+ setHasNextPage = _useState12[1];
51
+ var _useState13 = (0, _react.useState)(undefined),
48
52
  _useState14 = (0, _slicedToArray2.default)(_useState13, 2),
49
- columns = _useState14[0],
50
- setColumns = _useState14[1];
51
- var _useState15 = (0, _react.useState)(undefined),
53
+ nextCursor = _useState14[0],
54
+ setNextCursor = _useState14[1];
55
+ var _useState15 = (0, _react.useState)([]),
52
56
  _useState16 = (0, _slicedToArray2.default)(_useState15, 2),
53
- totalCount = _useState16[0],
54
- setTotalCount = _useState16[1];
55
- var _useState17 = (0, _react.useState)(false),
57
+ columns = _useState16[0],
58
+ setColumns = _useState16[1];
59
+ var _useState17 = (0, _react.useState)(undefined),
56
60
  _useState18 = (0, _slicedToArray2.default)(_useState17, 2),
57
- shouldForceRequest = _useState18[0],
58
- setShouldForceRequest = _useState18[1];
59
- var _useState19 = (0, _react.useState)([]),
61
+ totalCount = _useState18[0],
62
+ setTotalCount = _useState18[1];
63
+ var _useState19 = (0, _react.useState)(false),
60
64
  _useState20 = (0, _slicedToArray2.default)(_useState19, 2),
61
- destinationObjectTypes = _useState20[0],
62
- setDestinationObjectTypes = _useState20[1];
63
- var _useState21 = (0, _react.useState)(),
65
+ shouldForceRequest = _useState20[0],
66
+ setShouldForceRequest = _useState20[1];
67
+ var _useState21 = (0, _react.useState)([]),
64
68
  _useState22 = (0, _slicedToArray2.default)(_useState21, 2),
65
- extensionKey = _useState22[0],
66
- setExtensionKey = _useState22[1];
69
+ destinationObjectTypes = _useState22[0],
70
+ setDestinationObjectTypes = _useState22[1];
71
+ var _useState23 = (0, _react.useState)(),
72
+ _useState24 = (0, _slicedToArray2.default)(_useState23, 2),
73
+ extensionKey = _useState24[0],
74
+ setExtensionKey = _useState24[1];
67
75
  var _useDatasourceClientE = (0, _linkClientExtension.useDatasourceClientExtension)(),
68
76
  getDatasourceData = _useDatasourceClientE.getDatasourceData,
69
77
  getDatasourceDetails = _useDatasourceClientE.getDatasourceDetails;
@@ -121,21 +129,39 @@ var useDatasourceTableState = exports.useDatasourceTableState = function useData
121
129
  }
122
130
  }, _callee, null, [[2, 17]]);
123
131
  })), [columns, datasourceId, getDatasourceDetails, parameters]);
124
- var applySchemaProperties = (0, _react.useCallback)(function (properties) {
125
- if (!(0, _isEqual.default)(columns, properties)) {
126
- setColumns(properties);
132
+ var applySchemaProperties = (0, _react.useCallback)(function (schema, fieldKeys) {
133
+ var properties = schema.properties,
134
+ _schema$defaultProper = schema.defaultProperties,
135
+ defaultProperties = _schema$defaultProper === void 0 ? [] : _schema$defaultProper;
136
+ var propertiesToBeUsed = properties;
137
+ var propertyKeysToBeUsed = Array.isArray(fieldKeys) && fieldKeys.length > 0 ? fieldKeys : defaultProperties;
138
+ if (fieldKeys.length > 0 || defaultProperties.length > 0) {
139
+ propertiesToBeUsed = properties.filter(function (property) {
140
+ return propertyKeysToBeUsed.includes(property.key);
141
+ });
142
+ }
143
+
144
+ /*Jira adds identifier fields like id and key to all data responses
145
+ Since defaultProperties already send back the keyField, we are accounting only
146
+ for the idField when we are using defaulProperties
147
+ */
148
+ if (properties.length > fieldKeys.length + idFieldCount + keyFieldCount && properties.length > defaultProperties.length + idFieldCount) {
149
+ setFullSchema(schema);
127
150
  }
128
- var defaultProperties = properties.map(function (prop) {
151
+ if (!(0, _isEqual.default)(columns, propertiesToBeUsed)) {
152
+ setColumns(propertiesToBeUsed);
153
+ }
154
+ var newProperties = propertiesToBeUsed.map(function (prop) {
129
155
  return prop.key;
130
156
  });
131
157
 
132
158
  // when loading for the first time, we will need to set default visible props as /data does not give you that info
133
159
  // also, since we dont pass any fields, we will need to set this info as lastRequestedFieldKeys
134
- if (!(0, _isEqual.default)(defaultVisibleColumnKeys, defaultProperties)) {
135
- setDefaultVisibleColumnKeys(defaultProperties);
160
+ if (!(0, _isEqual.default)(defaultVisibleColumnKeys, newProperties)) {
161
+ setDefaultVisibleColumnKeys(newProperties);
136
162
  }
137
- if (!(0, _isEqual.default)(lastRequestedFieldKeys, defaultProperties)) {
138
- setLastRequestedFieldKeys(defaultProperties);
163
+ if (!(0, _isEqual.default)(lastRequestedFieldKeys, newProperties)) {
164
+ setLastRequestedFieldKeys(newProperties);
139
165
  }
140
166
  }, [columns, defaultVisibleColumnKeys, lastRequestedFieldKeys]);
141
167
  var onNextPage = (0, _react.useCallback)( /*#__PURE__*/(0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee2() {
@@ -145,6 +171,7 @@ var useDatasourceTableState = exports.useDatasourceTableState = function useData
145
171
  shouldRequestFirstPage,
146
172
  _requestInfo$shouldFo,
147
173
  shouldForceRequest,
174
+ isFullSchemaLoaded,
148
175
  datasourceDataRequest,
149
176
  _yield$getDatasourceD2,
150
177
  _yield$getDatasourceD3,
@@ -171,18 +198,19 @@ var useDatasourceTableState = exports.useDatasourceTableState = function useData
171
198
  return _context2.abrupt("return");
172
199
  case 3:
173
200
  _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;
201
+ isFullSchemaLoaded = fullSchema.properties.length > 0;
174
202
  datasourceDataRequest = {
175
203
  parameters: parameters,
176
204
  pageSize: _linkClientExtension.DEFAULT_GET_DATASOURCE_DATA_PAGE_SIZE,
177
205
  pageCursor: shouldRequestFirstPage ? undefined : nextCursor,
178
206
  fields: fieldKeys,
179
- includeSchema: isSchemaFromData
207
+ includeSchema: isFullSchemaLoaded ? false : isSchemaFromData
180
208
  };
181
209
  setStatus('loading');
182
- _context2.prev = 6;
183
- _context2.next = 9;
210
+ _context2.prev = 7;
211
+ _context2.next = 10;
184
212
  return getDatasourceData(datasourceId, datasourceDataRequest, shouldForceRequest);
185
- case 9:
213
+ case 10:
186
214
  _yield$getDatasourceD2 = _context2.sent;
187
215
  _yield$getDatasourceD3 = _yield$getDatasourceD2.meta;
188
216
  access = _yield$getDatasourceD3.access;
@@ -194,12 +222,12 @@ var useDatasourceTableState = exports.useDatasourceTableState = function useData
194
222
  _totalCount = _yield$getDatasourceD4.totalCount;
195
223
  schema = _yield$getDatasourceD4.schema;
196
224
  if (!(access === 'forbidden' || access === 'unauthorized')) {
197
- _context2.next = 22;
225
+ _context2.next = 23;
198
226
  break;
199
227
  }
200
228
  setStatus('unauthorized');
201
229
  return _context2.abrupt("return");
202
- case 22:
230
+ case 23:
203
231
  setExtensionKey(_extensionKey);
204
232
  setDestinationObjectTypes(_destinationObjectTypes);
205
233
  setTotalCount(_totalCount);
@@ -214,8 +242,8 @@ var useDatasourceTableState = exports.useDatasourceTableState = function useData
214
242
  if (fieldKeys.length > 0) {
215
243
  setLastRequestedFieldKeys(fieldKeys);
216
244
  }
217
- if (isSchemaFromData && schema && items.length > 0) {
218
- applySchemaProperties(schema.properties);
245
+ if ((isSchemaFromData && schema || fullSchema.properties.length > 0) && items.length > 0) {
246
+ applySchemaProperties(schema || fullSchema, fieldKeys);
219
247
  }
220
248
  isUserLoadingNextPage = (responseItems === null || responseItems === void 0 ? void 0 : responseItems.length) !== 0 && !shouldRequestFirstPage;
221
249
  if (isUserLoadingNextPage) {
@@ -228,25 +256,25 @@ var useDatasourceTableState = exports.useDatasourceTableState = function useData
228
256
  });
229
257
  }
230
258
  setStatus('resolved');
231
- _context2.next = 41;
259
+ _context2.next = 42;
232
260
  break;
233
- case 35:
234
- _context2.prev = 35;
235
- _context2.t0 = _context2["catch"](6);
261
+ case 36:
262
+ _context2.prev = 36;
263
+ _context2.t0 = _context2["catch"](7);
236
264
  if (!(_context2.t0 instanceof Response && (_context2.t0.status === 401 || _context2.t0.status === 403))) {
237
- _context2.next = 40;
265
+ _context2.next = 41;
238
266
  break;
239
267
  }
240
268
  setStatus('unauthorized');
241
269
  return _context2.abrupt("return");
242
- case 40:
243
- setStatus('rejected');
244
270
  case 41:
271
+ setStatus('rejected');
272
+ case 42:
245
273
  case "end":
246
274
  return _context2.stop();
247
275
  }
248
- }, _callee2, null, [[6, 35]]);
249
- })), [parameters, fieldKeys, nextCursor, getDatasourceData, datasourceId, responseItems === null || responseItems === void 0 ? void 0 : responseItems.length, applySchemaProperties, fireEvent]);
276
+ }, _callee2, null, [[7, 36]]);
277
+ })), [parameters, fieldKeys, nextCursor, getDatasourceData, datasourceId, responseItems === null || responseItems === void 0 ? void 0 : responseItems.length, applySchemaProperties, fireEvent, fullSchema]);
250
278
  var reset = (0, _react.useCallback)(function (options) {
251
279
  setStatus('empty');
252
280
  setResponseItems([]);
@@ -254,6 +282,9 @@ var useDatasourceTableState = exports.useDatasourceTableState = function useData
254
282
  setNextCursor(undefined);
255
283
  setTotalCount(undefined);
256
284
  setLastRequestedFieldKeys([]);
285
+ setFullSchema({
286
+ properties: []
287
+ });
257
288
  setShouldForceRequest((options === null || options === void 0 ? void 0 : options.shouldForceRequest) || false);
258
289
  if (options !== null && options !== void 0 && options.shouldResetColumns) {
259
290
  setColumns([]);
@@ -27,10 +27,14 @@ var useFilterOptions = exports.useFilterOptions = function useFilterOptions(_ref
27
27
  _useState6 = (0, _slicedToArray2.default)(_useState5, 2),
28
28
  status = _useState6[0],
29
29
  setStatus = _useState6[1];
30
- var _useState7 = (0, _react.useState)(undefined),
30
+ var _useState7 = (0, _react.useState)([]),
31
31
  _useState8 = (0, _slicedToArray2.default)(_useState7, 2),
32
- nextPageCursor = _useState8[0],
33
- setNextPageCursor = _useState8[1];
32
+ errors = _useState8[0],
33
+ setErrors = _useState8[1];
34
+ var _useState9 = (0, _react.useState)(undefined),
35
+ _useState10 = (0, _slicedToArray2.default)(_useState9, 2),
36
+ nextPageCursor = _useState10[0],
37
+ setNextPageCursor = _useState10[1];
34
38
  var initialData = (0, _react.useRef)();
35
39
  var _useBasicFilterAGG = (0, _useBasicFilterAGG2.useBasicFilterAGG)(),
36
40
  getFieldValues = _useBasicFilterAGG.getFieldValues;
@@ -73,12 +77,13 @@ var useFilterOptions = exports.useFilterOptions = function useFilterOptions(_ref
73
77
  case 13:
74
78
  response = _context.t0;
75
79
  if (!(response.errors && response.errors.length > 0)) {
76
- _context.next = 17;
80
+ _context.next = 18;
77
81
  break;
78
82
  }
79
83
  setStatus('rejected');
84
+ setErrors(response.errors);
80
85
  return _context.abrupt("return");
81
- case 17:
86
+ case 18:
82
87
  if (isNewSearch) {
83
88
  setFilterOptions((0, _transformers.mapFieldValuesToFilterOptions)(response));
84
89
  if (isRequestLikeInitialSearch) {
@@ -94,23 +99,25 @@ var useFilterOptions = exports.useFilterOptions = function useFilterOptions(_ref
94
99
  setTotalCount((0, _transformers.mapFieldValuesToTotalCount)(response));
95
100
  setNextPageCursor((0, _transformers.mapFieldValuesToPageCursor)(response));
96
101
  setStatus('resolved');
97
- _context.next = 26;
102
+ _context.next = 28;
98
103
  break;
99
- case 23:
100
- _context.prev = 23;
104
+ case 24:
105
+ _context.prev = 24;
101
106
  _context.t1 = _context["catch"](5);
107
+ setErrors([_context.t1]);
102
108
  setStatus('rejected');
103
- case 26:
109
+ case 28:
104
110
  case "end":
105
111
  return _context.stop();
106
112
  }
107
- }, _callee, null, [[5, 23]]);
113
+ }, _callee, null, [[5, 24]]);
108
114
  })), [cloudId, filterOptions, filterType, getFieldValues]);
109
115
  return {
110
116
  filterOptions: filterOptions,
111
117
  fetchFilterOptions: fetchFilterOptions,
112
118
  totalCount: totalCount,
113
119
  pageCursor: nextPageCursor,
114
- status: status
120
+ status: status,
121
+ errors: status === 'rejected' ? errors : []
115
122
  };
116
123
  };
@@ -9,6 +9,7 @@ exports.default = exports.SEARCH_DEBOUNCE_MS = void 0;
9
9
  var _objectWithoutProperties2 = _interopRequireDefault(require("@babel/runtime/helpers/objectWithoutProperties"));
10
10
  var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator"));
11
11
  var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));
12
+ var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
12
13
  var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator"));
13
14
  var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
14
15
  var _react = _interopRequireWildcard(require("react"));
@@ -41,7 +42,6 @@ var AsyncPopupSelect = function AsyncPopupSelect(_ref) {
41
42
  isDisabled = _ref$isDisabled === void 0 ? false : _ref$isDisabled;
42
43
  var _useIntl = (0, _reactIntlNext.useIntl)(),
43
44
  formatMessage = _useIntl.formatMessage;
44
- var pickerRef = (0, _react.useRef)(null);
45
45
  var _useState = (0, _react.useState)(''),
46
46
  _useState2 = (0, _slicedToArray2.default)(_useState, 2),
47
47
  searchTerm = _useState2[0],
@@ -50,6 +50,10 @@ var AsyncPopupSelect = function AsyncPopupSelect(_ref) {
50
50
  _useState4 = (0, _slicedToArray2.default)(_useState3, 2),
51
51
  selectedOptions = _useState4[0],
52
52
  setSelectedOptions = _useState4[1];
53
+ var _useState5 = (0, _react.useState)(selectedOptions),
54
+ _useState6 = (0, _slicedToArray2.default)(_useState5, 2),
55
+ sortedOptions = _useState6[0],
56
+ setSortedOptions = _useState6[1];
53
57
  var _useFilterOptions = (0, _useFilterOptions2.useFilterOptions)({
54
58
  filterType: filterType,
55
59
  cloudId: cloudId
@@ -58,7 +62,8 @@ var AsyncPopupSelect = function AsyncPopupSelect(_ref) {
58
62
  fetchFilterOptions = _useFilterOptions.fetchFilterOptions,
59
63
  totalCount = _useFilterOptions.totalCount,
60
64
  status = _useFilterOptions.status,
61
- pageCursor = _useFilterOptions.pageCursor;
65
+ pageCursor = _useFilterOptions.pageCursor,
66
+ errors = _useFilterOptions.errors;
62
67
  var _useDebouncedCallback = (0, _useDebounce.useDebouncedCallback)(function (searchString) {
63
68
  fetchFilterOptions({
64
69
  searchString: searchString
@@ -89,14 +94,46 @@ var AsyncPopupSelect = function AsyncPopupSelect(_ref) {
89
94
  setSelectedOptions(newValue);
90
95
  onSelectionChange(newValue);
91
96
  };
92
- var handleOpenPopup = (0, _react.useCallback)(function () {
93
- if (status === 'empty' || status === 'rejected') {
94
- // 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
95
- fetchFilterOptions({
96
- searchString: searchTerm
97
+ var sortOptionsOnPopupOpen = (0, _react.useCallback)(function () {
98
+ if (selectedOptions.length === 0) {
99
+ setSortedOptions(filterOptions);
100
+ return;
101
+ }
102
+ var nonSelectedOptions = filterOptions.filter(function (option) {
103
+ return !selectedOptions.find(function (selectedOption) {
104
+ return selectedOption.value === option.value;
105
+ });
106
+ });
107
+ var newOptions = [].concat((0, _toConsumableArray2.default)(selectedOptions), (0, _toConsumableArray2.default)(nonSelectedOptions));
108
+ setSortedOptions(newOptions);
109
+ }, [selectedOptions, filterOptions]);
110
+ var sortOptionsOnResolve = (0, _react.useCallback)(function () {
111
+ var newOptions = filterOptions.filter(function (option) {
112
+ return !sortedOptions.find(function (sortedOption) {
113
+ return sortedOption.value === option.value;
114
+ });
115
+ });
116
+ var shouldSetSortOptions = false;
117
+ if (sortedOptions.length !== filterOptions.length) {
118
+ shouldSetSortOptions = true;
119
+ } else {
120
+ sortedOptions.forEach(function (sortedOption) {
121
+ if (!filterOptions.some(function (filterOption) {
122
+ return filterOption.value === sortedOption.value;
123
+ })) {
124
+ shouldSetSortOptions = true;
125
+ }
97
126
  });
98
127
  }
99
- }, [fetchFilterOptions, searchTerm, status]);
128
+ if (shouldSetSortOptions) {
129
+ var sortedOptionsFiltered = sortedOptions.filter(function (sortedOption) {
130
+ return filterOptions.some(function (filterOption) {
131
+ return filterOption.value === sortedOption.value;
132
+ });
133
+ });
134
+ setSortedOptions([].concat((0, _toConsumableArray2.default)(sortedOptionsFiltered), (0, _toConsumableArray2.default)(newOptions)));
135
+ }
136
+ }, [filterOptions, sortedOptions]);
100
137
  var handleShowMore = (0, _react.useCallback)(function () {
101
138
  if (pageCursor) {
102
139
  fetchFilterOptions({
@@ -105,28 +142,34 @@ var AsyncPopupSelect = function AsyncPopupSelect(_ref) {
105
142
  });
106
143
  }
107
144
  }, [fetchFilterOptions, pageCursor, searchTerm]);
145
+ var handleOpenPopup = (0, _react.useCallback)(function () {
146
+ if (status === 'empty' || status === 'rejected') {
147
+ // 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
148
+ fetchFilterOptions({
149
+ searchString: searchTerm
150
+ });
151
+ } else if (status === 'resolved') {
152
+ sortOptionsOnPopupOpen();
153
+ }
154
+ }, [fetchFilterOptions, searchTerm, sortOptionsOnPopupOpen, status]);
108
155
  (0, _react.useEffect)(function () {
109
156
  if (status === 'resolved') {
110
- var _pickerRef$current;
111
- // necessary to refocus the search input after the loading state
112
- pickerRef === null || pickerRef === void 0 || (_pickerRef$current = pickerRef.current) === null || _pickerRef$current === void 0 || (_pickerRef$current = _pickerRef$current.selectRef) === null || _pickerRef$current === void 0 || (_pickerRef$current = _pickerRef$current.inputRef) === null || _pickerRef$current === void 0 || _pickerRef$current.focus();
157
+ sortOptionsOnResolve();
113
158
  }
114
- }, [status]);
159
+ }, [sortOptionsOnResolve, status]);
115
160
  var filterOptionsLength = filterOptions.length;
116
161
  var isError = status === 'rejected';
117
162
  var isLoading = status === 'loading' || status === 'empty';
118
163
  var isLoadingMore = status === 'loadingMore';
119
164
  var isEmpty = status === 'resolved' && filterOptionsLength === 0;
165
+ var popupSelectOptions = isLoading || isError ? [] : sortedOptions; // if not set to [], then on loading, no loading UI will be shown
120
166
  var areAllResultsLoaded = filterOptions.length === totalCount;
121
167
  var shouldShowFooter = (status === 'resolved' || isLoadingMore) && filterOptions.length > 0; // footer should not disappear when there is an inline spinner for loading more data
122
168
  var shouldDisplayShowMoreButton = status === 'resolved' && !!pageCursor && !areAllResultsLoaded;
123
- var options = isLoading || isError ? [] : filterOptions; // if not set to [], for eg: on loading, no loading UI will be shown
124
-
125
169
  return /*#__PURE__*/_react.default.createElement(_select.PopupSelect, {
126
170
  isMulti: true,
127
171
  maxMenuWidth: 300,
128
172
  minMenuWidth: 300,
129
- ref: pickerRef,
130
173
  testId: "jlol-basic-filter-popup-select",
131
174
  inputId: "jlol-basic-filter-popup-select--input"
132
175
  /*
@@ -152,7 +195,8 @@ var AsyncPopupSelect = function AsyncPopupSelect(_ref) {
152
195
  isLoading: isLoading,
153
196
  isLoadingMore: isLoadingMore,
154
197
  showMore: shouldDisplayShowMoreButton,
155
- handleShowMore: handleShowMore
198
+ handleShowMore: handleShowMore,
199
+ errors: errors
156
200
  }));
157
201
  },
158
202
  DropdownIndicator: _dropdownIndicator.default,
@@ -161,7 +205,7 @@ var AsyncPopupSelect = function AsyncPopupSelect(_ref) {
161
205
  IndicatorSeparator: undefined // disables the | separator between search input and icon
162
206
  },
163
207
 
164
- options: options,
208
+ options: popupSelectOptions,
165
209
  value: selectedOptions,
166
210
  filterOption: noFilterOptions,
167
211
  formatOptionLabel: _formatOptionLabel.default,
@@ -172,6 +216,7 @@ var AsyncPopupSelect = function AsyncPopupSelect(_ref) {
172
216
  triggerProps = (0, _objectWithoutProperties2.default)(_ref3, _excluded);
173
217
  return /*#__PURE__*/_react.default.createElement(_trigger.default, (0, _extends2.default)({}, triggerProps, {
174
218
  filterType: filterType,
219
+ selectedOptions: selectedOptions,
175
220
  isSelected: isOpen,
176
221
  onClick: handleOpenPopup,
177
222
  isDisabled: isDisabled
@@ -6,28 +6,51 @@ Object.defineProperty(exports, "__esModule", {
6
6
  value: true
7
7
  });
8
8
  exports.default = void 0;
9
+ var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
9
10
  var _react = _interopRequireWildcard(require("react"));
10
11
  var _reactIntlNext = require("react-intl-next");
12
+ var _badge = _interopRequireDefault(require("@atlaskit/badge"));
11
13
  var _standardButton = _interopRequireDefault(require("@atlaskit/button/standard-button"));
12
14
  var _chevronDown = _interopRequireDefault(require("@atlaskit/icon/glyph/chevron-down"));
15
+ var _primitives = require("@atlaskit/primitives");
13
16
  var _messages = require("./messages");
14
17
  function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
15
18
  function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || _typeof(obj) !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
19
+ var triggerButtonLabelStyles = (0, _primitives.xcss)({
20
+ textOverflow: 'ellipsis',
21
+ overflow: 'hidden',
22
+ maxWidth: '150px'
23
+ });
24
+ var badgeStyles = (0, _primitives.xcss)({
25
+ marginLeft: 'space.050'
26
+ });
16
27
  var PopupTrigger = /*#__PURE__*/(0, _react.forwardRef)(function (_ref, ref) {
17
28
  var filterType = _ref.filterType,
18
29
  isSelected = _ref.isSelected,
19
30
  isDisabled = _ref.isDisabled,
20
- onClick = _ref.onClick;
31
+ onClick = _ref.onClick,
32
+ selectedOptions = _ref.selectedOptions;
33
+ var _ref2 = selectedOptions || [],
34
+ _ref3 = (0, _slicedToArray2.default)(_ref2, 1),
35
+ firstOption = _ref3[0];
36
+ var hasOptions = selectedOptions && selectedOptions.length > 0;
21
37
  return /*#__PURE__*/_react.default.createElement(_standardButton.default, {
22
38
  ref: ref,
23
39
  appearance: "default",
24
- isSelected: isSelected,
40
+ isSelected: isSelected || hasOptions,
25
41
  isDisabled: isDisabled,
26
42
  onClick: onClick,
27
43
  testId: "jlol-basic-filter-".concat(filterType, "-trigger"),
28
44
  iconAfter: /*#__PURE__*/_react.default.createElement(_chevronDown.default, {
29
45
  label: ""
30
46
  })
31
- }, /*#__PURE__*/_react.default.createElement(_reactIntlNext.FormattedMessage, _messages.asyncPopupSelectMessages["".concat(filterType, "Label")]));
47
+ }, /*#__PURE__*/_react.default.createElement(_primitives.Flex, null, /*#__PURE__*/_react.default.createElement(_primitives.Box, {
48
+ xcss: triggerButtonLabelStyles
49
+ }, /*#__PURE__*/_react.default.createElement(_reactIntlNext.FormattedMessage, _messages.asyncPopupSelectMessages["".concat(filterType, "Label")]), firstOption && /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, ": ", firstOption.label)), selectedOptions && selectedOptions.length > 1 && /*#__PURE__*/_react.default.createElement(_primitives.Flex, {
50
+ xcss: badgeStyles,
51
+ alignItems: "center"
52
+ }, /*#__PURE__*/_react.default.createElement(_badge.default, {
53
+ appearance: "primary"
54
+ }, "+", selectedOptions.length - 1))));
32
55
  });
33
56
  var _default = exports.default = PopupTrigger;
@@ -21,14 +21,17 @@ var BasicFilterContainer = function BasicFilterContainer(_ref) {
21
21
  var jql = _ref.jql,
22
22
  cloudId = _ref.cloudId;
23
23
  var _useState = (0, _react.useState)([]),
24
- _useState2 = (0, _slicedToArray2.default)(_useState, 1),
25
- selection = _useState2[0];
24
+ _useState2 = (0, _slicedToArray2.default)(_useState, 2),
25
+ selection = _useState2[0],
26
+ setSelection = _useState2[1];
26
27
  (0, _react.useEffect)(function () {
27
28
  if ((0, _utils.isValidJql)(jql)) {
28
29
  // hydrate hook call goes in here
29
30
  }
30
31
  }, [jql]);
31
- var handleSelectionChange = function handleSelectionChange() {};
32
+ var handleSelectionChange = (0, _react.useCallback)(function (options) {
33
+ setSelection(options);
34
+ }, [setSelection]);
32
35
  return /*#__PURE__*/_react.default.createElement(_primitives.Flex, {
33
36
  xcss: basicFilterContainerStyles,
34
37
  gap: "space.100",
@@ -1,16 +1,53 @@
1
1
  "use strict";
2
2
 
3
3
  var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+ var _typeof = require("@babel/runtime/helpers/typeof");
4
5
  Object.defineProperty(exports, "__esModule", {
5
6
  value: true
6
7
  });
7
8
  exports.default = void 0;
8
- var _react = _interopRequireDefault(require("react"));
9
+ var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
10
+ var _react = _interopRequireWildcard(require("react"));
11
+ var _useDebounce = require("use-debounce");
9
12
  var _error = _interopRequireDefault(require("@atlaskit/icon/glyph/error"));
10
13
  var _colors = require("@atlaskit/theme/colors");
14
+ var _analytics = require("../../../../../analytics");
15
+ var _asyncPopupSelect = require("../async-popup-select");
11
16
  var _messages = require("./messages");
12
17
  var _selectMessage = _interopRequireDefault(require("./selectMessage"));
13
- var CustomErrorMessage = function CustomErrorMessage() {
18
+ function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
19
+ function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || _typeof(obj) !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
20
+ var getErrorReasonType = function getErrorReasonType(errors) {
21
+ var _ref = errors || [],
22
+ _ref2 = (0, _slicedToArray2.default)(_ref, 1),
23
+ error = _ref2[0];
24
+ if (error instanceof Error) {
25
+ return 'network';
26
+ }
27
+ if (errors && errors.length > 0) {
28
+ return 'agg';
29
+ }
30
+ return 'unknown';
31
+ };
32
+ var CustomErrorMessage = function CustomErrorMessage(_ref3) {
33
+ var filterType = _ref3.filterType,
34
+ errors = _ref3.errors;
35
+ var _useDatasourceAnalyti = (0, _analytics.useDatasourceAnalyticsEvents)(),
36
+ fireEvent = _useDatasourceAnalyti.fireEvent;
37
+
38
+ /**
39
+ * Debounce is required because our search is debounced
40
+ * ref: ./noOptionsMessage.tsx
41
+ */
42
+ var _useDebouncedCallback = (0, _useDebounce.useDebouncedCallback)(function () {
43
+ fireEvent('ui.error.shown.basicSearchDropdown', {
44
+ filterType: filterType,
45
+ reason: getErrorReasonType(errors)
46
+ });
47
+ }, _asyncPopupSelect.SEARCH_DEBOUNCE_MS),
48
+ _useDebouncedCallback2 = (0, _slicedToArray2.default)(_useDebouncedCallback, 1),
49
+ debouncedAnalyticsCallback = _useDebouncedCallback2[0];
50
+ (0, _react.useEffect)(debouncedAnalyticsCallback, [debouncedAnalyticsCallback]);
14
51
  return /*#__PURE__*/_react.default.createElement(_selectMessage.default, {
15
52
  icon: /*#__PURE__*/_react.default.createElement(_error.default, {
16
53
  primaryColor: "var(--ds-icon, ".concat(_colors.N500, ")"),
@@ -14,13 +14,14 @@ var _showMoreButton = _interopRequireDefault(require("../async-popup-select/show
14
14
  var _errorMessage = _interopRequireDefault(require("./errorMessage"));
15
15
  var _loadingMessage = _interopRequireDefault(require("./loadingMessage"));
16
16
  var _noOptionsMessage = _interopRequireDefault(require("./noOptionsMessage"));
17
- var _excluded = ["filterType", "isLoading", "isLoadingMore", "isError", "isEmpty", "showMore", "handleShowMore", "children"];
17
+ var _excluded = ["filterType", "isLoading", "isLoadingMore", "isError", "isEmpty", "errors", "showMore", "handleShowMore", "children"];
18
18
  var CustomMenuList = function CustomMenuList(_ref) {
19
19
  var filterType = _ref.filterType,
20
20
  isLoading = _ref.isLoading,
21
21
  isLoadingMore = _ref.isLoadingMore,
22
22
  isError = _ref.isError,
23
23
  isEmpty = _ref.isEmpty,
24
+ errors = _ref.errors,
24
25
  showMore = _ref.showMore,
25
26
  handleShowMore = _ref.handleShowMore,
26
27
  children = _ref.children,
@@ -39,7 +40,10 @@ var CustomMenuList = function CustomMenuList(_ref) {
39
40
  return /*#__PURE__*/_react.default.createElement(_loadingMessage.default, null);
40
41
  }
41
42
  if (isError) {
42
- return /*#__PURE__*/_react.default.createElement(_errorMessage.default, null);
43
+ return /*#__PURE__*/_react.default.createElement(_errorMessage.default, {
44
+ filterType: filterType,
45
+ errors: errors
46
+ });
43
47
  }
44
48
  if (isEmpty) {
45
49
  return /*#__PURE__*/_react.default.createElement(_noOptionsMessage.default, {