@atlaskit/smart-card 26.2.1 → 26.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (93) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/dist/cjs/extractors/block/index.js +5 -4
  3. package/dist/cjs/extractors/common/actions/extractPreviewAction.js +4 -2
  4. package/dist/cjs/messages.js +6 -0
  5. package/dist/cjs/state/actions/index.js +27 -11
  6. package/dist/cjs/state/hooks/use-invoke/index.js +8 -28
  7. package/dist/cjs/state/hooks/use-resolve/index.js +28 -12
  8. package/dist/cjs/utils/analytics/SmartLinkAnalyticsContext.js +47 -0
  9. package/dist/cjs/utils/analytics/analytics.js +13 -1
  10. package/dist/cjs/version.json +1 -1
  11. package/dist/cjs/view/BlockCard/actions/PreviewAction.js +4 -2
  12. package/dist/cjs/view/BlockCard/index.js +3 -1
  13. package/dist/cjs/view/CardWithUrl/component.js +13 -3
  14. package/dist/cjs/view/FlexibleCard/components/actions/action/preview-action/index.js +7 -1
  15. package/dist/cjs/view/FlexibleCard/components/actions/utils.js +1 -1
  16. package/dist/cjs/view/FlexibleCard/components/common/lozenge-action/index.js +38 -30
  17. package/dist/cjs/view/FlexibleCard/components/common/lozenge-action/lozenge-action-analytics.js +31 -0
  18. package/dist/cjs/view/FlexibleCard/components/common/lozenge-action/lozenge-action-error/styled.js +1 -1
  19. package/dist/cjs/view/HoverCard/components/HoverCardComponent.js +21 -2
  20. package/dist/cjs/view/HoverCard/components/views/resolved/index.js +26 -3
  21. package/dist/es2019/extractors/block/index.js +5 -4
  22. package/dist/es2019/extractors/common/actions/extractPreviewAction.js +4 -2
  23. package/dist/es2019/messages.js +6 -0
  24. package/dist/es2019/state/actions/index.js +32 -12
  25. package/dist/es2019/state/hooks/use-invoke/index.js +4 -23
  26. package/dist/es2019/state/hooks/use-resolve/index.js +28 -12
  27. package/dist/es2019/utils/analytics/SmartLinkAnalyticsContext.js +35 -0
  28. package/dist/es2019/utils/analytics/analytics.js +10 -0
  29. package/dist/es2019/version.json +1 -1
  30. package/dist/es2019/view/BlockCard/actions/PreviewAction.js +17 -13
  31. package/dist/es2019/view/BlockCard/index.js +3 -1
  32. package/dist/es2019/view/CardWithUrl/component.js +9 -2
  33. package/dist/es2019/view/FlexibleCard/components/actions/action/preview-action/index.js +7 -1
  34. package/dist/es2019/view/FlexibleCard/components/actions/utils.js +1 -1
  35. package/dist/es2019/view/FlexibleCard/components/common/lozenge-action/index.js +14 -6
  36. package/dist/es2019/view/FlexibleCard/components/common/lozenge-action/lozenge-action-analytics.js +21 -0
  37. package/dist/es2019/view/FlexibleCard/components/common/lozenge-action/lozenge-action-error/styled.js +1 -0
  38. package/dist/es2019/view/HoverCard/components/HoverCardComponent.js +21 -2
  39. package/dist/es2019/view/HoverCard/components/views/resolved/index.js +36 -11
  40. package/dist/esm/extractors/block/index.js +5 -4
  41. package/dist/esm/extractors/common/actions/extractPreviewAction.js +4 -2
  42. package/dist/esm/messages.js +6 -0
  43. package/dist/esm/state/actions/index.js +27 -11
  44. package/dist/esm/state/hooks/use-invoke/index.js +8 -28
  45. package/dist/esm/state/hooks/use-resolve/index.js +28 -12
  46. package/dist/esm/utils/analytics/SmartLinkAnalyticsContext.js +36 -0
  47. package/dist/esm/utils/analytics/analytics.js +10 -0
  48. package/dist/esm/version.json +1 -1
  49. package/dist/esm/view/BlockCard/actions/PreviewAction.js +4 -2
  50. package/dist/esm/view/BlockCard/index.js +3 -1
  51. package/dist/esm/view/CardWithUrl/component.js +11 -2
  52. package/dist/esm/view/FlexibleCard/components/actions/action/preview-action/index.js +7 -1
  53. package/dist/esm/view/FlexibleCard/components/actions/utils.js +1 -1
  54. package/dist/esm/view/FlexibleCard/components/common/lozenge-action/index.js +38 -30
  55. package/dist/esm/view/FlexibleCard/components/common/lozenge-action/lozenge-action-analytics.js +21 -0
  56. package/dist/esm/view/FlexibleCard/components/common/lozenge-action/lozenge-action-error/styled.js +1 -1
  57. package/dist/esm/view/HoverCard/components/HoverCardComponent.js +21 -2
  58. package/dist/esm/view/HoverCard/components/views/resolved/index.js +26 -3
  59. package/dist/types/extractors/block/index.d.ts +2 -2
  60. package/dist/types/extractors/block/types.d.ts +1 -0
  61. package/dist/types/extractors/common/actions/extractPreviewAction.d.ts +1 -1
  62. package/dist/types/messages.d.ts +1 -1
  63. package/dist/types/state/analytics/useSmartLinkAnalytics.d.ts +6 -3
  64. package/dist/types/state/flexible-ui-context/index.d.ts +10 -6
  65. package/dist/types/state/hooks/use-invoke/index.d.ts +1 -7
  66. package/dist/types/state/hooks/useSmartLink.d.ts +5 -3
  67. package/dist/types/utils/analytics/SmartLinkAnalyticsContext.d.ts +9 -0
  68. package/dist/types/utils/analytics/analytics.d.ts +11 -3
  69. package/dist/types/utils/mocks.d.ts +5 -3
  70. package/dist/types/view/BlockCard/actions/PreviewAction.d.ts +2 -1
  71. package/dist/types/view/BlockCard/views/ResolvedView.d.ts +2 -0
  72. package/dist/types/view/CardWithUrl/component.d.ts +1 -1
  73. package/dist/types/view/FlexibleCard/components/common/lozenge-action/lozenge-action-analytics.d.ts +21 -0
  74. package/dist/types/view/HoverCard/components/views/resolved/index.d.ts +1 -1
  75. package/dist/types-ts4.5/extractors/block/index.d.ts +2 -2
  76. package/dist/types-ts4.5/extractors/block/types.d.ts +1 -0
  77. package/dist/types-ts4.5/extractors/common/actions/extractPreviewAction.d.ts +1 -1
  78. package/dist/types-ts4.5/messages.d.ts +1 -1
  79. package/dist/types-ts4.5/state/analytics/useSmartLinkAnalytics.d.ts +6 -3
  80. package/dist/types-ts4.5/state/flexible-ui-context/index.d.ts +10 -6
  81. package/dist/types-ts4.5/state/hooks/use-invoke/index.d.ts +1 -7
  82. package/dist/types-ts4.5/state/hooks/useSmartLink.d.ts +5 -3
  83. package/dist/types-ts4.5/utils/analytics/SmartLinkAnalyticsContext.d.ts +9 -0
  84. package/dist/types-ts4.5/utils/analytics/analytics.d.ts +11 -3
  85. package/dist/types-ts4.5/utils/mocks.d.ts +5 -3
  86. package/dist/types-ts4.5/view/BlockCard/actions/PreviewAction.d.ts +2 -1
  87. package/dist/types-ts4.5/view/BlockCard/views/ResolvedView.d.ts +2 -0
  88. package/dist/types-ts4.5/view/CardWithUrl/component.d.ts +1 -1
  89. package/dist/types-ts4.5/view/FlexibleCard/components/common/lozenge-action/lozenge-action-analytics.d.ts +21 -0
  90. package/dist/types-ts4.5/view/HoverCard/components/views/resolved/index.d.ts +1 -1
  91. package/package.json +11 -3
  92. package/report.api.md +21 -3
  93. package/tmp/api-report-tmp.d.ts +21 -3
@@ -49,17 +49,21 @@ However src, details, icon, title, and providerName are STRONGLY encouraged
49
49
 
50
50
  export default (({
51
51
  details,
52
+ enableImprovedPreviewAction,
52
53
  ...rest
53
- }) => ({
54
- id: 'preview-content',
55
- text: /*#__PURE__*/React.createElement(FormattedMessage, messages.preview),
56
- promise: props => previewFunction({
57
- popupMountPointId: 'twp-editor-preview-iframe',
58
- providerName: 'Preview',
59
- showModal: true,
60
- iframeName: 'twp-editor-preview-iframe',
61
- onClose: () => {},
62
- ...props,
63
- ...rest
64
- })
65
- }));
54
+ }) => {
55
+ const previewText = enableImprovedPreviewAction ? messages.preview_improved : messages.preview;
56
+ return {
57
+ id: 'preview-content',
58
+ text: /*#__PURE__*/React.createElement(FormattedMessage, previewText),
59
+ promise: props => previewFunction({
60
+ popupMountPointId: 'twp-editor-preview-iframe',
61
+ providerName: 'Preview',
62
+ showModal: true,
63
+ iframeName: 'twp-editor-preview-iframe',
64
+ onClose: () => {},
65
+ ...props,
66
+ ...rest
67
+ })
68
+ };
69
+ });
@@ -22,6 +22,7 @@ import FlexibleForbiddenView from './views/flexible/FlexibleForbiddenView';
22
22
  import { tokens } from '../../utils/token';
23
23
  import { css, jsx } from '@emotion/react';
24
24
  import { handleClickCommon } from './utils/handlers';
25
+ import { useFeatureFlag } from '@atlaskit/link-provider';
25
26
  export { default as PreviewAction } from './actions/PreviewAction';
26
27
  export { ForbiddenAction, AuthorizeAction, BlockCardResolvedView, BlockCardResolvingView, BlockCardUnauthorisedView, BlockCardForbiddenView, BlockCardErroredView, BlockCardNotFoundView };
27
28
  const flexibleBlockCardElevationStyle = css`
@@ -63,6 +64,7 @@ export const BlockCard = ({
63
64
  handleInvoke,
64
65
  extensionKey
65
66
  };
67
+ const enableImprovedPreviewAction = Boolean(useFeatureFlag('enableImprovedPreviewAction'));
66
68
  if (enableFlexibleBlockCard) {
67
69
  const ui = {
68
70
  hideElevation: true
@@ -143,7 +145,7 @@ export const BlockCard = ({
143
145
  isSelected: isSelected
144
146
  });
145
147
  case 'resolved':
146
- const resolvedViewProps = extractBlockProps(data, meta, extractorOpts, renderers, platform);
148
+ const resolvedViewProps = extractBlockProps(data, meta, extractorOpts, renderers, platform, enableImprovedPreviewAction);
147
149
  if (onResolve) {
148
150
  onResolve({
149
151
  title: resolvedViewProps.title,
@@ -1,6 +1,7 @@
1
1
  import React, { useEffect, useCallback, useMemo } from 'react';
2
2
  import { useAnalyticsEvents } from '@atlaskit/analytics-next';
3
3
  import { useFeatureFlag } from '@atlaskit/link-provider';
4
+ import { getBooleanFF } from '@atlaskit/platform-feature-flags';
4
5
  import { isSpecialEvent } from '../../utils';
5
6
  import * as measure from '../../utils/performance';
6
7
  import { getDefinitionId, getServices, isFinalState, getClickUrl, getResourceType, getExtensionKey, getSubproduct, getProduct } from '../../state/helpers';
@@ -12,7 +13,8 @@ import { isFlexibleUiCard } from '../../utils/flexible';
12
13
  import FlexibleCard from '../FlexibleCard';
13
14
  import { CardDisplay } from '../../constants';
14
15
  import { fireLinkClickedEvent } from '../../utils/analytics/click';
15
- export function CardWithUrlContent({
16
+ import { SmartLinkAnalyticsContext } from '../../utils/analytics/SmartLinkAnalyticsContext';
17
+ function Component({
16
18
  id,
17
19
  url,
18
20
  isSelected,
@@ -255,4 +257,9 @@ export function CardWithUrlContent({
255
257
  onIframeFocus: onIframeFocus
256
258
  });
257
259
  }
258
- }
260
+ }
261
+ export const CardWithUrlContent = props => getBooleanFF('platform.linking-platform.smart-card.enable-analytics-context') ? /*#__PURE__*/React.createElement(SmartLinkAnalyticsContext, {
262
+ url: props.url,
263
+ appearance: props.appearance,
264
+ id: props.id
265
+ }, /*#__PURE__*/React.createElement(Component, props)) : /*#__PURE__*/React.createElement(Component, props);
@@ -4,6 +4,9 @@ import Action from '../index';
4
4
  import { useFlexibleUiAnalyticsContext } from '../../../../../../state/flexible-ui-context';
5
5
  import { useSmartLinkAnalytics } from '../../../../../../state';
6
6
  import { openPreviewModal } from '../../../../../EmbedModal/utils';
7
+ import { FormattedMessage } from 'react-intl-next';
8
+ import { messages } from '../../../../../../messages';
9
+ import { useFeatureFlag } from '@atlaskit/link-provider';
7
10
  const PreviewAction = props => {
8
11
  const {
9
12
  appearance,
@@ -20,6 +23,8 @@ const PreviewAction = props => {
20
23
  } = props;
21
24
  const defaultAnalytics = useSmartLinkAnalytics(url, () => {});
22
25
  const analytics = useFlexibleUiAnalyticsContext() || defaultAnalytics;
26
+ const enableImprovedPreviewAction = Boolean(useFeatureFlag('enableImprovedPreviewAction'));
27
+ const previewText = enableImprovedPreviewAction ? messages.preview_improved : messages.preview;
23
28
  if (src && url) {
24
29
  const embedModal = () => openPreviewModal({
25
30
  title,
@@ -37,7 +42,8 @@ const PreviewAction = props => {
37
42
  if (onClick) {
38
43
  onClick();
39
44
  }
40
- }
45
+ },
46
+ content: /*#__PURE__*/React.createElement(FormattedMessage, previewText)
41
47
  };
42
48
  return /*#__PURE__*/React.createElement(Action, _extends({}, action, {
43
49
  appearance: appearance,
@@ -46,7 +46,7 @@ const actionMappings = {
46
46
  testId: 'smart-action-preview-action',
47
47
  content: /*#__PURE__*/React.createElement(FormattedMessage, messages.preview),
48
48
  icon: /*#__PURE__*/React.createElement(VidFullScreenOnIcon, {
49
- label: "Full screen view"
49
+ label: "Open preview"
50
50
  }),
51
51
  tooltipMessage: /*#__PURE__*/React.createElement(FormattedMessage, messages.preview)
52
52
  }
@@ -14,6 +14,8 @@ import createStatusUpdateRequest from '../../../../../utils/actions/create-statu
14
14
  import useResolve from '../../../../../state/hooks/use-resolve';
15
15
  import { LozengeActionErrorMessages } from './lozenge-action-error/types';
16
16
  import { useFlexibleUiAnalyticsContext } from '../../../../../state/flexible-ui-context';
17
+ import { TrackQuickActionType } from '../../../../../utils/analytics/analytics';
18
+ import { permissionLoadErrorAnalyticsPayload, unknownLoadErrorAnalyticsPayload, unknownUpdateErrorAnalyticsPayload, validationUpdateErrorAnalyticsPayload } from './lozenge-action-analytics';
17
19
  const validateItems = (items = [], text) => {
18
20
  return items.filter(item => item.text !== text);
19
21
  };
@@ -38,11 +40,7 @@ const LozengeAction = ({
38
40
  const reload = useResolve();
39
41
  //TODO EDM-6583 Replace usage of useFlexibleUiAnalyticsContext with linking platform analytics context from find team.
40
42
  const analytics = useFlexibleUiAnalyticsContext();
41
- const invoke = useInvoke({
42
- started: analytics === null || analytics === void 0 ? void 0 : analytics.track.smartLinkQuickActionStarted,
43
- success: analytics === null || analytics === void 0 ? void 0 : analytics.track.smartLinkQuickActionSuccess,
44
- failed: analytics === null || analytics === void 0 ? void 0 : analytics.track.smartLinkQuickActionFailed
45
- });
43
+ const invoke = useInvoke();
46
44
  useEffect(() => {
47
45
  setSelected({
48
46
  text,
@@ -58,6 +56,9 @@ const LozengeAction = ({
58
56
  setIsOpen(args.isOpen);
59
57
  if (args.isOpen) {
60
58
  analytics === null || analytics === void 0 ? void 0 : analytics.ui.smartLinkLozengeActionClickedEvent();
59
+ analytics === null || analytics === void 0 ? void 0 : analytics.track.smartLinkQuickActionStarted({
60
+ smartLinkActionType: TrackQuickActionType.StatusUpdate
61
+ });
61
62
  if (!isLoaded && action !== null && action !== void 0 && action.read) {
62
63
  try {
63
64
  setIsLoading(true);
@@ -66,12 +67,14 @@ const LozengeAction = ({
66
67
  setItems(validItems);
67
68
  setIsLoaded(true);
68
69
  if ((validItems === null || validItems === void 0 ? void 0 : validItems.length) === 0) {
70
+ analytics === null || analytics === void 0 ? void 0 : analytics.track.smartLinkQuickActionFailed(permissionLoadErrorAnalyticsPayload);
69
71
  setErrorMessage(LozengeActionErrorMessages.noData);
70
72
  setIsLoaded(false);
71
73
  }
72
74
  } catch (err) {
73
75
  setErrorMessage(LozengeActionErrorMessages.unknown);
74
76
  setIsLoaded(false);
77
+ analytics === null || analytics === void 0 ? void 0 : analytics.track.smartLinkQuickActionFailed(unknownLoadErrorAnalyticsPayload);
75
78
  } finally {
76
79
  setIsLoading(false);
77
80
  }
@@ -102,6 +105,9 @@ const LozengeAction = ({
102
105
  setIsLoaded(false);
103
106
  setIsOpen(false);
104
107
  setItems([]);
108
+ analytics === null || analytics === void 0 ? void 0 : analytics.track.smartLinkQuickActionSuccess({
109
+ smartLinkActionType: TrackQuickActionType.StatusUpdate
110
+ });
105
111
  if (url) {
106
112
  await reload(url, true, undefined, linkId);
107
113
  }
@@ -110,11 +116,13 @@ const LozengeAction = ({
110
116
  setIsLoading(false);
111
117
  if (isInvokeCustomError(err)) {
112
118
  setErrorMessage(err.message);
119
+ analytics === null || analytics === void 0 ? void 0 : analytics.track.smartLinkQuickActionFailed(validationUpdateErrorAnalyticsPayload);
113
120
  } else {
114
121
  setErrorMessage(LozengeActionErrorMessages.updateFailed);
122
+ analytics === null || analytics === void 0 ? void 0 : analytics.track.smartLinkQuickActionFailed(unknownUpdateErrorAnalyticsPayload);
115
123
  }
116
124
  }
117
- }, [action === null || action === void 0 ? void 0 : action.update, analytics === null || analytics === void 0 ? void 0 : analytics.ui, invoke, linkId, reload, url]);
125
+ }, [action === null || action === void 0 ? void 0 : action.update, analytics, invoke, linkId, reload, url]);
118
126
  const dropdownItemGroup = useMemo(() => {
119
127
  if (errorMessage) {
120
128
  return jsx(LozengeActionError, {
@@ -0,0 +1,21 @@
1
+ import { TrackQuickActionFailureReason, TrackQuickActionType } from '../../../../../utils/analytics/analytics';
2
+ export const unknownLoadErrorAnalyticsPayload = {
3
+ smartLinkActionType: TrackQuickActionType.StatusUpdate,
4
+ reason: TrackQuickActionFailureReason.UnknownError,
5
+ step: 'load'
6
+ };
7
+ export const permissionLoadErrorAnalyticsPayload = {
8
+ smartLinkActionType: TrackQuickActionType.StatusUpdate,
9
+ reason: TrackQuickActionFailureReason.PermissionError,
10
+ step: 'load'
11
+ };
12
+ export const unknownUpdateErrorAnalyticsPayload = {
13
+ smartLinkActionType: TrackQuickActionType.StatusUpdate,
14
+ reason: TrackQuickActionFailureReason.UnknownError,
15
+ step: 'update'
16
+ };
17
+ export const validationUpdateErrorAnalyticsPayload = {
18
+ smartLinkActionType: TrackQuickActionType.StatusUpdate,
19
+ reason: TrackQuickActionFailureReason.ValidationError,
20
+ step: 'update'
21
+ };
@@ -36,6 +36,7 @@ export const contentStyles = css`
36
36
  export const linkStyles = css`
37
37
  ${sharedBlockStyles};
38
38
 
39
+ cursor: pointer;
39
40
  font-size: 0.875rem;
40
41
  margin-top: 10px;
41
42
  margin-left: ${"var(--ds-space-400, 32px)"};
@@ -1,5 +1,6 @@
1
1
  import _extends from "@babel/runtime/helpers/extends";
2
2
  /** @jsx jsx */
3
+ import { getBooleanFF } from '@atlaskit/platform-feature-flags';
3
4
  import Popup from '@atlaskit/popup';
4
5
  import { jsx } from '@emotion/react';
5
6
  import React, { useCallback, useMemo, useRef } from 'react';
@@ -9,9 +10,11 @@ import { useSmartCardState as useLinkState } from '../../../state/store';
9
10
  import HoverCardContent from '../components/HoverCardContent';
10
11
  import { CARD_GAP_PX, HOVER_CARD_Z_INDEX } from '../styled';
11
12
  import { CardDisplay } from '../../../constants';
13
+ import { SmartLinkAnalyticsContext } from '../../../utils/analytics/SmartLinkAnalyticsContext';
12
14
  export const HoverCardComponent = ({
13
15
  children,
14
16
  url,
17
+ id,
15
18
  analyticsHandler,
16
19
  analytics,
17
20
  canOpen = true,
@@ -112,7 +115,23 @@ export const HoverCardComponent = ({
112
115
  }, [closeOnChildClick, hideCard]);
113
116
  const content = useCallback(({
114
117
  update
115
- }) => jsx(HoverCardContent, {
118
+ }) => getBooleanFF('platform.linking-platform.smart-card.enable-analytics-context') ? jsx(SmartLinkAnalyticsContext, {
119
+ url: url,
120
+ appearance: CardDisplay.HoverCardPreview,
121
+ id: id
122
+ }, jsx(HoverCardContent, {
123
+ onMouseEnter: initShowCard,
124
+ onMouseLeave: initHideCard,
125
+ analytics: analytics,
126
+ cardActions: filteredActions,
127
+ cardState: linkState,
128
+ onActionClick: onActionClick,
129
+ onResolve: update,
130
+ renderers: renderers,
131
+ showServerActions: showServerActions,
132
+ url: url,
133
+ id: id
134
+ })) : jsx(HoverCardContent, {
116
135
  onMouseEnter: initShowCard,
117
136
  onMouseLeave: initHideCard,
118
137
  analytics: analytics,
@@ -123,7 +142,7 @@ export const HoverCardComponent = ({
123
142
  renderers: renderers,
124
143
  showServerActions: showServerActions,
125
144
  url: url
126
- }), [analytics, initHideCard, initShowCard, filteredActions, linkState, onActionClick, renderers, showServerActions, url]);
145
+ }), [analytics, initHideCard, initShowCard, filteredActions, linkState, onActionClick, renderers, showServerActions, url, id]);
127
146
  const trigger = useCallback(triggerProps => jsx("span", {
128
147
  ref: parentSpan
129
148
  }, jsx("span", _extends({}, triggerProps, {
@@ -8,17 +8,41 @@ import FlexibleCard from '../../../../FlexibleCard';
8
8
  import { getSimulatedMetadata, toActionableMetadata } from '../../../utils';
9
9
  import SnippetOrPreview from '../../SnippetOrPreview';
10
10
  import { extractMetadata } from '../../../../../extractors/hover/extractMetadata';
11
- export const toFooterActions = (cardActions, onActionClick) => cardActions.map(action => ({
12
- content: action.text,
13
- name: ActionName.CustomAction,
14
- onClick: () => {
15
- if (onActionClick) {
16
- onActionClick(action.id);
11
+ import { messages } from '../../../../../messages';
12
+ import { FormattedMessage } from 'react-intl-next';
13
+ export const toFooterActions = (cardActions, onActionClick, enableImprovedPreviewAction) => {
14
+ const appearance = enableImprovedPreviewAction ? {
15
+ appearance: 'primary'
16
+ } : undefined;
17
+ const previewText = enableImprovedPreviewAction ? messages.preview_improved : messages.preview;
18
+ return cardActions.map(action => {
19
+ if (action.id === 'preview-content') {
20
+ return {
21
+ content: /*#__PURE__*/React.createElement(FormattedMessage, previewText),
22
+ name: ActionName.CustomAction,
23
+ onClick: () => {
24
+ if (onActionClick) {
25
+ onActionClick(action.id);
26
+ }
27
+ return action.invoke();
28
+ },
29
+ testId: action.id,
30
+ ...appearance
31
+ };
17
32
  }
18
- return action.invoke();
19
- },
20
- testId: action.id
21
- }));
33
+ return {
34
+ content: action.text,
35
+ name: ActionName.CustomAction,
36
+ onClick: () => {
37
+ if (onActionClick) {
38
+ onActionClick(action.id);
39
+ }
40
+ return action.invoke();
41
+ },
42
+ testId: action.id
43
+ };
44
+ });
45
+ };
22
46
  const HoverCardResolvedView = ({
23
47
  flexibleCardProps,
24
48
  titleBlockProps,
@@ -32,6 +56,7 @@ const HoverCardResolvedView = ({
32
56
  }) => {
33
57
  var _cardState$details;
34
58
  const showActionableElement = useFeatureFlag('enableActionableElement');
59
+ const enableImprovedPreviewAction = useFeatureFlag('enableImprovedPreviewAction');
35
60
  useEffect(() => {
36
61
  // Since this hover view is only rendered on resolved status,
37
62
  // there is no need to check for statuses.
@@ -40,7 +65,7 @@ const HoverCardResolvedView = ({
40
65
  status: cardState.status
41
66
  });
42
67
  }, [analytics.ui, cardState.status]);
43
- const footerActions = useMemo(() => toFooterActions(cardActions, onActionClick), [cardActions, onActionClick]);
68
+ const footerActions = useMemo(() => toFooterActions(cardActions, onActionClick, Boolean(enableImprovedPreviewAction)), [cardActions, onActionClick, enableImprovedPreviewAction]);
44
69
  const data = (_cardState$details = cardState.details) === null || _cardState$details === void 0 ? void 0 : _cardState$details.data;
45
70
  const {
46
71
  primary,
@@ -28,7 +28,7 @@ var extractBlockDetails = function extractBlockDetails(jsonLd) {
28
28
  return !!detail;
29
29
  });
30
30
  };
31
- export var extractBlockActions = function extractBlockActions(props, jsonLd, opts, platform, meta) {
31
+ export var extractBlockActions = function extractBlockActions(props, jsonLd, opts, platform, meta, enableImprovedPreviewAction) {
32
32
  if (opts) {
33
33
  var handleInvoke = opts.handleInvoke;
34
34
  var actions = extractActions(jsonLd, handleInvoke);
@@ -36,7 +36,8 @@ export var extractBlockActions = function extractBlockActions(props, jsonLd, opt
36
36
  viewProps: props,
37
37
  jsonLd: jsonLd,
38
38
  platform: platform,
39
- meta: meta
39
+ meta: meta,
40
+ enableImprovedPreviewAction: enableImprovedPreviewAction
40
41
  }));
41
42
 
42
43
  // The previewAction should always be the last action
@@ -67,7 +68,7 @@ export var extractBlockUsers = function extractBlockUsers(jsonLd) {
67
68
  return updatedByMembers || createdByMembers;
68
69
  }
69
70
  };
70
- export var extractBlockProps = function extractBlockProps(jsonLd, meta, opts, renderers, platform) {
71
+ export var extractBlockProps = function extractBlockProps(jsonLd, meta, opts, renderers, platform, enableImprovedPreviewAction) {
71
72
  var props = {
72
73
  link: extractLink(jsonLd),
73
74
  title: extractTitle(jsonLd),
@@ -83,6 +84,6 @@ export var extractBlockProps = function extractBlockProps(jsonLd, meta, opts, re
83
84
  isTrusted: extractIsTrusted(meta)
84
85
  };
85
86
  return _objectSpread(_objectSpread({}, props), {}, {
86
- actions: extractBlockActions(props, jsonLd, opts, platform, meta)
87
+ actions: extractBlockActions(props, jsonLd, opts, platform, meta, enableImprovedPreviewAction)
87
88
  });
88
89
  };
@@ -57,7 +57,8 @@ export var extractPreviewAction = function extractPreviewAction(_ref) {
57
57
  _ref$source = _ref.source,
58
58
  source = _ref$source === void 0 ? 'block' : _ref$source,
59
59
  analytics = _ref.analytics,
60
- meta = _ref.meta;
60
+ meta = _ref.meta,
61
+ enableImprovedPreviewAction = _ref.enableImprovedPreviewAction;
61
62
  // Extract metadata from view props & raw JSON-LD.
62
63
  var metadataFromJsonLd = getMetadataFromJsonLd(jsonLd, platform);
63
64
  var metadataFromViewProps = getMetadataFromResolvedProps(viewProps);
@@ -76,7 +77,8 @@ export var extractPreviewAction = function extractPreviewAction(_ref) {
76
77
  onViewActionClick: function onViewActionClick() {
77
78
  handleInvoke(getInvokeOpts(key, 'ViewAction'));
78
79
  },
79
- isSupportTheming: extractIsSupportTheming(meta)
80
+ isSupportTheming: extractIsSupportTheming(meta),
81
+ enableImprovedPreviewAction: enableImprovedPreviewAction
80
82
  }));
81
83
  // Setup props to go through proper Redux 'invocation' flow
82
84
  // for analytics, further state management if required in future.
@@ -215,6 +215,12 @@ export var messages = defineMessages({
215
215
  defaultMessage: 'Owned by {context}',
216
216
  description: 'Indicates the person or entity that owns or maintains the resource.'
217
217
  },
218
+ // Move this to preview once FF has been merged
219
+ preview_improved: {
220
+ id: 'fabric.linking.preview_improved',
221
+ defaultMessage: 'Open preview',
222
+ description: 'Click to view a richer view of your content, without needing to navigate to it.'
223
+ },
218
224
  preview: {
219
225
  id: 'fabric.linking.preview',
220
226
  defaultMessage: 'Full screen view',
@@ -15,13 +15,20 @@ export var useSmartCardActions = function useSmartCardActions(id, url, analytics
15
15
  connections = _useSmartLinkContext.connections;
16
16
  var getState = store.getState,
17
17
  dispatch = store.dispatch;
18
- var _ref = getState()[url] || {
19
- status: SmartLinkStatus.Pending,
20
- details: undefined
21
- },
22
- details = _ref.details,
23
- status = _ref.status,
24
- metadataStatus = _ref.metadataStatus;
18
+ var getSmartLinkState = useCallback(function () {
19
+ var _getState$url;
20
+ var _ref = (_getState$url = getState()[url]) !== null && _getState$url !== void 0 ? _getState$url : {
21
+ status: SmartLinkStatus.Pending
22
+ },
23
+ details = _ref.details,
24
+ status = _ref.status,
25
+ metadataStatus = _ref.metadataStatus;
26
+ return {
27
+ details: details,
28
+ status: status,
29
+ metadataStatus: metadataStatus
30
+ };
31
+ }, [getState, url]);
25
32
  var setMetadataStatus = useCallback(function (metadataStatus) {
26
33
  dispatch(cardAction(ACTION_UPDATE_METADATA_STATUS, {
27
34
  url: url
@@ -46,6 +53,8 @@ export var useSmartCardActions = function useSmartCardActions(id, url, analytics
46
53
  }, _callee);
47
54
  })), [id, resolveUrl, url]);
48
55
  var register = useCallback(function () {
56
+ var _getSmartLinkState = getSmartLinkState(),
57
+ details = _getSmartLinkState.details;
49
58
  if (!details) {
50
59
  dispatch(cardAction(ACTION_RESOLVING, {
51
60
  url: url
@@ -53,8 +62,10 @@ export var useSmartCardActions = function useSmartCardActions(id, url, analytics
53
62
  setMetadataStatus('pending');
54
63
  }
55
64
  return resolve();
56
- }, [details, resolve, dispatch, url, setMetadataStatus]);
65
+ }, [getSmartLinkState, resolve, dispatch, url, setMetadataStatus]);
57
66
  var reload = useCallback(function () {
67
+ var _getSmartLinkState2 = getSmartLinkState(),
68
+ details = _getSmartLinkState2.details;
58
69
  var definitionId = getDefinitionId(details);
59
70
  if (definitionId) {
60
71
  getByDefinitionId(definitionId, getState()).map(function (url) {
@@ -63,15 +74,20 @@ export var useSmartCardActions = function useSmartCardActions(id, url, analytics
63
74
  } else {
64
75
  resolve(url, true);
65
76
  }
66
- }, [details, url, getState, resolve]);
77
+ }, [getSmartLinkState, url, getState, resolve]);
67
78
  var loadMetadata = useCallback(function () {
79
+ var _getSmartLinkState3 = getSmartLinkState(),
80
+ metadataStatus = _getSmartLinkState3.metadataStatus;
68
81
  //metadataStatus will be undefined for SSR links only
69
82
  if (metadataStatus === undefined) {
70
83
  setMetadataStatus('pending');
71
84
  return resolve(url, false, true);
72
85
  }
73
- }, [metadataStatus, resolve, setMetadataStatus, url]);
86
+ }, [getSmartLinkState, resolve, setMetadataStatus, url]);
74
87
  var authorize = useCallback(function (appearance) {
88
+ var _getSmartLinkState4 = getSmartLinkState(),
89
+ details = _getSmartLinkState4.details,
90
+ status = _getSmartLinkState4.status;
75
91
  var definitionId = getDefinitionId(details);
76
92
  var extensionKey = getExtensionKey(details);
77
93
  var services = getServices(details);
@@ -123,7 +139,7 @@ export var useSmartCardActions = function useSmartCardActions(id, url, analytics
123
139
  reload();
124
140
  });
125
141
  }
126
- }, [analytics.ui, analytics.screen, analytics.track, analytics.operational, id, reload, details, status]);
142
+ }, [getSmartLinkState, analytics.ui, analytics.screen, analytics.track, analytics.operational, id, reload]);
127
143
  var invoke = useCallback( /*#__PURE__*/function () {
128
144
  var _ref3 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee2(opts, appearance) {
129
145
  var key, action, source, markName, response;
@@ -4,49 +4,29 @@ import { useCallback } from 'react';
4
4
  import { useSmartLinkClientExtension } from '@atlaskit/link-client-extension';
5
5
  import { useSmartLinkContext } from '@atlaskit/link-provider';
6
6
  var useInvoke = function useInvoke() {
7
- var _ref = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
8
- failed = _ref.failed,
9
- started = _ref.started,
10
- success = _ref.success;
11
7
  var _useSmartLinkContext = useSmartLinkContext(),
12
8
  connections = _useSmartLinkContext.connections;
13
9
  var clientExt = useSmartLinkClientExtension(connections.client);
14
10
  return useCallback( /*#__PURE__*/function () {
15
- var _ref2 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee(req, cb) {
16
- var _req$action;
17
- var smartLinkActionType, response;
11
+ var _ref = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee(req, cb) {
12
+ var response;
18
13
  return _regeneratorRuntime.wrap(function _callee$(_context) {
19
14
  while (1) switch (_context.prev = _context.next) {
20
15
  case 0:
21
- smartLinkActionType = req === null || req === void 0 ? void 0 : (_req$action = req.action) === null || _req$action === void 0 ? void 0 : _req$action.actionType;
22
- _context.prev = 1;
23
- started && started({
24
- smartLinkActionType: smartLinkActionType
25
- });
26
- _context.next = 5;
16
+ _context.next = 2;
27
17
  return clientExt.invoke(req);
28
- case 5:
18
+ case 2:
29
19
  response = _context.sent;
30
- success && success({
31
- smartLinkActionType: smartLinkActionType
32
- });
33
20
  return _context.abrupt("return", cb ? cb(response) : response);
34
- case 10:
35
- _context.prev = 10;
36
- _context.t0 = _context["catch"](1);
37
- failed && failed({
38
- smartLinkActionType: smartLinkActionType
39
- });
40
- throw _context.t0;
41
- case 14:
21
+ case 4:
42
22
  case "end":
43
23
  return _context.stop();
44
24
  }
45
- }, _callee, null, [[1, 10]]);
25
+ }, _callee);
46
26
  }));
47
27
  return function (_x, _x2) {
48
- return _ref2.apply(this, arguments);
28
+ return _ref.apply(this, arguments);
49
29
  };
50
- }(), [clientExt, failed, started, success]);
30
+ }(), [clientExt]);
51
31
  };
52
32
  export default useInvoke;
@@ -1,9 +1,11 @@
1
1
  import _asyncToGenerator from "@babel/runtime/helpers/asyncToGenerator";
2
2
  import _regeneratorRuntime from "@babel/runtime/regenerator";
3
3
  import { useCallback } from 'react';
4
+ import { unstable_batchedUpdates } from 'react-dom';
4
5
  import { addMetadataToExperience } from '../../analytics';
5
6
  import { getStatus } from '../../helpers';
6
7
  import { ACTION_ERROR, ACTION_ERROR_FALLBACK, ACTION_RELOADING, ACTION_RESOLVED, ACTION_UPDATE_METADATA_STATUS, APIError, cardAction } from '@atlaskit/linking-common';
8
+ import { getBooleanFF } from '@atlaskit/platform-feature-flags';
7
9
  import { ERROR_MESSAGE_FATAL, ERROR_MESSAGE_METADATA, ERROR_MESSAGE_OAUTH } from '../../actions/constants';
8
10
  import { getUnauthorizedJsonLd } from '../../../utils/jsonld';
9
11
  import { SmartLinkStatus } from '../../../constants';
@@ -73,6 +75,20 @@ var useResolve = function useResolve() {
73
75
  }
74
76
  }
75
77
  }, [getState, setMetadataStatus, dispatch]);
78
+ var handleResolvedLinkSuccess = useCallback(function (resourceUrl, response, isReloading, isMetadataRequest) {
79
+ //if a link resolves normally, metadata will also always be resolved
80
+ setMetadataStatus(resourceUrl, 'resolved');
81
+ // Dispatch Analytics and resolved card action - including unauthorized states.
82
+ if (isReloading) {
83
+ dispatch(cardAction(ACTION_RELOADING, {
84
+ url: resourceUrl
85
+ }, response));
86
+ } else {
87
+ dispatch(cardAction(ACTION_RESOLVED, {
88
+ url: resourceUrl
89
+ }, response, undefined, undefined, isMetadataRequest));
90
+ }
91
+ }, [setMetadataStatus, dispatch]);
76
92
  var handleResolvedLinkResponse = useCallback(function (resourceUrl, response) {
77
93
  var isReloading = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
78
94
  var isMetadataRequest = arguments.length > 3 ? arguments[3] : undefined;
@@ -97,20 +113,20 @@ var useResolve = function useResolve() {
97
113
  handleResolvedLinkError(resourceUrl, new APIError('error', hostname, ERROR_MESSAGE_METADATA), response, isMetadataRequest);
98
114
  return;
99
115
  }
100
-
101
- //if a link resolves normally, metadata will also always be resolved
102
- setMetadataStatus(resourceUrl, 'resolved');
103
- // Dispatch Analytics and resolved card action - including unauthorized states.
104
- if (isReloading) {
105
- dispatch(cardAction(ACTION_RELOADING, {
106
- url: resourceUrl
107
- }, response));
116
+ if (getBooleanFF('platform.linking-platform.smart-card.enable-analytics-context')) {
117
+ /**
118
+ * Using unstable_batchedUpdates because this store update happens async and trigers a rerender
119
+ * more info:
120
+ * https://github.com/facebook/react/blob/v18.2.0/packages/use-sync-external-store/src/useSyncExternalStoreShimClient.js#L113
121
+ * https://react-redux.js.org/api/batch
122
+ */
123
+ unstable_batchedUpdates(function () {
124
+ handleResolvedLinkSuccess(resourceUrl, response, isReloading, isMetadataRequest);
125
+ });
108
126
  } else {
109
- dispatch(cardAction(ACTION_RESOLVED, {
110
- url: resourceUrl
111
- }, response, undefined, undefined, isMetadataRequest));
127
+ handleResolvedLinkSuccess(resourceUrl, response, isReloading, isMetadataRequest);
112
128
  }
113
- }, [dispatch, handleResolvedLinkError, hasAuthFlowSupported, setMetadataStatus]);
129
+ }, [handleResolvedLinkError, handleResolvedLinkSuccess, hasAuthFlowSupported]);
114
130
  return useCallback( /*#__PURE__*/function () {
115
131
  var _ref2 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee(url) {
116
132
  var isReloading,