@atlaskit/link-datasource 5.5.1 → 5.6.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 (29) hide show
  1. package/CHANGELOG.md +7 -0
  2. package/dist/cjs/ui/datasource-table-view/datasource-column-sort.js +51 -0
  3. package/dist/cjs/ui/datasource-table-view/datasourceTableView.js +52 -5
  4. package/dist/cjs/ui/issue-like-table/index.compiled.css +5 -0
  5. package/dist/cjs/ui/issue-like-table/index.js +120 -62
  6. package/dist/cjs/ui/issue-like-table/messages.js +10 -0
  7. package/dist/es2019/ui/datasource-table-view/datasource-column-sort.js +43 -0
  8. package/dist/es2019/ui/datasource-table-view/datasourceTableView.js +46 -6
  9. package/dist/es2019/ui/issue-like-table/index.compiled.css +5 -0
  10. package/dist/es2019/ui/issue-like-table/index.js +58 -4
  11. package/dist/es2019/ui/issue-like-table/messages.js +10 -0
  12. package/dist/esm/ui/datasource-table-view/datasource-column-sort.js +44 -0
  13. package/dist/esm/ui/datasource-table-view/datasourceTableView.js +53 -6
  14. package/dist/esm/ui/issue-like-table/index.compiled.css +5 -0
  15. package/dist/esm/ui/issue-like-table/index.js +120 -62
  16. package/dist/esm/ui/issue-like-table/messages.js +10 -0
  17. package/dist/types/ui/datasource-table-view/datasource-column-sort.d.ts +12 -0
  18. package/dist/types/ui/datasource-table-view/datasourceTableView.d.ts +2 -2
  19. package/dist/types/ui/datasource-table-view/types.d.ts +1 -1
  20. package/dist/types/ui/issue-like-table/index.d.ts +1 -1
  21. package/dist/types/ui/issue-like-table/messages.d.ts +33 -23
  22. package/dist/types/ui/issue-like-table/types.d.ts +10 -0
  23. package/dist/types-ts4.5/ui/datasource-table-view/datasource-column-sort.d.ts +12 -0
  24. package/dist/types-ts4.5/ui/datasource-table-view/datasourceTableView.d.ts +2 -2
  25. package/dist/types-ts4.5/ui/datasource-table-view/types.d.ts +1 -1
  26. package/dist/types-ts4.5/ui/issue-like-table/index.d.ts +1 -1
  27. package/dist/types-ts4.5/ui/issue-like-table/messages.d.ts +33 -23
  28. package/dist/types-ts4.5/ui/issue-like-table/types.d.ts +10 -0
  29. package/package.json +6 -3
package/CHANGELOG.md CHANGED
@@ -1,5 +1,12 @@
1
1
  # @atlaskit/link-datasource
2
2
 
3
+ ## 5.6.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [`5700d1a0bb7b0`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/5700d1a0bb7b0) -
8
+ [ux] Add sortable columns to read only (Renderer) view without persistance
9
+
3
10
  ## 5.5.1
4
11
 
5
12
  ### Patch Changes
@@ -0,0 +1,51 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+ Object.defineProperty(exports, "__esModule", {
5
+ value: true
6
+ });
7
+ exports.getDatasourceColumnSortGetter = void 0;
8
+ var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
9
+ var _jiraIssuesModal = require("../jira-issues-modal");
10
+ 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; }
11
+ 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; }
12
+ var getNextSortDirection = function getNextSortDirection(columnKey, currentSort) {
13
+ if ((currentSort === null || currentSort === void 0 ? void 0 : currentSort.key) === columnKey) {
14
+ return currentSort.direction === 'ASC' ? 'DESC' : 'ASC';
15
+ }
16
+ return 'ASC';
17
+ };
18
+ // Match and remove an existing trailing ORDER BY clause before appending the next sort:
19
+ // - (?:^|\\s+) allows ORDER BY at the start of the JQL or after whitespace.
20
+ // - ORDER\\s+BY matches ORDER BY with flexible spacing and is case-insensitive (/i).
21
+ // - [\\s\\S]*$ consumes everything after ORDER BY to the end of the JQL.
22
+ // Examples:
23
+ // - "project = TEST ORDER BY created DESC" -> "project = TEST"
24
+ // - "ORDER BY priority ASC" -> ""
25
+ var JIRA_ORDER_BY_PATTERN = /(?:^|\s+)ORDER\s+BY\s+[\s\S]*$/i;
26
+ var getJiraColumnSortParameters = function getJiraColumnSortParameters(_ref) {
27
+ var parameters = _ref.parameters,
28
+ columnKey = _ref.columnKey,
29
+ currentSort = _ref.currentSort;
30
+ if (typeof parameters.jql !== 'string') {
31
+ return undefined;
32
+ }
33
+ var direction = getNextSortDirection(columnKey, currentSort);
34
+ var jqlWithoutOrder = parameters.jql.replace(JIRA_ORDER_BY_PATTERN, '').trim();
35
+ var nextOrderByClause = "ORDER BY ".concat(columnKey, " ").concat(direction);
36
+ return {
37
+ parameters: _objectSpread(_objectSpread({}, parameters), {}, {
38
+ jql: "".concat(jqlWithoutOrder, " ").concat(nextOrderByClause)
39
+ }),
40
+ sort: {
41
+ key: columnKey,
42
+ direction: direction
43
+ }
44
+ };
45
+ };
46
+ var getDatasourceColumnSortGetter = exports.getDatasourceColumnSortGetter = function getDatasourceColumnSortGetter(datasourceId) {
47
+ if (datasourceId === _jiraIssuesModal.JIRA_LIST_OF_LINKS_DATASOURCE_ID) {
48
+ return getJiraColumnSortParameters;
49
+ }
50
+ return undefined;
51
+ };
@@ -11,6 +11,9 @@ require("./datasourceTableView.compiled.css");
11
11
  var _react = _interopRequireWildcard(require("react"));
12
12
  var React = _react;
13
13
  var _runtime = require("@compiled/react/runtime");
14
+ var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));
15
+ var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
16
+ var _isEqual = _interopRequireDefault(require("lodash/isEqual"));
14
17
  var _analyticsNext = require("@atlaskit/analytics-next");
15
18
  var _intlMessagesProvider = require("@atlaskit/intl-messages-provider");
16
19
  var _platformFeatureFlags = require("@atlaskit/platform-feature-flags");
@@ -34,6 +37,7 @@ var _providerAuthRequired = require("../common/error-state/provider-auth-require
34
37
  var _issueLikeTable = require("../issue-like-table");
35
38
  var _emptyState = _interopRequireDefault(require("../issue-like-table/empty-state"));
36
39
  var _tableFooter = require("../table-footer");
40
+ var _datasourceColumnSort = require("./datasource-column-sort");
37
41
  function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function _interopRequireWildcard(e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != _typeof(e) && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (var _t in e) "default" !== _t && {}.hasOwnProperty.call(e, _t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, _t)) && (i.get || i.set) ? o(f, _t, i) : f[_t] = e[_t]); return f; })(e, t); }
38
42
  var containerStyles = null;
39
43
  var DefaultScrollableContainerHeight = 590;
@@ -49,9 +53,35 @@ var DatasourceTableViewWithoutAnalytics = function DatasourceTableViewWithoutAna
49
53
  onWrappedColumnChange = _ref.onWrappedColumnChange,
50
54
  _ref$scrollableContai = _ref.scrollableContainerHeight,
51
55
  scrollableContainerHeight = _ref$scrollableContai === void 0 ? DefaultScrollableContainerHeight : _ref$scrollableContai;
56
+ // Local copy lets us apply in-session sort mutations without mutating external parameters.
57
+ var _useState = (0, _react.useState)(parameters),
58
+ _useState2 = (0, _slicedToArray2.default)(_useState, 2),
59
+ sessionParameters = _useState2[0],
60
+ setSessionParameters = _useState2[1];
61
+ // Tracks the external parameters that the current session/sort state was derived from.
62
+ var sessionBaseParametersRef = (0, _react.useRef)(parameters);
63
+ var _useState3 = (0, _react.useState)(),
64
+ _useState4 = (0, _slicedToArray2.default)(_useState3, 2),
65
+ sortState = _useState4[0],
66
+ setSortState = _useState4[1];
67
+ var columnSortGetter = (0, _datasourceColumnSort.getDatasourceColumnSortGetter)(datasourceId);
68
+ // Sorting is only owned by this view when parent callbacks are absent (read-only rendering mode).
69
+ var isReadOnlyDatasourceTable = !onVisibleColumnKeysChange && !onColumnResize && !onWrappedColumnChange;
70
+ // Keep sort UI hidden unless datasource + ownership + feature gate all allow it.
71
+ var shouldEnableColumnSort = !!columnSortGetter && isReadOnlyDatasourceTable && (0, _platformFeatureFlags.fg)('platform_lp_jira_sllv_renderer_column_sorting');
72
+ (0, _useDeepEffect.useDeepEffect)(function () {
73
+ // External parameter updates should always reset local sort/session state back to source-of-truth.
74
+ sessionBaseParametersRef.current = parameters;
75
+ setSessionParameters(parameters);
76
+ setSortState(undefined);
77
+ }, [parameters]);
78
+ var isSessionBasedOnCurrentParameters = (0, _isEqual.default)(sessionBaseParametersRef.current, parameters);
79
+ // Use session parameters only when they are known to be based on the current external parameters.
80
+ // This avoids a one-render stale read during the deep-effect update cycle above.
81
+ var activeParameters = isSessionBasedOnCurrentParameters && (0, _platformFeatureFlags.fg)('platform_lp_jira_sllv_renderer_column_sorting') ? sessionParameters : parameters;
52
82
  var _useDatasourceTableSt = (0, _useDatasourceTableState.useDatasourceTableState)({
53
83
  datasourceId: datasourceId,
54
- parameters: parameters,
84
+ parameters: activeParameters,
55
85
  fieldKeys: visibleColumnKeys
56
86
  }),
57
87
  reset = _useDatasourceTableSt.reset,
@@ -107,7 +137,7 @@ var DatasourceTableViewWithoutAnalytics = function DatasourceTableViewWithoutAna
107
137
  reset();
108
138
  }
109
139
  isInitialRender.current = false;
110
- }, [reset, parameters]);
140
+ }, [reset, activeParameters]);
111
141
  (0, _react.useEffect)(function () {
112
142
  if (onVisibleColumnKeysChange && (visibleColumnKeys || []).length === 0 && defaultVisibleColumnKeys.length > 0) {
113
143
  onVisibleColumnKeysChange(defaultVisibleColumnKeys);
@@ -153,6 +183,19 @@ var DatasourceTableViewWithoutAnalytics = function DatasourceTableViewWithoutAna
153
183
  });
154
184
  forcedReset();
155
185
  }, [destinationObjectTypes, extensionKey, fireEvent, forcedReset]);
186
+ var onColumnSort = (0, _react.useCallback)(function (columnKey) {
187
+ // Build next params/sort atomically so UI state and query state stay in sync.
188
+ var result = columnSortGetter === null || columnSortGetter === void 0 ? void 0 : columnSortGetter({
189
+ parameters: sessionParameters,
190
+ columnKey: columnKey,
191
+ currentSort: sortState
192
+ });
193
+ if (!result) {
194
+ return;
195
+ }
196
+ setSortState(result.sort);
197
+ setSessionParameters(result.parameters);
198
+ }, [columnSortGetter, sessionParameters, sortState]);
156
199
  var handleErrorRefresh = (0, _react.useCallback)(function () {
157
200
  reset({
158
201
  shouldForceRequest: true
@@ -184,7 +227,7 @@ var DatasourceTableViewWithoutAnalytics = function DatasourceTableViewWithoutAna
184
227
  loaderFn: _fetchMessagesForLocale.fetchMessagesForLocale
185
228
  }, /*#__PURE__*/React.createElement("div", {
186
229
  className: (0, _runtime.ax)(["_2rko1kw7", "datasource-table"])
187
- }, hasColumns ? /*#__PURE__*/React.createElement(_issueLikeTable.IssueLikeDataTableView, {
230
+ }, hasColumns ? /*#__PURE__*/React.createElement(_issueLikeTable.IssueLikeDataTableView, (0, _extends2.default)({
188
231
  testId: 'datasource-table-view',
189
232
  hasNextPage: hasNextPage,
190
233
  items: responseItems,
@@ -196,12 +239,16 @@ var DatasourceTableViewWithoutAnalytics = function DatasourceTableViewWithoutAna
196
239
  visibleColumnKeys: hasStaleVisibleColumnKeys ? defaultVisibleColumnKeys : visibleColumnKeys || defaultVisibleColumnKeys,
197
240
  onVisibleColumnKeysChange: onVisibleColumnKeysChange,
198
241
  columnCustomSizes: columnCustomSizes,
199
- onColumnResize: onColumnResize,
242
+ onColumnResize: onColumnResize
243
+ }, shouldEnableColumnSort && (0, _platformFeatureFlags.fg)('platform_lp_jira_sllv_renderer_column_sorting') ? {
244
+ onColumnSort: onColumnSort,
245
+ sortState: sortState
246
+ } : {}, {
200
247
  wrappedColumnKeys: wrappedColumnKeys,
201
248
  onWrappedColumnChange: onWrappedColumnChange,
202
249
  scrollableContainerHeight: isInPDFRender ? undefined : (0, _platformFeatureFlags.fg)('lp_enable_datasource-table-view_height_override') ? scrollableContainerHeight : DefaultScrollableContainerHeight,
203
250
  extensionKey: extensionKey
204
- }) : /*#__PURE__*/React.createElement(_emptyState.default, {
251
+ })) : /*#__PURE__*/React.createElement(_emptyState.default, {
205
252
  testId: "datasource-table-view-skeleton",
206
253
  isCompact: true
207
254
  }), /*#__PURE__*/React.createElement(_tableFooter.TableFooter, {
@@ -14,6 +14,7 @@
14
14
  .pm-table-wrapper>table thead ._1rmlidpf:last-of-type{border:0}
15
15
  .pm-table-wrapper>table thead ._1u3bidpf{border:0}
16
16
  .pm-table-wrapper>table thead ._ex0g13hi:last-of-type{background:linear-gradient(90deg,hsla(0,0%,100%,0) 0,var(--ds-elevation-surface-current,#fff) 10%)}
17
+ ._1wtnze3t button{padding-block:var(--ds-space-0,0)}
17
18
  .ProseMirror .pm-table-wrapper>table tbody ._15lria51{border-bottom:var(--ds-border-width,1px) solid var(--ds-border,#0b120e24)}
18
19
  .ProseMirror .pm-table-wrapper>table tbody ._1ho1idpf:last-of-type{border-right:0}
19
20
  .ProseMirror .pm-table-wrapper>table tbody ._1xqpia51{border-right:var(--ds-border-width,1px) solid var(--ds-border,#0b120e24)}
@@ -66,6 +67,7 @@ thead.has-column-picker ._10i2idpf:nth-last-of-type(2){border-right:0}.ProseMirr
66
67
  .ProseMirror .pm-table-wrapper>table thead ._zjk41if8:last-of-type{position:sticky}
67
68
  ._11681tcg [data-testid=datasource-header-content--container]{line-height:24px}
68
69
  ._11j11b66 [data-testid=datasource-header-content--container]{padding-right:var(--ds-space-050,4px)}
70
+ ._11lvze3t button{padding-left:var(--ds-space-0,0)}
69
71
  ._124in7od [data-testid=inline-card-icon-and-title]{white-space:unset}
70
72
  ._12pn15vq [data-testid=datasource-header-content--container]{overflow-x:hidden}
71
73
  ._12ruusvi:last-of-type{box-sizing:border-box}
@@ -108,7 +110,9 @@ thead.has-column-picker ._10i2idpf:nth-last-of-type(2){border-right:0}.ProseMirr
108
110
  ._btyzidpf{border-spacing:0}
109
111
  ._ca0qv77o{padding-top:var(--ds-space-025,2px)}
110
112
  ._ca0qze3t{padding-top:var(--ds-space-0,0)}
113
+ ._ficf1e5h button{text-align:left}
111
114
  ._iscccj1k [data-testid=datasource-header-content--container]{display:-webkit-box}
115
+ ._jq8g1wug button{height:auto}
112
116
  ._k48p1wq8{font-weight:var(--ds-font-weight-medium,500)}
113
117
  ._kqsw1if8{position:sticky}
114
118
  ._kqswh2mm{position:relative}
@@ -130,6 +134,7 @@ thead.has-column-picker ._10i2idpf:nth-last-of-type(2){border-right:0}.ProseMirr
130
134
  ._vchh1ntv{box-sizing:content-box}
131
135
  ._vchhusvi{box-sizing:border-box}
132
136
  ._vwz41tcg{line-height:24px}
137
+ ._yhjm1b66 button{padding-right:var(--ds-space-050,4px)}
133
138
  ._yq5hus1c{border-collapse:separate}
134
139
  .pm-table-wrapper>table tbody ._18a21kw7{vertical-align:inherit}
135
140
  .pm-table-wrapper>table tbody ._1h12ze3t{padding-right:var(--ds-space-0,0)}
@@ -18,9 +18,14 @@ var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/sli
18
18
  var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
19
19
  var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));
20
20
  var _objectWithoutProperties2 = _interopRequireDefault(require("@babel/runtime/helpers/objectWithoutProperties"));
21
+ var _reactIntl = require("react-intl");
21
22
  var _tinyInvariant = _interopRequireDefault(require("tiny-invariant"));
23
+ var _new = _interopRequireDefault(require("@atlaskit/button/new"));
22
24
  var _flag = require("@atlaskit/flag");
25
+ var _sortAscending = _interopRequireDefault(require("@atlaskit/icon/core/sort-ascending"));
26
+ var _sortDescending = _interopRequireDefault(require("@atlaskit/icon/core/sort-descending"));
23
27
  var _linkingCommon = require("@atlaskit/linking-common");
28
+ var _platformFeatureFlags = require("@atlaskit/platform-feature-flags");
24
29
  var _closestEdge = require("@atlaskit/pragmatic-drag-and-drop-hitbox/closest-edge");
25
30
  var _reorderWithEdge = require("@atlaskit/pragmatic-drag-and-drop-hitbox/util/reorder-with-edge");
26
31
  var _pragmaticDragAndDropReactBeautifulDndAutoscroll = require("@atlaskit/pragmatic-drag-and-drop-react-beautiful-dnd-autoscroll");
@@ -32,9 +37,11 @@ var _ufoExperiences = require("../../analytics/ufoExperiences");
32
37
  var _datasourceExperienceId = require("../../contexts/datasource-experience-id");
33
38
  var _useIsInPDFRender = require("../../hooks/useIsInPDFRender");
34
39
  var _columnPicker = require("./column-picker");
40
+ var _customIcons = require("./custom-icons");
35
41
  var _dragColumnPreview = require("./drag-column-preview");
36
42
  var _draggableTableHeading = require("./draggable-table-heading");
37
43
  var _emptyState = _interopRequireDefault(require("./empty-state"));
44
+ var _messages = require("./messages");
38
45
  var _renderType = require("./render-type");
39
46
  var _tableCellContent = require("./table-cell-content");
40
47
  var _useIsOnScreen = require("./useIsOnScreen");
@@ -42,7 +49,8 @@ var _utils = require("./utils");
42
49
  var _excluded = ["as", "style"],
43
50
  _excluded2 = ["as", "style"],
44
51
  _excluded3 = ["as", "style"],
45
- _excluded4 = ["as", "style"];
52
+ _excluded4 = ["as", "style"],
53
+ _excluded5 = ["as", "style"];
46
54
  /* eslint-disable @atlaskit/design-system/use-tokens-typography */
47
55
  function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function _interopRequireWildcard(e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != _typeof(e) && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (var _t2 in e) "default" !== _t2 && {}.hasOwnProperty.call(e, _t2) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, _t2)) && (i.get || i.set) ? o(f, _t2, i) : f[_t2] = e[_t2]); return f; })(e, t); }
48
56
  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; }
@@ -134,6 +142,22 @@ var tableStyles = null;
134
142
  var noDefaultBorderStyles = null;
135
143
  var headerStyles = null;
136
144
  var headingHoverEffectStyles = null;
145
+
146
+ // eslint-disable-next-line @atlaskit/ui-styling-standard/no-styled -- Matches DraggableTableHeading button normalization.
147
+ var SortableHeaderParent = (0, _react.forwardRef)(function (_ref5, __cmplr) {
148
+ var _ref5$as = _ref5.as,
149
+ C = _ref5$as === void 0 ? "div" : _ref5$as,
150
+ __cmpls = _ref5.style,
151
+ __cmplp = (0, _objectWithoutProperties2.default)(_ref5, _excluded5);
152
+ return /*#__PURE__*/React.createElement(C, (0, _extends2.default)({}, __cmplp, {
153
+ style: __cmpls,
154
+ ref: __cmplr,
155
+ className: (0, _runtime.ax)(["_1e0c1txw _4cvr1h6o _o5721q9c _1wtnze3t _ficf1e5h _jq8g1wug _11lvze3t _yhjm1b66", __cmplp.className])
156
+ }));
157
+ });
158
+ if (process.env.NODE_ENV !== 'production') {
159
+ SortableHeaderParent.displayName = 'SortableHeaderParent';
160
+ }
137
161
  function extractIndex(data) {
138
162
  var index = data.index;
139
163
  (0, _tinyInvariant.default)(typeof index === 'number');
@@ -180,26 +204,30 @@ function getDefaultColumnWidth(key, type) {
180
204
  return DEFAULT_WIDTH;
181
205
  }
182
206
  }
183
- var IssueLikeDataTableView = exports.IssueLikeDataTableView = function IssueLikeDataTableView(_ref5) {
207
+ var IssueLikeDataTableView = exports.IssueLikeDataTableView = function IssueLikeDataTableView(_ref6) {
184
208
  var _containerRef$current;
185
- var testId = _ref5.testId,
186
- onNextPage = _ref5.onNextPage,
187
- onLoadDatasourceDetails = _ref5.onLoadDatasourceDetails,
188
- items = _ref5.items,
189
- itemIds = _ref5.itemIds,
190
- columns = _ref5.columns,
191
- _ref5$renderItem = _ref5.renderItem,
192
- renderItem = _ref5$renderItem === void 0 ? _renderType.renderType : _ref5$renderItem,
193
- visibleColumnKeys = _ref5.visibleColumnKeys,
194
- onVisibleColumnKeysChange = _ref5.onVisibleColumnKeysChange,
195
- columnCustomSizes = _ref5.columnCustomSizes,
196
- onColumnResize = _ref5.onColumnResize,
197
- wrappedColumnKeys = _ref5.wrappedColumnKeys,
198
- onWrappedColumnChange = _ref5.onWrappedColumnChange,
199
- status = _ref5.status,
200
- hasNextPage = _ref5.hasNextPage,
201
- scrollableContainerHeight = _ref5.scrollableContainerHeight,
202
- extensionKey = _ref5.extensionKey;
209
+ var testId = _ref6.testId,
210
+ onNextPage = _ref6.onNextPage,
211
+ onLoadDatasourceDetails = _ref6.onLoadDatasourceDetails,
212
+ items = _ref6.items,
213
+ itemIds = _ref6.itemIds,
214
+ columns = _ref6.columns,
215
+ _ref6$renderItem = _ref6.renderItem,
216
+ renderItem = _ref6$renderItem === void 0 ? _renderType.renderType : _ref6$renderItem,
217
+ visibleColumnKeys = _ref6.visibleColumnKeys,
218
+ onVisibleColumnKeysChange = _ref6.onVisibleColumnKeysChange,
219
+ columnCustomSizes = _ref6.columnCustomSizes,
220
+ onColumnResize = _ref6.onColumnResize,
221
+ onColumnSort = _ref6.onColumnSort,
222
+ wrappedColumnKeys = _ref6.wrappedColumnKeys,
223
+ onWrappedColumnChange = _ref6.onWrappedColumnChange,
224
+ sortState = _ref6.sortState,
225
+ status = _ref6.status,
226
+ hasNextPage = _ref6.hasNextPage,
227
+ scrollableContainerHeight = _ref6.scrollableContainerHeight,
228
+ extensionKey = _ref6.extensionKey;
229
+ var _useIntl = (0, _reactIntl.useIntl)(),
230
+ formatMessage = _useIntl.formatMessage;
203
231
  var tableId = (0, _react.useMemo)(function () {
204
232
  return Symbol('unique-id');
205
233
  }, []);
@@ -236,8 +264,8 @@ var IssueLikeDataTableView = exports.IssueLikeDataTableView = function IssueLike
236
264
  }, [experienceId, status]);
237
265
  var visibleSortedColumns = (0, _react.useMemo)(function () {
238
266
  return visibleColumnKeys.map(function (visibleKey) {
239
- return orderedColumns.find(function (_ref6) {
240
- var key = _ref6.key;
267
+ return orderedColumns.find(function (_ref7) {
268
+ var key = _ref7.key;
241
269
  return visibleKey === key;
242
270
  });
243
271
  }).filter(Boolean);
@@ -247,9 +275,9 @@ var IssueLikeDataTableView = exports.IssueLikeDataTableView = function IssueLike
247
275
  // If data comes first, then columns and then visibleColumnKeys it blows up,
248
276
  // or some other combination.
249
277
  var columnsWidthsSum = (0, _react.useMemo)(function () {
250
- return visibleSortedColumns.map(function (_ref7) {
251
- var key = _ref7.key,
252
- type = _ref7.type;
278
+ return visibleSortedColumns.map(function (_ref8) {
279
+ var key = _ref8.key,
280
+ type = _ref8.type;
253
281
  return (columnCustomSizes === null || columnCustomSizes === void 0 ? void 0 : columnCustomSizes[key]) || getDefaultColumnWidth(key, type);
254
282
  }).reduce(function (sum, width) {
255
283
  return width + sum;
@@ -265,10 +293,10 @@ var IssueLikeDataTableView = exports.IssueLikeDataTableView = function IssueLike
265
293
  }
266
294
  }, [columnCustomSizes, columnsWidthsSum, shouldUseWidth, tableContainerWidth]);
267
295
  var headerColumns = (0, _react.useMemo)(function () {
268
- return visibleSortedColumns.map(function (_ref8, index) {
269
- var key = _ref8.key,
270
- title = _ref8.title,
271
- type = _ref8.type;
296
+ return visibleSortedColumns.map(function (_ref9, index) {
297
+ var key = _ref9.key,
298
+ title = _ref9.title,
299
+ type = _ref9.type;
272
300
  return {
273
301
  key: key,
274
302
  content: title,
@@ -323,9 +351,9 @@ var IssueLikeDataTableView = exports.IssueLikeDataTableView = function IssueLike
323
351
  return;
324
352
  }
325
353
  return (0, _combine.combine)((0, _adapter.monitorForElements)({
326
- onDragStart: function onDragStart(_ref9) {
327
- var location = _ref9.location,
328
- source = _ref9.source;
354
+ onDragStart: function onDragStart(_ref0) {
355
+ var location = _ref0.location,
356
+ source = _ref0.source;
329
357
  initialAutoScrollerClientY.current = location.current.input.clientY;
330
358
  if (source.data.type === 'table-header') {
331
359
  var _containerRef$current2;
@@ -341,9 +369,9 @@ var IssueLikeDataTableView = exports.IssueLikeDataTableView = function IssueLike
341
369
  });
342
370
  }
343
371
  },
344
- onDrag: function onDrag(_ref0) {
345
- var location = _ref0.location,
346
- source = _ref0.source;
372
+ onDrag: function onDrag(_ref1) {
373
+ var location = _ref1.location,
374
+ source = _ref1.source;
347
375
  if (source.data.type === 'table-header') {
348
376
  var _containerRef$current3;
349
377
  _pragmaticDragAndDropReactBeautifulDndAutoscroll.autoScroller.updateInput({
@@ -353,9 +381,9 @@ var IssueLikeDataTableView = exports.IssueLikeDataTableView = function IssueLike
353
381
  });
354
382
  }
355
383
  },
356
- onDrop: function onDrop(_ref1) {
357
- var source = _ref1.source,
358
- location = _ref1.location;
384
+ onDrop: function onDrop(_ref10) {
385
+ var source = _ref10.source,
386
+ location = _ref10.location;
359
387
  _pragmaticDragAndDropReactBeautifulDndAutoscroll.autoScroller.stop();
360
388
  if (location.current.dropTargets.length === 0) {
361
389
  return;
@@ -390,10 +418,10 @@ var IssueLikeDataTableView = exports.IssueLikeDataTableView = function IssueLike
390
418
  return itemIds.map(function (id, rowIndex) {
391
419
  return {
392
420
  key: id,
393
- cells: visibleSortedColumns.map(function (_ref10, cellIndex) {
394
- var key = _ref10.key,
395
- type = _ref10.type,
396
- title = _ref10.title;
421
+ cells: visibleSortedColumns.map(function (_ref11, cellIndex) {
422
+ var key = _ref11.key,
423
+ type = _ref11.type,
424
+ title = _ref11.title;
397
425
  return {
398
426
  key: key,
399
427
  columnKey: key,
@@ -473,6 +501,9 @@ var IssueLikeDataTableView = exports.IssueLikeDataTableView = function IssueLike
473
501
  }, _callee, null, [[2, 4]]);
474
502
  })), [experienceId, extensionKey, hasFullSchema, onLoadDatasourceDetails]);
475
503
  var isEditable = onVisibleColumnKeysChange && hasData;
504
+ // Sorting is enabled only when the table owns the header interaction (read-only mode).
505
+ // Editable tables reserve header interactions for drag/resize/wrap controls.
506
+ var shouldEnableColumnSort = !!onColumnSort && !onVisibleColumnKeysChange && !onColumnResize && !onWrappedColumnChange;
476
507
  var orderedColumnsAreUpToDate = orderedColumns.length === columns.length;
477
508
  var shouldDisplayColumnsInPicker = hasFullSchema && orderedColumnsAreUpToDate;
478
509
  var view = /*#__PURE__*/React.createElement("div", {
@@ -502,10 +533,10 @@ var IssueLikeDataTableView = exports.IssueLikeDataTableView = function IssueLike
502
533
  className: (0, _runtime.ax)(["_n7zlidpf", "_bfhkchd4 _kqsw1if8 _154iidpf _1pbyzo7u", !!onVisibleColumnKeysChange ? 'has-column-picker' : ''])
503
534
  }, /*#__PURE__*/React.createElement("tr", {
504
535
  ref: tableHeaderRowRef
505
- }, headerColumns.map(function (_ref12, cellIndex) {
506
- var key = _ref12.key,
507
- content = _ref12.content,
508
- width = _ref12.width;
536
+ }, headerColumns.map(function (_ref13, cellIndex) {
537
+ var key = _ref13.key,
538
+ content = _ref13.content,
539
+ width = _ref13.width;
509
540
  var heading = /*#__PURE__*/React.createElement(_tooltip.default, {
510
541
  content: content,
511
542
  tag: "span",
@@ -516,17 +547,42 @@ var IssueLikeDataTableView = exports.IssueLikeDataTableView = function IssueLike
516
547
  className: (0, _runtime.ax)(["_11c8wadc _k48p1wq8"])
517
548
  }, content));
518
549
  var isHeadingOutsideButton = !isEditable || !onWrappedColumnChange;
519
- if (isHeadingOutsideButton) {
550
+ if (shouldEnableColumnSort) {
551
+ var sortedDirection = (sortState === null || sortState === void 0 ? void 0 : sortState.key) === key ? sortState.direction : undefined;
552
+ // Use directional icon only for the active sort column; keep width stable otherwise.
553
+ var SortIcon = sortedDirection ? sortedDirection === 'ASC' ? _sortAscending.default : _sortDescending.default : _customIcons.GlyphPlaceholder;
554
+ var sortLabel = typeof content === 'string' ? content : key;
555
+ var sortButtonAriaLabel = sortedDirection === 'ASC' ? formatMessage(_messages.issueLikeTableMessages.sortByColumnDescendingAction, {
556
+ column: sortLabel
557
+ }) : formatMessage(_messages.issueLikeTableMessages.sortByColumnAscendingAction, {
558
+ column: sortLabel
559
+ });
560
+ heading = /*#__PURE__*/React.createElement(SortableHeaderParent, null, /*#__PURE__*/React.createElement(_new.default, {
561
+ appearance: "subtle",
562
+ spacing: "compact",
563
+ shouldFitContainer: true,
564
+ testId: "".concat(key, "-column-sort-button"),
565
+ "aria-label": sortButtonAriaLabel,
566
+ iconAfter: function iconAfter(iconProps) {
567
+ return /*#__PURE__*/React.createElement(SortIcon, (0, _extends2.default)({}, iconProps, {
568
+ size: "small"
569
+ }));
570
+ },
571
+ onClick: function onClick() {
572
+ return onColumnSort === null || onColumnSort === void 0 ? void 0 : onColumnSort(key);
573
+ }
574
+ }, heading));
575
+ } else if (isHeadingOutsideButton) {
520
576
  heading = /*#__PURE__*/React.createElement("div", {
521
577
  className: (0, _runtime.ax)(["_1e0c1txw _4cvr1h6o _o5721q9c _8vu418qm _irr3l4ek"])
522
578
  }, heading);
523
579
  }
524
580
  if (isEditable) {
525
581
  var _containerRef$current4;
526
- var previewRows = tableRows.map(function (_ref13) {
527
- var cells = _ref13.cells;
528
- var cell = cells.find(function (_ref14) {
529
- var cellKey = _ref14.key;
582
+ var previewRows = tableRows.map(function (_ref14) {
583
+ var cells = _ref14.cells;
584
+ var cell = cells.find(function (_ref15) {
585
+ var cellKey = _ref15.key;
530
586
  return cellKey === key;
531
587
  });
532
588
  if (cell) {
@@ -550,16 +606,18 @@ var IssueLikeDataTableView = exports.IssueLikeDataTableView = function IssueLike
550
606
  onIsWrappedChange: onWrappedColumnChange === null || onWrappedColumnChange === void 0 ? void 0 : onWrappedColumnChange.bind(null, key)
551
607
  }, heading);
552
608
  } else {
553
- return /*#__PURE__*/React.createElement(TableHeading, {
609
+ return /*#__PURE__*/React.createElement(TableHeading, (0, _extends2.default)({
554
610
  key: key,
555
611
  "data-testid": "".concat(key, "-column-heading")
612
+ }, (0, _platformFeatureFlags.fg)('platform_lp_jira_sllv_renderer_column_sorting') ? {
613
+ 'aria-sort': (sortState === null || sortState === void 0 ? void 0 : sortState.key) === key && sortState.direction === 'ASC' ? 'ascending' : (sortState === null || sortState === void 0 ? void 0 : sortState.key) === key && sortState.direction === 'DESC' ? 'descending' : undefined
614
+ } : {}, {
556
615
  // eslint-disable-next-line @atlaskit/ui-styling-standard/enforce-style-prop, @atlaskit/ui-styling-standard/no-imported-style-values -- Ignored via go/DSP-18766
557
- ,
558
616
  style: (0, _utils.getWidthCss)({
559
617
  shouldUseWidth: shouldUseWidth,
560
618
  width: width
561
619
  })
562
- }, heading);
620
+ }), heading);
563
621
  }
564
622
  }), onVisibleColumnKeysChange && /*#__PURE__*/React.createElement(ColumnPickerHeader, null, /*#__PURE__*/React.createElement(_columnPicker.ColumnPicker, {
565
623
  columns: shouldDisplayColumnsInPicker ? orderedColumns : [],
@@ -569,18 +627,18 @@ var IssueLikeDataTableView = exports.IssueLikeDataTableView = function IssueLike
569
627
  })))), /*#__PURE__*/React.createElement("tbody", {
570
628
  "data-testid": testId && "".concat(testId, "--body"),
571
629
  className: (0, _runtime.ax)(["_n7zlidpf"])
572
- }, rows.map(function (_ref15) {
573
- var key = _ref15.key,
574
- cells = _ref15.cells,
575
- ref = _ref15.ref;
630
+ }, rows.map(function (_ref16) {
631
+ var key = _ref16.key,
632
+ cells = _ref16.cells,
633
+ ref = _ref16.ref;
576
634
  return /*#__PURE__*/React.createElement("tr", {
577
635
  key: key,
578
636
  "data-testid": testId && "".concat(testId, "--row-").concat(key),
579
637
  ref: ref
580
- }, cells.map(function (_ref16, cellIndex) {
581
- var cellKey = _ref16.key,
582
- content = _ref16.content,
583
- width = _ref16.width;
638
+ }, cells.map(function (_ref17, cellIndex) {
639
+ var cellKey = _ref17.key,
640
+ content = _ref17.content,
641
+ width = _ref17.width;
584
642
  var isLastCell = cellIndex === cells.length - 1;
585
643
  var loadingRowStyle = (0, _utils.getWidthCss)({
586
644
  shouldUseWidth: shouldUseWidth,
@@ -46,6 +46,16 @@ var issueLikeTableMessages = exports.issueLikeTableMessages = (0, _reactIntl.def
46
46
  description: 'Table header Dropdown item for making whole column to not wrap text',
47
47
  defaultMessage: 'Unwrap text'
48
48
  },
49
+ sortByColumnAscendingAction: {
50
+ id: 'linkDataSource.issue-line-table.sort-by-column-ascending-action',
51
+ description: 'Accessible label for sorting a table column in ascending order',
52
+ defaultMessage: 'Sort by {column} ascending.'
53
+ },
54
+ sortByColumnDescendingAction: {
55
+ id: 'linkDataSource.issue-line-table.sort-by-column-descending-action',
56
+ description: 'Accessible label for sorting a table column in descending order',
57
+ defaultMessage: 'Sort by {column} descending.'
58
+ },
49
59
  fetchActionErrorGenericDescriptionGalaxia: {
50
60
  id: 'linkDataSource.issue-line-table.fetch-action-error-generic-description-galaxia',
51
61
  description: 'Generic error message description shown when fetching inline edit dropdown field fails',
@@ -0,0 +1,43 @@
1
+ import { JIRA_LIST_OF_LINKS_DATASOURCE_ID } from '../jira-issues-modal';
2
+ const getNextSortDirection = (columnKey, currentSort) => {
3
+ if ((currentSort === null || currentSort === void 0 ? void 0 : currentSort.key) === columnKey) {
4
+ return currentSort.direction === 'ASC' ? 'DESC' : 'ASC';
5
+ }
6
+ return 'ASC';
7
+ };
8
+ // Match and remove an existing trailing ORDER BY clause before appending the next sort:
9
+ // - (?:^|\\s+) allows ORDER BY at the start of the JQL or after whitespace.
10
+ // - ORDER\\s+BY matches ORDER BY with flexible spacing and is case-insensitive (/i).
11
+ // - [\\s\\S]*$ consumes everything after ORDER BY to the end of the JQL.
12
+ // Examples:
13
+ // - "project = TEST ORDER BY created DESC" -> "project = TEST"
14
+ // - "ORDER BY priority ASC" -> ""
15
+ const JIRA_ORDER_BY_PATTERN = /(?:^|\s+)ORDER\s+BY\s+[\s\S]*$/i;
16
+ const getJiraColumnSortParameters = ({
17
+ parameters,
18
+ columnKey,
19
+ currentSort
20
+ }) => {
21
+ if (typeof parameters.jql !== 'string') {
22
+ return undefined;
23
+ }
24
+ const direction = getNextSortDirection(columnKey, currentSort);
25
+ const jqlWithoutOrder = parameters.jql.replace(JIRA_ORDER_BY_PATTERN, '').trim();
26
+ const nextOrderByClause = `ORDER BY ${columnKey} ${direction}`;
27
+ return {
28
+ parameters: {
29
+ ...parameters,
30
+ jql: `${jqlWithoutOrder} ${nextOrderByClause}`
31
+ },
32
+ sort: {
33
+ key: columnKey,
34
+ direction
35
+ }
36
+ };
37
+ };
38
+ export const getDatasourceColumnSortGetter = datasourceId => {
39
+ if (datasourceId === JIRA_LIST_OF_LINKS_DATASOURCE_ID) {
40
+ return getJiraColumnSortParameters;
41
+ }
42
+ return undefined;
43
+ };