@atlaskit/link-datasource 1.17.1 → 1.17.3

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 (30) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/dist/cjs/analytics/constants.js +1 -1
  3. package/dist/cjs/ui/issue-like-table/draggable-table-heading.js +14 -7
  4. package/dist/cjs/ui/issue-like-table/index.js +11 -4
  5. package/dist/cjs/ui/jira-issues-modal/basic-filters/hooks/useFilterOptions.js +8 -0
  6. package/dist/cjs/ui/jira-issues-modal/basic-filters/ui/async-popup-select/index.js +59 -34
  7. package/dist/cjs/ui/jira-issues-modal/basic-filters/ui/index.js +18 -6
  8. package/dist/cjs/ui/jira-issues-modal/basic-filters/utils/index.js +2 -1
  9. package/dist/es2019/analytics/constants.js +1 -1
  10. package/dist/es2019/ui/issue-like-table/draggable-table-heading.js +11 -4
  11. package/dist/es2019/ui/issue-like-table/index.js +11 -4
  12. package/dist/es2019/ui/jira-issues-modal/basic-filters/hooks/useFilterOptions.js +8 -0
  13. package/dist/es2019/ui/jira-issues-modal/basic-filters/ui/async-popup-select/index.js +57 -27
  14. package/dist/es2019/ui/jira-issues-modal/basic-filters/ui/index.js +16 -6
  15. package/dist/es2019/ui/jira-issues-modal/basic-filters/utils/index.js +2 -1
  16. package/dist/esm/analytics/constants.js +1 -1
  17. package/dist/esm/ui/issue-like-table/draggable-table-heading.js +14 -5
  18. package/dist/esm/ui/issue-like-table/index.js +11 -4
  19. package/dist/esm/ui/jira-issues-modal/basic-filters/hooks/useFilterOptions.js +8 -0
  20. package/dist/esm/ui/jira-issues-modal/basic-filters/ui/async-popup-select/index.js +60 -35
  21. package/dist/esm/ui/jira-issues-modal/basic-filters/ui/index.js +18 -6
  22. package/dist/esm/ui/jira-issues-modal/basic-filters/utils/index.js +2 -1
  23. package/dist/types/ui/jira-issues-modal/basic-filters/hooks/useFilterOptions.d.ts +1 -0
  24. package/dist/types/ui/jira-issues-modal/basic-filters/ui/async-popup-select/index.d.ts +2 -1
  25. package/dist/types/ui/jira-issues-modal/basic-filters/ui/index.d.ts +1 -1
  26. package/dist/types-ts4.5/ui/jira-issues-modal/basic-filters/hooks/useFilterOptions.d.ts +1 -0
  27. package/dist/types-ts4.5/ui/jira-issues-modal/basic-filters/ui/async-popup-select/index.d.ts +2 -1
  28. package/dist/types-ts4.5/ui/jira-issues-modal/basic-filters/ui/index.d.ts +1 -1
  29. package/examples-helpers/buildIssueLikeTable.tsx +13 -4
  30. package/package.json +1 -1
package/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # @atlaskit/link-datasource
2
2
 
3
+ ## 1.17.3
4
+
5
+ ### Patch Changes
6
+
7
+ - [#43122](https://bitbucket.org/atlassian/atlassian-frontend/pull-requests/43122) [`5690dd4a0d3`](https://bitbucket.org/atlassian/atlassian-frontend/commits/5690dd4a0d3) - When no onColumnResize is defined OR when columnCustomSizes in readonly more use max-width instead of width
8
+
9
+ ## 1.17.2
10
+
11
+ ### Patch Changes
12
+
13
+ - [#43143](https://bitbucket.org/atlassian/atlassian-frontend/pull-requests/43143) [`de7541cc6ab`](https://bitbucket.org/atlassian/atlassian-frontend/commits/de7541cc6ab) - Reset filter selection when site selection changes and fixes a bug when selecting filter values.
14
+
3
15
  ## 1.17.1
4
16
 
5
17
  ### 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.17.1"
10
+ packageVersion: "1.17.3"
11
11
  };
@@ -5,6 +5,7 @@ Object.defineProperty(exports, "__esModule", {
5
5
  value: true
6
6
  });
7
7
  exports.DraggableTableHeading = void 0;
8
+ var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
8
9
  var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
9
10
  var _react = require("react");
10
11
  var _react2 = require("@emotion/react");
@@ -20,8 +21,8 @@ var _closestEdge = require("@atlaskit/pragmatic-drag-and-drop-hitbox/addon/close
20
21
  var _boxWithoutTerminal = require("@atlaskit/pragmatic-drag-and-drop-react-indicator/box-without-terminal");
21
22
  var _styled = require("./styled");
22
23
  var _index = require("./index");
23
- /** @jsx jsx */
24
-
24
+ function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
25
+ function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { (0, _defineProperty2.default)(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; } /** @jsx jsx */
25
26
  var verticallyAlignedStyles = (0, _react2.css)({
26
27
  display: 'flex',
27
28
  alignItems: 'center',
@@ -207,6 +208,9 @@ var DraggableTableHeading = exports.DraggableTableHeading = function DraggableTa
207
208
 
208
209
  // Handling column resizing
209
210
  (0, _react.useEffect)(function () {
211
+ if (!onWidthChange) {
212
+ return;
213
+ }
210
214
  var resizeHandle = columnResizeHandleRef.current;
211
215
  (0, _tinyInvariant.default)(resizeHandle);
212
216
  var mainHeaderCell = mainHeaderCellRef.current;
@@ -265,18 +269,21 @@ var DraggableTableHeading = exports.DraggableTableHeading = function DraggableTa
265
269
  return (0, _react2.jsx)(_styled.TableHeading, {
266
270
  ref: mainHeaderCellRef,
267
271
  "data-testid": "".concat(id, "-column-heading"),
268
- style: {
269
- width: width,
272
+ style: _objectSpread({
270
273
  cursor: 'grab'
271
- }
272
- }, (0, _react2.jsx)("div", {
274
+ }, onWidthChange ? {
275
+ width: width
276
+ } : {
277
+ maxWidth: width
278
+ })
279
+ }, onWidthChange ? (0, _react2.jsx)("div", {
273
280
  ref: columnResizeHandleRef,
274
281
  css: [resizerStyles, state.type === 'resizing' && resizingStyles],
275
282
  style: {
276
283
  height: "".concat(dndPreviewHeight, "px")
277
284
  },
278
285
  "data-testid": "column-resize-handle"
279
- }), (0, _react2.jsx)("div", {
286
+ }) : null, (0, _react2.jsx)("div", {
280
287
  ref: dropTargetRef,
281
288
  css: [dropTargetStyles, isDraggingAnyColumn ? null : noPointerEventsStyles],
282
289
  style: {
@@ -57,7 +57,6 @@ var scrollableContainerStyles = (0, _react2.css)({
57
57
  borderRadius: "var(--ds-border-radius-100, 3px)"
58
58
  });
59
59
  var tableStyles = (0, _react2.css)({
60
- tableLayout: 'fixed',
61
60
  // These styles are needed to prevent thead bottom border from scrolling away.
62
61
  // This happens because it is sticky. https://stackoverflow.com/questions/50361698/border-style-do-not-work-with-sticky-position-element
63
62
  borderCollapse: 'separate',
@@ -372,6 +371,7 @@ var IssueLikeDataTableView = exports.IssueLikeDataTableView = function IssueLike
372
371
  }
373
372
  }, _callee, null, [[3, 9]]);
374
373
  })), [parentContainerRenderInstanceId, extensionKey, hasFullSchema, onLoadDatasourceDetails]);
374
+ var shouldUseWidth = onColumnResize || columnCustomSizes;
375
375
  return (0, _react2.jsx)("div", {
376
376
  /* There is required contentEditable={true} in editor-card-plugin
377
377
  * But this brakes how DND works. We set contentEditable={false} to allow DND to work
@@ -385,7 +385,10 @@ var IssueLikeDataTableView = exports.IssueLikeDataTableView = function IssueLike
385
385
  } : undefined
386
386
  }, (0, _react2.jsx)(_styled2.Table, {
387
387
  css: tableStyles,
388
- "data-testid": testId
388
+ "data-testid": testId,
389
+ style: shouldUseWidth ? {
390
+ tableLayout: 'fixed'
391
+ } : {}
389
392
  }, (0, _react2.jsx)("thead", {
390
393
  "data-testid": testId && "".concat(testId, "--head"),
391
394
  css: [noDefaultBorderStyles, tableHeadStyles]
@@ -433,8 +436,10 @@ var IssueLikeDataTableView = exports.IssueLikeDataTableView = function IssueLike
433
436
  return (0, _react2.jsx)(_styled2.TableHeading, {
434
437
  key: key,
435
438
  "data-testid": "".concat(key, "-column-heading"),
436
- style: {
439
+ style: shouldUseWidth ? {
437
440
  width: width
441
+ } : {
442
+ maxWidth: width
438
443
  }
439
444
  }, heading);
440
445
  }
@@ -459,8 +464,10 @@ var IssueLikeDataTableView = exports.IssueLikeDataTableView = function IssueLike
459
464
  var cellKey = _ref13.key,
460
465
  content = _ref13.content,
461
466
  width = _ref13.width;
462
- var loadingRowStyle = {
467
+ var loadingRowStyle = shouldUseWidth ? {
463
468
  width: width
469
+ } : {
470
+ maxWidth: width
464
471
  };
465
472
  // extra padding is required around skeleton loader to avoid vertical jumps when data loads
466
473
  if (key !== null && key !== void 0 && key.includes('loading')) {
@@ -112,12 +112,20 @@ var useFilterOptions = exports.useFilterOptions = function useFilterOptions(_ref
112
112
  }
113
113
  }, _callee, null, [[5, 24]]);
114
114
  })), [cloudId, filterOptions, filterType, getFieldValues]);
115
+ var reset = (0, _react.useCallback)(function () {
116
+ setStatus('empty');
117
+ setFilterOptions([]);
118
+ setTotalCount(0);
119
+ setNextPageCursor(undefined);
120
+ initialData.current = undefined;
121
+ }, []);
115
122
  return {
116
123
  filterOptions: filterOptions,
117
124
  fetchFilterOptions: fetchFilterOptions,
118
125
  totalCount: totalCount,
119
126
  pageCursor: nextPageCursor,
120
127
  status: status,
128
+ reset: reset,
121
129
  errors: status === 'rejected' ? errors : []
122
130
  };
123
131
  };
@@ -13,6 +13,7 @@ var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers
13
13
  var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator"));
14
14
  var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
15
15
  var _react = _interopRequireWildcard(require("react"));
16
+ var _isEqual = _interopRequireDefault(require("lodash/isEqual"));
16
17
  var _reactIntlNext = require("react-intl-next");
17
18
  var _useDebounce = require("use-debounce");
18
19
  var _select = require("@atlaskit/select");
@@ -38,6 +39,8 @@ var AsyncPopupSelect = function AsyncPopupSelect(_ref) {
38
39
  selection = _ref.selection,
39
40
  _ref$onSelectionChang = _ref.onSelectionChange,
40
41
  onSelectionChange = _ref$onSelectionChang === void 0 ? function () {} : _ref$onSelectionChang,
42
+ _ref$onReset = _ref.onReset,
43
+ resetSelection = _ref$onReset === void 0 ? function () {} : _ref$onReset,
41
44
  _ref$isDisabled = _ref.isDisabled,
42
45
  isDisabled = _ref$isDisabled === void 0 ? false : _ref$isDisabled;
43
46
  var _useIntl = (0, _reactIntlNext.useIntl)(),
@@ -50,10 +53,13 @@ var AsyncPopupSelect = function AsyncPopupSelect(_ref) {
50
53
  _useState4 = (0, _slicedToArray2.default)(_useState3, 2),
51
54
  selectedOptions = _useState4[0],
52
55
  setSelectedOptions = _useState4[1];
53
- var _useState5 = (0, _react.useState)(selectedOptions),
56
+ var _useState5 = (0, _react.useState)([]),
54
57
  _useState6 = (0, _slicedToArray2.default)(_useState5, 2),
55
58
  sortedOptions = _useState6[0],
56
59
  setSortedOptions = _useState6[1];
60
+ var currentSiteCloudId = (0, _react.useRef)(cloudId);
61
+ var sortPaginatedResults = (0, _react.useRef)(false); // this is to track pagination for sorting purpose
62
+
57
63
  var _useFilterOptions = (0, _useFilterOptions2.useFilterOptions)({
58
64
  filterType: filterType,
59
65
  cloudId: cloudId
@@ -63,6 +69,7 @@ var AsyncPopupSelect = function AsyncPopupSelect(_ref) {
63
69
  totalCount = _useFilterOptions.totalCount,
64
70
  status = _useFilterOptions.status,
65
71
  pageCursor = _useFilterOptions.pageCursor,
72
+ resetHook = _useFilterOptions.reset,
66
73
  errors = _useFilterOptions.errors;
67
74
  var _useDebouncedCallback = (0, _useDebounce.useDebouncedCallback)(function (searchString) {
68
75
  fetchFilterOptions({
@@ -90,14 +97,12 @@ var AsyncPopupSelect = function AsyncPopupSelect(_ref) {
90
97
  return _ref2.apply(this, arguments);
91
98
  };
92
99
  }(), [handleDebouncedFetchFilterOptions, searchTerm]);
93
- var handleOptionSelection = function handleOptionSelection(newValue) {
94
- setSelectedOptions(newValue);
100
+ var handleOptionSelection = (0, _react.useCallback)(function (newValue) {
95
101
  onSelectionChange(newValue);
96
- };
102
+ }, [onSelectionChange]);
97
103
  var sortOptionsOnPopupOpen = (0, _react.useCallback)(function () {
98
104
  if (selectedOptions.length === 0) {
99
- setSortedOptions(filterOptions);
100
- return;
105
+ return setSortedOptions(filterOptions);
101
106
  }
102
107
  var nonSelectedOptions = filterOptions.filter(function (option) {
103
108
  return !selectedOptions.find(function (selectedOption) {
@@ -105,37 +110,41 @@ var AsyncPopupSelect = function AsyncPopupSelect(_ref) {
105
110
  });
106
111
  });
107
112
  var newOptions = [].concat((0, _toConsumableArray2.default)(selectedOptions), (0, _toConsumableArray2.default)(nonSelectedOptions));
108
- setSortedOptions(newOptions);
109
- }, [selectedOptions, filterOptions]);
113
+ if (!(0, _isEqual.default)(newOptions, sortedOptions)) {
114
+ setSortedOptions(newOptions);
115
+ }
116
+ }, [selectedOptions, filterOptions, sortedOptions]);
110
117
  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
- }
126
- });
118
+ // sortedOptions is empty initially, this will take care of setting the initial value and bring the selected items to the top
119
+ if (sortedOptions.length === 0) {
120
+ return sortOptionsOnPopupOpen();
121
+ }
122
+
123
+ // when the user is searching, we want the search result to be displayed as it is, and the select component will take care of marking the selected items
124
+ if (searchTerm) {
125
+ sortPaginatedResults.current = false; // set to false to indicate pagination resolve action is completed from the sorting perspective
126
+ return setSortedOptions(filterOptions);
127
127
  }
128
- if (shouldSetSortOptions) {
129
- var sortedOptionsFiltered = sortedOptions.filter(function (sortedOption) {
130
- return filterOptions.some(function (filterOption) {
131
- return filterOption.value === sortedOption.value;
128
+
129
+ // this block handles the pagination, where on pagination, we will just append newOptions to the current list
130
+ if (sortPaginatedResults.current) {
131
+ var newOptions = filterOptions.filter(function (option) {
132
+ return !sortedOptions.find(function (sortedOption) {
133
+ return sortedOption.value === option.value;
132
134
  });
133
135
  });
134
- setSortedOptions([].concat((0, _toConsumableArray2.default)(sortedOptionsFiltered), (0, _toConsumableArray2.default)(newOptions)));
136
+ if (newOptions.length > 0) {
137
+ setSortedOptions([].concat((0, _toConsumableArray2.default)(sortedOptions), (0, _toConsumableArray2.default)(newOptions)));
138
+ }
139
+ sortPaginatedResults.current = false; // set to false to indicate pagination resolve action is completed from the sorting perspective
140
+ return;
135
141
  }
136
- }, [filterOptions, sortedOptions]);
142
+ sortPaginatedResults.current = false; // set to false to indicate pagination resolve action is completed from the sorting perspective
143
+ sortOptionsOnPopupOpen();
144
+ }, [filterOptions, searchTerm, sortOptionsOnPopupOpen, sortedOptions]);
137
145
  var handleShowMore = (0, _react.useCallback)(function () {
138
146
  if (pageCursor) {
147
+ sortPaginatedResults.current = true;
139
148
  fetchFilterOptions({
140
149
  pageCursor: pageCursor,
141
150
  searchString: searchTerm
@@ -156,15 +165,31 @@ var AsyncPopupSelect = function AsyncPopupSelect(_ref) {
156
165
  if (status === 'resolved') {
157
166
  sortOptionsOnResolve();
158
167
  }
159
- }, [sortOptionsOnResolve, status]);
168
+ // eslint-disable-next-line react-hooks/exhaustive-deps
169
+ }, [status]); // we only want the sortOptionsOnResolve to run when there is a status change
170
+
171
+ (0, _react.useEffect)(function () {
172
+ if (currentSiteCloudId.current !== cloudId) {
173
+ currentSiteCloudId.current = cloudId;
174
+ setSortedOptions([]);
175
+ setSearchTerm('');
176
+ resetHook();
177
+ resetSelection();
178
+ }
179
+ }, [cloudId, resetHook, resetSelection]);
180
+ (0, _react.useEffect)(function () {
181
+ if (!(0, _isEqual.default)(selection, selectedOptions)) {
182
+ setSelectedOptions(selection);
183
+ }
184
+ }, [selectedOptions, selection]);
160
185
  var filterOptionsLength = filterOptions.length;
161
186
  var isError = status === 'rejected';
162
187
  var isLoading = status === 'loading' || status === 'empty';
163
188
  var isLoadingMore = status === 'loadingMore';
164
189
  var isEmpty = status === 'resolved' && filterOptionsLength === 0;
165
190
  var popupSelectOptions = isLoading || isError ? [] : sortedOptions; // if not set to [], then on loading, no loading UI will be shown
166
- var areAllResultsLoaded = filterOptions.length === totalCount;
167
- var shouldShowFooter = (status === 'resolved' || isLoadingMore) && filterOptions.length > 0; // footer should not disappear when there is an inline spinner for loading more data
191
+ var areAllResultsLoaded = filterOptionsLength === totalCount;
192
+ var shouldShowFooter = (status === 'resolved' || isLoadingMore) && filterOptionsLength > 0; // footer should not disappear when there is an inline spinner for loading more data
168
193
  var shouldDisplayShowMoreButton = status === 'resolved' && !!pageCursor && !areAllResultsLoaded;
169
194
  return /*#__PURE__*/_react.default.createElement(_select.PopupSelect, {
170
195
  isMulti: true,
@@ -223,7 +248,7 @@ var AsyncPopupSelect = function AsyncPopupSelect(_ref) {
223
248
  }));
224
249
  },
225
250
  footer: shouldShowFooter && /*#__PURE__*/_react.default.createElement(_footer.default, {
226
- currentDisplayCount: filterOptionsLength,
251
+ currentDisplayCount: popupSelectOptions.length,
227
252
  totalCount: totalCount
228
253
  })
229
254
  });
@@ -6,6 +6,7 @@ Object.defineProperty(exports, "__esModule", {
6
6
  value: true
7
7
  });
8
8
  exports.default = void 0;
9
+ var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
9
10
  var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
10
11
  var _react = _interopRequireWildcard(require("react"));
11
12
  var _primitives = require("@atlaskit/primitives");
@@ -13,6 +14,8 @@ var _utils = require("../utils");
13
14
  var _asyncPopupSelect = _interopRequireDefault(require("./async-popup-select"));
14
15
  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
16
  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; }
17
+ function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
18
+ function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { (0, _defineProperty2.default)(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
16
19
  var availableBasicFilterTypes = ['project', 'issuetype', 'status', 'assignee'];
17
20
  var basicFilterContainerStyles = (0, _primitives.xcss)({
18
21
  paddingLeft: "var(--ds-space-100, 8px)"
@@ -20,7 +23,7 @@ var basicFilterContainerStyles = (0, _primitives.xcss)({
20
23
  var BasicFilterContainer = function BasicFilterContainer(_ref) {
21
24
  var jql = _ref.jql,
22
25
  cloudId = _ref.cloudId;
23
- var _useState = (0, _react.useState)([]),
26
+ var _useState = (0, _react.useState)({}),
24
27
  _useState2 = (0, _slicedToArray2.default)(_useState, 2),
25
28
  selection = _useState2[0],
26
29
  setSelection = _useState2[1];
@@ -29,9 +32,15 @@ var BasicFilterContainer = function BasicFilterContainer(_ref) {
29
32
  // hydrate hook call goes in here
30
33
  }
31
34
  }, [jql]);
32
- var handleSelectionChange = (0, _react.useCallback)(function (options) {
33
- setSelection(options);
34
- }, [setSelection]);
35
+ var handleSelectionChange = (0, _react.useCallback)(function (options, filter) {
36
+ var updatedSelection = _objectSpread(_objectSpread({}, selection), {}, (0, _defineProperty2.default)({}, filter, options));
37
+ setSelection(updatedSelection);
38
+ }, [selection]);
39
+ var handleReset = (0, _react.useCallback)(function () {
40
+ if (Object.keys(selection).length > 0) {
41
+ setSelection({});
42
+ }
43
+ }, [selection]);
35
44
  return /*#__PURE__*/_react.default.createElement(_primitives.Flex, {
36
45
  xcss: basicFilterContainerStyles,
37
46
  gap: "space.100",
@@ -41,9 +50,12 @@ var BasicFilterContainer = function BasicFilterContainer(_ref) {
41
50
  cloudId: cloudId,
42
51
  filterType: filter,
43
52
  key: filter,
44
- selection: selection,
53
+ selection: selection[filter] || [],
45
54
  isDisabled: !cloudId,
46
- onSelectionChange: handleSelectionChange
55
+ onSelectionChange: function onSelectionChange(options) {
56
+ return handleSelectionChange(options, filter);
57
+ },
58
+ onReset: handleReset
47
59
  });
48
60
  }));
49
61
  };
@@ -6,6 +6,7 @@ Object.defineProperty(exports, "__esModule", {
6
6
  exports.isValidJql = void 0;
7
7
  var _jqlAst = require("@atlaskit/jql-ast");
8
8
  var isValidJql = exports.isValidJql = function isValidJql(jql) {
9
+ var _jast$errors;
9
10
  var jast = new _jqlAst.JastBuilder().build(jql);
10
- return jast.errors.length === 0;
11
+ return (jast === null || jast === void 0 || (_jast$errors = jast.errors) === null || _jast$errors === void 0 ? void 0 : _jast$errors.length) === 0;
11
12
  };
@@ -1,5 +1,5 @@
1
1
  export const EVENT_CHANNEL = 'media';
2
2
  export const packageMetaData = {
3
3
  packageName: "@atlaskit/link-datasource",
4
- packageVersion: "1.17.1"
4
+ packageVersion: "1.17.3"
5
5
  };
@@ -192,6 +192,9 @@ export const DraggableTableHeading = ({
192
192
 
193
193
  // Handling column resizing
194
194
  useEffect(() => {
195
+ if (!onWidthChange) {
196
+ return;
197
+ }
195
198
  const resizeHandle = columnResizeHandleRef.current;
196
199
  invariant(resizeHandle);
197
200
  const mainHeaderCell = mainHeaderCellRef.current;
@@ -255,17 +258,21 @@ export const DraggableTableHeading = ({
255
258
  ref: mainHeaderCellRef,
256
259
  "data-testid": `${id}-column-heading`,
257
260
  style: {
258
- width,
259
- cursor: 'grab'
261
+ cursor: 'grab',
262
+ ...(onWidthChange ? {
263
+ width
264
+ } : {
265
+ maxWidth: width
266
+ })
260
267
  }
261
- }, jsx("div", {
268
+ }, onWidthChange ? jsx("div", {
262
269
  ref: columnResizeHandleRef,
263
270
  css: [resizerStyles, state.type === 'resizing' && resizingStyles],
264
271
  style: {
265
272
  height: `${dndPreviewHeight}px`
266
273
  },
267
274
  "data-testid": "column-resize-handle"
268
- }), jsx("div", {
275
+ }) : null, jsx("div", {
269
276
  ref: dropTargetRef,
270
277
  css: [dropTargetStyles, isDraggingAnyColumn ? null : noPointerEventsStyles],
271
278
  style: {
@@ -58,7 +58,6 @@ const scrollableContainerStyles = css({
58
58
  borderRadius: "var(--ds-border-radius-100, 3px)"
59
59
  });
60
60
  const tableStyles = css({
61
- tableLayout: 'fixed',
62
61
  // These styles are needed to prevent thead bottom border from scrolling away.
63
62
  // This happens because it is sticky. https://stackoverflow.com/questions/50361698/border-style-do-not-work-with-sticky-position-element
64
63
  borderCollapse: 'separate',
@@ -325,6 +324,7 @@ export const IssueLikeDataTableView = ({
325
324
  setHasFullSchema(false);
326
325
  }
327
326
  }, [parentContainerRenderInstanceId, extensionKey, hasFullSchema, onLoadDatasourceDetails]);
327
+ const shouldUseWidth = onColumnResize || columnCustomSizes;
328
328
  return jsx("div", {
329
329
  /* There is required contentEditable={true} in editor-card-plugin
330
330
  * But this brakes how DND works. We set contentEditable={false} to allow DND to work
@@ -338,7 +338,10 @@ export const IssueLikeDataTableView = ({
338
338
  } : undefined
339
339
  }, jsx(Table, {
340
340
  css: tableStyles,
341
- "data-testid": testId
341
+ "data-testid": testId,
342
+ style: shouldUseWidth ? {
343
+ tableLayout: 'fixed'
344
+ } : {}
342
345
  }, jsx("thead", {
343
346
  "data-testid": testId && `${testId}--head`,
344
347
  css: [noDefaultBorderStyles, tableHeadStyles]
@@ -387,8 +390,10 @@ export const IssueLikeDataTableView = ({
387
390
  return jsx(TableHeading, {
388
391
  key: key,
389
392
  "data-testid": `${key}-column-heading`,
390
- style: {
393
+ style: shouldUseWidth ? {
391
394
  width
395
+ } : {
396
+ maxWidth: width
392
397
  }
393
398
  }, heading);
394
399
  }
@@ -414,8 +419,10 @@ export const IssueLikeDataTableView = ({
414
419
  content,
415
420
  width
416
421
  }, cellIndex) => {
417
- let loadingRowStyle = {
422
+ let loadingRowStyle = shouldUseWidth ? {
418
423
  width
424
+ } : {
425
+ maxWidth: width
419
426
  };
420
427
  // extra padding is required around skeleton loader to avoid vertical jumps when data loads
421
428
  if (key !== null && key !== void 0 && key.includes('loading')) {
@@ -57,12 +57,20 @@ export const useFilterOptions = ({
57
57
  setStatus('rejected');
58
58
  }
59
59
  }, [cloudId, filterOptions, filterType, getFieldValues]);
60
+ const reset = useCallback(() => {
61
+ setStatus('empty');
62
+ setFilterOptions([]);
63
+ setTotalCount(0);
64
+ setNextPageCursor(undefined);
65
+ initialData.current = undefined;
66
+ }, []);
60
67
  return {
61
68
  filterOptions,
62
69
  fetchFilterOptions,
63
70
  totalCount,
64
71
  pageCursor: nextPageCursor,
65
72
  status,
73
+ reset,
66
74
  errors: status === 'rejected' ? errors : []
67
75
  };
68
76
  };
@@ -1,5 +1,6 @@
1
1
  import _extends from "@babel/runtime/helpers/extends";
2
- import React, { useCallback, useEffect, useState } from 'react';
2
+ import React, { useCallback, useEffect, useRef, useState } from 'react';
3
+ import isEqual from 'lodash/isEqual';
3
4
  import { useIntl } from 'react-intl-next';
4
5
  import { useDebouncedCallback } from 'use-debounce';
5
6
  import { CheckboxOption, PopupSelect } from '@atlaskit/select';
@@ -19,6 +20,7 @@ const AsyncPopupSelect = ({
19
20
  cloudId,
20
21
  selection,
21
22
  onSelectionChange = () => {},
23
+ onReset: resetSelection = () => {},
22
24
  isDisabled = false
23
25
  }) => {
24
26
  const {
@@ -26,13 +28,17 @@ const AsyncPopupSelect = ({
26
28
  } = useIntl();
27
29
  const [searchTerm, setSearchTerm] = useState('');
28
30
  const [selectedOptions, setSelectedOptions] = useState(selection);
29
- const [sortedOptions, setSortedOptions] = useState(selectedOptions);
31
+ const [sortedOptions, setSortedOptions] = useState([]);
32
+ const currentSiteCloudId = useRef(cloudId);
33
+ const sortPaginatedResults = useRef(false); // this is to track pagination for sorting purpose
34
+
30
35
  const {
31
36
  filterOptions,
32
37
  fetchFilterOptions,
33
38
  totalCount,
34
39
  status,
35
40
  pageCursor,
41
+ reset: resetHook,
36
42
  errors
37
43
  } = useFilterOptions({
38
44
  filterType,
@@ -49,38 +55,46 @@ const AsyncPopupSelect = ({
49
55
  handleDebouncedFetchFilterOptions(newSearchTerm);
50
56
  }
51
57
  }, [handleDebouncedFetchFilterOptions, searchTerm]);
52
- const handleOptionSelection = newValue => {
53
- setSelectedOptions(newValue);
58
+ const handleOptionSelection = useCallback(newValue => {
54
59
  onSelectionChange(newValue);
55
- };
60
+ }, [onSelectionChange]);
56
61
  const sortOptionsOnPopupOpen = useCallback(() => {
57
62
  if (selectedOptions.length === 0) {
58
- setSortedOptions(filterOptions);
59
- return;
63
+ return setSortedOptions(filterOptions);
60
64
  }
61
65
  const nonSelectedOptions = filterOptions.filter(option => !selectedOptions.find(selectedOption => selectedOption.value === option.value));
62
66
  const newOptions = [...selectedOptions, ...nonSelectedOptions];
63
- setSortedOptions(newOptions);
64
- }, [selectedOptions, filterOptions]);
67
+ if (!isEqual(newOptions, sortedOptions)) {
68
+ setSortedOptions(newOptions);
69
+ }
70
+ }, [selectedOptions, filterOptions, sortedOptions]);
65
71
  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
- }
75
- });
72
+ // sortedOptions is empty initially, this will take care of setting the initial value and bring the selected items to the top
73
+ if (sortedOptions.length === 0) {
74
+ return sortOptionsOnPopupOpen();
76
75
  }
77
- if (shouldSetSortOptions) {
78
- const sortedOptionsFiltered = sortedOptions.filter(sortedOption => filterOptions.some(filterOption => filterOption.value === sortedOption.value));
79
- setSortedOptions([...sortedOptionsFiltered, ...newOptions]);
76
+
77
+ // when the user is searching, we want the search result to be displayed as it is, and the select component will take care of marking the selected items
78
+ if (searchTerm) {
79
+ sortPaginatedResults.current = false; // set to false to indicate pagination resolve action is completed from the sorting perspective
80
+ return setSortedOptions(filterOptions);
80
81
  }
81
- }, [filterOptions, sortedOptions]);
82
+
83
+ // this block handles the pagination, where on pagination, we will just append newOptions to the current list
84
+ if (sortPaginatedResults.current) {
85
+ const newOptions = filterOptions.filter(option => !sortedOptions.find(sortedOption => sortedOption.value === option.value));
86
+ if (newOptions.length > 0) {
87
+ setSortedOptions([...sortedOptions, ...newOptions]);
88
+ }
89
+ sortPaginatedResults.current = false; // set to false to indicate pagination resolve action is completed from the sorting perspective
90
+ return;
91
+ }
92
+ sortPaginatedResults.current = false; // set to false to indicate pagination resolve action is completed from the sorting perspective
93
+ sortOptionsOnPopupOpen();
94
+ }, [filterOptions, searchTerm, sortOptionsOnPopupOpen, sortedOptions]);
82
95
  const handleShowMore = useCallback(() => {
83
96
  if (pageCursor) {
97
+ sortPaginatedResults.current = true;
84
98
  fetchFilterOptions({
85
99
  pageCursor,
86
100
  searchString: searchTerm
@@ -101,15 +115,31 @@ const AsyncPopupSelect = ({
101
115
  if (status === 'resolved') {
102
116
  sortOptionsOnResolve();
103
117
  }
104
- }, [sortOptionsOnResolve, status]);
118
+ // eslint-disable-next-line react-hooks/exhaustive-deps
119
+ }, [status]); // we only want the sortOptionsOnResolve to run when there is a status change
120
+
121
+ useEffect(() => {
122
+ if (currentSiteCloudId.current !== cloudId) {
123
+ currentSiteCloudId.current = cloudId;
124
+ setSortedOptions([]);
125
+ setSearchTerm('');
126
+ resetHook();
127
+ resetSelection();
128
+ }
129
+ }, [cloudId, resetHook, resetSelection]);
130
+ useEffect(() => {
131
+ if (!isEqual(selection, selectedOptions)) {
132
+ setSelectedOptions(selection);
133
+ }
134
+ }, [selectedOptions, selection]);
105
135
  const filterOptionsLength = filterOptions.length;
106
136
  const isError = status === 'rejected';
107
137
  const isLoading = status === 'loading' || status === 'empty';
108
138
  const isLoadingMore = status === 'loadingMore';
109
139
  const isEmpty = status === 'resolved' && filterOptionsLength === 0;
110
140
  const popupSelectOptions = isLoading || isError ? [] : sortedOptions; // if not set to [], then on loading, no loading UI will be shown
111
- const areAllResultsLoaded = filterOptions.length === totalCount;
112
- const shouldShowFooter = (status === 'resolved' || isLoadingMore) && filterOptions.length > 0; // footer should not disappear when there is an inline spinner for loading more data
141
+ const areAllResultsLoaded = filterOptionsLength === totalCount;
142
+ const shouldShowFooter = (status === 'resolved' || isLoadingMore) && filterOptionsLength > 0; // footer should not disappear when there is an inline spinner for loading more data
113
143
  const shouldDisplayShowMoreButton = status === 'resolved' && !!pageCursor && !areAllResultsLoaded;
114
144
  return /*#__PURE__*/React.createElement(PopupSelect, {
115
145
  isMulti: true,
@@ -165,7 +195,7 @@ const AsyncPopupSelect = ({
165
195
  isDisabled: isDisabled
166
196
  })),
167
197
  footer: shouldShowFooter && /*#__PURE__*/React.createElement(PopupFooter, {
168
- currentDisplayCount: filterOptionsLength,
198
+ currentDisplayCount: popupSelectOptions.length,
169
199
  totalCount: totalCount
170
200
  })
171
201
  });
@@ -10,15 +10,24 @@ const BasicFilterContainer = ({
10
10
  jql,
11
11
  cloudId
12
12
  }) => {
13
- const [selection, setSelection] = 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 = useCallback(options => {
20
- setSelection(options);
21
- }, [setSelection]);
19
+ const handleSelectionChange = useCallback((options, filter) => {
20
+ const updatedSelection = {
21
+ ...selection,
22
+ [filter]: options
23
+ };
24
+ setSelection(updatedSelection);
25
+ }, [selection]);
26
+ const handleReset = useCallback(() => {
27
+ if (Object.keys(selection).length > 0) {
28
+ setSelection({});
29
+ }
30
+ }, [selection]);
22
31
  return /*#__PURE__*/React.createElement(Flex, {
23
32
  xcss: basicFilterContainerStyles,
24
33
  gap: "space.100",
@@ -27,9 +36,10 @@ const BasicFilterContainer = ({
27
36
  cloudId: cloudId,
28
37
  filterType: filter,
29
38
  key: filter,
30
- selection: selection,
39
+ selection: selection[filter] || [],
31
40
  isDisabled: !cloudId,
32
- onSelectionChange: handleSelectionChange
41
+ onSelectionChange: options => handleSelectionChange(options, filter),
42
+ onReset: handleReset
33
43
  })));
34
44
  };
35
45
  export default BasicFilterContainer;
@@ -1,5 +1,6 @@
1
1
  import { JastBuilder } from '@atlaskit/jql-ast';
2
2
  export const isValidJql = jql => {
3
+ var _jast$errors;
3
4
  const jast = new JastBuilder().build(jql);
4
- return jast.errors.length === 0;
5
+ return (jast === null || jast === void 0 ? void 0 : (_jast$errors = jast.errors) === null || _jast$errors === void 0 ? void 0 : _jast$errors.length) === 0;
5
6
  };
@@ -1,5 +1,5 @@
1
1
  export var EVENT_CHANNEL = 'media';
2
2
  export var packageMetaData = {
3
3
  packageName: "@atlaskit/link-datasource",
4
- packageVersion: "1.17.1"
4
+ packageVersion: "1.17.3"
5
5
  };
@@ -1,4 +1,7 @@
1
+ import _defineProperty from "@babel/runtime/helpers/defineProperty";
1
2
  import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
3
+ function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
4
+ function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
2
5
  /** @jsx jsx */
3
6
  import { useEffect, useRef, useState } from 'react';
4
7
  import { css, jsx } from '@emotion/react';
@@ -199,6 +202,9 @@ export var DraggableTableHeading = function DraggableTableHeading(_ref) {
199
202
 
200
203
  // Handling column resizing
201
204
  useEffect(function () {
205
+ if (!onWidthChange) {
206
+ return;
207
+ }
202
208
  var resizeHandle = columnResizeHandleRef.current;
203
209
  invariant(resizeHandle);
204
210
  var mainHeaderCell = mainHeaderCellRef.current;
@@ -257,18 +263,21 @@ export var DraggableTableHeading = function DraggableTableHeading(_ref) {
257
263
  return jsx(TableHeading, {
258
264
  ref: mainHeaderCellRef,
259
265
  "data-testid": "".concat(id, "-column-heading"),
260
- style: {
261
- width: width,
266
+ style: _objectSpread({
262
267
  cursor: 'grab'
263
- }
264
- }, jsx("div", {
268
+ }, onWidthChange ? {
269
+ width: width
270
+ } : {
271
+ maxWidth: width
272
+ })
273
+ }, onWidthChange ? jsx("div", {
265
274
  ref: columnResizeHandleRef,
266
275
  css: [resizerStyles, state.type === 'resizing' && resizingStyles],
267
276
  style: {
268
277
  height: "".concat(dndPreviewHeight, "px")
269
278
  },
270
279
  "data-testid": "column-resize-handle"
271
- }), jsx("div", {
280
+ }) : null, jsx("div", {
272
281
  ref: dropTargetRef,
273
282
  css: [dropTargetStyles, isDraggingAnyColumn ? null : noPointerEventsStyles],
274
283
  style: {
@@ -50,7 +50,6 @@ var scrollableContainerStyles = css({
50
50
  borderRadius: "var(--ds-border-radius-100, 3px)"
51
51
  });
52
52
  var tableStyles = css({
53
- tableLayout: 'fixed',
54
53
  // These styles are needed to prevent thead bottom border from scrolling away.
55
54
  // This happens because it is sticky. https://stackoverflow.com/questions/50361698/border-style-do-not-work-with-sticky-position-element
56
55
  borderCollapse: 'separate',
@@ -365,6 +364,7 @@ export var IssueLikeDataTableView = function IssueLikeDataTableView(_ref) {
365
364
  }
366
365
  }, _callee, null, [[3, 9]]);
367
366
  })), [parentContainerRenderInstanceId, extensionKey, hasFullSchema, onLoadDatasourceDetails]);
367
+ var shouldUseWidth = onColumnResize || columnCustomSizes;
368
368
  return jsx("div", {
369
369
  /* There is required contentEditable={true} in editor-card-plugin
370
370
  * But this brakes how DND works. We set contentEditable={false} to allow DND to work
@@ -378,7 +378,10 @@ export var IssueLikeDataTableView = function IssueLikeDataTableView(_ref) {
378
378
  } : undefined
379
379
  }, jsx(Table, {
380
380
  css: tableStyles,
381
- "data-testid": testId
381
+ "data-testid": testId,
382
+ style: shouldUseWidth ? {
383
+ tableLayout: 'fixed'
384
+ } : {}
382
385
  }, jsx("thead", {
383
386
  "data-testid": testId && "".concat(testId, "--head"),
384
387
  css: [noDefaultBorderStyles, tableHeadStyles]
@@ -426,8 +429,10 @@ export var IssueLikeDataTableView = function IssueLikeDataTableView(_ref) {
426
429
  return jsx(TableHeading, {
427
430
  key: key,
428
431
  "data-testid": "".concat(key, "-column-heading"),
429
- style: {
432
+ style: shouldUseWidth ? {
430
433
  width: width
434
+ } : {
435
+ maxWidth: width
431
436
  }
432
437
  }, heading);
433
438
  }
@@ -452,8 +457,10 @@ export var IssueLikeDataTableView = function IssueLikeDataTableView(_ref) {
452
457
  var cellKey = _ref13.key,
453
458
  content = _ref13.content,
454
459
  width = _ref13.width;
455
- var loadingRowStyle = {
460
+ var loadingRowStyle = shouldUseWidth ? {
456
461
  width: width
462
+ } : {
463
+ maxWidth: width
457
464
  };
458
465
  // extra padding is required around skeleton loader to avoid vertical jumps when data loads
459
466
  if (key !== null && key !== void 0 && key.includes('loading')) {
@@ -105,12 +105,20 @@ export var useFilterOptions = function useFilterOptions(_ref) {
105
105
  }
106
106
  }, _callee, null, [[5, 24]]);
107
107
  })), [cloudId, filterOptions, filterType, getFieldValues]);
108
+ var reset = useCallback(function () {
109
+ setStatus('empty');
110
+ setFilterOptions([]);
111
+ setTotalCount(0);
112
+ setNextPageCursor(undefined);
113
+ initialData.current = undefined;
114
+ }, []);
108
115
  return {
109
116
  filterOptions: filterOptions,
110
117
  fetchFilterOptions: fetchFilterOptions,
111
118
  totalCount: totalCount,
112
119
  pageCursor: nextPageCursor,
113
120
  status: status,
121
+ reset: reset,
114
122
  errors: status === 'rejected' ? errors : []
115
123
  };
116
124
  };
@@ -5,7 +5,8 @@ import _asyncToGenerator from "@babel/runtime/helpers/asyncToGenerator";
5
5
  import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
6
6
  var _excluded = ["isOpen"];
7
7
  import _regeneratorRuntime from "@babel/runtime/regenerator";
8
- import React, { useCallback, useEffect, useState } from 'react';
8
+ import React, { useCallback, useEffect, useRef, useState } from 'react';
9
+ import isEqual from 'lodash/isEqual';
9
10
  import { useIntl } from 'react-intl-next';
10
11
  import { useDebouncedCallback } from 'use-debounce';
11
12
  import { CheckboxOption, PopupSelect } from '@atlaskit/select';
@@ -28,6 +29,8 @@ var AsyncPopupSelect = function AsyncPopupSelect(_ref) {
28
29
  selection = _ref.selection,
29
30
  _ref$onSelectionChang = _ref.onSelectionChange,
30
31
  onSelectionChange = _ref$onSelectionChang === void 0 ? function () {} : _ref$onSelectionChang,
32
+ _ref$onReset = _ref.onReset,
33
+ resetSelection = _ref$onReset === void 0 ? function () {} : _ref$onReset,
31
34
  _ref$isDisabled = _ref.isDisabled,
32
35
  isDisabled = _ref$isDisabled === void 0 ? false : _ref$isDisabled;
33
36
  var _useIntl = useIntl(),
@@ -40,10 +43,13 @@ var AsyncPopupSelect = function AsyncPopupSelect(_ref) {
40
43
  _useState4 = _slicedToArray(_useState3, 2),
41
44
  selectedOptions = _useState4[0],
42
45
  setSelectedOptions = _useState4[1];
43
- var _useState5 = useState(selectedOptions),
46
+ var _useState5 = useState([]),
44
47
  _useState6 = _slicedToArray(_useState5, 2),
45
48
  sortedOptions = _useState6[0],
46
49
  setSortedOptions = _useState6[1];
50
+ var currentSiteCloudId = useRef(cloudId);
51
+ var sortPaginatedResults = useRef(false); // this is to track pagination for sorting purpose
52
+
47
53
  var _useFilterOptions = useFilterOptions({
48
54
  filterType: filterType,
49
55
  cloudId: cloudId
@@ -53,6 +59,7 @@ var AsyncPopupSelect = function AsyncPopupSelect(_ref) {
53
59
  totalCount = _useFilterOptions.totalCount,
54
60
  status = _useFilterOptions.status,
55
61
  pageCursor = _useFilterOptions.pageCursor,
62
+ resetHook = _useFilterOptions.reset,
56
63
  errors = _useFilterOptions.errors;
57
64
  var _useDebouncedCallback = useDebouncedCallback(function (searchString) {
58
65
  fetchFilterOptions({
@@ -80,14 +87,12 @@ var AsyncPopupSelect = function AsyncPopupSelect(_ref) {
80
87
  return _ref2.apply(this, arguments);
81
88
  };
82
89
  }(), [handleDebouncedFetchFilterOptions, searchTerm]);
83
- var handleOptionSelection = function handleOptionSelection(newValue) {
84
- setSelectedOptions(newValue);
90
+ var handleOptionSelection = useCallback(function (newValue) {
85
91
  onSelectionChange(newValue);
86
- };
92
+ }, [onSelectionChange]);
87
93
  var sortOptionsOnPopupOpen = useCallback(function () {
88
94
  if (selectedOptions.length === 0) {
89
- setSortedOptions(filterOptions);
90
- return;
95
+ return setSortedOptions(filterOptions);
91
96
  }
92
97
  var nonSelectedOptions = filterOptions.filter(function (option) {
93
98
  return !selectedOptions.find(function (selectedOption) {
@@ -95,37 +100,41 @@ var AsyncPopupSelect = function AsyncPopupSelect(_ref) {
95
100
  });
96
101
  });
97
102
  var newOptions = [].concat(_toConsumableArray(selectedOptions), _toConsumableArray(nonSelectedOptions));
98
- setSortedOptions(newOptions);
99
- }, [selectedOptions, filterOptions]);
103
+ if (!isEqual(newOptions, sortedOptions)) {
104
+ setSortedOptions(newOptions);
105
+ }
106
+ }, [selectedOptions, filterOptions, sortedOptions]);
100
107
  var sortOptionsOnResolve = useCallback(function () {
101
- var newOptions = filterOptions.filter(function (option) {
102
- return !sortedOptions.find(function (sortedOption) {
103
- return sortedOption.value === option.value;
104
- });
105
- });
106
- var shouldSetSortOptions = false;
107
- if (sortedOptions.length !== filterOptions.length) {
108
- shouldSetSortOptions = true;
109
- } else {
110
- sortedOptions.forEach(function (sortedOption) {
111
- if (!filterOptions.some(function (filterOption) {
112
- return filterOption.value === sortedOption.value;
113
- })) {
114
- shouldSetSortOptions = true;
115
- }
116
- });
108
+ // sortedOptions is empty initially, this will take care of setting the initial value and bring the selected items to the top
109
+ if (sortedOptions.length === 0) {
110
+ return sortOptionsOnPopupOpen();
111
+ }
112
+
113
+ // when the user is searching, we want the search result to be displayed as it is, and the select component will take care of marking the selected items
114
+ if (searchTerm) {
115
+ sortPaginatedResults.current = false; // set to false to indicate pagination resolve action is completed from the sorting perspective
116
+ return setSortedOptions(filterOptions);
117
117
  }
118
- if (shouldSetSortOptions) {
119
- var sortedOptionsFiltered = sortedOptions.filter(function (sortedOption) {
120
- return filterOptions.some(function (filterOption) {
121
- return filterOption.value === sortedOption.value;
118
+
119
+ // this block handles the pagination, where on pagination, we will just append newOptions to the current list
120
+ if (sortPaginatedResults.current) {
121
+ var newOptions = filterOptions.filter(function (option) {
122
+ return !sortedOptions.find(function (sortedOption) {
123
+ return sortedOption.value === option.value;
122
124
  });
123
125
  });
124
- setSortedOptions([].concat(_toConsumableArray(sortedOptionsFiltered), _toConsumableArray(newOptions)));
126
+ if (newOptions.length > 0) {
127
+ setSortedOptions([].concat(_toConsumableArray(sortedOptions), _toConsumableArray(newOptions)));
128
+ }
129
+ sortPaginatedResults.current = false; // set to false to indicate pagination resolve action is completed from the sorting perspective
130
+ return;
125
131
  }
126
- }, [filterOptions, sortedOptions]);
132
+ sortPaginatedResults.current = false; // set to false to indicate pagination resolve action is completed from the sorting perspective
133
+ sortOptionsOnPopupOpen();
134
+ }, [filterOptions, searchTerm, sortOptionsOnPopupOpen, sortedOptions]);
127
135
  var handleShowMore = useCallback(function () {
128
136
  if (pageCursor) {
137
+ sortPaginatedResults.current = true;
129
138
  fetchFilterOptions({
130
139
  pageCursor: pageCursor,
131
140
  searchString: searchTerm
@@ -146,15 +155,31 @@ var AsyncPopupSelect = function AsyncPopupSelect(_ref) {
146
155
  if (status === 'resolved') {
147
156
  sortOptionsOnResolve();
148
157
  }
149
- }, [sortOptionsOnResolve, status]);
158
+ // eslint-disable-next-line react-hooks/exhaustive-deps
159
+ }, [status]); // we only want the sortOptionsOnResolve to run when there is a status change
160
+
161
+ useEffect(function () {
162
+ if (currentSiteCloudId.current !== cloudId) {
163
+ currentSiteCloudId.current = cloudId;
164
+ setSortedOptions([]);
165
+ setSearchTerm('');
166
+ resetHook();
167
+ resetSelection();
168
+ }
169
+ }, [cloudId, resetHook, resetSelection]);
170
+ useEffect(function () {
171
+ if (!isEqual(selection, selectedOptions)) {
172
+ setSelectedOptions(selection);
173
+ }
174
+ }, [selectedOptions, selection]);
150
175
  var filterOptionsLength = filterOptions.length;
151
176
  var isError = status === 'rejected';
152
177
  var isLoading = status === 'loading' || status === 'empty';
153
178
  var isLoadingMore = status === 'loadingMore';
154
179
  var isEmpty = status === 'resolved' && filterOptionsLength === 0;
155
180
  var popupSelectOptions = isLoading || isError ? [] : sortedOptions; // if not set to [], then on loading, no loading UI will be shown
156
- var areAllResultsLoaded = filterOptions.length === totalCount;
157
- var shouldShowFooter = (status === 'resolved' || isLoadingMore) && filterOptions.length > 0; // footer should not disappear when there is an inline spinner for loading more data
181
+ var areAllResultsLoaded = filterOptionsLength === totalCount;
182
+ var shouldShowFooter = (status === 'resolved' || isLoadingMore) && filterOptionsLength > 0; // footer should not disappear when there is an inline spinner for loading more data
158
183
  var shouldDisplayShowMoreButton = status === 'resolved' && !!pageCursor && !areAllResultsLoaded;
159
184
  return /*#__PURE__*/React.createElement(PopupSelect, {
160
185
  isMulti: true,
@@ -213,7 +238,7 @@ var AsyncPopupSelect = function AsyncPopupSelect(_ref) {
213
238
  }));
214
239
  },
215
240
  footer: shouldShowFooter && /*#__PURE__*/React.createElement(PopupFooter, {
216
- currentDisplayCount: filterOptionsLength,
241
+ currentDisplayCount: popupSelectOptions.length,
217
242
  totalCount: totalCount
218
243
  })
219
244
  });
@@ -1,4 +1,7 @@
1
+ import _defineProperty from "@babel/runtime/helpers/defineProperty";
1
2
  import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
3
+ function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
4
+ function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
2
5
  import React, { useCallback, useEffect, useState } from 'react';
3
6
  import { Flex, xcss } from '@atlaskit/primitives';
4
7
  import { isValidJql } from '../utils';
@@ -10,7 +13,7 @@ var basicFilterContainerStyles = xcss({
10
13
  var BasicFilterContainer = function BasicFilterContainer(_ref) {
11
14
  var jql = _ref.jql,
12
15
  cloudId = _ref.cloudId;
13
- var _useState = useState([]),
16
+ var _useState = useState({}),
14
17
  _useState2 = _slicedToArray(_useState, 2),
15
18
  selection = _useState2[0],
16
19
  setSelection = _useState2[1];
@@ -19,9 +22,15 @@ var BasicFilterContainer = function BasicFilterContainer(_ref) {
19
22
  // hydrate hook call goes in here
20
23
  }
21
24
  }, [jql]);
22
- var handleSelectionChange = useCallback(function (options) {
23
- setSelection(options);
24
- }, [setSelection]);
25
+ var handleSelectionChange = useCallback(function (options, filter) {
26
+ var updatedSelection = _objectSpread(_objectSpread({}, selection), {}, _defineProperty({}, filter, options));
27
+ setSelection(updatedSelection);
28
+ }, [selection]);
29
+ var handleReset = useCallback(function () {
30
+ if (Object.keys(selection).length > 0) {
31
+ setSelection({});
32
+ }
33
+ }, [selection]);
25
34
  return /*#__PURE__*/React.createElement(Flex, {
26
35
  xcss: basicFilterContainerStyles,
27
36
  gap: "space.100",
@@ -31,9 +40,12 @@ var BasicFilterContainer = function BasicFilterContainer(_ref) {
31
40
  cloudId: cloudId,
32
41
  filterType: filter,
33
42
  key: filter,
34
- selection: selection,
43
+ selection: selection[filter] || [],
35
44
  isDisabled: !cloudId,
36
- onSelectionChange: handleSelectionChange
45
+ onSelectionChange: function onSelectionChange(options) {
46
+ return handleSelectionChange(options, filter);
47
+ },
48
+ onReset: handleReset
37
49
  });
38
50
  }));
39
51
  };
@@ -1,5 +1,6 @@
1
1
  import { JastBuilder } from '@atlaskit/jql-ast';
2
2
  export var isValidJql = function isValidJql(jql) {
3
+ var _jast$errors;
3
4
  var jast = new JastBuilder().build(jql);
4
- return jast.errors.length === 0;
5
+ return (jast === null || jast === void 0 || (_jast$errors = jast.errors) === null || _jast$errors === void 0 ? void 0 : _jast$errors.length) === 0;
5
6
  };
@@ -10,6 +10,7 @@ export interface FetchFilterOptionsProps {
10
10
  export interface FilterOptionsState {
11
11
  filterOptions: SelectOption[];
12
12
  fetchFilterOptions: (prop?: FetchFilterOptionsProps) => Promise<void>;
13
+ reset: () => void;
13
14
  totalCount: number;
14
15
  pageCursor?: string;
15
16
  status: 'empty' | 'loading' | 'resolved' | 'rejected' | 'loadingMore';
@@ -5,8 +5,9 @@ export interface AsyncPopupSelectProps {
5
5
  cloudId: string;
6
6
  selection: SelectOption[];
7
7
  onSelectionChange?: (selection: SelectOption[]) => void;
8
+ onReset?: () => void;
8
9
  isDisabled?: boolean;
9
10
  }
10
11
  export declare const SEARCH_DEBOUNCE_MS = 350;
11
- declare const AsyncPopupSelect: ({ filterType, cloudId, selection, onSelectionChange, isDisabled, }: AsyncPopupSelectProps) => JSX.Element;
12
+ declare const AsyncPopupSelect: ({ filterType, cloudId, selection, onSelectionChange, onReset: resetSelection, isDisabled, }: AsyncPopupSelectProps) => JSX.Element;
12
13
  export default AsyncPopupSelect;
@@ -1,5 +1,5 @@
1
1
  /// <reference types="react" />
2
- interface BasicFilterContainerProps {
2
+ export interface BasicFilterContainerProps {
3
3
  jql: string;
4
4
  cloudId: string;
5
5
  }
@@ -10,6 +10,7 @@ export interface FetchFilterOptionsProps {
10
10
  export interface FilterOptionsState {
11
11
  filterOptions: SelectOption[];
12
12
  fetchFilterOptions: (prop?: FetchFilterOptionsProps) => Promise<void>;
13
+ reset: () => void;
13
14
  totalCount: number;
14
15
  pageCursor?: string;
15
16
  status: 'empty' | 'loading' | 'resolved' | 'rejected' | 'loadingMore';
@@ -5,8 +5,9 @@ export interface AsyncPopupSelectProps {
5
5
  cloudId: string;
6
6
  selection: SelectOption[];
7
7
  onSelectionChange?: (selection: SelectOption[]) => void;
8
+ onReset?: () => void;
8
9
  isDisabled?: boolean;
9
10
  }
10
11
  export declare const SEARCH_DEBOUNCE_MS = 350;
11
- declare const AsyncPopupSelect: ({ filterType, cloudId, selection, onSelectionChange, isDisabled, }: AsyncPopupSelectProps) => JSX.Element;
12
+ declare const AsyncPopupSelect: ({ filterType, cloudId, selection, onSelectionChange, onReset: resetSelection, isDisabled, }: AsyncPopupSelectProps) => JSX.Element;
12
13
  export default AsyncPopupSelect;
@@ -1,5 +1,5 @@
1
1
  /// <reference types="react" />
2
- interface BasicFilterContainerProps {
2
+ export interface BasicFilterContainerProps {
3
3
  jql: string;
4
4
  cloudId: string;
5
5
  }
@@ -22,6 +22,7 @@ mockDatasourceFetchRequests();
22
22
 
23
23
  interface Props {
24
24
  isReadonly?: boolean;
25
+ canResizeColumns?: boolean;
25
26
  }
26
27
 
27
28
  const TableViewWrapper = styled.div`
@@ -32,7 +33,7 @@ const TableViewWrapper = styled.div`
32
33
  height: 100%;
33
34
  `;
34
35
 
35
- const ExampleBody = ({ isReadonly }: Props) => {
36
+ const ExampleBody = ({ isReadonly, canResizeColumns = true }: Props) => {
36
37
  const parameters = useMemo<JiraIssueDatasourceParameters>(
37
38
  () => ({
38
39
  cloudId: 'some-cloud-id',
@@ -90,7 +91,9 @@ const ExampleBody = ({ isReadonly }: Props) => {
90
91
  onVisibleColumnKeysChange={
91
92
  isReadonly ? undefined : setVisibleColumnKeys
92
93
  }
93
- onColumnResize={isReadonly ? undefined : onColumnResize}
94
+ onColumnResize={
95
+ isReadonly || !canResizeColumns ? undefined : onColumnResize
96
+ }
94
97
  columnCustomSizes={columnCustomSizes}
95
98
  />
96
99
  ) : (
@@ -100,11 +103,17 @@ const ExampleBody = ({ isReadonly }: Props) => {
100
103
  );
101
104
  };
102
105
 
103
- export const ExampleIssueLikeTable = ({ isReadonly }: Props) => {
106
+ export const ExampleIssueLikeTable = ({
107
+ isReadonly,
108
+ canResizeColumns,
109
+ }: Props) => {
104
110
  return (
105
111
  <IntlProvider locale="en">
106
112
  <SmartCardProvider client={new SmartLinkClient()}>
107
- <ExampleBody isReadonly={isReadonly} />
113
+ <ExampleBody
114
+ isReadonly={isReadonly}
115
+ canResizeColumns={canResizeColumns}
116
+ />
108
117
  </SmartCardProvider>
109
118
  </IntlProvider>
110
119
  );
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atlaskit/link-datasource",
3
- "version": "1.17.1",
3
+ "version": "1.17.3",
4
4
  "description": "UI Components to support linking platform dataset feature",
5
5
  "publishConfig": {
6
6
  "registry": "https://registry.npmjs.org/"