@atlaskit/link-datasource 6.4.13 → 6.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,27 @@
1
1
  # @atlaskit/link-datasource
2
2
 
3
+ ## 6.5.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [`f0073f4c89113`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/f0073f4c89113) -
8
+ Adds cross-product (XPC) MAU analytics to the datasource modals and the shared issue-like table
9
+ renderer, behind the `electric_issue_like_table_xpc_url_wrapping` feature gate. When the gate is
10
+ on, outbound issue/link URLs are enriched with XPC attribution query params; when it is off (or
11
+ when no host product context is present) the URL is returned untouched, so behaviour matches
12
+ `master`.
13
+
14
+ Attribution is host-driven and follows the same pattern as Smart Links: the host product identity
15
+ (`xpcProduct`, `xpcSubProduct`, `bridgeProduct`) is read from the surrounding `SmartCardProvider`
16
+ (`@atlaskit/link-provider`) — which datasource consumers already render — via the gated
17
+ `useDatasourceCrossProductAttribution` hook. There is no dedicated XPC provider to wire up;
18
+ consumers that already set `xpcProduct` on their `SmartCardProvider` get attribution
19
+ automatically.
20
+
21
+ ### Patch Changes
22
+
23
+ - Updated dependencies
24
+
3
25
  ## 6.4.13
4
26
 
5
27
  ### Patch Changes
@@ -0,0 +1,75 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+ Object.defineProperty(exports, "__esModule", {
5
+ value: true
6
+ });
7
+ exports.useDatasourceCrossProductAttribution = void 0;
8
+ var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
9
+ var _react = require("react");
10
+ var _useCrossProductUrlWrapper = require("@atlaskit/analytics-cross-product/useCrossProductUrlWrapper");
11
+ var _context = require("@atlaskit/link-provider/context");
12
+ var _functionWithFg = require("@atlaskit/platform-feature-flags-react/function-with-fg");
13
+ 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; }
14
+ 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; }
15
+ var DATASOURCE_XPC_BRIDGE = 'linkDatasource';
16
+ var XPC_QUERY_PARAM = 'xpis';
17
+ var identityUrlWrapper = function identityUrlWrapper(url) {
18
+ return url;
19
+ };
20
+ var noopAttribution = {
21
+ wrapCrossProductUrl: identityUrlWrapper
22
+ };
23
+
24
+ /**
25
+ * No-op fallback used when the `electric_issue_like_table_xpc_url_wrapping` gate is off
26
+ */
27
+ var useDatasourceCrossProductAttributionFallback = function useDatasourceCrossProductAttributionFallback() {
28
+ return noopAttribution;
29
+ };
30
+
31
+ /**
32
+ * Returns cross-product (XPC) MAU attribution helpers for the linking-platform datasource modals
33
+ * and the shared issue-like table renderer.
34
+ *
35
+ * Prefer the gated export {@link useDatasourceCrossProductAttribution} which swaps in a no-op
36
+ * fallback when the gate is off (matching smart-card's `functionWithFG` pattern).
37
+ */
38
+ var useDatasourceCrossProductAttributionUngated = function useDatasourceCrossProductAttributionUngated() {
39
+ var _effectiveProduct$toL;
40
+ var _useSmartCardContext = (0, _context.useSmartCardContext)(),
41
+ smartLinkContext = _useSmartCardContext.value;
42
+ var _ref = smartLinkContext !== null && smartLinkContext !== void 0 ? smartLinkContext : {},
43
+ product = _ref.product,
44
+ bridgeProduct = _ref.bridgeProduct,
45
+ xpcProduct = _ref.xpcProduct,
46
+ xpcSubProduct = _ref.xpcSubProduct;
47
+ var effectiveProduct = xpcProduct !== null && xpcProduct !== void 0 ? xpcProduct : product;
48
+ var effectiveProductForWrapper = (_effectiveProduct$toL = effectiveProduct === null || effectiveProduct === void 0 ? void 0 : effectiveProduct.toLowerCase()) !== null && _effectiveProduct$toL !== void 0 ? _effectiveProduct$toL : 'unknown';
49
+ var effectiveBridge = bridgeProduct !== null && bridgeProduct !== void 0 ? bridgeProduct : "".concat(effectiveProductForWrapper, "-").concat(DATASOURCE_XPC_BRIDGE);
50
+ var wrapUrl = (0, _useCrossProductUrlWrapper.useCrossProductUrlWrapper)(_objectSpread({
51
+ bridge: effectiveBridge,
52
+ product: effectiveProductForWrapper
53
+ }, xpcSubProduct ? {
54
+ subProduct: xpcSubProduct
55
+ } : {}));
56
+ var wrapCrossProductUrl = (0, _react.useCallback)(function (url) {
57
+ if (typeof window === 'undefined' || !effectiveProduct) {
58
+ return url;
59
+ }
60
+ var parsedUrl;
61
+ try {
62
+ parsedUrl = new URL(url);
63
+ } catch (_unused) {
64
+ return url;
65
+ }
66
+ if (parsedUrl.searchParams.has(XPC_QUERY_PARAM)) {
67
+ return url;
68
+ }
69
+ return wrapUrl(url);
70
+ }, [effectiveProduct, wrapUrl]);
71
+ return {
72
+ wrapCrossProductUrl: wrapCrossProductUrl
73
+ };
74
+ };
75
+ var useDatasourceCrossProductAttribution = exports.useDatasourceCrossProductAttribution = (0, _functionWithFg.functionWithFG)('electric_issue_like_table_xpc_url_wrapping', useDatasourceCrossProductAttributionUngated, useDatasourceCrossProductAttributionFallback);
@@ -10,6 +10,7 @@ var _react = _interopRequireWildcard(require("react"));
10
10
  var _reactIntl = require("react-intl");
11
11
  var _fg = require("@atlaskit/platform-feature-flags/fg");
12
12
  var _smartCard = require("@atlaskit/smart-card");
13
+ var _useSmartLinkDestinationUrl = require("@atlaskit/smart-card/hook/use-smart-link-destination-url");
13
14
  var _hoverCard = require("@atlaskit/smart-card/hover-card");
14
15
  var _linkUrl = _interopRequireDefault(require("@atlaskit/smart-card/link-url"));
15
16
  var _visuallyHidden = _interopRequireDefault(require("@atlaskit/visually-hidden/visually-hidden"));
@@ -35,11 +36,13 @@ var LinkRenderType = function LinkRenderType(_ref) {
35
36
  var linkStyle = (0, _react.useMemo)(function () {
36
37
  return (style === null || style === void 0 ? void 0 : style.appearance) && linkStyles[style.appearance] || {};
37
38
  }, [style]);
39
+ var destinationUrl = (0, _useSmartLinkDestinationUrl.useSmartLinkDestinationUrl)(url);
40
+ var crossProductUrlGated = (0, _fg.fg)('electric_issue_like_table_xpc_url_wrapping') ? destinationUrl : url;
38
41
  var anchor = (0, _react.useMemo)(function () {
39
42
  return /*#__PURE__*/_react.default.createElement(_hoverCard.HoverCard, {
40
43
  url: url
41
44
  }, /*#__PURE__*/_react.default.createElement(_linkUrl.default, {
42
- href: url
45
+ href: crossProductUrlGated
43
46
  // NOTE: This will no longer apply styles to `@atlaskit/link`.
44
47
  // Wrap `@atlaskit/link` in a Text component to provide font styles to Link
45
48
  // eslint-disable-next-line @atlaskit/ui-styling-standard/enforce-style-prop, @atlaskit/ui-styling-standard/no-imported-style-values -- Ignored via go/DSP-18766
@@ -52,11 +55,11 @@ var LinkRenderType = function LinkRenderType(_ref) {
52
55
  // This link always opens in a new tab (`target="_blank"` above), so
53
56
  // screen reader users need to be told before activating it (WCAG 2.4.4).
54
57
  _react.default.createElement(_visuallyHidden.default, null, " ".concat(formatMessage(_messages.messages.opensInNewTab)))));
55
- }, [linkStyle, url, text, testId, formatMessage]);
58
+ }, [linkStyle, url, text, testId, formatMessage, crossProductUrlGated]);
56
59
  var SmartCard = function SmartCard() {
57
60
  var handleClick = function handleClick(e) {
58
61
  e.preventDefault();
59
- window.open(url, '_blank', 'noopener, noreferrer');
62
+ window.open(crossProductUrlGated, '_blank', 'noopener, noreferrer');
60
63
  };
61
64
  return /*#__PURE__*/_react.default.createElement(_smartCard.Card, {
62
65
  appearance: "inline",
@@ -10,10 +10,11 @@ require("./index.compiled.css");
10
10
  var _runtime = require("@compiled/react/runtime");
11
11
  var _react = _interopRequireDefault(require("react"));
12
12
  var _reactIntl = require("react-intl");
13
- var _platformFeatureFlags = require("@atlaskit/platform-feature-flags");
13
+ var _fg = require("@atlaskit/platform-feature-flags/fg");
14
14
  var _compiled = require("@atlaskit/primitives/compiled");
15
15
  var _linkUrl = _interopRequireDefault(require("@atlaskit/smart-card/link-url"));
16
16
  var _tooltip = _interopRequireDefault(require("@atlaskit/tooltip"));
17
+ var _useDatasourceCrossProductAttribution = require("../../../analytics/xpc/useDatasourceCrossProductAttribution");
17
18
  var _state = require("../../../state");
18
19
  var _actions = require("../../../state/actions");
19
20
  var _editType = require("../edit-type");
@@ -79,17 +80,32 @@ var getLinkedCellContent = function getLinkedCellContent(_ref2) {
79
80
  "data-testid": 'issue-like-table-type-icon-link'
80
81
  }, children);
81
82
  };
83
+ var LinkedCellContentWrapped = function LinkedCellContentWrapped(_ref3) {
84
+ var children = _ref3.children,
85
+ issueLinkData = _ref3.issueLinkData;
86
+ var _useDatasourceCrossPr = (0, _useDatasourceCrossProductAttribution.useDatasourceCrossProductAttribution)(),
87
+ wrapCrossProductUrl = _useDatasourceCrossPr.wrapCrossProductUrl;
88
+ if (!issueLinkData) {
89
+ return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, children);
90
+ }
91
+ return /*#__PURE__*/_react.default.createElement(_linkUrl.default, {
92
+ href: wrapCrossProductUrl(issueLinkData.url),
93
+ target: "_blank",
94
+ "aria-label": issueLinkData.text || issueLinkData.url,
95
+ "data-testid": 'issue-like-table-type-icon-link'
96
+ }, children);
97
+ };
82
98
  var isIssueTypeColumnFn = function isIssueTypeColumnFn(columnKey) {
83
99
  return columnKey === 'issuetype';
84
100
  };
85
- var ReadOnlyCell = exports.ReadOnlyCell = function ReadOnlyCell(_ref3) {
101
+ var ReadOnlyCell = exports.ReadOnlyCell = function ReadOnlyCell(_ref4) {
86
102
  var _useDatasourceItem, _rowData$columnKey;
87
- var id = _ref3.id,
88
- columnType = _ref3.columnType,
89
- _ref3$wrappedColumnKe = _ref3.wrappedColumnKeys,
90
- wrappedColumnKeys = _ref3$wrappedColumnKe === void 0 ? [] : _ref3$wrappedColumnKe,
91
- renderItem = _ref3.renderItem,
92
- columnKey = _ref3.columnKey;
103
+ var id = _ref4.id,
104
+ columnType = _ref4.columnType,
105
+ _ref4$wrappedColumnKe = _ref4.wrappedColumnKeys,
106
+ wrappedColumnKeys = _ref4$wrappedColumnKe === void 0 ? [] : _ref4$wrappedColumnKe,
107
+ renderItem = _ref4.renderItem,
108
+ columnKey = _ref4.columnKey;
93
109
  var rowData = (_useDatasourceItem = (0, _state.useDatasourceItem)({
94
110
  id: id
95
111
  })) === null || _useDatasourceItem === void 0 ? void 0 : _useDatasourceItem.data;
@@ -104,14 +120,16 @@ var ReadOnlyCell = exports.ReadOnlyCell = function ReadOnlyCell(_ref3) {
104
120
  type: columnType,
105
121
  values: values
106
122
  };
107
- if ((0, _platformFeatureFlags.fg)('platform_lp_sllv_jira_type_as_link')) {
123
+ if ((0, _fg.fg)('platform_lp_sllv_jira_type_as_link')) {
108
124
  var isIssueTypeColumn = isIssueTypeColumnFn(columnKey);
109
125
  var issueLinkData = getIssueLinkData(rowData);
110
126
  return /*#__PURE__*/_react.default.createElement(TooltipWrapper, {
111
127
  columnKey: columnKey,
112
128
  datasourceTypeWithValues: datasourceTypeWithValues,
113
129
  wrappedColumnKeys: wrappedColumnKeys
114
- }, isIssueTypeColumn && issueLinkData ? getLinkedCellContent({
130
+ }, isIssueTypeColumn && issueLinkData ? (0, _fg.fg)('electric_issue_like_table_xpc_url_wrapping') ? /*#__PURE__*/_react.default.createElement(LinkedCellContentWrapped, {
131
+ issueLinkData: issueLinkData
132
+ }, renderItem(datasourceTypeWithValues)) : getLinkedCellContent({
115
133
  children: renderItem(datasourceTypeWithValues),
116
134
  issueLinkData: issueLinkData
117
135
  }) : renderItem(datasourceTypeWithValues));
@@ -122,15 +140,15 @@ var ReadOnlyCell = exports.ReadOnlyCell = function ReadOnlyCell(_ref3) {
122
140
  wrappedColumnKeys: wrappedColumnKeys
123
141
  }, renderItem(datasourceTypeWithValues));
124
142
  };
125
- var InlineEditableCell = function InlineEditableCell(_ref4) {
126
- var ari = _ref4.ari,
127
- values = _ref4.values,
128
- columnKey = _ref4.columnKey,
129
- columnTitle = _ref4.columnTitle,
130
- renderItem = _ref4.renderItem,
131
- integrationKey = _ref4.integrationKey,
132
- issueLinkData = _ref4.issueLinkData,
133
- wrappedColumnKeys = _ref4.wrappedColumnKeys;
143
+ var InlineEditableCell = function InlineEditableCell(_ref5) {
144
+ var ari = _ref5.ari,
145
+ values = _ref5.values,
146
+ columnKey = _ref5.columnKey,
147
+ columnTitle = _ref5.columnTitle,
148
+ renderItem = _ref5.renderItem,
149
+ integrationKey = _ref5.integrationKey,
150
+ issueLinkData = _ref5.issueLinkData,
151
+ wrappedColumnKeys = _ref5.wrappedColumnKeys;
134
152
  // Callbacks are returned only when the ari is editable and the action schemas exist in the store
135
153
  var _useExecuteAtomicActi = (0, _actions.useExecuteAtomicAction)({
136
154
  ari: ari,
@@ -157,7 +175,9 @@ var InlineEditableCell = function InlineEditableCell(_ref4) {
157
175
  style: {
158
176
  minHeight: 'calc(40px - 2px * 2)'
159
177
  }
160
- }, (0, _platformFeatureFlags.fg)('platform_lp_sllv_jira_type_as_link') ? !isEditable && isIssueTypeColumnFn(columnKey) && issueLinkData ? getLinkedCellContent({
178
+ }, (0, _fg.fg)('platform_lp_sllv_jira_type_as_link') ? !isEditable && isIssueTypeColumnFn(columnKey) && issueLinkData ? (0, _fg.fg)('electric_issue_like_table_xpc_url_wrapping') ? /*#__PURE__*/_react.default.createElement(LinkedCellContentWrapped, {
179
+ issueLinkData: issueLinkData
180
+ }, renderItem(values)) : getLinkedCellContent({
161
181
  children: renderItem(values),
162
182
  issueLinkData: issueLinkData
163
183
  }) : renderItem(values) : renderItem(values)));
@@ -179,11 +199,11 @@ var InlineEditableCell = function InlineEditableCell(_ref4) {
179
199
  datasourceTypeWithValues: values
180
200
  });
181
201
  };
182
- var toDatasourceTypeWithValues = function toDatasourceTypeWithValues(_ref5) {
202
+ var toDatasourceTypeWithValues = function toDatasourceTypeWithValues(_ref6) {
183
203
  var _rowData$columnKey2;
184
- var rowData = _ref5.rowData,
185
- columnKey = _ref5.columnKey,
186
- columnType = _ref5.columnType;
204
+ var rowData = _ref6.rowData,
205
+ columnKey = _ref6.columnKey,
206
+ columnType = _ref6.columnType;
187
207
  // Need to make sure we keep falsy values like 0 and '', as well as the boolean false.
188
208
  var value = (_rowData$columnKey2 = rowData[columnKey]) === null || _rowData$columnKey2 === void 0 ? void 0 : _rowData$columnKey2.data;
189
209
  var values = !value ? [] : Array.isArray(value) ? value : [value];
@@ -192,13 +212,13 @@ var toDatasourceTypeWithValues = function toDatasourceTypeWithValues(_ref5) {
192
212
  values: values
193
213
  };
194
214
  };
195
- var TableCellContent = exports.TableCellContent = function TableCellContent(_ref6) {
196
- var id = _ref6.id,
197
- columnKey = _ref6.columnKey,
198
- columnTitle = _ref6.columnTitle,
199
- columnType = _ref6.columnType,
200
- renderItem = _ref6.renderItem,
201
- wrappedColumnKeys = _ref6.wrappedColumnKeys;
215
+ var TableCellContent = exports.TableCellContent = function TableCellContent(_ref7) {
216
+ var id = _ref7.id,
217
+ columnKey = _ref7.columnKey,
218
+ columnTitle = _ref7.columnTitle,
219
+ columnType = _ref7.columnType,
220
+ renderItem = _ref7.renderItem,
221
+ wrappedColumnKeys = _ref7.wrappedColumnKeys;
202
222
  var item = (0, _state.useDatasourceItem)({
203
223
  id: id
204
224
  });
@@ -214,7 +234,7 @@ var TableCellContent = exports.TableCellContent = function TableCellContent(_ref
214
234
  columnTitle: columnTitle,
215
235
  renderItem: renderItem,
216
236
  integrationKey: integrationKey,
217
- issueLinkData: (0, _platformFeatureFlags.fg)('platform_lp_sllv_jira_type_as_link') ? getIssueLinkData(rowData) : undefined,
237
+ issueLinkData: (0, _fg.fg)('platform_lp_sllv_jira_type_as_link') ? getIssueLinkData(rowData) : undefined,
218
238
  values: toDatasourceTypeWithValues({
219
239
  rowData: rowData,
220
240
  columnKey: columnKey,
@@ -18,7 +18,7 @@ var _featureGateJsClient = _interopRequireDefault(require("@atlaskit/feature-gat
18
18
  var _main = _interopRequireDefault(require("@atlaskit/intl-messages-provider/main"));
19
19
  var _link = _interopRequireDefault(require("@atlaskit/link"));
20
20
  var _modalDialog = require("@atlaskit/modal-dialog");
21
- var _platformFeatureFlags = require("@atlaskit/platform-feature-flags");
21
+ var _fg = require("@atlaskit/platform-feature-flags/fg");
22
22
  var _compiled = require("@atlaskit/primitives/compiled");
23
23
  var _analytics = require("../../../analytics");
24
24
  var _constants = require("../../../analytics/constants");
@@ -27,6 +27,7 @@ var _ufoExperiences = require("../../../analytics/ufoExperiences");
27
27
  var _useColumnPickerRenderedFailedUfoExperience = require("../../../analytics/ufoExperiences/hooks/useColumnPickerRenderedFailedUfoExperience");
28
28
  var _useDataRenderedUfoExperience = require("../../../analytics/ufoExperiences/hooks/useDataRenderedUfoExperience");
29
29
  var _utils = require("../../../analytics/utils");
30
+ var _useDatasourceCrossProductAttribution = require("../../../analytics/xpc/useDatasourceCrossProductAttribution");
30
31
  var _search = require("../../../common/ui/rich-icon/search");
31
32
  var _fetchMessagesForLocale = require("../../../common/utils/locale/fetch-messages-for-locale");
32
33
  var _datasourceExperienceId = require("../../../contexts/datasource-experience-id");
@@ -129,6 +130,8 @@ var PlainJiraIssuesConfigModal = function PlainJiraIssuesConfigModal(props) {
129
130
  var _useDatasourceAnalyti = (0, _analytics.useDatasourceAnalyticsEvents)(),
130
131
  fireEvent = _useDatasourceAnalyti.fireEvent;
131
132
  var experienceId = (0, _datasourceExperienceId.useDatasourceExperienceId)();
133
+ var _useDatasourceCrossPr = (0, _useDatasourceCrossProductAttribution.useDatasourceCrossProductAttribution)(),
134
+ wrapCrossProductUrl = _useDatasourceCrossPr.wrapCrossProductUrl;
132
135
  var _useIntl = (0, _reactIntl.useIntl)(),
133
136
  formatMessage = _useIntl.formatMessage;
134
137
  var analyticsPayload = (0, _react.useMemo)(function () {
@@ -140,8 +143,9 @@ var PlainJiraIssuesConfigModal = function PlainJiraIssuesConfigModal(props) {
140
143
  var resolvedWithNoResults = status === 'resolved' && !responseItems.length;
141
144
  // With columns available the table can keep its headers and show the empty state in place of
142
145
  // the rows, instead of replacing the whole table with it.
143
- var shouldRenderTableWithNoResults = resolvedWithNoResults && !!columns.length && (0, _platformFeatureFlags.fg)('platform_lp_sllv_ux_improvements');
144
- var jqlUrl = selectedJiraSite && jql && "".concat(selectedJiraSite.url, "/issues/?jql=").concat(encodeURI(jql));
146
+ var shouldRenderTableWithNoResults = resolvedWithNoResults && !!columns.length && (0, _fg.fg)('platform_lp_sllv_ux_improvements');
147
+ var jqlUrlUnwrapped = selectedJiraSite && jql && "".concat(selectedJiraSite.url, "/issues/?jql=").concat(encodeURI(jql));
148
+ var jqlUrl = jqlUrlUnwrapped && (0, _fg.fg)('electric_issue_like_table_xpc_url_wrapping') ? wrapCrossProductUrl(jqlUrlUnwrapped) : jqlUrlUnwrapped;
145
149
  var shouldShowIssueCount = !!totalCount && totalCount !== 1 && currentViewMode === 'table';
146
150
  var isDataReady = (visibleColumnKeys || []).length > 0;
147
151
  var hasNoJiraSites = availableSites && availableSites.length === 0;
@@ -273,7 +277,7 @@ var PlainJiraIssuesConfigModal = function PlainJiraIssuesConfigModal(props) {
273
277
  });
274
278
  } else if (status === 'empty' || !jql || !selectedJiraSiteUrl) {
275
279
  return /*#__PURE__*/_react.default.createElement(_countViewSmartLink.SmartCardPlaceholder, {
276
- placeholderText: (0, _platformFeatureFlags.fg)('confluence-issue-terminology-refresh') ? _messages3.modalMessages.issuesCountSmartCardPlaceholderTextIssueTermRefresh : _messages3.modalMessages.issuesCountSmartCardPlaceholderText
280
+ placeholderText: (0, _fg.fg)('confluence-issue-terminology-refresh') ? _messages3.modalMessages.issuesCountSmartCardPlaceholderTextIssueTermRefresh : _messages3.modalMessages.issuesCountSmartCardPlaceholderText
277
281
  });
278
282
  } else {
279
283
  var url;
@@ -293,7 +297,7 @@ var PlainJiraIssuesConfigModal = function PlainJiraIssuesConfigModal(props) {
293
297
  if (currentSearchMethod === 'basic') {
294
298
  return _messages2.initialStateViewMessages.searchDescriptionForBasicSearchSllv;
295
299
  }
296
- if ((0, _platformFeatureFlags.fg)('confluence-issue-terminology-refresh')) {
300
+ if ((0, _fg.fg)('confluence-issue-terminology-refresh')) {
297
301
  return currentSearchMethod === 'jql' ? _messages2.initialStateViewMessages.searchDescriptionForJQLSearchIssueTermRefresh : _messages2.initialStateViewMessages.searchDescriptionForBasicSearchIssueTermRefresh;
298
302
  }
299
303
  return currentSearchMethod === 'jql' ? _messages2.initialStateViewMessages.searchDescriptionForJQLSearch : _messages2.initialStateViewMessages.searchDescriptionForBasicSearch;
@@ -329,10 +333,10 @@ var PlainJiraIssuesConfigModal = function PlainJiraIssuesConfigModal(props) {
329
333
  testId: "jira-datasource-modal--empty-state"
330
334
  }) : /*#__PURE__*/_react.default.createElement(_initialStateView.InitialStateView, {
331
335
  icon: /*#__PURE__*/_react.default.createElement(_search.RichIconSearch, {
332
- alt: formatMessage((0, _platformFeatureFlags.fg)('confluence-issue-terminology-refresh') ? _messages3.modalMessages.searchJiraTitleIssueTermRefresh : _messages3.modalMessages.searchJiraTitle),
336
+ alt: formatMessage((0, _fg.fg)('confluence-issue-terminology-refresh') ? _messages3.modalMessages.searchJiraTitleIssueTermRefresh : _messages3.modalMessages.searchJiraTitle),
333
337
  size: 'xlarge'
334
338
  }),
335
- title: (0, _platformFeatureFlags.fg)('confluence-issue-terminology-refresh') ? _messages3.modalMessages.searchJiraTitleIssueTermRefresh : _messages3.modalMessages.searchJiraTitle,
339
+ title: (0, _fg.fg)('confluence-issue-terminology-refresh') ? _messages3.modalMessages.searchJiraTitleIssueTermRefresh : _messages3.modalMessages.searchJiraTitle,
336
340
  description: getDescriptionMessage(),
337
341
  learnMoreLink: currentSearchMethod === 'jql' ? {
338
342
  href: jqlSupportDocumentLink,
@@ -350,7 +354,7 @@ var PlainJiraIssuesConfigModal = function PlainJiraIssuesConfigModal(props) {
350
354
  }));
351
355
  }, [columns.length, currentSearchMethod, formatMessage, jql, jqlUrl, resolvedWithNoResults, shouldRenderTableWithNoResults, selectedJiraSite === null || selectedJiraSite === void 0 ? void 0 : selectedJiraSite.url, status, urlBeingEdited, reset]);
352
356
  var siteSelectorLabel = (0, _react.useMemo)(function () {
353
- if ((0, _platformFeatureFlags.fg)('confluence-issue-terminology-refresh')) {
357
+ if ((0, _fg.fg)('confluence-issue-terminology-refresh')) {
354
358
  return availableSites && availableSites.length > 1 ? _messages3.modalMessages.insertIssuesTitleManySitesIssueTermRefresh : _messages3.modalMessages.insertIssuesTitleIssueTermRefresh;
355
359
  }
356
360
  return availableSites && availableSites.length > 1 ? _messages3.modalMessages.insertIssuesTitleManySites : _messages3.modalMessages.insertIssuesTitle;
@@ -0,0 +1,64 @@
1
+ import { useCallback } from 'react';
2
+ import { useCrossProductUrlWrapper } from '@atlaskit/analytics-cross-product/useCrossProductUrlWrapper';
3
+ import { useSmartCardContext } from '@atlaskit/link-provider/context';
4
+ import { functionWithFG } from '@atlaskit/platform-feature-flags-react/function-with-fg';
5
+ const DATASOURCE_XPC_BRIDGE = 'linkDatasource';
6
+ const XPC_QUERY_PARAM = 'xpis';
7
+ const identityUrlWrapper = url => url;
8
+ const noopAttribution = {
9
+ wrapCrossProductUrl: identityUrlWrapper
10
+ };
11
+
12
+ /**
13
+ * No-op fallback used when the `electric_issue_like_table_xpc_url_wrapping` gate is off
14
+ */
15
+ const useDatasourceCrossProductAttributionFallback = () => noopAttribution;
16
+
17
+ /**
18
+ * Returns cross-product (XPC) MAU attribution helpers for the linking-platform datasource modals
19
+ * and the shared issue-like table renderer.
20
+ *
21
+ * Prefer the gated export {@link useDatasourceCrossProductAttribution} which swaps in a no-op
22
+ * fallback when the gate is off (matching smart-card's `functionWithFG` pattern).
23
+ */
24
+ const useDatasourceCrossProductAttributionUngated = () => {
25
+ var _effectiveProduct$toL;
26
+ const {
27
+ value: smartLinkContext
28
+ } = useSmartCardContext();
29
+ const {
30
+ product,
31
+ bridgeProduct,
32
+ xpcProduct,
33
+ xpcSubProduct
34
+ } = smartLinkContext !== null && smartLinkContext !== void 0 ? smartLinkContext : {};
35
+ const effectiveProduct = xpcProduct !== null && xpcProduct !== void 0 ? xpcProduct : product;
36
+ const effectiveProductForWrapper = (_effectiveProduct$toL = effectiveProduct === null || effectiveProduct === void 0 ? void 0 : effectiveProduct.toLowerCase()) !== null && _effectiveProduct$toL !== void 0 ? _effectiveProduct$toL : 'unknown';
37
+ const effectiveBridge = bridgeProduct !== null && bridgeProduct !== void 0 ? bridgeProduct : `${effectiveProductForWrapper}-${DATASOURCE_XPC_BRIDGE}`;
38
+ const wrapUrl = useCrossProductUrlWrapper({
39
+ bridge: effectiveBridge,
40
+ product: effectiveProductForWrapper,
41
+ ...(xpcSubProduct ? {
42
+ subProduct: xpcSubProduct
43
+ } : {})
44
+ });
45
+ const wrapCrossProductUrl = useCallback(url => {
46
+ if (typeof window === 'undefined' || !effectiveProduct) {
47
+ return url;
48
+ }
49
+ let parsedUrl;
50
+ try {
51
+ parsedUrl = new URL(url);
52
+ } catch {
53
+ return url;
54
+ }
55
+ if (parsedUrl.searchParams.has(XPC_QUERY_PARAM)) {
56
+ return url;
57
+ }
58
+ return wrapUrl(url);
59
+ }, [effectiveProduct, wrapUrl]);
60
+ return {
61
+ wrapCrossProductUrl
62
+ };
63
+ };
64
+ export const useDatasourceCrossProductAttribution = functionWithFG('electric_issue_like_table_xpc_url_wrapping', useDatasourceCrossProductAttributionUngated, useDatasourceCrossProductAttributionFallback);
@@ -2,6 +2,7 @@ import React, { useMemo } from 'react';
2
2
  import { useIntl } from 'react-intl';
3
3
  import { fg } from '@atlaskit/platform-feature-flags/fg';
4
4
  import { Card } from '@atlaskit/smart-card';
5
+ import { useSmartLinkDestinationUrl } from '@atlaskit/smart-card/hook/use-smart-link-destination-url';
5
6
  import { HoverCard } from '@atlaskit/smart-card/hover-card';
6
7
  import LinkUrl from '@atlaskit/smart-card/link-url';
7
8
  import VisuallyHidden from '@atlaskit/visually-hidden/visually-hidden';
@@ -27,10 +28,12 @@ const LinkRenderType = ({
27
28
  const linkStyle = useMemo(() => {
28
29
  return (style === null || style === void 0 ? void 0 : style.appearance) && linkStyles[style.appearance] || {};
29
30
  }, [style]);
31
+ const destinationUrl = useSmartLinkDestinationUrl(url);
32
+ const crossProductUrlGated = fg('electric_issue_like_table_xpc_url_wrapping') ? destinationUrl : url;
30
33
  const anchor = useMemo(() => /*#__PURE__*/React.createElement(HoverCard, {
31
34
  url: url
32
35
  }, /*#__PURE__*/React.createElement(LinkUrl, {
33
- href: url
36
+ href: crossProductUrlGated
34
37
  // NOTE: This will no longer apply styles to `@atlaskit/link`.
35
38
  // Wrap `@atlaskit/link` in a Text component to provide font styles to Link
36
39
  // eslint-disable-next-line @atlaskit/ui-styling-standard/enforce-style-prop, @atlaskit/ui-styling-standard/no-imported-style-values -- Ignored via go/DSP-18766
@@ -42,11 +45,11 @@ const LinkRenderType = ({
42
45
  /*#__PURE__*/
43
46
  // This link always opens in a new tab (`target="_blank"` above), so
44
47
  // screen reader users need to be told before activating it (WCAG 2.4.4).
45
- React.createElement(VisuallyHidden, null, ` ${formatMessage(messages.opensInNewTab)}`))), [linkStyle, url, text, testId, formatMessage]);
48
+ React.createElement(VisuallyHidden, null, ` ${formatMessage(messages.opensInNewTab)}`))), [linkStyle, url, text, testId, formatMessage, crossProductUrlGated]);
46
49
  const SmartCard = () => {
47
50
  const handleClick = e => {
48
51
  e.preventDefault();
49
- window.open(url, '_blank', 'noopener, noreferrer');
52
+ window.open(crossProductUrlGated, '_blank', 'noopener, noreferrer');
50
53
  };
51
54
  return /*#__PURE__*/React.createElement(Card, {
52
55
  appearance: "inline",
@@ -3,10 +3,11 @@ import "./index.compiled.css";
3
3
  import { ax, ix } from "@compiled/react/runtime";
4
4
  import React from 'react';
5
5
  import { useIntl } from 'react-intl';
6
- import { fg } from '@atlaskit/platform-feature-flags';
6
+ import { fg } from '@atlaskit/platform-feature-flags/fg';
7
7
  import { Box } from '@atlaskit/primitives/compiled';
8
8
  import LinkUrl from '@atlaskit/smart-card/link-url';
9
9
  import Tooltip from '@atlaskit/tooltip';
10
+ import { useDatasourceCrossProductAttribution } from '../../../analytics/xpc/useDatasourceCrossProductAttribution';
10
11
  import { useDatasourceItem } from '../../../state';
11
12
  import { useExecuteAtomicAction } from '../../../state/actions';
12
13
  import { isEditTypeSelectable, isEditTypeSupported } from '../edit-type';
@@ -71,6 +72,23 @@ const getLinkedCellContent = ({
71
72
  "data-testid": 'issue-like-table-type-icon-link'
72
73
  }, children);
73
74
  };
75
+ const LinkedCellContentWrapped = ({
76
+ children,
77
+ issueLinkData
78
+ }) => {
79
+ const {
80
+ wrapCrossProductUrl
81
+ } = useDatasourceCrossProductAttribution();
82
+ if (!issueLinkData) {
83
+ return /*#__PURE__*/React.createElement(React.Fragment, null, children);
84
+ }
85
+ return /*#__PURE__*/React.createElement(LinkUrl, {
86
+ href: wrapCrossProductUrl(issueLinkData.url),
87
+ target: "_blank",
88
+ "aria-label": issueLinkData.text || issueLinkData.url,
89
+ "data-testid": 'issue-like-table-type-icon-link'
90
+ }, children);
91
+ };
74
92
  const isIssueTypeColumnFn = columnKey => {
75
93
  return columnKey === 'issuetype';
76
94
  };
@@ -103,7 +121,9 @@ export const ReadOnlyCell = ({
103
121
  columnKey: columnKey,
104
122
  datasourceTypeWithValues: datasourceTypeWithValues,
105
123
  wrappedColumnKeys: wrappedColumnKeys
106
- }, isIssueTypeColumn && issueLinkData ? getLinkedCellContent({
124
+ }, isIssueTypeColumn && issueLinkData ? fg('electric_issue_like_table_xpc_url_wrapping') ? /*#__PURE__*/React.createElement(LinkedCellContentWrapped, {
125
+ issueLinkData: issueLinkData
126
+ }, renderItem(datasourceTypeWithValues)) : getLinkedCellContent({
107
127
  children: renderItem(datasourceTypeWithValues),
108
128
  issueLinkData
109
129
  }) : renderItem(datasourceTypeWithValues));
@@ -151,7 +171,9 @@ const InlineEditableCell = ({
151
171
  style: {
152
172
  minHeight: 'calc(40px - 2px * 2)'
153
173
  }
154
- }, fg('platform_lp_sllv_jira_type_as_link') ? !isEditable && isIssueTypeColumnFn(columnKey) && issueLinkData ? getLinkedCellContent({
174
+ }, fg('platform_lp_sllv_jira_type_as_link') ? !isEditable && isIssueTypeColumnFn(columnKey) && issueLinkData ? fg('electric_issue_like_table_xpc_url_wrapping') ? /*#__PURE__*/React.createElement(LinkedCellContentWrapped, {
175
+ issueLinkData: issueLinkData
176
+ }, renderItem(values)) : getLinkedCellContent({
155
177
  children: renderItem(values),
156
178
  issueLinkData
157
179
  }) : renderItem(values) : renderItem(values)));
@@ -9,7 +9,7 @@ import FeatureGates from '@atlaskit/feature-gate-js-client';
9
9
  import IntlMessagesProvider from '@atlaskit/intl-messages-provider/main';
10
10
  import LinkComponent from '@atlaskit/link';
11
11
  import { CloseButton, ModalBody, ModalFooter, ModalHeader, ModalTitle, ModalTransition } from '@atlaskit/modal-dialog';
12
- import { fg } from '@atlaskit/platform-feature-flags';
12
+ import { fg } from '@atlaskit/platform-feature-flags/fg';
13
13
  import { Flex } from '@atlaskit/primitives/compiled';
14
14
  import { useDatasourceAnalyticsEvents } from '../../../analytics';
15
15
  import { EVENT_CHANNEL } from '../../../analytics/constants';
@@ -18,6 +18,7 @@ import { startUfoExperience } from '../../../analytics/ufoExperiences';
18
18
  import { useColumnPickerRenderedFailedUfoExperience } from '../../../analytics/ufoExperiences/hooks/useColumnPickerRenderedFailedUfoExperience';
19
19
  import { useDataRenderedUfoExperience } from '../../../analytics/ufoExperiences/hooks/useDataRenderedUfoExperience';
20
20
  import { mapSearchMethod } from '../../../analytics/utils';
21
+ import { useDatasourceCrossProductAttribution } from '../../../analytics/xpc/useDatasourceCrossProductAttribution';
21
22
  import { RichIconSearch } from '../../../common/ui/rich-icon/search';
22
23
  import { fetchMessagesForLocale } from '../../../common/utils/locale/fetch-messages-for-locale';
23
24
  import { useDatasourceExperienceId } from '../../../contexts/datasource-experience-id';
@@ -112,6 +113,9 @@ const PlainJiraIssuesConfigModal = props => {
112
113
  fireEvent
113
114
  } = useDatasourceAnalyticsEvents();
114
115
  const experienceId = useDatasourceExperienceId();
116
+ const {
117
+ wrapCrossProductUrl
118
+ } = useDatasourceCrossProductAttribution();
115
119
  const {
116
120
  formatMessage
117
121
  } = useIntl();
@@ -123,7 +127,8 @@ const PlainJiraIssuesConfigModal = props => {
123
127
  // With columns available the table can keep its headers and show the empty state in place of
124
128
  // the rows, instead of replacing the whole table with it.
125
129
  const shouldRenderTableWithNoResults = resolvedWithNoResults && !!columns.length && fg('platform_lp_sllv_ux_improvements');
126
- const jqlUrl = selectedJiraSite && jql && `${selectedJiraSite.url}/issues/?jql=${encodeURI(jql)}`;
130
+ const jqlUrlUnwrapped = selectedJiraSite && jql && `${selectedJiraSite.url}/issues/?jql=${encodeURI(jql)}`;
131
+ const jqlUrl = jqlUrlUnwrapped && fg('electric_issue_like_table_xpc_url_wrapping') ? wrapCrossProductUrl(jqlUrlUnwrapped) : jqlUrlUnwrapped;
127
132
  const shouldShowIssueCount = !!totalCount && totalCount !== 1 && currentViewMode === 'table';
128
133
  const isDataReady = (visibleColumnKeys || []).length > 0;
129
134
  const hasNoJiraSites = availableSites && availableSites.length === 0;
@@ -0,0 +1,68 @@
1
+ import _defineProperty from "@babel/runtime/helpers/defineProperty";
2
+ 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; }
3
+ 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; }
4
+ import { useCallback } from 'react';
5
+ import { useCrossProductUrlWrapper } from '@atlaskit/analytics-cross-product/useCrossProductUrlWrapper';
6
+ import { useSmartCardContext } from '@atlaskit/link-provider/context';
7
+ import { functionWithFG } from '@atlaskit/platform-feature-flags-react/function-with-fg';
8
+ var DATASOURCE_XPC_BRIDGE = 'linkDatasource';
9
+ var XPC_QUERY_PARAM = 'xpis';
10
+ var identityUrlWrapper = function identityUrlWrapper(url) {
11
+ return url;
12
+ };
13
+ var noopAttribution = {
14
+ wrapCrossProductUrl: identityUrlWrapper
15
+ };
16
+
17
+ /**
18
+ * No-op fallback used when the `electric_issue_like_table_xpc_url_wrapping` gate is off
19
+ */
20
+ var useDatasourceCrossProductAttributionFallback = function useDatasourceCrossProductAttributionFallback() {
21
+ return noopAttribution;
22
+ };
23
+
24
+ /**
25
+ * Returns cross-product (XPC) MAU attribution helpers for the linking-platform datasource modals
26
+ * and the shared issue-like table renderer.
27
+ *
28
+ * Prefer the gated export {@link useDatasourceCrossProductAttribution} which swaps in a no-op
29
+ * fallback when the gate is off (matching smart-card's `functionWithFG` pattern).
30
+ */
31
+ var useDatasourceCrossProductAttributionUngated = function useDatasourceCrossProductAttributionUngated() {
32
+ var _effectiveProduct$toL;
33
+ var _useSmartCardContext = useSmartCardContext(),
34
+ smartLinkContext = _useSmartCardContext.value;
35
+ var _ref = smartLinkContext !== null && smartLinkContext !== void 0 ? smartLinkContext : {},
36
+ product = _ref.product,
37
+ bridgeProduct = _ref.bridgeProduct,
38
+ xpcProduct = _ref.xpcProduct,
39
+ xpcSubProduct = _ref.xpcSubProduct;
40
+ var effectiveProduct = xpcProduct !== null && xpcProduct !== void 0 ? xpcProduct : product;
41
+ var effectiveProductForWrapper = (_effectiveProduct$toL = effectiveProduct === null || effectiveProduct === void 0 ? void 0 : effectiveProduct.toLowerCase()) !== null && _effectiveProduct$toL !== void 0 ? _effectiveProduct$toL : 'unknown';
42
+ var effectiveBridge = bridgeProduct !== null && bridgeProduct !== void 0 ? bridgeProduct : "".concat(effectiveProductForWrapper, "-").concat(DATASOURCE_XPC_BRIDGE);
43
+ var wrapUrl = useCrossProductUrlWrapper(_objectSpread({
44
+ bridge: effectiveBridge,
45
+ product: effectiveProductForWrapper
46
+ }, xpcSubProduct ? {
47
+ subProduct: xpcSubProduct
48
+ } : {}));
49
+ var wrapCrossProductUrl = useCallback(function (url) {
50
+ if (typeof window === 'undefined' || !effectiveProduct) {
51
+ return url;
52
+ }
53
+ var parsedUrl;
54
+ try {
55
+ parsedUrl = new URL(url);
56
+ } catch (_unused) {
57
+ return url;
58
+ }
59
+ if (parsedUrl.searchParams.has(XPC_QUERY_PARAM)) {
60
+ return url;
61
+ }
62
+ return wrapUrl(url);
63
+ }, [effectiveProduct, wrapUrl]);
64
+ return {
65
+ wrapCrossProductUrl: wrapCrossProductUrl
66
+ };
67
+ };
68
+ export var useDatasourceCrossProductAttribution = functionWithFG('electric_issue_like_table_xpc_url_wrapping', useDatasourceCrossProductAttributionUngated, useDatasourceCrossProductAttributionFallback);
@@ -2,6 +2,7 @@ import React, { useMemo } from 'react';
2
2
  import { useIntl } from 'react-intl';
3
3
  import { fg } from '@atlaskit/platform-feature-flags/fg';
4
4
  import { Card } from '@atlaskit/smart-card';
5
+ import { useSmartLinkDestinationUrl } from '@atlaskit/smart-card/hook/use-smart-link-destination-url';
5
6
  import { HoverCard } from '@atlaskit/smart-card/hover-card';
6
7
  import LinkUrl from '@atlaskit/smart-card/link-url';
7
8
  import VisuallyHidden from '@atlaskit/visually-hidden/visually-hidden';
@@ -26,11 +27,13 @@ var LinkRenderType = function LinkRenderType(_ref) {
26
27
  var linkStyle = useMemo(function () {
27
28
  return (style === null || style === void 0 ? void 0 : style.appearance) && linkStyles[style.appearance] || {};
28
29
  }, [style]);
30
+ var destinationUrl = useSmartLinkDestinationUrl(url);
31
+ var crossProductUrlGated = fg('electric_issue_like_table_xpc_url_wrapping') ? destinationUrl : url;
29
32
  var anchor = useMemo(function () {
30
33
  return /*#__PURE__*/React.createElement(HoverCard, {
31
34
  url: url
32
35
  }, /*#__PURE__*/React.createElement(LinkUrl, {
33
- href: url
36
+ href: crossProductUrlGated
34
37
  // NOTE: This will no longer apply styles to `@atlaskit/link`.
35
38
  // Wrap `@atlaskit/link` in a Text component to provide font styles to Link
36
39
  // eslint-disable-next-line @atlaskit/ui-styling-standard/enforce-style-prop, @atlaskit/ui-styling-standard/no-imported-style-values -- Ignored via go/DSP-18766
@@ -43,11 +46,11 @@ var LinkRenderType = function LinkRenderType(_ref) {
43
46
  // This link always opens in a new tab (`target="_blank"` above), so
44
47
  // screen reader users need to be told before activating it (WCAG 2.4.4).
45
48
  React.createElement(VisuallyHidden, null, " ".concat(formatMessage(messages.opensInNewTab)))));
46
- }, [linkStyle, url, text, testId, formatMessage]);
49
+ }, [linkStyle, url, text, testId, formatMessage, crossProductUrlGated]);
47
50
  var SmartCard = function SmartCard() {
48
51
  var handleClick = function handleClick(e) {
49
52
  e.preventDefault();
50
- window.open(url, '_blank', 'noopener, noreferrer');
53
+ window.open(crossProductUrlGated, '_blank', 'noopener, noreferrer');
51
54
  };
52
55
  return /*#__PURE__*/React.createElement(Card, {
53
56
  appearance: "inline",
@@ -3,10 +3,11 @@ import "./index.compiled.css";
3
3
  import { ax, ix } from "@compiled/react/runtime";
4
4
  import React from 'react';
5
5
  import { useIntl } from 'react-intl';
6
- import { fg } from '@atlaskit/platform-feature-flags';
6
+ import { fg } from '@atlaskit/platform-feature-flags/fg';
7
7
  import { Box } from '@atlaskit/primitives/compiled';
8
8
  import LinkUrl from '@atlaskit/smart-card/link-url';
9
9
  import Tooltip from '@atlaskit/tooltip';
10
+ import { useDatasourceCrossProductAttribution } from '../../../analytics/xpc/useDatasourceCrossProductAttribution';
10
11
  import { useDatasourceItem } from '../../../state';
11
12
  import { useExecuteAtomicAction } from '../../../state/actions';
12
13
  import { isEditTypeSelectable, isEditTypeSupported } from '../edit-type';
@@ -72,17 +73,32 @@ var getLinkedCellContent = function getLinkedCellContent(_ref2) {
72
73
  "data-testid": 'issue-like-table-type-icon-link'
73
74
  }, children);
74
75
  };
76
+ var LinkedCellContentWrapped = function LinkedCellContentWrapped(_ref3) {
77
+ var children = _ref3.children,
78
+ issueLinkData = _ref3.issueLinkData;
79
+ var _useDatasourceCrossPr = useDatasourceCrossProductAttribution(),
80
+ wrapCrossProductUrl = _useDatasourceCrossPr.wrapCrossProductUrl;
81
+ if (!issueLinkData) {
82
+ return /*#__PURE__*/React.createElement(React.Fragment, null, children);
83
+ }
84
+ return /*#__PURE__*/React.createElement(LinkUrl, {
85
+ href: wrapCrossProductUrl(issueLinkData.url),
86
+ target: "_blank",
87
+ "aria-label": issueLinkData.text || issueLinkData.url,
88
+ "data-testid": 'issue-like-table-type-icon-link'
89
+ }, children);
90
+ };
75
91
  var isIssueTypeColumnFn = function isIssueTypeColumnFn(columnKey) {
76
92
  return columnKey === 'issuetype';
77
93
  };
78
- export var ReadOnlyCell = function ReadOnlyCell(_ref3) {
94
+ export var ReadOnlyCell = function ReadOnlyCell(_ref4) {
79
95
  var _useDatasourceItem, _rowData$columnKey;
80
- var id = _ref3.id,
81
- columnType = _ref3.columnType,
82
- _ref3$wrappedColumnKe = _ref3.wrappedColumnKeys,
83
- wrappedColumnKeys = _ref3$wrappedColumnKe === void 0 ? [] : _ref3$wrappedColumnKe,
84
- renderItem = _ref3.renderItem,
85
- columnKey = _ref3.columnKey;
96
+ var id = _ref4.id,
97
+ columnType = _ref4.columnType,
98
+ _ref4$wrappedColumnKe = _ref4.wrappedColumnKeys,
99
+ wrappedColumnKeys = _ref4$wrappedColumnKe === void 0 ? [] : _ref4$wrappedColumnKe,
100
+ renderItem = _ref4.renderItem,
101
+ columnKey = _ref4.columnKey;
86
102
  var rowData = (_useDatasourceItem = useDatasourceItem({
87
103
  id: id
88
104
  })) === null || _useDatasourceItem === void 0 ? void 0 : _useDatasourceItem.data;
@@ -104,7 +120,9 @@ export var ReadOnlyCell = function ReadOnlyCell(_ref3) {
104
120
  columnKey: columnKey,
105
121
  datasourceTypeWithValues: datasourceTypeWithValues,
106
122
  wrappedColumnKeys: wrappedColumnKeys
107
- }, isIssueTypeColumn && issueLinkData ? getLinkedCellContent({
123
+ }, isIssueTypeColumn && issueLinkData ? fg('electric_issue_like_table_xpc_url_wrapping') ? /*#__PURE__*/React.createElement(LinkedCellContentWrapped, {
124
+ issueLinkData: issueLinkData
125
+ }, renderItem(datasourceTypeWithValues)) : getLinkedCellContent({
108
126
  children: renderItem(datasourceTypeWithValues),
109
127
  issueLinkData: issueLinkData
110
128
  }) : renderItem(datasourceTypeWithValues));
@@ -115,15 +133,15 @@ export var ReadOnlyCell = function ReadOnlyCell(_ref3) {
115
133
  wrappedColumnKeys: wrappedColumnKeys
116
134
  }, renderItem(datasourceTypeWithValues));
117
135
  };
118
- var InlineEditableCell = function InlineEditableCell(_ref4) {
119
- var ari = _ref4.ari,
120
- values = _ref4.values,
121
- columnKey = _ref4.columnKey,
122
- columnTitle = _ref4.columnTitle,
123
- renderItem = _ref4.renderItem,
124
- integrationKey = _ref4.integrationKey,
125
- issueLinkData = _ref4.issueLinkData,
126
- wrappedColumnKeys = _ref4.wrappedColumnKeys;
136
+ var InlineEditableCell = function InlineEditableCell(_ref5) {
137
+ var ari = _ref5.ari,
138
+ values = _ref5.values,
139
+ columnKey = _ref5.columnKey,
140
+ columnTitle = _ref5.columnTitle,
141
+ renderItem = _ref5.renderItem,
142
+ integrationKey = _ref5.integrationKey,
143
+ issueLinkData = _ref5.issueLinkData,
144
+ wrappedColumnKeys = _ref5.wrappedColumnKeys;
127
145
  // Callbacks are returned only when the ari is editable and the action schemas exist in the store
128
146
  var _useExecuteAtomicActi = useExecuteAtomicAction({
129
147
  ari: ari,
@@ -150,7 +168,9 @@ var InlineEditableCell = function InlineEditableCell(_ref4) {
150
168
  style: {
151
169
  minHeight: 'calc(40px - 2px * 2)'
152
170
  }
153
- }, fg('platform_lp_sllv_jira_type_as_link') ? !isEditable && isIssueTypeColumnFn(columnKey) && issueLinkData ? getLinkedCellContent({
171
+ }, fg('platform_lp_sllv_jira_type_as_link') ? !isEditable && isIssueTypeColumnFn(columnKey) && issueLinkData ? fg('electric_issue_like_table_xpc_url_wrapping') ? /*#__PURE__*/React.createElement(LinkedCellContentWrapped, {
172
+ issueLinkData: issueLinkData
173
+ }, renderItem(values)) : getLinkedCellContent({
154
174
  children: renderItem(values),
155
175
  issueLinkData: issueLinkData
156
176
  }) : renderItem(values) : renderItem(values)));
@@ -172,11 +192,11 @@ var InlineEditableCell = function InlineEditableCell(_ref4) {
172
192
  datasourceTypeWithValues: values
173
193
  });
174
194
  };
175
- var toDatasourceTypeWithValues = function toDatasourceTypeWithValues(_ref5) {
195
+ var toDatasourceTypeWithValues = function toDatasourceTypeWithValues(_ref6) {
176
196
  var _rowData$columnKey2;
177
- var rowData = _ref5.rowData,
178
- columnKey = _ref5.columnKey,
179
- columnType = _ref5.columnType;
197
+ var rowData = _ref6.rowData,
198
+ columnKey = _ref6.columnKey,
199
+ columnType = _ref6.columnType;
180
200
  // Need to make sure we keep falsy values like 0 and '', as well as the boolean false.
181
201
  var value = (_rowData$columnKey2 = rowData[columnKey]) === null || _rowData$columnKey2 === void 0 ? void 0 : _rowData$columnKey2.data;
182
202
  var values = !value ? [] : Array.isArray(value) ? value : [value];
@@ -185,13 +205,13 @@ var toDatasourceTypeWithValues = function toDatasourceTypeWithValues(_ref5) {
185
205
  values: values
186
206
  };
187
207
  };
188
- export var TableCellContent = function TableCellContent(_ref6) {
189
- var id = _ref6.id,
190
- columnKey = _ref6.columnKey,
191
- columnTitle = _ref6.columnTitle,
192
- columnType = _ref6.columnType,
193
- renderItem = _ref6.renderItem,
194
- wrappedColumnKeys = _ref6.wrappedColumnKeys;
208
+ export var TableCellContent = function TableCellContent(_ref7) {
209
+ var id = _ref7.id,
210
+ columnKey = _ref7.columnKey,
211
+ columnTitle = _ref7.columnTitle,
212
+ columnType = _ref7.columnType,
213
+ renderItem = _ref7.renderItem,
214
+ wrappedColumnKeys = _ref7.wrappedColumnKeys;
195
215
  var item = useDatasourceItem({
196
216
  id: id
197
217
  });
@@ -13,7 +13,7 @@ import FeatureGates from '@atlaskit/feature-gate-js-client';
13
13
  import IntlMessagesProvider from '@atlaskit/intl-messages-provider/main';
14
14
  import LinkComponent from '@atlaskit/link';
15
15
  import { CloseButton, ModalBody, ModalFooter, ModalHeader, ModalTitle, ModalTransition } from '@atlaskit/modal-dialog';
16
- import { fg } from '@atlaskit/platform-feature-flags';
16
+ import { fg } from '@atlaskit/platform-feature-flags/fg';
17
17
  import { Flex } from '@atlaskit/primitives/compiled';
18
18
  import { useDatasourceAnalyticsEvents } from '../../../analytics';
19
19
  import { EVENT_CHANNEL } from '../../../analytics/constants';
@@ -22,6 +22,7 @@ import { startUfoExperience } from '../../../analytics/ufoExperiences';
22
22
  import { useColumnPickerRenderedFailedUfoExperience } from '../../../analytics/ufoExperiences/hooks/useColumnPickerRenderedFailedUfoExperience';
23
23
  import { useDataRenderedUfoExperience } from '../../../analytics/ufoExperiences/hooks/useDataRenderedUfoExperience';
24
24
  import { mapSearchMethod } from '../../../analytics/utils';
25
+ import { useDatasourceCrossProductAttribution } from '../../../analytics/xpc/useDatasourceCrossProductAttribution';
25
26
  import { RichIconSearch } from '../../../common/ui/rich-icon/search';
26
27
  import { fetchMessagesForLocale } from '../../../common/utils/locale/fetch-messages-for-locale';
27
28
  import { useDatasourceExperienceId } from '../../../contexts/datasource-experience-id';
@@ -121,6 +122,8 @@ var PlainJiraIssuesConfigModal = function PlainJiraIssuesConfigModal(props) {
121
122
  var _useDatasourceAnalyti = useDatasourceAnalyticsEvents(),
122
123
  fireEvent = _useDatasourceAnalyti.fireEvent;
123
124
  var experienceId = useDatasourceExperienceId();
125
+ var _useDatasourceCrossPr = useDatasourceCrossProductAttribution(),
126
+ wrapCrossProductUrl = _useDatasourceCrossPr.wrapCrossProductUrl;
124
127
  var _useIntl = useIntl(),
125
128
  formatMessage = _useIntl.formatMessage;
126
129
  var analyticsPayload = useMemo(function () {
@@ -133,7 +136,8 @@ var PlainJiraIssuesConfigModal = function PlainJiraIssuesConfigModal(props) {
133
136
  // With columns available the table can keep its headers and show the empty state in place of
134
137
  // the rows, instead of replacing the whole table with it.
135
138
  var shouldRenderTableWithNoResults = resolvedWithNoResults && !!columns.length && fg('platform_lp_sllv_ux_improvements');
136
- var jqlUrl = selectedJiraSite && jql && "".concat(selectedJiraSite.url, "/issues/?jql=").concat(encodeURI(jql));
139
+ var jqlUrlUnwrapped = selectedJiraSite && jql && "".concat(selectedJiraSite.url, "/issues/?jql=").concat(encodeURI(jql));
140
+ var jqlUrl = jqlUrlUnwrapped && fg('electric_issue_like_table_xpc_url_wrapping') ? wrapCrossProductUrl(jqlUrlUnwrapped) : jqlUrlUnwrapped;
137
141
  var shouldShowIssueCount = !!totalCount && totalCount !== 1 && currentViewMode === 'table';
138
142
  var isDataReady = (visibleColumnKeys || []).length > 0;
139
143
  var hasNoJiraSites = availableSites && availableSites.length === 0;
@@ -0,0 +1,13 @@
1
+ export interface DatasourceCrossProductAttribution {
2
+ wrapCrossProductUrl: (url: string) => string;
3
+ }
4
+ /**
5
+ * Returns cross-product (XPC) MAU attribution helpers for the linking-platform datasource modals
6
+ * and the shared issue-like table renderer.
7
+ *
8
+ * Prefer the gated export {@link useDatasourceCrossProductAttribution} which swaps in a no-op
9
+ * fallback when the gate is off (matching smart-card's `functionWithFG` pattern).
10
+ */
11
+ declare const useDatasourceCrossProductAttributionUngated: () => DatasourceCrossProductAttribution;
12
+ export declare const useDatasourceCrossProductAttribution: typeof useDatasourceCrossProductAttributionUngated;
13
+ export {};
@@ -1,5 +1,5 @@
1
1
  import React from 'react';
2
- import { type Link } from '@atlaskit/linking-types';
2
+ import { type Link } from '@atlaskit/linking-types/datasource';
3
3
  interface LinkProps extends Link {
4
4
  testId?: string;
5
5
  }
@@ -1,5 +1,5 @@
1
1
  import React from 'react';
2
- import { type DatasourceType } from '@atlaskit/linking-types';
2
+ import { type DatasourceType } from '@atlaskit/linking-types/datasource';
3
3
  import { type TableViewPropsRenderType } from '../types';
4
4
  interface TableCellContentProps {
5
5
  columnKey: string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atlaskit/link-datasource",
3
- "version": "6.4.13",
3
+ "version": "6.5.0",
4
4
  "description": "UI Components to support linking platform dataset feature",
5
5
  "author": "Atlassian Pty Ltd",
6
6
  "license": "Apache-2.0",
@@ -37,22 +37,23 @@
37
37
  "dependencies": {
38
38
  "@atlaskit/adf-schema": "^57.0.0",
39
39
  "@atlaskit/afm-i18n-platform-linking-platform-link-datasource": "2.201.0",
40
+ "@atlaskit/analytics-cross-product": "^2.1.0",
40
41
  "@atlaskit/analytics-next": "^12.3.0",
41
42
  "@atlaskit/atlassian-context": "^1.1.0",
42
- "@atlaskit/avatar": "^27.0.0",
43
- "@atlaskit/avatar-group": "^14.0.0",
43
+ "@atlaskit/avatar": "^27.1.0",
44
+ "@atlaskit/avatar-group": "^14.1.0",
44
45
  "@atlaskit/badge": "^21.0.0",
45
- "@atlaskit/button": "^25.0.0",
46
+ "@atlaskit/button": "^25.1.0",
46
47
  "@atlaskit/css": "^1.0.0",
47
48
  "@atlaskit/datetime-picker": "^18.3.0",
48
- "@atlaskit/dropdown-menu": "^18.0.0",
49
+ "@atlaskit/dropdown-menu": "^18.1.0",
49
50
  "@atlaskit/editor-prosemirror": "^8.0.0",
50
51
  "@atlaskit/empty-state": "^12.0.0",
51
52
  "@atlaskit/feature-gate-js-client": "^6.0.0",
52
- "@atlaskit/flag": "^18.2.0",
53
+ "@atlaskit/flag": "^18.3.0",
53
54
  "@atlaskit/form": "^17.0.0",
54
55
  "@atlaskit/heading": "^7.0.0",
55
- "@atlaskit/icon": "^37.3.0",
56
+ "@atlaskit/icon": "^37.4.0",
56
57
  "@atlaskit/image": "^5.0.0",
57
58
  "@atlaskit/inline-edit": "^16.2.0",
58
59
  "@atlaskit/intl-messages-provider": "^4.2.0",
@@ -63,31 +64,32 @@
63
64
  "@atlaskit/link": "^5.0.0",
64
65
  "@atlaskit/link-client-extension": "^7.1.0",
65
66
  "@atlaskit/link-provider": "^5.3.0",
66
- "@atlaskit/linking-common": "^11.1.0",
67
+ "@atlaskit/linking-common": "^11.2.0",
67
68
  "@atlaskit/linking-types": "^15.0.0",
68
69
  "@atlaskit/logo": "^21.4.0",
69
- "@atlaskit/lozenge": "^15.1.0",
70
- "@atlaskit/modal-dialog": "^16.3.0",
70
+ "@atlaskit/lozenge": "^15.2.0",
71
+ "@atlaskit/modal-dialog": "^16.4.0",
71
72
  "@atlaskit/object": "^2.2.0",
72
73
  "@atlaskit/outbound-auth-flow-client": "^4.1.0",
73
74
  "@atlaskit/platform-feature-flags": "^2.1.0",
74
- "@atlaskit/popup": "^6.0.0",
75
+ "@atlaskit/platform-feature-flags-react": "^1.1.0",
76
+ "@atlaskit/popup": "^6.1.0",
75
77
  "@atlaskit/pragmatic-drag-and-drop": "^3.0.0",
76
- "@atlaskit/pragmatic-drag-and-drop-hitbox": "^2.0.0",
78
+ "@atlaskit/pragmatic-drag-and-drop-hitbox": "^2.1.0",
77
79
  "@atlaskit/pragmatic-drag-and-drop-react-beautiful-dnd-autoscroll": "^3.0.0",
78
80
  "@atlaskit/pragmatic-drag-and-drop-react-drop-indicator": "^4.1.0",
79
- "@atlaskit/primitives": "^22.2.0",
81
+ "@atlaskit/primitives": "^22.3.0",
80
82
  "@atlaskit/react-compiler-gating": "^0.2.0",
81
83
  "@atlaskit/react-select": "^4.7.0",
82
- "@atlaskit/select": "^22.6.0",
84
+ "@atlaskit/select": "^22.7.0",
83
85
  "@atlaskit/smart-card": "^45.17.0",
84
86
  "@atlaskit/smart-user-picker": "^11.5.0",
85
- "@atlaskit/spinner": "^20.1.0",
86
- "@atlaskit/tag": "^15.4.0",
87
+ "@atlaskit/spinner": "^20.2.0",
88
+ "@atlaskit/tag": "^15.5.0",
87
89
  "@atlaskit/textfield": "^10.0.0",
88
90
  "@atlaskit/theme": "^28.0.0",
89
91
  "@atlaskit/tokens": "^16.7.0",
90
- "@atlaskit/tooltip": "^24.0.0",
92
+ "@atlaskit/tooltip": "^24.1.0",
91
93
  "@atlaskit/ufo": "^1.0.0",
92
94
  "@atlaskit/visually-hidden": "^4.2.0",
93
95
  "@atlaskit/width-detector": "^7.0.0",
@@ -114,8 +116,8 @@
114
116
  "@atlaskit/json-ld-types": "^2.0.0",
115
117
  "@atlaskit/link-test-helpers": "^11.0.0",
116
118
  "@atlaskit/ssr": "workspace:^",
117
- "@atlassian/a11y-jest-testing": "^0.15.0",
118
- "@atlassian/a11y-playwright-testing": "^0.10.0",
119
+ "@atlassian/a11y-jest-testing": "^0.16.0",
120
+ "@atlassian/a11y-playwright-testing": "^0.11.0",
119
121
  "@atlassian/feature-flags-test-utils": "^1.2.0",
120
122
  "@atlassian/structured-docs-types": "workspace:^",
121
123
  "@faker-js/faker": "^7.5.0",
@@ -196,6 +198,9 @@
196
198
  },
197
199
  "astral_units_workspace_host_resolver": {
198
200
  "type": "boolean"
201
+ },
202
+ "electric_issue_like_table_xpc_url_wrapping": {
203
+ "type": "boolean"
199
204
  }
200
205
  },
201
206
  "compassUnitTestMetricSourceId": "ari:cloud:compass:a436116f-02ce-4520-8fbb-7301462a1674:metric-source/c5751cc6-3513-4070-9deb-af31e86aed34/9c893299-a527-4457-9b46-f3bc4c828766"