@atlaskit/smart-card 40.10.1 → 40.10.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,20 @@
1
1
  # @atlaskit/smart-card
2
2
 
3
+ ## 40.10.3
4
+
5
+ ### Patch Changes
6
+
7
+ - [`eeed50fbee70e`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/eeed50fbee70e) -
8
+ Updated SmartCard module for legal spec changes for 3P Click Analytics
9
+
10
+ ## 40.10.2
11
+
12
+ ### Patch Changes
13
+
14
+ - [`2115cfcea4013`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/2115cfcea4013) -
15
+ Add Jira Issue ID, Confluence Content ID/Page ID, and helper methods to retrieve, as well as
16
+ include in component onclick result
17
+
3
18
  ## 40.10.1
4
19
 
5
20
  ### Patch Changes
@@ -753,13 +753,21 @@ events:
753
753
  3P Workflows team
754
754
  attributes:
755
755
  <<: [*PackageMetaDataContext, *CommonContext, *ResolvedContext]
756
- sourceURL:
757
- required: true
758
- type: string
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
762
756
  thirdPartyARI:
763
757
  required: true
764
758
  type: string
765
759
  description: The third-party ARI for this Smart Link
760
+ eventName:
761
+ required: true
762
+ type: string
763
+ description:
764
+ The name of the event being tracked - for this event will always be
765
+ smartLinkClickAnalyticsThirdPartyWorkflows since there are multiple event types in the
766
+ same SQS pipeline
767
+ firstPartyIdentifier:
768
+ required: false
769
+ type: string
770
+ description:
771
+ A null-capable field representing the Confluence content ID, Confluence page ID, or Jira
772
+ issue key. This can be null if it is a value for an unsupported 1P provider (eg,
773
+ Bitbucket, Loom), and will be prefixed by an identifier based on the source product.
@@ -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.getObjectName = exports.getObjectIconUrl = exports.getObjectAri = exports.getFirstPartyIdentifier = exports.getExtensionKey = exports.getDefinitionId = exports.getDatasources = 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,30 @@ var getThirdPartyARI = exports.getThirdPartyARI = function getThirdPartyARI(deta
43
43
  }
44
44
  return undefined;
45
45
  };
46
+ var getFirstPartyIdentifier = exports.getFirstPartyIdentifier = function getFirstPartyIdentifier() {
47
+ if (!(0, _platformFeatureFlags.fg)('platform_smartlink_3pclick_analytics')) {
48
+ return undefined;
49
+ }
50
+ var product = getProductFromWindowURL();
51
+ var currentURL = window.location.href;
52
+ if (product === 'confluence') {
53
+ var contentId = extractContentIdFromURL(currentURL);
54
+ if (contentId) {
55
+ return "ConfluenceContentId:".concat(contentId);
56
+ }
57
+ var pageId = extractPageIdFromURL(currentURL);
58
+ if (pageId) {
59
+ return "ConfluencePageId:".concat(pageId);
60
+ }
61
+ } else if (product === 'jira') {
62
+ var issueKey = extractJiraIssueIdFromURL(currentURL);
63
+ if (issueKey) {
64
+ return "JiraIssueKey:".concat(issueKey);
65
+ }
66
+ } else {
67
+ return undefined;
68
+ }
69
+ };
46
70
  var getObjectName = exports.getObjectName = function getObjectName(details) {
47
71
  return (details === null || details === void 0 ? void 0 : details.data) && 'name' in details.data && details.data.name || undefined;
48
72
  };
@@ -96,4 +120,102 @@ var getCanBeDatasource = exports.getCanBeDatasource = function getCanBeDatasourc
96
120
  };
97
121
  var hasAuthScopeOverrides = exports.hasAuthScopeOverrides = function hasAuthScopeOverrides(details) {
98
122
  return !!(details !== null && details !== void 0 && details.meta.hasScopeOverrides);
123
+ };
124
+
125
+ // Helper function to extract page ID from standard Confluence page URLs
126
+ var extractPageIdFromURL = function extractPageIdFromURL(url) {
127
+ try {
128
+ var urlObj = new URL(url);
129
+
130
+ // Following this pattern for confluence URL -> /wiki/spaces/{space}/pages/{pageId}/{title}
131
+ var pagesMatch = urlObj.pathname.match(/\/wiki\/spaces\/[^\/]+\/pages\/(\d+)/);
132
+ if (pagesMatch && pagesMatch[1]) {
133
+ return pagesMatch[1];
134
+ }
135
+
136
+ // Following this pattern for confluence URL -> /wiki/pages/viewpage.action?pageId={pageId}
137
+ var pageIdParam = urlObj.searchParams.get('pageId');
138
+ if (pageIdParam) {
139
+ return pageIdParam;
140
+ }
141
+
142
+ // Following this pattern for confluence URL -> /wiki/display/{space}/{pageId}
143
+ var displayMatch = urlObj.pathname.match(/\/wiki\/display\/[^\/]+\/(\d+)/);
144
+ if (displayMatch && displayMatch[1]) {
145
+ return displayMatch[1];
146
+ }
147
+ } catch (_unused) {
148
+ return undefined;
149
+ }
150
+ return undefined;
151
+ };
152
+
153
+ // Helper function to extract content ID from app connector URLs
154
+ var extractContentIdFromURL = function extractContentIdFromURL(url) {
155
+ try {
156
+ var urlObj = new URL(url);
157
+
158
+ // Pattern: ?content.id={contentId} (for app connector URLs)
159
+ var contentId = urlObj.searchParams.get('content.id');
160
+ if (contentId) {
161
+ return contentId;
162
+ }
163
+ } catch (_unused2) {
164
+ return undefined;
165
+ }
166
+ return undefined;
167
+ };
168
+ var extractJiraIssueIdFromURL = function extractJiraIssueIdFromURL(url) {
169
+ try {
170
+ var urlObj = new URL(url);
171
+
172
+ // Following this pattern for jira URL -> /browse/{issueKey} (most common)
173
+ // Example: https://product-fabric.atlassian.net/browse/AI3W-1064
174
+ var browseMatch = urlObj.pathname.match(/\/browse\/([A-Z]+-\d+)/);
175
+ if (browseMatch && browseMatch[1]) {
176
+ return browseMatch[1];
177
+ }
178
+
179
+ // Following this pattern for jira URL -> /jira/browse/{issueKey} (for some installations)
180
+ var jiraBrowseMatch = urlObj.pathname.match(/\/jira\/browse\/([A-Z]+-\d+)/);
181
+ if (jiraBrowseMatch && jiraBrowseMatch[1]) {
182
+ return jiraBrowseMatch[1];
183
+ }
184
+
185
+ // Following this pattern for jira URL -> Query parameter ?selectedIssue={issueKey}
186
+ var selectedIssue = urlObj.searchParams.get('selectedIssue');
187
+ if (selectedIssue && /^[A-Z]+-\d+$/.test(selectedIssue)) {
188
+ return selectedIssue;
189
+ }
190
+
191
+ // Following this pattern for jira URL -> Query parameter ?issueKey={issueKey}
192
+ var issueKeyParam = urlObj.searchParams.get('issueKey');
193
+ if (issueKeyParam && /^[A-Z]+-\d+$/.test(issueKeyParam)) {
194
+ return issueKeyParam;
195
+ }
196
+ } catch (_unused3) {
197
+ return undefined;
198
+ }
199
+ return undefined;
200
+ };
201
+ var getProductFromWindowURL = function getProductFromWindowURL() {
202
+ try {
203
+ var currentUrl = window.location.href;
204
+ var urlObj = new URL(currentUrl);
205
+ var hostname = urlObj.hostname.toLowerCase();
206
+ var pathname = urlObj.pathname.toLowerCase();
207
+
208
+ // Check for Confluence patterns
209
+ if (hostname.includes('confluence') || pathname.includes('/wiki/') || pathname.includes('/display/') || pathname.includes('/spaces/')) {
210
+ return 'confluence';
211
+ }
212
+
213
+ // Check for Jira patterns
214
+ if (hostname.includes('jira') || pathname.includes('/browse/') || pathname.includes('/projects/') || pathname.includes('/secure/')) {
215
+ return 'jira';
216
+ }
217
+ } catch (_unused4) {
218
+ return undefined;
219
+ }
220
+ return undefined;
99
221
  };
@@ -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.2"
15
15
  };
16
16
  var TrackQuickActionType = exports.TrackQuickActionType = /*#__PURE__*/function (TrackQuickActionType) {
17
17
  TrackQuickActionType["StatusUpdate"] = "StatusUpdate";
@@ -68,12 +68,13 @@ 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
+ var firstPartyIdentifier = (0, _helpers.getFirstPartyIdentifier)();
77
78
  var isFlexibleUi = (0, _react.useMemo)(function () {
78
79
  return (0, _flexible.isFlexibleUiCard)(children, ui);
79
80
  }, [children, ui]);
@@ -93,7 +94,6 @@ function Component(_ref) {
93
94
  });
94
95
  if ((0, _platformFeatureFlags.fg)('platform_smartlink_3pclick_analytics')) {
95
96
  if (thirdPartyARI && thirdPartyARI.startsWith(thirdPartyARIPrefix)) {
96
- var sourceURL = window.location.href;
97
97
  var clickURL = (0, _helpers.getClickUrl)(url, state.details);
98
98
  if (clickURL === url) {
99
99
  // For questions or concerns about this event,
@@ -104,10 +104,10 @@ function Component(_ref) {
104
104
  actionSubjectId: 'smartlinkClickAnalyticsWorkflows',
105
105
  eventType: 'ui',
106
106
  attributes: {
107
- eventName: 'smartLinkClickAnalyticsThirdPartyWorkflows'
107
+ eventName: 'smartLinkClickAnalyticsThirdPartyWorkflows',
108
+ firstPartyIdentifier: firstPartyIdentifier
108
109
  },
109
110
  nonPrivacySafeAttributes: {
110
- sourceURL: sourceURL,
111
111
  thirdPartyARI: thirdPartyARI
112
112
  }
113
113
  });
@@ -154,7 +154,7 @@ function Component(_ref) {
154
154
  }
155
155
  (0, _click.fireLinkClickedEvent)(createAnalyticsEvent)(event);
156
156
  }
157
- }, [fireEvent, id, isFlexibleUi, appearance, definitionId, onClick, url, state.details, ari, name, isPreviewPanelAvailable, openPreviewPanel, createAnalyticsEvent, thirdPartyARI]);
157
+ }, [fireEvent, id, isFlexibleUi, appearance, definitionId, onClick, url, state.details, ari, name, isPreviewPanelAvailable, openPreviewPanel, createAnalyticsEvent, thirdPartyARI, firstPartyIdentifier]);
158
158
  var handleAuthorize = (0, _react.useCallback)(function () {
159
159
  return actions.authorize(appearance);
160
160
  }, [actions, appearance]);
@@ -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.2",
23
23
  componentName: 'linkUrl'
24
24
  };
25
25
  var Anchor = (0, _click.withLinkClickedEvent)('a');
@@ -35,6 +35,30 @@ export const getThirdPartyARI = details => {
35
35
  }
36
36
  return undefined;
37
37
  };
38
+ export const getFirstPartyIdentifier = () => {
39
+ if (!fg('platform_smartlink_3pclick_analytics')) {
40
+ return undefined;
41
+ }
42
+ const product = getProductFromWindowURL();
43
+ const currentURL = window.location.href;
44
+ if (product === 'confluence') {
45
+ const contentId = extractContentIdFromURL(currentURL);
46
+ if (contentId) {
47
+ return `ConfluenceContentId:${contentId}`;
48
+ }
49
+ const pageId = extractPageIdFromURL(currentURL);
50
+ if (pageId) {
51
+ return `ConfluencePageId:${pageId}`;
52
+ }
53
+ } else if (product === 'jira') {
54
+ const issueKey = extractJiraIssueIdFromURL(currentURL);
55
+ if (issueKey) {
56
+ return `JiraIssueKey:${issueKey}`;
57
+ }
58
+ } else {
59
+ return undefined;
60
+ }
61
+ };
38
62
  export const getObjectName = details => (details === null || details === void 0 ? void 0 : details.data) && 'name' in details.data && details.data.name || undefined;
39
63
  export const getObjectIconUrl = details => {
40
64
  if (details !== null && details !== void 0 && details.data && 'icon' in details.data && details.data.icon) {
@@ -80,4 +104,102 @@ export const getCanBeDatasource = details => {
80
104
  const datasources = getDatasources(details);
81
105
  return !!datasources && datasources.length > 0;
82
106
  };
83
- export const hasAuthScopeOverrides = details => !!(details !== null && details !== void 0 && details.meta.hasScopeOverrides);
107
+ export const hasAuthScopeOverrides = details => !!(details !== null && details !== void 0 && details.meta.hasScopeOverrides);
108
+
109
+ // Helper function to extract page ID from standard Confluence page URLs
110
+ const extractPageIdFromURL = url => {
111
+ try {
112
+ const urlObj = new URL(url);
113
+
114
+ // Following this pattern for confluence URL -> /wiki/spaces/{space}/pages/{pageId}/{title}
115
+ const pagesMatch = urlObj.pathname.match(/\/wiki\/spaces\/[^\/]+\/pages\/(\d+)/);
116
+ if (pagesMatch && pagesMatch[1]) {
117
+ return pagesMatch[1];
118
+ }
119
+
120
+ // Following this pattern for confluence URL -> /wiki/pages/viewpage.action?pageId={pageId}
121
+ const pageIdParam = urlObj.searchParams.get('pageId');
122
+ if (pageIdParam) {
123
+ return pageIdParam;
124
+ }
125
+
126
+ // Following this pattern for confluence URL -> /wiki/display/{space}/{pageId}
127
+ const displayMatch = urlObj.pathname.match(/\/wiki\/display\/[^\/]+\/(\d+)/);
128
+ if (displayMatch && displayMatch[1]) {
129
+ return displayMatch[1];
130
+ }
131
+ } catch {
132
+ return undefined;
133
+ }
134
+ return undefined;
135
+ };
136
+
137
+ // Helper function to extract content ID from app connector URLs
138
+ const extractContentIdFromURL = url => {
139
+ try {
140
+ const urlObj = new URL(url);
141
+
142
+ // Pattern: ?content.id={contentId} (for app connector URLs)
143
+ const contentId = urlObj.searchParams.get('content.id');
144
+ if (contentId) {
145
+ return contentId;
146
+ }
147
+ } catch {
148
+ return undefined;
149
+ }
150
+ return undefined;
151
+ };
152
+ const extractJiraIssueIdFromURL = url => {
153
+ try {
154
+ const urlObj = new URL(url);
155
+
156
+ // Following this pattern for jira URL -> /browse/{issueKey} (most common)
157
+ // Example: https://product-fabric.atlassian.net/browse/AI3W-1064
158
+ const browseMatch = urlObj.pathname.match(/\/browse\/([A-Z]+-\d+)/);
159
+ if (browseMatch && browseMatch[1]) {
160
+ return browseMatch[1];
161
+ }
162
+
163
+ // Following this pattern for jira URL -> /jira/browse/{issueKey} (for some installations)
164
+ const jiraBrowseMatch = urlObj.pathname.match(/\/jira\/browse\/([A-Z]+-\d+)/);
165
+ if (jiraBrowseMatch && jiraBrowseMatch[1]) {
166
+ return jiraBrowseMatch[1];
167
+ }
168
+
169
+ // Following this pattern for jira URL -> Query parameter ?selectedIssue={issueKey}
170
+ const selectedIssue = urlObj.searchParams.get('selectedIssue');
171
+ if (selectedIssue && /^[A-Z]+-\d+$/.test(selectedIssue)) {
172
+ return selectedIssue;
173
+ }
174
+
175
+ // Following this pattern for jira URL -> Query parameter ?issueKey={issueKey}
176
+ const issueKeyParam = urlObj.searchParams.get('issueKey');
177
+ if (issueKeyParam && /^[A-Z]+-\d+$/.test(issueKeyParam)) {
178
+ return issueKeyParam;
179
+ }
180
+ } catch {
181
+ return undefined;
182
+ }
183
+ return undefined;
184
+ };
185
+ const getProductFromWindowURL = () => {
186
+ try {
187
+ const currentUrl = window.location.href;
188
+ const urlObj = new URL(currentUrl);
189
+ const hostname = urlObj.hostname.toLowerCase();
190
+ const pathname = urlObj.pathname.toLowerCase();
191
+
192
+ // Check for Confluence patterns
193
+ if (hostname.includes('confluence') || pathname.includes('/wiki/') || pathname.includes('/display/') || pathname.includes('/spaces/')) {
194
+ return 'confluence';
195
+ }
196
+
197
+ // Check for Jira patterns
198
+ if (hostname.includes('jira') || pathname.includes('/browse/') || pathname.includes('/projects/') || pathname.includes('/secure/')) {
199
+ return 'jira';
200
+ }
201
+ } catch {
202
+ return undefined;
203
+ }
204
+ return undefined;
205
+ };
@@ -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.2"
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, getFirstPartyIdentifier, 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,13 @@ 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
+ const firstPartyIdentifier = getFirstPartyIdentifier();
72
73
  let isFlexibleUi = useMemo(() => isFlexibleUiCard(children, ui), [children, ui]);
73
74
  const actionOptions = combineActionOptions({
74
75
  actionOptions: actionOptionsProp,
@@ -86,7 +87,6 @@ function Component({
86
87
  });
87
88
  if (fg('platform_smartlink_3pclick_analytics')) {
88
89
  if (thirdPartyARI && thirdPartyARI.startsWith(thirdPartyARIPrefix)) {
89
- const sourceURL = window.location.href;
90
90
  const clickURL = getClickUrl(url, state.details);
91
91
  if (clickURL === url) {
92
92
  // For questions or concerns about this event,
@@ -97,10 +97,10 @@ function Component({
97
97
  actionSubjectId: 'smartlinkClickAnalyticsWorkflows',
98
98
  eventType: 'ui',
99
99
  attributes: {
100
- eventName: 'smartLinkClickAnalyticsThirdPartyWorkflows'
100
+ eventName: 'smartLinkClickAnalyticsThirdPartyWorkflows',
101
+ firstPartyIdentifier: firstPartyIdentifier
101
102
  },
102
103
  nonPrivacySafeAttributes: {
103
- sourceURL: sourceURL,
104
104
  thirdPartyARI: thirdPartyARI
105
105
  }
106
106
  });
@@ -147,7 +147,7 @@ function Component({
147
147
  }
148
148
  fireLinkClickedEvent(createAnalyticsEvent)(event);
149
149
  }
150
- }, [fireEvent, id, isFlexibleUi, appearance, definitionId, onClick, url, state.details, ari, name, isPreviewPanelAvailable, openPreviewPanel, createAnalyticsEvent, thirdPartyARI]);
150
+ }, [fireEvent, id, isFlexibleUi, appearance, definitionId, onClick, url, state.details, ari, name, isPreviewPanelAvailable, openPreviewPanel, createAnalyticsEvent, thirdPartyARI, firstPartyIdentifier]);
151
151
  const handleAuthorize = useCallback(() => actions.authorize(appearance), [actions, appearance]);
152
152
  const handleRetry = useCallback(() => {
153
153
  actions.reload();
@@ -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.2",
13
13
  componentName: 'linkUrl'
14
14
  };
15
15
  const Anchor = withLinkClickedEvent('a');
@@ -36,6 +36,30 @@ export var getThirdPartyARI = function getThirdPartyARI(details) {
36
36
  }
37
37
  return undefined;
38
38
  };
39
+ export var getFirstPartyIdentifier = function getFirstPartyIdentifier() {
40
+ if (!fg('platform_smartlink_3pclick_analytics')) {
41
+ return undefined;
42
+ }
43
+ var product = getProductFromWindowURL();
44
+ var currentURL = window.location.href;
45
+ if (product === 'confluence') {
46
+ var contentId = extractContentIdFromURL(currentURL);
47
+ if (contentId) {
48
+ return "ConfluenceContentId:".concat(contentId);
49
+ }
50
+ var pageId = extractPageIdFromURL(currentURL);
51
+ if (pageId) {
52
+ return "ConfluencePageId:".concat(pageId);
53
+ }
54
+ } else if (product === 'jira') {
55
+ var issueKey = extractJiraIssueIdFromURL(currentURL);
56
+ if (issueKey) {
57
+ return "JiraIssueKey:".concat(issueKey);
58
+ }
59
+ } else {
60
+ return undefined;
61
+ }
62
+ };
39
63
  export var getObjectName = function getObjectName(details) {
40
64
  return (details === null || details === void 0 ? void 0 : details.data) && 'name' in details.data && details.data.name || undefined;
41
65
  };
@@ -89,4 +113,102 @@ export var getCanBeDatasource = function getCanBeDatasource(details) {
89
113
  };
90
114
  export var hasAuthScopeOverrides = function hasAuthScopeOverrides(details) {
91
115
  return !!(details !== null && details !== void 0 && details.meta.hasScopeOverrides);
116
+ };
117
+
118
+ // Helper function to extract page ID from standard Confluence page URLs
119
+ var extractPageIdFromURL = function extractPageIdFromURL(url) {
120
+ try {
121
+ var urlObj = new URL(url);
122
+
123
+ // Following this pattern for confluence URL -> /wiki/spaces/{space}/pages/{pageId}/{title}
124
+ var pagesMatch = urlObj.pathname.match(/\/wiki\/spaces\/[^\/]+\/pages\/(\d+)/);
125
+ if (pagesMatch && pagesMatch[1]) {
126
+ return pagesMatch[1];
127
+ }
128
+
129
+ // Following this pattern for confluence URL -> /wiki/pages/viewpage.action?pageId={pageId}
130
+ var pageIdParam = urlObj.searchParams.get('pageId');
131
+ if (pageIdParam) {
132
+ return pageIdParam;
133
+ }
134
+
135
+ // Following this pattern for confluence URL -> /wiki/display/{space}/{pageId}
136
+ var displayMatch = urlObj.pathname.match(/\/wiki\/display\/[^\/]+\/(\d+)/);
137
+ if (displayMatch && displayMatch[1]) {
138
+ return displayMatch[1];
139
+ }
140
+ } catch (_unused) {
141
+ return undefined;
142
+ }
143
+ return undefined;
144
+ };
145
+
146
+ // Helper function to extract content ID from app connector URLs
147
+ var extractContentIdFromURL = function extractContentIdFromURL(url) {
148
+ try {
149
+ var urlObj = new URL(url);
150
+
151
+ // Pattern: ?content.id={contentId} (for app connector URLs)
152
+ var contentId = urlObj.searchParams.get('content.id');
153
+ if (contentId) {
154
+ return contentId;
155
+ }
156
+ } catch (_unused2) {
157
+ return undefined;
158
+ }
159
+ return undefined;
160
+ };
161
+ var extractJiraIssueIdFromURL = function extractJiraIssueIdFromURL(url) {
162
+ try {
163
+ var urlObj = new URL(url);
164
+
165
+ // Following this pattern for jira URL -> /browse/{issueKey} (most common)
166
+ // Example: https://product-fabric.atlassian.net/browse/AI3W-1064
167
+ var browseMatch = urlObj.pathname.match(/\/browse\/([A-Z]+-\d+)/);
168
+ if (browseMatch && browseMatch[1]) {
169
+ return browseMatch[1];
170
+ }
171
+
172
+ // Following this pattern for jira URL -> /jira/browse/{issueKey} (for some installations)
173
+ var jiraBrowseMatch = urlObj.pathname.match(/\/jira\/browse\/([A-Z]+-\d+)/);
174
+ if (jiraBrowseMatch && jiraBrowseMatch[1]) {
175
+ return jiraBrowseMatch[1];
176
+ }
177
+
178
+ // Following this pattern for jira URL -> Query parameter ?selectedIssue={issueKey}
179
+ var selectedIssue = urlObj.searchParams.get('selectedIssue');
180
+ if (selectedIssue && /^[A-Z]+-\d+$/.test(selectedIssue)) {
181
+ return selectedIssue;
182
+ }
183
+
184
+ // Following this pattern for jira URL -> Query parameter ?issueKey={issueKey}
185
+ var issueKeyParam = urlObj.searchParams.get('issueKey');
186
+ if (issueKeyParam && /^[A-Z]+-\d+$/.test(issueKeyParam)) {
187
+ return issueKeyParam;
188
+ }
189
+ } catch (_unused3) {
190
+ return undefined;
191
+ }
192
+ return undefined;
193
+ };
194
+ var getProductFromWindowURL = function getProductFromWindowURL() {
195
+ try {
196
+ var currentUrl = window.location.href;
197
+ var urlObj = new URL(currentUrl);
198
+ var hostname = urlObj.hostname.toLowerCase();
199
+ var pathname = urlObj.pathname.toLowerCase();
200
+
201
+ // Check for Confluence patterns
202
+ if (hostname.includes('confluence') || pathname.includes('/wiki/') || pathname.includes('/display/') || pathname.includes('/spaces/')) {
203
+ return 'confluence';
204
+ }
205
+
206
+ // Check for Jira patterns
207
+ if (hostname.includes('jira') || pathname.includes('/browse/') || pathname.includes('/projects/') || pathname.includes('/secure/')) {
208
+ return 'jira';
209
+ }
210
+ } catch (_unused4) {
211
+ return undefined;
212
+ }
213
+ return undefined;
92
214
  };
@@ -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.2"
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, getFirstPartyIdentifier, 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,13 @@ 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
+ var firstPartyIdentifier = getFirstPartyIdentifier();
68
69
  var isFlexibleUi = useMemo(function () {
69
70
  return isFlexibleUiCard(children, ui);
70
71
  }, [children, ui]);
@@ -84,7 +85,6 @@ function Component(_ref) {
84
85
  });
85
86
  if (fg('platform_smartlink_3pclick_analytics')) {
86
87
  if (thirdPartyARI && thirdPartyARI.startsWith(thirdPartyARIPrefix)) {
87
- var sourceURL = window.location.href;
88
88
  var clickURL = getClickUrl(url, state.details);
89
89
  if (clickURL === url) {
90
90
  // For questions or concerns about this event,
@@ -95,10 +95,10 @@ function Component(_ref) {
95
95
  actionSubjectId: 'smartlinkClickAnalyticsWorkflows',
96
96
  eventType: 'ui',
97
97
  attributes: {
98
- eventName: 'smartLinkClickAnalyticsThirdPartyWorkflows'
98
+ eventName: 'smartLinkClickAnalyticsThirdPartyWorkflows',
99
+ firstPartyIdentifier: firstPartyIdentifier
99
100
  },
100
101
  nonPrivacySafeAttributes: {
101
- sourceURL: sourceURL,
102
102
  thirdPartyARI: thirdPartyARI
103
103
  }
104
104
  });
@@ -145,7 +145,7 @@ function Component(_ref) {
145
145
  }
146
146
  fireLinkClickedEvent(createAnalyticsEvent)(event);
147
147
  }
148
- }, [fireEvent, id, isFlexibleUi, appearance, definitionId, onClick, url, state.details, ari, name, isPreviewPanelAvailable, openPreviewPanel, createAnalyticsEvent, thirdPartyARI]);
148
+ }, [fireEvent, id, isFlexibleUi, appearance, definitionId, onClick, url, state.details, ari, name, isPreviewPanelAvailable, openPreviewPanel, createAnalyticsEvent, thirdPartyARI, firstPartyIdentifier]);
149
149
  var handleAuthorize = useCallback(function () {
150
150
  return actions.authorize(appearance);
151
151
  }, [actions, appearance]);
@@ -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.2",
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::2d9f03b82528803f03b90d6cae5d690d>>
7
7
  * @codegenCommand yarn workspace @atlassian/analytics-tooling run analytics:codegen smart-card
8
8
  */
9
9
  export type PackageMetaDataContextType = {
@@ -231,8 +231,9 @@ export type SmartLinkRenderFailedAttributesType = {
231
231
  id: string | null;
232
232
  };
233
233
  export type SmartLinkClickedSmartlinkClickAnalyticsWorkflowsAttributesType = {
234
- sourceURL: string;
235
234
  thirdPartyARI: string;
235
+ eventName: string;
236
+ firstPartyIdentifier: string | null;
236
237
  };
237
238
  export type AnalyticsEventAttributes = {
238
239
  /**
@@ -9,6 +9,7 @@ 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 getFirstPartyIdentifier: () => string | undefined;
12
13
  export declare const getObjectName: (details?: JsonLd.Response) => string | undefined;
13
14
  export declare const getObjectIconUrl: (details?: JsonLd.Response) => string | undefined;
14
15
  export declare const getResourceType: (details?: JsonLd.Response) => string | undefined;
@@ -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::2d9f03b82528803f03b90d6cae5d690d>>
7
7
  * @codegenCommand yarn workspace @atlassian/analytics-tooling run analytics:codegen smart-card
8
8
  */
9
9
  export type PackageMetaDataContextType = {
@@ -231,8 +231,9 @@ export type SmartLinkRenderFailedAttributesType = {
231
231
  id: string | null;
232
232
  };
233
233
  export type SmartLinkClickedSmartlinkClickAnalyticsWorkflowsAttributesType = {
234
- sourceURL: string;
235
234
  thirdPartyARI: string;
235
+ eventName: string;
236
+ firstPartyIdentifier: string | null;
236
237
  };
237
238
  export type AnalyticsEventAttributes = {
238
239
  /**
@@ -9,6 +9,7 @@ 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 getFirstPartyIdentifier: () => string | undefined;
12
13
  export declare const getObjectName: (details?: JsonLd.Response) => string | undefined;
13
14
  export declare const getObjectIconUrl: (details?: JsonLd.Response) => string | undefined;
14
15
  export declare const getResourceType: (details?: JsonLd.Response) => string | undefined;
@@ -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.3",
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
  ]