@atlaskit/smart-card 40.10.1 → 40.10.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,13 @@
1
1
  # @atlaskit/smart-card
2
2
 
3
+ ## 40.10.2
4
+
5
+ ### Patch Changes
6
+
7
+ - [`2115cfcea4013`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/2115cfcea4013) -
8
+ Add Jira Issue ID, Confluence Content ID/Page ID, and helper methods to retrieve, as well as
9
+ include in component onclick result
10
+
3
11
  ## 40.10.1
4
12
 
5
13
  ### Patch Changes
@@ -753,13 +753,25 @@ events:
753
753
  3P Workflows team
754
754
  attributes:
755
755
  <<: [*PackageMetaDataContext, *CommonContext, *ResolvedContext]
756
- sourceURL:
756
+ firstPartyARI:
757
757
  required: true
758
758
  type: string
759
759
  description:
760
- The first party URL for this Smart Link - this is NOT the URL the user clicked on, but
761
- the URL of the page where the Smart Link is rendered
760
+ The first party ARI for this Smart Link - this is NOT the ARI of the link the user
761
+ clicked on, but the ARI of the page where the Smart Link is rendered
762
762
  thirdPartyARI:
763
763
  required: true
764
764
  type: string
765
765
  description: The third-party ARI for this Smart Link
766
+ jiraIssueId:
767
+ required: false
768
+ type: string
769
+ description: The Issue ID for the Jira specific ticket this Smart Link is pasted on
770
+ confluenceContentId:
771
+ required: false
772
+ type: string
773
+ description: The Content ID for the Confluence specific page this Smart Link is pasted on
774
+ confluencePageId:
775
+ required: false
776
+ type: string
777
+ description: The Page ID for the Confluence specific page this Smart Link is pasted on
@@ -4,7 +4,7 @@ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefau
4
4
  Object.defineProperty(exports, "__esModule", {
5
5
  value: true
6
6
  });
7
- exports.isVisible = exports.isFinalState = exports.isAccessible = exports.hasResolved = exports.hasAuthScopeOverrides = exports.getThirdPartyARI = exports.getSubproduct = exports.getStatusDetails = exports.getServices = exports.getResourceType = exports.getProduct = exports.getObjectName = exports.getObjectIconUrl = exports.getObjectAri = exports.getExtensionKey = exports.getDefinitionId = exports.getDatasources = exports.getClickUrl = exports.getCanBeDatasource = exports.getByDefinitionId = void 0;
7
+ exports.isVisible = exports.isFinalState = exports.isAccessible = exports.hasResolved = exports.hasAuthScopeOverrides = exports.getThirdPartyARI = exports.getSubproduct = exports.getStatusDetails = exports.getServices = exports.getResourceType = exports.getProduct = exports.getPageId = exports.getObjectName = exports.getObjectIconUrl = exports.getObjectAri = exports.getLinkClickAnalyticsThirdPartyAttributes = exports.getJiraIssueId = exports.getExtensionKey = exports.getDefinitionId = exports.getDatasources = exports.getContentId = exports.getClickUrl = exports.getCanBeDatasource = exports.getByDefinitionId = void 0;
8
8
  var _typeof2 = _interopRequireDefault(require("@babel/runtime/helpers/typeof"));
9
9
  var _platformFeatureFlags = require("@atlaskit/platform-feature-flags");
10
10
  var _extractVisitUrl = require("../extractors/common/primitives/extractVisitUrl");
@@ -43,6 +43,45 @@ var getThirdPartyARI = exports.getThirdPartyARI = function getThirdPartyARI(deta
43
43
  }
44
44
  return undefined;
45
45
  };
46
+ var getPageId = exports.getPageId = function getPageId(details) {
47
+ if ((0, _platformFeatureFlags.fg)('platform_smartlink_3pclick_analytics')) {
48
+ var currentProduct = getProductFromWindowUrl();
49
+ if (currentProduct === 'confluence') {
50
+ if (details !== null && details !== void 0 && details.data && 'url' in details.data) {
51
+ if (typeof details.data.url === 'string') {
52
+ return extractPageIdFromURL(details.data.url);
53
+ }
54
+ }
55
+ }
56
+ }
57
+ return undefined;
58
+ };
59
+ var getContentId = exports.getContentId = function getContentId(details) {
60
+ if ((0, _platformFeatureFlags.fg)('platform_smartlink_3pclick_analytics')) {
61
+ var currentProduct = getProductFromWindowUrl();
62
+ if (currentProduct === 'confluence') {
63
+ if (details !== null && details !== void 0 && details.data && 'url' in details.data) {
64
+ if (typeof details.data.url === 'string') {
65
+ return extractContentIdFromURL(details.data.url);
66
+ }
67
+ }
68
+ }
69
+ }
70
+ return undefined;
71
+ };
72
+ var getJiraIssueId = exports.getJiraIssueId = function getJiraIssueId(details) {
73
+ if ((0, _platformFeatureFlags.fg)('platform_smartlink_3pclick_analytics')) {
74
+ var currentProduct = getProductFromWindowUrl();
75
+ if (currentProduct === 'jira') {
76
+ if (details !== null && details !== void 0 && details.data && 'url' in details.data) {
77
+ if (typeof details.data.url === 'string') {
78
+ return extractJiraIssueIdFromURL(details.data.url);
79
+ }
80
+ }
81
+ }
82
+ }
83
+ return undefined;
84
+ };
46
85
  var getObjectName = exports.getObjectName = function getObjectName(details) {
47
86
  return (details === null || details === void 0 ? void 0 : details.data) && 'name' in details.data && details.data.name || undefined;
48
87
  };
@@ -96,4 +135,111 @@ var getCanBeDatasource = exports.getCanBeDatasource = function getCanBeDatasourc
96
135
  };
97
136
  var hasAuthScopeOverrides = exports.hasAuthScopeOverrides = function hasAuthScopeOverrides(details) {
98
137
  return !!(details !== null && details !== void 0 && details.meta.hasScopeOverrides);
138
+ };
139
+
140
+ // Helper function to extract page ID from standard Confluence page URLs
141
+ var extractPageIdFromURL = function extractPageIdFromURL(url) {
142
+ try {
143
+ var urlObj = new URL(url);
144
+
145
+ // Following this pattern for confluence URL -> /wiki/spaces/{space}/pages/{pageId}/{title}
146
+ var pagesMatch = urlObj.pathname.match(/\/wiki\/spaces\/[^\/]+\/pages\/(\d+)/);
147
+ if (pagesMatch && pagesMatch[1]) {
148
+ return pagesMatch[1];
149
+ }
150
+
151
+ // Following this pattern for confluence URL -> /wiki/pages/viewpage.action?pageId={pageId}
152
+ var pageIdParam = urlObj.searchParams.get('pageId');
153
+ if (pageIdParam) {
154
+ return pageIdParam;
155
+ }
156
+
157
+ // Following this pattern for confluence URL -> /wiki/display/{space}/{pageId}
158
+ var displayMatch = urlObj.pathname.match(/\/wiki\/display\/[^\/]+\/(\d+)/);
159
+ if (displayMatch && displayMatch[1]) {
160
+ return displayMatch[1];
161
+ }
162
+ } catch (_unused) {
163
+ return undefined;
164
+ }
165
+ return undefined;
166
+ };
167
+
168
+ // Helper function to extract content ID from app connector URLs
169
+ var extractContentIdFromURL = function extractContentIdFromURL(url) {
170
+ try {
171
+ var urlObj = new URL(url);
172
+
173
+ // Pattern: ?content.id={contentId} (for app connector URLs)
174
+ var contentId = urlObj.searchParams.get('content.id');
175
+ if (contentId) {
176
+ return contentId;
177
+ }
178
+ } catch (_unused2) {
179
+ return undefined;
180
+ }
181
+ return undefined;
182
+ };
183
+ var extractJiraIssueIdFromURL = function extractJiraIssueIdFromURL(url) {
184
+ try {
185
+ var urlObj = new URL(url);
186
+
187
+ // Following this pattern for jira URL -> /browse/{issueKey} (most common)
188
+ // Example: https://product-fabric.atlassian.net/browse/AI3W-1064
189
+ var browseMatch = urlObj.pathname.match(/\/browse\/([A-Z]+-\d+)/);
190
+ if (browseMatch && browseMatch[1]) {
191
+ return browseMatch[1];
192
+ }
193
+
194
+ // Following this pattern for jira URL -> /jira/browse/{issueKey} (for some installations)
195
+ var jiraBrowseMatch = urlObj.pathname.match(/\/jira\/browse\/([A-Z]+-\d+)/);
196
+ if (jiraBrowseMatch && jiraBrowseMatch[1]) {
197
+ return jiraBrowseMatch[1];
198
+ }
199
+
200
+ // Following this pattern for jira URL -> Query parameter ?selectedIssue={issueKey}
201
+ var selectedIssue = urlObj.searchParams.get('selectedIssue');
202
+ if (selectedIssue && /^[A-Z]+-\d+$/.test(selectedIssue)) {
203
+ return selectedIssue;
204
+ }
205
+
206
+ // Following this pattern for jira URL -> Query parameter ?issueKey={issueKey}
207
+ var issueKeyParam = urlObj.searchParams.get('issueKey');
208
+ if (issueKeyParam && /^[A-Z]+-\d+$/.test(issueKeyParam)) {
209
+ return issueKeyParam;
210
+ }
211
+ } catch (_unused3) {
212
+ return undefined;
213
+ }
214
+ return undefined;
215
+ };
216
+ var getLinkClickAnalyticsThirdPartyAttributes = exports.getLinkClickAnalyticsThirdPartyAttributes = function getLinkClickAnalyticsThirdPartyAttributes(thirdPartyARI, details) {
217
+ return {
218
+ firstPartyARI: getObjectAri(details),
219
+ thirdPartyARI: thirdPartyARI,
220
+ jiraIssueId: getJiraIssueId(details),
221
+ confluenceContentId: getContentId(details),
222
+ confluencePageId: getPageId(details)
223
+ };
224
+ };
225
+ var getProductFromWindowUrl = function getProductFromWindowUrl() {
226
+ try {
227
+ var currentUrl = window.location.href;
228
+ var urlObj = new URL(currentUrl);
229
+ var hostname = urlObj.hostname.toLowerCase();
230
+ var pathname = urlObj.pathname.toLowerCase();
231
+
232
+ // Check for Confluence patterns
233
+ if (hostname.includes('confluence') || pathname.includes('/wiki/') || pathname.includes('/display/') || pathname.includes('/spaces/')) {
234
+ return 'confluence';
235
+ }
236
+
237
+ // Check for Jira patterns
238
+ if (hostname.includes('jira') || pathname.includes('/browse/') || pathname.includes('/projects/') || pathname.includes('/secure/')) {
239
+ return 'jira';
240
+ }
241
+ } catch (_unused4) {
242
+ return undefined;
243
+ }
244
+ return undefined;
99
245
  };
@@ -11,7 +11,7 @@ var ANALYTICS_CHANNEL = exports.ANALYTICS_CHANNEL = 'media';
11
11
  var context = exports.context = {
12
12
  componentName: 'smart-cards',
13
13
  packageName: "@atlaskit/smart-card",
14
- packageVersion: "40.10.0"
14
+ packageVersion: "40.10.1"
15
15
  };
16
16
  var TrackQuickActionType = exports.TrackQuickActionType = /*#__PURE__*/function (TrackQuickActionType) {
17
17
  TrackQuickActionType["StatusUpdate"] = "StatusUpdate";
@@ -68,12 +68,12 @@ function Component(_ref) {
68
68
  isPreviewPanelAvailable = _useSmartLink.isPreviewPanelAvailable,
69
69
  openPreviewPanel = _useSmartLink.openPreviewPanel;
70
70
  var ari = (0, _helpers.getObjectAri)(state.details);
71
- var thirdPartyARI = (0, _helpers.getThirdPartyARI)(state.details);
72
71
  var name = (0, _helpers.getObjectName)(state.details);
73
72
  var definitionId = (0, _helpers.getDefinitionId)(state.details);
74
73
  var extensionKey = (0, _helpers.getExtensionKey)(state.details);
75
74
  var resourceType = (0, _helpers.getResourceType)(state.details);
76
75
  var services = (0, _helpers.getServices)(state.details);
76
+ var thirdPartyARI = (0, _helpers.getThirdPartyARI)(state.details);
77
77
  var isFlexibleUi = (0, _react.useMemo)(function () {
78
78
  return (0, _flexible.isFlexibleUiCard)(children, ui);
79
79
  }, [children, ui]);
@@ -93,7 +93,6 @@ function Component(_ref) {
93
93
  });
94
94
  if ((0, _platformFeatureFlags.fg)('platform_smartlink_3pclick_analytics')) {
95
95
  if (thirdPartyARI && thirdPartyARI.startsWith(thirdPartyARIPrefix)) {
96
- var sourceURL = window.location.href;
97
96
  var clickURL = (0, _helpers.getClickUrl)(url, state.details);
98
97
  if (clickURL === url) {
99
98
  // For questions or concerns about this event,
@@ -106,10 +105,7 @@ function Component(_ref) {
106
105
  attributes: {
107
106
  eventName: 'smartLinkClickAnalyticsThirdPartyWorkflows'
108
107
  },
109
- nonPrivacySafeAttributes: {
110
- sourceURL: sourceURL,
111
- thirdPartyARI: thirdPartyARI
112
- }
108
+ nonPrivacySafeAttributes: (0, _helpers.getLinkClickAnalyticsThirdPartyAttributes)(thirdPartyARI, state.details)
113
109
  });
114
110
  smartlinkClickAnalyticsEvent.fire('media');
115
111
  }
@@ -19,7 +19,7 @@ var _excluded = ["href", "children", "checkSafety", "onClick", "testId", "isLink
19
19
  _excluded2 = ["isLinkSafe", "showSafetyWarningModal"];
20
20
  var PACKAGE_DATA = {
21
21
  packageName: "@atlaskit/smart-card",
22
- packageVersion: "40.10.0",
22
+ packageVersion: "40.10.1",
23
23
  componentName: 'linkUrl'
24
24
  };
25
25
  var Anchor = (0, _click.withLinkClickedEvent)('a');
@@ -35,6 +35,45 @@ export const getThirdPartyARI = details => {
35
35
  }
36
36
  return undefined;
37
37
  };
38
+ export const getPageId = details => {
39
+ if (fg('platform_smartlink_3pclick_analytics')) {
40
+ const currentProduct = getProductFromWindowUrl();
41
+ if (currentProduct === 'confluence') {
42
+ if (details !== null && details !== void 0 && details.data && 'url' in details.data) {
43
+ if (typeof details.data.url === 'string') {
44
+ return extractPageIdFromURL(details.data.url);
45
+ }
46
+ }
47
+ }
48
+ }
49
+ return undefined;
50
+ };
51
+ export const getContentId = details => {
52
+ if (fg('platform_smartlink_3pclick_analytics')) {
53
+ const currentProduct = getProductFromWindowUrl();
54
+ if (currentProduct === 'confluence') {
55
+ if (details !== null && details !== void 0 && details.data && 'url' in details.data) {
56
+ if (typeof details.data.url === 'string') {
57
+ return extractContentIdFromURL(details.data.url);
58
+ }
59
+ }
60
+ }
61
+ }
62
+ return undefined;
63
+ };
64
+ export const getJiraIssueId = details => {
65
+ if (fg('platform_smartlink_3pclick_analytics')) {
66
+ const currentProduct = getProductFromWindowUrl();
67
+ if (currentProduct === 'jira') {
68
+ if (details !== null && details !== void 0 && details.data && 'url' in details.data) {
69
+ if (typeof details.data.url === 'string') {
70
+ return extractJiraIssueIdFromURL(details.data.url);
71
+ }
72
+ }
73
+ }
74
+ }
75
+ return undefined;
76
+ };
38
77
  export const getObjectName = details => (details === null || details === void 0 ? void 0 : details.data) && 'name' in details.data && details.data.name || undefined;
39
78
  export const getObjectIconUrl = details => {
40
79
  if (details !== null && details !== void 0 && details.data && 'icon' in details.data && details.data.icon) {
@@ -80,4 +119,109 @@ export const getCanBeDatasource = details => {
80
119
  const datasources = getDatasources(details);
81
120
  return !!datasources && datasources.length > 0;
82
121
  };
83
- export const hasAuthScopeOverrides = details => !!(details !== null && details !== void 0 && details.meta.hasScopeOverrides);
122
+ export const hasAuthScopeOverrides = details => !!(details !== null && details !== void 0 && details.meta.hasScopeOverrides);
123
+
124
+ // Helper function to extract page ID from standard Confluence page URLs
125
+ const extractPageIdFromURL = url => {
126
+ try {
127
+ const urlObj = new URL(url);
128
+
129
+ // Following this pattern for confluence URL -> /wiki/spaces/{space}/pages/{pageId}/{title}
130
+ const pagesMatch = urlObj.pathname.match(/\/wiki\/spaces\/[^\/]+\/pages\/(\d+)/);
131
+ if (pagesMatch && pagesMatch[1]) {
132
+ return pagesMatch[1];
133
+ }
134
+
135
+ // Following this pattern for confluence URL -> /wiki/pages/viewpage.action?pageId={pageId}
136
+ const pageIdParam = urlObj.searchParams.get('pageId');
137
+ if (pageIdParam) {
138
+ return pageIdParam;
139
+ }
140
+
141
+ // Following this pattern for confluence URL -> /wiki/display/{space}/{pageId}
142
+ const displayMatch = urlObj.pathname.match(/\/wiki\/display\/[^\/]+\/(\d+)/);
143
+ if (displayMatch && displayMatch[1]) {
144
+ return displayMatch[1];
145
+ }
146
+ } catch {
147
+ return undefined;
148
+ }
149
+ return undefined;
150
+ };
151
+
152
+ // Helper function to extract content ID from app connector URLs
153
+ const extractContentIdFromURL = url => {
154
+ try {
155
+ const urlObj = new URL(url);
156
+
157
+ // Pattern: ?content.id={contentId} (for app connector URLs)
158
+ const contentId = urlObj.searchParams.get('content.id');
159
+ if (contentId) {
160
+ return contentId;
161
+ }
162
+ } catch {
163
+ return undefined;
164
+ }
165
+ return undefined;
166
+ };
167
+ const extractJiraIssueIdFromURL = url => {
168
+ try {
169
+ const urlObj = new URL(url);
170
+
171
+ // Following this pattern for jira URL -> /browse/{issueKey} (most common)
172
+ // Example: https://product-fabric.atlassian.net/browse/AI3W-1064
173
+ const browseMatch = urlObj.pathname.match(/\/browse\/([A-Z]+-\d+)/);
174
+ if (browseMatch && browseMatch[1]) {
175
+ return browseMatch[1];
176
+ }
177
+
178
+ // Following this pattern for jira URL -> /jira/browse/{issueKey} (for some installations)
179
+ const jiraBrowseMatch = urlObj.pathname.match(/\/jira\/browse\/([A-Z]+-\d+)/);
180
+ if (jiraBrowseMatch && jiraBrowseMatch[1]) {
181
+ return jiraBrowseMatch[1];
182
+ }
183
+
184
+ // Following this pattern for jira URL -> Query parameter ?selectedIssue={issueKey}
185
+ const selectedIssue = urlObj.searchParams.get('selectedIssue');
186
+ if (selectedIssue && /^[A-Z]+-\d+$/.test(selectedIssue)) {
187
+ return selectedIssue;
188
+ }
189
+
190
+ // Following this pattern for jira URL -> Query parameter ?issueKey={issueKey}
191
+ const issueKeyParam = urlObj.searchParams.get('issueKey');
192
+ if (issueKeyParam && /^[A-Z]+-\d+$/.test(issueKeyParam)) {
193
+ return issueKeyParam;
194
+ }
195
+ } catch {
196
+ return undefined;
197
+ }
198
+ return undefined;
199
+ };
200
+ export const getLinkClickAnalyticsThirdPartyAttributes = (thirdPartyARI, details) => ({
201
+ firstPartyARI: getObjectAri(details),
202
+ thirdPartyARI: thirdPartyARI,
203
+ jiraIssueId: getJiraIssueId(details),
204
+ confluenceContentId: getContentId(details),
205
+ confluencePageId: getPageId(details)
206
+ });
207
+ const getProductFromWindowUrl = () => {
208
+ try {
209
+ const currentUrl = window.location.href;
210
+ const urlObj = new URL(currentUrl);
211
+ const hostname = urlObj.hostname.toLowerCase();
212
+ const pathname = urlObj.pathname.toLowerCase();
213
+
214
+ // Check for Confluence patterns
215
+ if (hostname.includes('confluence') || pathname.includes('/wiki/') || pathname.includes('/display/') || pathname.includes('/spaces/')) {
216
+ return 'confluence';
217
+ }
218
+
219
+ // Check for Jira patterns
220
+ if (hostname.includes('jira') || pathname.includes('/browse/') || pathname.includes('/projects/') || pathname.includes('/secure/')) {
221
+ return 'jira';
222
+ }
223
+ } catch {
224
+ return undefined;
225
+ }
226
+ return undefined;
227
+ };
@@ -2,7 +2,7 @@ export const ANALYTICS_CHANNEL = 'media';
2
2
  export const context = {
3
3
  componentName: 'smart-cards',
4
4
  packageName: "@atlaskit/smart-card",
5
- packageVersion: "40.10.0"
5
+ packageVersion: "40.10.1"
6
6
  };
7
7
  export let TrackQuickActionType = /*#__PURE__*/function (TrackQuickActionType) {
8
8
  TrackQuickActionType["StatusUpdate"] = "StatusUpdate";
@@ -5,7 +5,7 @@ import { useAnalyticsEvents } from '../../common/analytics/generated/use-analyti
5
5
  import { CardDisplay } from '../../constants';
6
6
  import { useSmartLink } from '../../state';
7
7
  import { succeedUfoExperience } from '../../state/analytics';
8
- import { getClickUrl, getDefinitionId, getExtensionKey, getObjectAri, getObjectIconUrl, getObjectName, getResourceType, getServices, getThirdPartyARI, isFinalState } from '../../state/helpers';
8
+ import { getClickUrl, getDefinitionId, getExtensionKey, getLinkClickAnalyticsThirdPartyAttributes, getObjectAri, getObjectIconUrl, getObjectName, getResourceType, getServices, getThirdPartyARI, isFinalState } from '../../state/helpers';
9
9
  import { SmartLinkModalProvider } from '../../state/modal';
10
10
  import { isSpecialClick, isSpecialEvent, isSpecialKey } from '../../utils';
11
11
  import { combineActionOptions } from '../../utils/actions/combine-action-options';
@@ -63,12 +63,12 @@ function Component({
63
63
  openPreviewPanel
64
64
  } = useSmartLink(id, url);
65
65
  const ari = getObjectAri(state.details);
66
- const thirdPartyARI = getThirdPartyARI(state.details);
67
66
  const name = getObjectName(state.details);
68
67
  const definitionId = getDefinitionId(state.details);
69
68
  const extensionKey = getExtensionKey(state.details);
70
69
  const resourceType = getResourceType(state.details);
71
70
  const services = getServices(state.details);
71
+ const thirdPartyARI = getThirdPartyARI(state.details);
72
72
  let isFlexibleUi = useMemo(() => isFlexibleUiCard(children, ui), [children, ui]);
73
73
  const actionOptions = combineActionOptions({
74
74
  actionOptions: actionOptionsProp,
@@ -86,7 +86,6 @@ function Component({
86
86
  });
87
87
  if (fg('platform_smartlink_3pclick_analytics')) {
88
88
  if (thirdPartyARI && thirdPartyARI.startsWith(thirdPartyARIPrefix)) {
89
- const sourceURL = window.location.href;
90
89
  const clickURL = getClickUrl(url, state.details);
91
90
  if (clickURL === url) {
92
91
  // For questions or concerns about this event,
@@ -99,10 +98,7 @@ function Component({
99
98
  attributes: {
100
99
  eventName: 'smartLinkClickAnalyticsThirdPartyWorkflows'
101
100
  },
102
- nonPrivacySafeAttributes: {
103
- sourceURL: sourceURL,
104
- thirdPartyARI: thirdPartyARI
105
- }
101
+ nonPrivacySafeAttributes: getLinkClickAnalyticsThirdPartyAttributes(thirdPartyARI, state.details)
106
102
  });
107
103
  smartlinkClickAnalyticsEvent.fire('media');
108
104
  }
@@ -9,7 +9,7 @@ import LinkWarningModal from './LinkWarningModal';
9
9
  import { useLinkWarningModal } from './LinkWarningModal/hooks/use-link-warning-modal';
10
10
  const PACKAGE_DATA = {
11
11
  packageName: "@atlaskit/smart-card",
12
- packageVersion: "40.10.0",
12
+ packageVersion: "40.10.1",
13
13
  componentName: 'linkUrl'
14
14
  };
15
15
  const Anchor = withLinkClickedEvent('a');
@@ -36,6 +36,45 @@ export var getThirdPartyARI = function getThirdPartyARI(details) {
36
36
  }
37
37
  return undefined;
38
38
  };
39
+ export var getPageId = function getPageId(details) {
40
+ if (fg('platform_smartlink_3pclick_analytics')) {
41
+ var currentProduct = getProductFromWindowUrl();
42
+ if (currentProduct === 'confluence') {
43
+ if (details !== null && details !== void 0 && details.data && 'url' in details.data) {
44
+ if (typeof details.data.url === 'string') {
45
+ return extractPageIdFromURL(details.data.url);
46
+ }
47
+ }
48
+ }
49
+ }
50
+ return undefined;
51
+ };
52
+ export var getContentId = function getContentId(details) {
53
+ if (fg('platform_smartlink_3pclick_analytics')) {
54
+ var currentProduct = getProductFromWindowUrl();
55
+ if (currentProduct === 'confluence') {
56
+ if (details !== null && details !== void 0 && details.data && 'url' in details.data) {
57
+ if (typeof details.data.url === 'string') {
58
+ return extractContentIdFromURL(details.data.url);
59
+ }
60
+ }
61
+ }
62
+ }
63
+ return undefined;
64
+ };
65
+ export var getJiraIssueId = function getJiraIssueId(details) {
66
+ if (fg('platform_smartlink_3pclick_analytics')) {
67
+ var currentProduct = getProductFromWindowUrl();
68
+ if (currentProduct === 'jira') {
69
+ if (details !== null && details !== void 0 && details.data && 'url' in details.data) {
70
+ if (typeof details.data.url === 'string') {
71
+ return extractJiraIssueIdFromURL(details.data.url);
72
+ }
73
+ }
74
+ }
75
+ }
76
+ return undefined;
77
+ };
39
78
  export var getObjectName = function getObjectName(details) {
40
79
  return (details === null || details === void 0 ? void 0 : details.data) && 'name' in details.data && details.data.name || undefined;
41
80
  };
@@ -89,4 +128,111 @@ export var getCanBeDatasource = function getCanBeDatasource(details) {
89
128
  };
90
129
  export var hasAuthScopeOverrides = function hasAuthScopeOverrides(details) {
91
130
  return !!(details !== null && details !== void 0 && details.meta.hasScopeOverrides);
131
+ };
132
+
133
+ // Helper function to extract page ID from standard Confluence page URLs
134
+ var extractPageIdFromURL = function extractPageIdFromURL(url) {
135
+ try {
136
+ var urlObj = new URL(url);
137
+
138
+ // Following this pattern for confluence URL -> /wiki/spaces/{space}/pages/{pageId}/{title}
139
+ var pagesMatch = urlObj.pathname.match(/\/wiki\/spaces\/[^\/]+\/pages\/(\d+)/);
140
+ if (pagesMatch && pagesMatch[1]) {
141
+ return pagesMatch[1];
142
+ }
143
+
144
+ // Following this pattern for confluence URL -> /wiki/pages/viewpage.action?pageId={pageId}
145
+ var pageIdParam = urlObj.searchParams.get('pageId');
146
+ if (pageIdParam) {
147
+ return pageIdParam;
148
+ }
149
+
150
+ // Following this pattern for confluence URL -> /wiki/display/{space}/{pageId}
151
+ var displayMatch = urlObj.pathname.match(/\/wiki\/display\/[^\/]+\/(\d+)/);
152
+ if (displayMatch && displayMatch[1]) {
153
+ return displayMatch[1];
154
+ }
155
+ } catch (_unused) {
156
+ return undefined;
157
+ }
158
+ return undefined;
159
+ };
160
+
161
+ // Helper function to extract content ID from app connector URLs
162
+ var extractContentIdFromURL = function extractContentIdFromURL(url) {
163
+ try {
164
+ var urlObj = new URL(url);
165
+
166
+ // Pattern: ?content.id={contentId} (for app connector URLs)
167
+ var contentId = urlObj.searchParams.get('content.id');
168
+ if (contentId) {
169
+ return contentId;
170
+ }
171
+ } catch (_unused2) {
172
+ return undefined;
173
+ }
174
+ return undefined;
175
+ };
176
+ var extractJiraIssueIdFromURL = function extractJiraIssueIdFromURL(url) {
177
+ try {
178
+ var urlObj = new URL(url);
179
+
180
+ // Following this pattern for jira URL -> /browse/{issueKey} (most common)
181
+ // Example: https://product-fabric.atlassian.net/browse/AI3W-1064
182
+ var browseMatch = urlObj.pathname.match(/\/browse\/([A-Z]+-\d+)/);
183
+ if (browseMatch && browseMatch[1]) {
184
+ return browseMatch[1];
185
+ }
186
+
187
+ // Following this pattern for jira URL -> /jira/browse/{issueKey} (for some installations)
188
+ var jiraBrowseMatch = urlObj.pathname.match(/\/jira\/browse\/([A-Z]+-\d+)/);
189
+ if (jiraBrowseMatch && jiraBrowseMatch[1]) {
190
+ return jiraBrowseMatch[1];
191
+ }
192
+
193
+ // Following this pattern for jira URL -> Query parameter ?selectedIssue={issueKey}
194
+ var selectedIssue = urlObj.searchParams.get('selectedIssue');
195
+ if (selectedIssue && /^[A-Z]+-\d+$/.test(selectedIssue)) {
196
+ return selectedIssue;
197
+ }
198
+
199
+ // Following this pattern for jira URL -> Query parameter ?issueKey={issueKey}
200
+ var issueKeyParam = urlObj.searchParams.get('issueKey');
201
+ if (issueKeyParam && /^[A-Z]+-\d+$/.test(issueKeyParam)) {
202
+ return issueKeyParam;
203
+ }
204
+ } catch (_unused3) {
205
+ return undefined;
206
+ }
207
+ return undefined;
208
+ };
209
+ export var getLinkClickAnalyticsThirdPartyAttributes = function getLinkClickAnalyticsThirdPartyAttributes(thirdPartyARI, details) {
210
+ return {
211
+ firstPartyARI: getObjectAri(details),
212
+ thirdPartyARI: thirdPartyARI,
213
+ jiraIssueId: getJiraIssueId(details),
214
+ confluenceContentId: getContentId(details),
215
+ confluencePageId: getPageId(details)
216
+ };
217
+ };
218
+ var getProductFromWindowUrl = function getProductFromWindowUrl() {
219
+ try {
220
+ var currentUrl = window.location.href;
221
+ var urlObj = new URL(currentUrl);
222
+ var hostname = urlObj.hostname.toLowerCase();
223
+ var pathname = urlObj.pathname.toLowerCase();
224
+
225
+ // Check for Confluence patterns
226
+ if (hostname.includes('confluence') || pathname.includes('/wiki/') || pathname.includes('/display/') || pathname.includes('/spaces/')) {
227
+ return 'confluence';
228
+ }
229
+
230
+ // Check for Jira patterns
231
+ if (hostname.includes('jira') || pathname.includes('/browse/') || pathname.includes('/projects/') || pathname.includes('/secure/')) {
232
+ return 'jira';
233
+ }
234
+ } catch (_unused4) {
235
+ return undefined;
236
+ }
237
+ return undefined;
92
238
  };
@@ -4,7 +4,7 @@ export var ANALYTICS_CHANNEL = 'media';
4
4
  export var context = {
5
5
  componentName: 'smart-cards',
6
6
  packageName: "@atlaskit/smart-card",
7
- packageVersion: "40.10.0"
7
+ packageVersion: "40.10.1"
8
8
  };
9
9
  export var TrackQuickActionType = /*#__PURE__*/function (TrackQuickActionType) {
10
10
  TrackQuickActionType["StatusUpdate"] = "StatusUpdate";
@@ -5,7 +5,7 @@ import { useAnalyticsEvents } from '../../common/analytics/generated/use-analyti
5
5
  import { CardDisplay } from '../../constants';
6
6
  import { useSmartLink } from '../../state';
7
7
  import { succeedUfoExperience } from '../../state/analytics';
8
- import { getClickUrl, getDefinitionId, getExtensionKey, getObjectAri, getObjectIconUrl, getObjectName, getResourceType, getServices, getThirdPartyARI, isFinalState } from '../../state/helpers';
8
+ import { getClickUrl, getDefinitionId, getExtensionKey, getLinkClickAnalyticsThirdPartyAttributes, getObjectAri, getObjectIconUrl, getObjectName, getResourceType, getServices, getThirdPartyARI, isFinalState } from '../../state/helpers';
9
9
  import { SmartLinkModalProvider } from '../../state/modal';
10
10
  import { isSpecialClick, isSpecialEvent, isSpecialKey } from '../../utils';
11
11
  import { combineActionOptions } from '../../utils/actions/combine-action-options';
@@ -59,12 +59,12 @@ function Component(_ref) {
59
59
  isPreviewPanelAvailable = _useSmartLink.isPreviewPanelAvailable,
60
60
  openPreviewPanel = _useSmartLink.openPreviewPanel;
61
61
  var ari = getObjectAri(state.details);
62
- var thirdPartyARI = getThirdPartyARI(state.details);
63
62
  var name = getObjectName(state.details);
64
63
  var definitionId = getDefinitionId(state.details);
65
64
  var extensionKey = getExtensionKey(state.details);
66
65
  var resourceType = getResourceType(state.details);
67
66
  var services = getServices(state.details);
67
+ var thirdPartyARI = getThirdPartyARI(state.details);
68
68
  var isFlexibleUi = useMemo(function () {
69
69
  return isFlexibleUiCard(children, ui);
70
70
  }, [children, ui]);
@@ -84,7 +84,6 @@ function Component(_ref) {
84
84
  });
85
85
  if (fg('platform_smartlink_3pclick_analytics')) {
86
86
  if (thirdPartyARI && thirdPartyARI.startsWith(thirdPartyARIPrefix)) {
87
- var sourceURL = window.location.href;
88
87
  var clickURL = getClickUrl(url, state.details);
89
88
  if (clickURL === url) {
90
89
  // For questions or concerns about this event,
@@ -97,10 +96,7 @@ function Component(_ref) {
97
96
  attributes: {
98
97
  eventName: 'smartLinkClickAnalyticsThirdPartyWorkflows'
99
98
  },
100
- nonPrivacySafeAttributes: {
101
- sourceURL: sourceURL,
102
- thirdPartyARI: thirdPartyARI
103
- }
99
+ nonPrivacySafeAttributes: getLinkClickAnalyticsThirdPartyAttributes(thirdPartyARI, state.details)
104
100
  });
105
101
  smartlinkClickAnalyticsEvent.fire('media');
106
102
  }
@@ -12,7 +12,7 @@ import LinkWarningModal from './LinkWarningModal';
12
12
  import { useLinkWarningModal } from './LinkWarningModal/hooks/use-link-warning-modal';
13
13
  var PACKAGE_DATA = {
14
14
  packageName: "@atlaskit/smart-card",
15
- packageVersion: "40.10.0",
15
+ packageVersion: "40.10.1",
16
16
  componentName: 'linkUrl'
17
17
  };
18
18
  var Anchor = withLinkClickedEvent('a');
@@ -3,7 +3,7 @@
3
3
  *
4
4
  * Generates Typescript types for analytics events from analytics.spec.yaml
5
5
  *
6
- * @codegen <<SignedSource::18e5687cdc42ba3ac58b306a03a60d9d>>
6
+ * @codegen <<SignedSource::9e03e5e3a6be04ef3aa7e2d7a018d8a7>>
7
7
  * @codegenCommand yarn workspace @atlassian/analytics-tooling run analytics:codegen smart-card
8
8
  */
9
9
  export type PackageMetaDataContextType = {
@@ -231,8 +231,11 @@ export type SmartLinkRenderFailedAttributesType = {
231
231
  id: string | null;
232
232
  };
233
233
  export type SmartLinkClickedSmartlinkClickAnalyticsWorkflowsAttributesType = {
234
- sourceURL: string;
234
+ firstPartyARI: string;
235
235
  thirdPartyARI: string;
236
+ jiraIssueId: string | null;
237
+ confluenceContentId: string | null;
238
+ confluencePageId: string | null;
236
239
  };
237
240
  export type AnalyticsEventAttributes = {
238
241
  /**
@@ -9,6 +9,9 @@ export declare const getDefinitionId: (details?: JsonLd.Response) => string | un
9
9
  export declare const getExtensionKey: (details?: JsonLd.Response) => string | undefined;
10
10
  export declare const getObjectAri: (details?: JsonLd.Response) => string | undefined;
11
11
  export declare const getThirdPartyARI: (details?: SmartLinkResponse) => string | undefined;
12
+ export declare const getPageId: (details?: JsonLd.Response) => string | undefined;
13
+ export declare const getContentId: (details?: JsonLd.Response) => string | undefined;
14
+ export declare const getJiraIssueId: (details?: JsonLd.Response) => string | undefined;
12
15
  export declare const getObjectName: (details?: JsonLd.Response) => string | undefined;
13
16
  export declare const getObjectIconUrl: (details?: JsonLd.Response) => string | undefined;
14
17
  export declare const getResourceType: (details?: JsonLd.Response) => string | undefined;
@@ -23,3 +26,10 @@ export declare const isFinalState: (status: CardType) => boolean;
23
26
  export declare const getDatasources: (details?: JsonLdDatasourceResponse) => DatasourceResolveResponse[] | undefined;
24
27
  export declare const getCanBeDatasource: (details?: JsonLdDatasourceResponse) => boolean;
25
28
  export declare const hasAuthScopeOverrides: (details?: JsonLd.Response) => boolean;
29
+ export declare const getLinkClickAnalyticsThirdPartyAttributes: (thirdPartyARI: string | undefined, details?: JsonLd.Response) => {
30
+ firstPartyARI: string | undefined;
31
+ thirdPartyARI: string | undefined;
32
+ jiraIssueId: string | undefined;
33
+ confluenceContentId: string | undefined;
34
+ confluencePageId: string | undefined;
35
+ };
@@ -3,7 +3,7 @@
3
3
  *
4
4
  * Generates Typescript types for analytics events from analytics.spec.yaml
5
5
  *
6
- * @codegen <<SignedSource::18e5687cdc42ba3ac58b306a03a60d9d>>
6
+ * @codegen <<SignedSource::9e03e5e3a6be04ef3aa7e2d7a018d8a7>>
7
7
  * @codegenCommand yarn workspace @atlassian/analytics-tooling run analytics:codegen smart-card
8
8
  */
9
9
  export type PackageMetaDataContextType = {
@@ -231,8 +231,11 @@ export type SmartLinkRenderFailedAttributesType = {
231
231
  id: string | null;
232
232
  };
233
233
  export type SmartLinkClickedSmartlinkClickAnalyticsWorkflowsAttributesType = {
234
- sourceURL: string;
234
+ firstPartyARI: string;
235
235
  thirdPartyARI: string;
236
+ jiraIssueId: string | null;
237
+ confluenceContentId: string | null;
238
+ confluencePageId: string | null;
236
239
  };
237
240
  export type AnalyticsEventAttributes = {
238
241
  /**
@@ -9,6 +9,9 @@ export declare const getDefinitionId: (details?: JsonLd.Response) => string | un
9
9
  export declare const getExtensionKey: (details?: JsonLd.Response) => string | undefined;
10
10
  export declare const getObjectAri: (details?: JsonLd.Response) => string | undefined;
11
11
  export declare const getThirdPartyARI: (details?: SmartLinkResponse) => string | undefined;
12
+ export declare const getPageId: (details?: JsonLd.Response) => string | undefined;
13
+ export declare const getContentId: (details?: JsonLd.Response) => string | undefined;
14
+ export declare const getJiraIssueId: (details?: JsonLd.Response) => string | undefined;
12
15
  export declare const getObjectName: (details?: JsonLd.Response) => string | undefined;
13
16
  export declare const getObjectIconUrl: (details?: JsonLd.Response) => string | undefined;
14
17
  export declare const getResourceType: (details?: JsonLd.Response) => string | undefined;
@@ -23,3 +26,10 @@ export declare const isFinalState: (status: CardType) => boolean;
23
26
  export declare const getDatasources: (details?: JsonLdDatasourceResponse) => DatasourceResolveResponse[] | undefined;
24
27
  export declare const getCanBeDatasource: (details?: JsonLdDatasourceResponse) => boolean;
25
28
  export declare const hasAuthScopeOverrides: (details?: JsonLd.Response) => boolean;
29
+ export declare const getLinkClickAnalyticsThirdPartyAttributes: (thirdPartyARI: string | undefined, details?: JsonLd.Response) => {
30
+ firstPartyARI: string | undefined;
31
+ thirdPartyARI: string | undefined;
32
+ jiraIssueId: string | undefined;
33
+ confluenceContentId: string | undefined;
34
+ confluencePageId: string | undefined;
35
+ };
@@ -8,7 +8,7 @@
8
8
  ],
9
9
  "types": "../dist/types/hooks.d.ts",
10
10
  "typesVersions": {
11
- ">=4.5 <5.4": {
11
+ ">=4.5 <5.9": {
12
12
  "*": [
13
13
  "../dist/types-ts4.5/hooks.d.ts"
14
14
  ]
@@ -8,7 +8,7 @@
8
8
  ],
9
9
  "types": "../dist/types/hoverCard.d.ts",
10
10
  "typesVersions": {
11
- ">=4.5 <5.4": {
11
+ ">=4.5 <5.9": {
12
12
  "*": [
13
13
  "../dist/types-ts4.5/hoverCard.d.ts"
14
14
  ]
@@ -8,7 +8,7 @@
8
8
  ],
9
9
  "types": "../dist/types/linkUrl.d.ts",
10
10
  "typesVersions": {
11
- ">=4.5 <5.4": {
11
+ ">=4.5 <5.9": {
12
12
  "*": [
13
13
  "../dist/types-ts4.5/linkUrl.d.ts"
14
14
  ]
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atlaskit/smart-card",
3
- "version": "40.10.1",
3
+ "version": "40.10.2",
4
4
  "description": "Smart card component",
5
5
  "publishConfig": {
6
6
  "registry": "https://registry.npmjs.org/"
@@ -97,7 +97,7 @@
97
97
  "@atlaskit/analytics-listeners": "^9.0.0",
98
98
  "@atlaskit/css-reset": "^7.3.0",
99
99
  "@atlaskit/media-test-helpers": "^38.0.0",
100
- "@atlaskit/react-ufo": "^4.2.0",
100
+ "@atlaskit/react-ufo": "^4.3.0",
101
101
  "@atlaskit/ssr": "workspace:^",
102
102
  "@atlaskit/visual-regression": "workspace:^",
103
103
  "@atlassian/analytics-tooling": "^0.5.0",
package/ssr/package.json CHANGED
@@ -8,7 +8,7 @@
8
8
  ],
9
9
  "types": "../dist/types/ssr.d.ts",
10
10
  "typesVersions": {
11
- ">=4.5 <5.4": {
11
+ ">=4.5 <5.9": {
12
12
  "*": [
13
13
  "../dist/types-ts4.5/ssr.d.ts"
14
14
  ]
@@ -8,7 +8,7 @@
8
8
  ],
9
9
  "types": "../dist/types/types.d.ts",
10
10
  "typesVersions": {
11
- ">=4.5 <5.4": {
11
+ ">=4.5 <5.9": {
12
12
  "*": [
13
13
  "../dist/types-ts4.5/types.d.ts"
14
14
  ]