@atlaskit/smart-card 21.3.0 → 22.1.1
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 +56 -0
- package/dist/cjs/extractors/block/index.js +6 -7
- package/dist/cjs/extractors/common/actions/extractPreviewAction.js +16 -19
- package/dist/cjs/state/actions/index.js +54 -10
- package/dist/cjs/state/analytics/types.js +5 -0
- package/dist/cjs/state/analytics/useSmartLinkAnalytics.js +429 -109
- package/dist/cjs/state/hooks-external/useSmartLinkActions.js +5 -3
- package/dist/cjs/utils/analytics/analytics.js +241 -74
- package/dist/cjs/utils/analytics/index.js +32 -5
- package/dist/cjs/utils/mocks.js +28 -2
- package/dist/cjs/version.json +1 -1
- package/dist/cjs/view/BlockCard/actions/PreviewAction.js +2 -2
- package/dist/cjs/view/BlockCard/index.js +6 -5
- package/dist/cjs/view/CardWithUrl/component.js +27 -5
- package/dist/cjs/view/CardWithUrl/loader.js +6 -1
- package/dist/cjs/view/EmbedCard/index.js +3 -2
- package/dist/cjs/view/EmbedModal/components/analytics/index.js +100 -0
- package/dist/cjs/view/EmbedModal/components/analytics/types.js +5 -0
- package/dist/cjs/view/EmbedModal/components/size-experiment/index.js +5 -10
- package/dist/cjs/view/EmbedModal/index.js +54 -15
- package/dist/cjs/view/EmbedModal/types.js +9 -1
- package/dist/cjs/view/HoverCard/components/HoverCardComponent.js +11 -3
- package/dist/cjs/view/HoverCard/components/HoverCardContent.js +15 -4
- package/dist/cjs/view/HoverCard/index.js +6 -1
- package/dist/cjs/view/InlineCard/IconAndTitleLayout/styled.js +2 -2
- package/dist/cjs/view/common/Modal.js +29 -4
- package/dist/cjs/view/common/ModalHeader.js +3 -2
- package/dist/es2019/extractors/block/index.js +6 -7
- package/dist/es2019/extractors/common/actions/extractPreviewAction.js +16 -10
- package/dist/es2019/state/actions/index.js +54 -10
- package/dist/es2019/state/analytics/types.js +1 -0
- package/dist/es2019/state/analytics/useSmartLinkAnalytics.js +424 -41
- package/dist/es2019/state/hooks-external/useSmartLinkActions.js +5 -3
- package/dist/es2019/utils/analytics/analytics.js +254 -79
- package/dist/es2019/utils/analytics/index.js +32 -4
- package/dist/es2019/utils/mocks.js +26 -1
- package/dist/es2019/version.json +1 -1
- package/dist/es2019/view/BlockCard/actions/PreviewAction.js +3 -3
- package/dist/es2019/view/BlockCard/index.js +5 -4
- package/dist/es2019/view/CardWithUrl/component.js +27 -5
- package/dist/es2019/view/CardWithUrl/loader.js +6 -1
- package/dist/es2019/view/EmbedCard/index.js +3 -2
- package/dist/es2019/view/EmbedModal/components/analytics/index.js +80 -0
- package/dist/es2019/view/EmbedModal/components/analytics/types.js +1 -0
- package/dist/es2019/view/EmbedModal/components/size-experiment/index.js +5 -9
- package/dist/es2019/view/EmbedModal/index.js +46 -13
- package/dist/es2019/view/EmbedModal/types.js +6 -1
- package/dist/es2019/view/HoverCard/components/HoverCardComponent.js +11 -3
- package/dist/es2019/view/HoverCard/components/HoverCardContent.js +15 -4
- package/dist/es2019/view/HoverCard/index.js +6 -1
- package/dist/es2019/view/InlineCard/IconAndTitleLayout/styled.js +0 -2
- package/dist/es2019/view/common/Modal.js +27 -6
- package/dist/es2019/view/common/ModalHeader.js +3 -2
- package/dist/esm/extractors/block/index.js +6 -7
- package/dist/esm/extractors/common/actions/extractPreviewAction.js +17 -19
- package/dist/esm/state/actions/index.js +54 -10
- package/dist/esm/state/analytics/types.js +1 -0
- package/dist/esm/state/analytics/useSmartLinkAnalytics.js +428 -111
- package/dist/esm/state/hooks-external/useSmartLinkActions.js +5 -3
- package/dist/esm/utils/analytics/analytics.js +241 -74
- package/dist/esm/utils/analytics/index.js +31 -4
- package/dist/esm/utils/mocks.js +25 -0
- package/dist/esm/version.json +1 -1
- package/dist/esm/view/BlockCard/actions/PreviewAction.js +3 -3
- package/dist/esm/view/BlockCard/index.js +5 -4
- package/dist/esm/view/CardWithUrl/component.js +27 -5
- package/dist/esm/view/CardWithUrl/loader.js +6 -1
- package/dist/esm/view/EmbedCard/index.js +3 -2
- package/dist/esm/view/EmbedModal/components/analytics/index.js +82 -0
- package/dist/esm/view/EmbedModal/components/analytics/types.js +1 -0
- package/dist/esm/view/EmbedModal/components/size-experiment/index.js +5 -10
- package/dist/esm/view/EmbedModal/index.js +52 -15
- package/dist/esm/view/EmbedModal/types.js +6 -1
- package/dist/esm/view/HoverCard/components/HoverCardComponent.js +11 -3
- package/dist/esm/view/HoverCard/components/HoverCardContent.js +15 -4
- package/dist/esm/view/HoverCard/index.js +6 -1
- package/dist/esm/view/InlineCard/IconAndTitleLayout/styled.js +2 -2
- package/dist/esm/view/common/Modal.js +28 -6
- package/dist/esm/view/common/ModalHeader.js +3 -2
- package/dist/types/extractors/block/types.d.ts +4 -2
- package/dist/types/extractors/common/actions/extractPreviewAction.d.ts +7 -5
- package/dist/types/state/analytics/types.d.ts +9 -0
- package/dist/types/state/analytics/useSmartLinkAnalytics.d.ts +41 -24
- package/dist/types/state/hooks/useSmartLink.d.ts +26 -18
- package/dist/types/state/hooks-external/useSmartLinkActions.d.ts +6 -2
- package/dist/types/utils/analytics/analytics.d.ts +19 -21
- package/dist/types/utils/analytics/index.d.ts +2 -2
- package/dist/types/utils/analytics/types.d.ts +91 -0
- package/dist/types/utils/mocks.d.ts +48 -0
- package/dist/types/utils/types.d.ts +3 -1
- package/dist/types/view/BlockCard/actions/PreviewAction.d.ts +4 -0
- package/dist/types/view/BlockCard/index.d.ts +2 -2
- package/dist/types/view/BlockCard/types.d.ts +4 -4
- package/dist/types/view/Card/index.d.ts +1 -1
- package/dist/types/view/EmbedCard/types.d.ts +2 -2
- package/dist/types/view/EmbedModal/components/analytics/index.d.ts +5 -0
- package/dist/types/view/EmbedModal/components/analytics/types.d.ts +6 -0
- package/dist/types/view/EmbedModal/components/size-experiment/index.d.ts +4 -3
- package/dist/types/view/EmbedModal/index.d.ts +3 -1
- package/dist/types/view/EmbedModal/types.d.ts +14 -4
- package/dist/types/view/common/Modal.d.ts +6 -8
- package/package.json +17 -17
- package/report.api.md +302 -107
|
@@ -61,7 +61,16 @@ export function CardWithUrlContent({
|
|
|
61
61
|
}, [state.details, url]);
|
|
62
62
|
const handleClickWrapper = useCallback(event => {
|
|
63
63
|
const isModifierKeyPressed = isSpecialEvent(event);
|
|
64
|
-
analytics.ui.cardClickedEvent(
|
|
64
|
+
analytics.ui.cardClickedEvent({
|
|
65
|
+
id,
|
|
66
|
+
display: isFlexibleUi ? 'flexible' : appearance,
|
|
67
|
+
status: state.status,
|
|
68
|
+
definitionId,
|
|
69
|
+
extensionKey,
|
|
70
|
+
isModifierKeyPressed,
|
|
71
|
+
destinationProduct: product,
|
|
72
|
+
destinationSubproduct: subproduct
|
|
73
|
+
});
|
|
65
74
|
|
|
66
75
|
if (onClick) {
|
|
67
76
|
onClick(event);
|
|
@@ -81,7 +90,14 @@ export function CardWithUrlContent({
|
|
|
81
90
|
|
|
82
91
|
if (state.status !== 'pending') {
|
|
83
92
|
measure.create(id, state.status);
|
|
84
|
-
analytics.operational.instrument(
|
|
93
|
+
analytics.operational.instrument({
|
|
94
|
+
id,
|
|
95
|
+
status: state.status,
|
|
96
|
+
definitionId,
|
|
97
|
+
extensionKey,
|
|
98
|
+
resourceType,
|
|
99
|
+
error: state.error
|
|
100
|
+
});
|
|
85
101
|
}
|
|
86
102
|
}, [id, appearance, state.status, state.error, definitionId, extensionKey, resourceType, analytics.operational]); // NB: once the smart-card has rendered into an end state, we capture
|
|
87
103
|
// this as a successful render. These can be one of:
|
|
@@ -90,7 +106,13 @@ export function CardWithUrlContent({
|
|
|
90
106
|
|
|
91
107
|
useEffect(() => {
|
|
92
108
|
if (isFinalState(state.status)) {
|
|
93
|
-
analytics.ui.renderSuccessEvent(
|
|
109
|
+
analytics.ui.renderSuccessEvent({
|
|
110
|
+
display: appearance,
|
|
111
|
+
status: state.status,
|
|
112
|
+
id,
|
|
113
|
+
definitionId,
|
|
114
|
+
extensionKey
|
|
115
|
+
});
|
|
94
116
|
}
|
|
95
117
|
}, [appearance, state.status, url, definitionId, extensionKey, analytics.ui, id]);
|
|
96
118
|
|
|
@@ -154,7 +176,7 @@ export function CardWithUrlContent({
|
|
|
154
176
|
handleErrorRetry: handleRetry,
|
|
155
177
|
handleInvoke: handleInvoke,
|
|
156
178
|
handleFrameClick: handleClickWrapper,
|
|
157
|
-
|
|
179
|
+
analytics: analytics,
|
|
158
180
|
isSelected: isSelected,
|
|
159
181
|
onResolve: onResolve,
|
|
160
182
|
onError: onError,
|
|
@@ -172,7 +194,7 @@ export function CardWithUrlContent({
|
|
|
172
194
|
handleErrorRetry: handleRetry,
|
|
173
195
|
handleFrameClick: handleClickWrapper,
|
|
174
196
|
handleInvoke: handleInvoke,
|
|
175
|
-
|
|
197
|
+
analytics: analytics,
|
|
176
198
|
isSelected: isSelected,
|
|
177
199
|
isFrameVisible: isFrameVisible,
|
|
178
200
|
platform: platform,
|
|
@@ -68,7 +68,12 @@ export function CardWithURLRenderer(props) {
|
|
|
68
68
|
const errorInfo = {
|
|
69
69
|
componentStack
|
|
70
70
|
};
|
|
71
|
-
analytics.ui.renderFailedEvent(
|
|
71
|
+
analytics.ui.renderFailedEvent({
|
|
72
|
+
display: appearance,
|
|
73
|
+
id,
|
|
74
|
+
error,
|
|
75
|
+
errorInfo
|
|
76
|
+
});
|
|
72
77
|
}
|
|
73
78
|
}, [analytics.ui, appearance, id]);
|
|
74
79
|
|
|
@@ -22,7 +22,7 @@ export const EmbedCard = /*#__PURE__*/React.forwardRef(({
|
|
|
22
22
|
handleAuthorize,
|
|
23
23
|
handleErrorRetry,
|
|
24
24
|
handleFrameClick,
|
|
25
|
-
|
|
25
|
+
analytics,
|
|
26
26
|
handleInvoke,
|
|
27
27
|
showActions,
|
|
28
28
|
isSelected,
|
|
@@ -79,7 +79,8 @@ export const EmbedCard = /*#__PURE__*/React.forwardRef(({
|
|
|
79
79
|
}
|
|
80
80
|
|
|
81
81
|
const resolvedBlockViewProps = extractBlockProps(data, meta, {
|
|
82
|
-
|
|
82
|
+
analytics,
|
|
83
|
+
origin: 'smartLinkEmbed',
|
|
83
84
|
handleInvoke,
|
|
84
85
|
extensionKey: getExtensionKey(details)
|
|
85
86
|
});
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import _extends from "@babel/runtime/helpers/extends";
|
|
2
|
+
import React, { useCallback } from 'react';
|
|
3
|
+
import { EmbedModalSize } from '../../types';
|
|
4
|
+
|
|
5
|
+
const getResizeFrom = size => size === EmbedModalSize.Small ? EmbedModalSize.Large : EmbedModalSize.Small;
|
|
6
|
+
|
|
7
|
+
const withAnalytics = Component => props => {
|
|
8
|
+
const {
|
|
9
|
+
analytics,
|
|
10
|
+
onClose,
|
|
11
|
+
onOpen,
|
|
12
|
+
onOpenFailed,
|
|
13
|
+
onResize,
|
|
14
|
+
origin
|
|
15
|
+
} = props;
|
|
16
|
+
const handleOnOpen = useCallback(context => {
|
|
17
|
+
analytics.screen.modalViewedEvent({
|
|
18
|
+
name: 'embedPreviewModal',
|
|
19
|
+
attributes: {
|
|
20
|
+
origin,
|
|
21
|
+
size: context.size
|
|
22
|
+
}
|
|
23
|
+
});
|
|
24
|
+
analytics.ui.renderSuccessEvent({
|
|
25
|
+
status: 'resolved',
|
|
26
|
+
display: 'preview'
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
if (onOpen) {
|
|
30
|
+
onOpen(context);
|
|
31
|
+
}
|
|
32
|
+
}, [analytics.screen, analytics.ui, onOpen, origin]);
|
|
33
|
+
const handleOnOpenFailed = useCallback((error, errorInfo) => {
|
|
34
|
+
analytics.ui.renderFailedEvent({
|
|
35
|
+
display: 'preview',
|
|
36
|
+
error,
|
|
37
|
+
errorInfo
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
if (onOpenFailed) {
|
|
41
|
+
onOpenFailed(error, errorInfo);
|
|
42
|
+
}
|
|
43
|
+
}, [analytics.ui, onOpenFailed]);
|
|
44
|
+
const handleOnClose = useCallback(context => {
|
|
45
|
+
analytics.ui.modalClosedEvent({
|
|
46
|
+
actionSubjectId: 'embedPreview',
|
|
47
|
+
attributes: {
|
|
48
|
+
origin,
|
|
49
|
+
previewTime: context.duration,
|
|
50
|
+
size: context.size
|
|
51
|
+
}
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
if (onClose) {
|
|
55
|
+
onClose(context);
|
|
56
|
+
}
|
|
57
|
+
}, [analytics.ui, onClose, origin]);
|
|
58
|
+
const handleOnResize = useCallback(context => {
|
|
59
|
+
analytics.ui.buttonClickedEvent({
|
|
60
|
+
actionSubjectId: 'embedPreviewResize',
|
|
61
|
+
attributes: {
|
|
62
|
+
newSize: context.size,
|
|
63
|
+
origin,
|
|
64
|
+
previousSize: getResizeFrom(context.size)
|
|
65
|
+
}
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
if (onResize) {
|
|
69
|
+
onResize(context);
|
|
70
|
+
}
|
|
71
|
+
}, [analytics.ui, onResize, origin]);
|
|
72
|
+
return /*#__PURE__*/React.createElement(Component, _extends({}, props, {
|
|
73
|
+
onClose: handleOnClose,
|
|
74
|
+
onOpen: handleOnOpen,
|
|
75
|
+
onOpenFailed: handleOnOpenFailed,
|
|
76
|
+
onResize: handleOnResize
|
|
77
|
+
}));
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
export default withAnalytics;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -1,28 +1,24 @@
|
|
|
1
1
|
import _extends from "@babel/runtime/helpers/extends";
|
|
2
2
|
import React from 'react';
|
|
3
3
|
import Modal from '../../../common/Modal';
|
|
4
|
-
import {
|
|
4
|
+
import { EmbedModalSize } from '../../types';
|
|
5
5
|
|
|
6
6
|
const withSizeExperiment = Component => props => {
|
|
7
7
|
const {
|
|
8
|
-
featureFlags = {}
|
|
9
|
-
closeLabel = 'Close Preview'
|
|
8
|
+
featureFlags = {}
|
|
10
9
|
} = props;
|
|
11
10
|
const {
|
|
12
|
-
embedModalSize
|
|
11
|
+
embedModalSize: size
|
|
13
12
|
} = featureFlags; // Experiment
|
|
14
13
|
|
|
15
|
-
if (
|
|
16
|
-
const size = embedModalSize === 'large' ? MAX_MODAL_SIZE : MIN_MODAL_SIZE;
|
|
14
|
+
if (size === EmbedModalSize.Large || size === EmbedModalSize.Small) {
|
|
17
15
|
return /*#__PURE__*/React.createElement(Component, _extends({}, props, {
|
|
18
16
|
size: size
|
|
19
17
|
}));
|
|
20
18
|
} // Control
|
|
21
19
|
|
|
22
20
|
|
|
23
|
-
return /*#__PURE__*/React.createElement(Modal,
|
|
24
|
-
closeLabel: closeLabel
|
|
25
|
-
}));
|
|
21
|
+
return /*#__PURE__*/React.createElement(Modal, props);
|
|
26
22
|
};
|
|
27
23
|
|
|
28
24
|
export default withSizeExperiment;
|
|
@@ -1,10 +1,16 @@
|
|
|
1
|
-
import React, { useCallback, useState } from 'react';
|
|
1
|
+
import React, { useCallback, useRef, useState } from 'react';
|
|
2
2
|
import ModalDialog, { ModalBody, ModalTransition } from '@atlaskit/modal-dialog';
|
|
3
3
|
import LinkInfo from './components/link-info';
|
|
4
4
|
import { MAX_MODAL_SIZE, MIN_MODAL_SIZE } from './constants';
|
|
5
5
|
import EmbedContent from './components/embed-content';
|
|
6
|
+
import { EmbedModalSize } from './types';
|
|
6
7
|
import withErrorBoundary from './components/error-boundary';
|
|
7
8
|
import withSizeExperiment from './components/size-experiment';
|
|
9
|
+
import withAnalytics from './components/analytics';
|
|
10
|
+
|
|
11
|
+
const toSize = width => width === MAX_MODAL_SIZE ? EmbedModalSize.Large : EmbedModalSize.Small;
|
|
12
|
+
|
|
13
|
+
const toWidth = size => size === EmbedModalSize.Large ? MAX_MODAL_SIZE : MIN_MODAL_SIZE;
|
|
8
14
|
|
|
9
15
|
const EmbedModal = ({
|
|
10
16
|
download: downloadUrl,
|
|
@@ -14,37 +20,64 @@ const EmbedModal = ({
|
|
|
14
20
|
onClose,
|
|
15
21
|
onDownloadActionClick,
|
|
16
22
|
onOpen,
|
|
23
|
+
onResize,
|
|
17
24
|
onViewActionClick,
|
|
18
25
|
providerName,
|
|
19
26
|
showModal,
|
|
20
|
-
size
|
|
27
|
+
size = EmbedModalSize.Small,
|
|
21
28
|
src,
|
|
22
29
|
testId = 'smart-embed-preview-modal',
|
|
23
30
|
title,
|
|
24
31
|
url
|
|
25
32
|
}) => {
|
|
33
|
+
const defaultWidth = toWidth(size);
|
|
26
34
|
const [isOpen, setIsOpen] = useState(showModal);
|
|
27
|
-
const [
|
|
35
|
+
const [width, setWidth] = useState(defaultWidth);
|
|
36
|
+
const openAt = useRef();
|
|
37
|
+
const handleOnOpenComplete = useCallback(() => {
|
|
38
|
+
openAt.current = Date.now();
|
|
39
|
+
|
|
40
|
+
if (onOpen) {
|
|
41
|
+
onOpen({
|
|
42
|
+
size
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
}, [onOpen, size]);
|
|
28
46
|
const handleOnClose = useCallback(() => setIsOpen(false), []);
|
|
29
|
-
const
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
47
|
+
const handleOnCloseComplete = useCallback(() => {
|
|
48
|
+
if (onClose) {
|
|
49
|
+
const duration = openAt.current ? Date.now() - openAt.current : undefined;
|
|
50
|
+
onClose({
|
|
51
|
+
duration,
|
|
52
|
+
size: toSize(width)
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
}, [onClose, width]);
|
|
56
|
+
const handleOnResizeClick = useCallback(() => {
|
|
57
|
+
const newWidth = width === MIN_MODAL_SIZE ? MAX_MODAL_SIZE : MIN_MODAL_SIZE;
|
|
58
|
+
setWidth(newWidth);
|
|
59
|
+
|
|
60
|
+
if (onResize) {
|
|
61
|
+
onResize({
|
|
62
|
+
size: toSize(newWidth)
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
}, [onResize, width]);
|
|
33
66
|
return /*#__PURE__*/React.createElement(ModalTransition, null, isOpen && /*#__PURE__*/React.createElement(ModalDialog, {
|
|
34
67
|
height: "100%",
|
|
35
68
|
onClose: handleOnClose,
|
|
36
|
-
onCloseComplete:
|
|
37
|
-
onOpenComplete:
|
|
69
|
+
onCloseComplete: handleOnCloseComplete,
|
|
70
|
+
onOpenComplete: handleOnOpenComplete,
|
|
38
71
|
testId: testId,
|
|
39
|
-
width:
|
|
72
|
+
width: width
|
|
40
73
|
}, /*#__PURE__*/React.createElement(LinkInfo, {
|
|
41
74
|
downloadUrl: downloadUrl,
|
|
42
75
|
icon: icon,
|
|
43
76
|
providerName: providerName,
|
|
44
77
|
onViewButtonClick: onViewActionClick,
|
|
45
78
|
onDownloadButtonClick: onDownloadActionClick,
|
|
46
|
-
onResizeButtonClick:
|
|
47
|
-
size:
|
|
79
|
+
onResizeButtonClick: handleOnResizeClick,
|
|
80
|
+
size: width,
|
|
48
81
|
title: title,
|
|
49
82
|
testId: testId,
|
|
50
83
|
url: url
|
|
@@ -56,4 +89,4 @@ const EmbedModal = ({
|
|
|
56
89
|
}))));
|
|
57
90
|
};
|
|
58
91
|
|
|
59
|
-
export default withSizeExperiment(withErrorBoundary(EmbedModal));
|
|
92
|
+
export default withSizeExperiment(withAnalytics(withErrorBoundary(EmbedModal)));
|
|
@@ -43,7 +43,11 @@ export const HoverCardComponent = ({
|
|
|
43
43
|
//Check its previously open to avoid firing events when moving between the child and hover card components
|
|
44
44
|
if (isOpen === true && cardOpenTime.current) {
|
|
45
45
|
const hoverTime = Date.now() - cardOpenTime.current;
|
|
46
|
-
analytics.ui.hoverCardDismissedEvent(
|
|
46
|
+
analytics.ui.hoverCardDismissedEvent({
|
|
47
|
+
previewDisplay: 'card',
|
|
48
|
+
hoverTime,
|
|
49
|
+
previewInvokeMethod: 'mouse_hover'
|
|
50
|
+
});
|
|
47
51
|
}
|
|
48
52
|
|
|
49
53
|
setIsOpen(false);
|
|
@@ -66,7 +70,10 @@ export const HoverCardComponent = ({
|
|
|
66
70
|
//Check if its previously closed to avoid firing events when moving between the child and hover card components
|
|
67
71
|
if (isOpen === false) {
|
|
68
72
|
cardOpenTime.current = Date.now();
|
|
69
|
-
analytics.ui.hoverCardViewedEvent(
|
|
73
|
+
analytics.ui.hoverCardViewedEvent({
|
|
74
|
+
previewDisplay: hoverDisplay,
|
|
75
|
+
previewInvokeMethod: invokeMethod
|
|
76
|
+
});
|
|
70
77
|
} //If these are undefined then popupOffset is undefined and we fallback to default bottom-start placement
|
|
71
78
|
|
|
72
79
|
|
|
@@ -84,7 +91,8 @@ export const HoverCardComponent = ({
|
|
|
84
91
|
const linkActions = useSmartLinkActions({
|
|
85
92
|
url,
|
|
86
93
|
appearance: SMART_CARD_ANALYTICS_DISPLAY,
|
|
87
|
-
analyticsHandler
|
|
94
|
+
analyticsHandler,
|
|
95
|
+
origin: 'smartLinkPreviewHoverCard'
|
|
88
96
|
});
|
|
89
97
|
const onActionClick = useCallback(actionId => {
|
|
90
98
|
if (actionId === 'preview-content') {
|
|
@@ -25,7 +25,9 @@ export const getOpenAction = (url, analytics, onActionClick) => ({
|
|
|
25
25
|
}
|
|
26
26
|
|
|
27
27
|
window.open(url, '_blank');
|
|
28
|
-
analytics.ui.hoverCardOpenLinkClickedEvent(
|
|
28
|
+
analytics.ui.hoverCardOpenLinkClickedEvent({
|
|
29
|
+
previewDisplay: 'card'
|
|
30
|
+
});
|
|
29
31
|
},
|
|
30
32
|
testId: 'hover-card-open-button'
|
|
31
33
|
});
|
|
@@ -61,13 +63,22 @@ const HoverCardContent = ({
|
|
|
61
63
|
useEffect(() => {
|
|
62
64
|
// Since hover preview only render on resolved status,
|
|
63
65
|
// there is no need to check for statuses.
|
|
64
|
-
analytics.ui.renderSuccessEvent(
|
|
66
|
+
analytics.ui.renderSuccessEvent({
|
|
67
|
+
display: SMART_CARD_ANALYTICS_DISPLAY,
|
|
68
|
+
status: cardState.status
|
|
69
|
+
});
|
|
65
70
|
}, [analytics.ui, cardState.status]);
|
|
66
71
|
const extensionKey = useMemo(() => getExtensionKey(cardState.details), [cardState.details]);
|
|
67
72
|
const onClick = useCallback(event => {
|
|
68
73
|
const isModifierKeyPressed = isSpecialEvent(event);
|
|
69
|
-
analytics.ui.cardClickedEvent(
|
|
70
|
-
|
|
74
|
+
analytics.ui.cardClickedEvent({
|
|
75
|
+
id,
|
|
76
|
+
display: SMART_CARD_ANALYTICS_DISPLAY,
|
|
77
|
+
status: cardState.status,
|
|
78
|
+
isModifierKeyPressed,
|
|
79
|
+
actionSubjectId: 'titleGoToLink'
|
|
80
|
+
});
|
|
81
|
+
}, [cardState.status, analytics.ui, id]);
|
|
71
82
|
const titleActions = useMemo(() => [getOpenAction(url, analytics, onActionClick)], [url, analytics, onActionClick]);
|
|
72
83
|
const footerActions = useMemo(() => toFooterActions(cardActions, onActionClick), [cardActions, onActionClick]);
|
|
73
84
|
const data = (_cardState$details = cardState.details) === null || _cardState$details === void 0 ? void 0 : _cardState$details.data;
|
|
@@ -22,7 +22,12 @@ const HoverCardWithErrorBoundary = props => {
|
|
|
22
22
|
}, [createAnalyticsEvent]);
|
|
23
23
|
const analytics = useSmartLinkAnalytics(url, analyticsHandler, id);
|
|
24
24
|
const onError = useCallback((error, info) => {
|
|
25
|
-
analytics.ui.renderFailedEvent(
|
|
25
|
+
analytics.ui.renderFailedEvent({
|
|
26
|
+
display: SMART_CARD_ANALYTICS_DISPLAY,
|
|
27
|
+
id,
|
|
28
|
+
error,
|
|
29
|
+
errorInfo: info
|
|
30
|
+
});
|
|
26
31
|
}, [analytics.ui, id]);
|
|
27
32
|
return jsx(ErrorBoundary, {
|
|
28
33
|
fallback: children,
|
|
@@ -64,14 +64,12 @@ export const LozengeWrapper = styled.span`
|
|
|
64
64
|
vertical-align: 1px;
|
|
65
65
|
& > span {
|
|
66
66
|
margin-left: 4px;
|
|
67
|
-
padding: 2px 0 2px 0;
|
|
68
67
|
}
|
|
69
68
|
`; // TODO: Replace overrides with proper AtlasKit solution.
|
|
70
69
|
|
|
71
70
|
export const LozengeBlockWrapper = styled.span`
|
|
72
71
|
& > span {
|
|
73
72
|
margin-left: 4px;
|
|
74
|
-
padding: 2px 0 2px 0;
|
|
75
73
|
}
|
|
76
74
|
`;
|
|
77
75
|
export const RightIconPositionWrapper = styled.span`
|
|
@@ -14,10 +14,12 @@ manually passed to your custom components.
|
|
|
14
14
|
|
|
15
15
|
For a complete guide on customization using the new compositional API, refer to the docs at
|
|
16
16
|
https://atlassian.design/components/modal-dialog/examples#customizing-modal-dialog. */
|
|
17
|
-
import React, { useState } from 'react';
|
|
18
|
-
import ModalDialog, {
|
|
17
|
+
import React, { useCallback, useRef, useState } from 'react';
|
|
18
|
+
import ModalDialog, { ModalBody, ModalTransition } from '@atlaskit/modal-dialog';
|
|
19
19
|
import { Header } from './ModalHeader';
|
|
20
20
|
import { getIframeSandboxAttribute } from '../../utils';
|
|
21
|
+
import withAnalytics from '../EmbedModal/components/analytics';
|
|
22
|
+
import { EmbedModalSize } from '../EmbedModal/types';
|
|
21
23
|
const iframeStyles = {
|
|
22
24
|
width: `100%`,
|
|
23
25
|
height: 'calc(100vh - 248px)'
|
|
@@ -45,7 +47,7 @@ const Modal = ({
|
|
|
45
47
|
providerName,
|
|
46
48
|
metadata,
|
|
47
49
|
icon,
|
|
48
|
-
closeLabel,
|
|
50
|
+
closeLabel = 'Close Preview',
|
|
49
51
|
iframeName,
|
|
50
52
|
title,
|
|
51
53
|
url,
|
|
@@ -56,16 +58,35 @@ const Modal = ({
|
|
|
56
58
|
onDownloadActionClick
|
|
57
59
|
}) => {
|
|
58
60
|
let [isOpen, setIsOpen] = useState(showModal);
|
|
61
|
+
const openAt = useRef();
|
|
62
|
+
const handleOnOpenComplete = useCallback(() => {
|
|
63
|
+
openAt.current = Date.now();
|
|
64
|
+
|
|
65
|
+
if (onOpen) {
|
|
66
|
+
onOpen({
|
|
67
|
+
size: EmbedModalSize.Small
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
}, [onOpen]);
|
|
71
|
+
const handleOnCloseComplete = useCallback(() => {
|
|
72
|
+
if (onClose) {
|
|
73
|
+
const duration = openAt.current ? Date.now() - openAt.current : undefined;
|
|
74
|
+
onClose({
|
|
75
|
+
duration,
|
|
76
|
+
size: EmbedModalSize.Small
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
}, [onClose]);
|
|
59
80
|
const sandbox = getIframeSandboxAttribute(isTrusted);
|
|
60
81
|
return /*#__PURE__*/React.createElement(ModalTransition, null, isOpen && /*#__PURE__*/React.createElement(ModalDialog, {
|
|
61
82
|
height: "100%",
|
|
62
83
|
width: "large",
|
|
63
84
|
testId: testId,
|
|
64
|
-
onOpenComplete:
|
|
85
|
+
onOpenComplete: handleOnOpenComplete,
|
|
65
86
|
onClose: () => {
|
|
66
87
|
setIsOpen(false);
|
|
67
88
|
},
|
|
68
|
-
onCloseComplete:
|
|
89
|
+
onCloseComplete: handleOnCloseComplete
|
|
69
90
|
}, /*#__PURE__*/React.createElement(Header, {
|
|
70
91
|
providerName: providerName,
|
|
71
92
|
icon: icon,
|
|
@@ -91,4 +112,4 @@ const Modal = ({
|
|
|
91
112
|
}))));
|
|
92
113
|
};
|
|
93
114
|
|
|
94
|
-
export default ModalWithErrorBoundary;
|
|
115
|
+
export default withAnalytics(ModalWithErrorBoundary);
|
|
@@ -74,7 +74,7 @@ export const Header = ({
|
|
|
74
74
|
testId: "preview-view-action",
|
|
75
75
|
iconAfter: jsx(ShortcutIcon, {
|
|
76
76
|
size: "small",
|
|
77
|
-
label: "
|
|
77
|
+
label: ""
|
|
78
78
|
}),
|
|
79
79
|
onClick: onViewActionClick
|
|
80
80
|
}, providerName ? jsx(F, null, jsx(FormattedMessage, messages.viewIn), " ", providerName) : jsx(FormattedMessage, messages.viewOriginal)), jsx(Button, {
|
|
@@ -82,6 +82,7 @@ export const Header = ({
|
|
|
82
82
|
iconBefore: jsx(EditorCloseIcon, {
|
|
83
83
|
label: label
|
|
84
84
|
}),
|
|
85
|
-
onClick: onClose
|
|
85
|
+
onClick: onClose,
|
|
86
|
+
testId: "preview-close-button"
|
|
86
87
|
}))));
|
|
87
88
|
};
|
|
@@ -37,14 +37,13 @@ var extractBlockDetails = function extractBlockDetails(jsonLd) {
|
|
|
37
37
|
|
|
38
38
|
export var extractBlockActions = function extractBlockActions(props, jsonLd, opts, platform) {
|
|
39
39
|
if (opts) {
|
|
40
|
-
var
|
|
41
|
-
handleInvoke = opts.handleInvoke,
|
|
42
|
-
handleAnalytics = opts.handleAnalytics,
|
|
43
|
-
extensionKey = opts.extensionKey,
|
|
44
|
-
source = opts.source,
|
|
45
|
-
testId = opts.testId;
|
|
40
|
+
var handleInvoke = opts.handleInvoke;
|
|
46
41
|
var actions = extractActions(jsonLd, handleInvoke);
|
|
47
|
-
var previewAction = extractPreviewAction(
|
|
42
|
+
var previewAction = extractPreviewAction(_objectSpread(_objectSpread({}, opts), {}, {
|
|
43
|
+
viewProps: props,
|
|
44
|
+
jsonLd: jsonLd,
|
|
45
|
+
platform: platform
|
|
46
|
+
})); // The previewAction should always be the last action
|
|
48
47
|
|
|
49
48
|
if (previewAction) {
|
|
50
49
|
actions.push(previewAction);
|
|
@@ -4,9 +4,8 @@ function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (O
|
|
|
4
4
|
|
|
5
5
|
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { _defineProperty(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }
|
|
6
6
|
|
|
7
|
-
import { uiRenderSuccessEvent, uiRenderFailedEvent } from '../../../utils/analytics';
|
|
8
7
|
import { extractDownloadUrl } from '../detail';
|
|
9
|
-
import {
|
|
8
|
+
import { extractPreview, extractProvider } from '@atlaskit/linking-common/extractors';
|
|
10
9
|
import { PreviewAction } from '../../../view/BlockCard';
|
|
11
10
|
|
|
12
11
|
var getMetadataFromJsonLd = function getMetadataFromJsonLd(jsonLd, platform) {
|
|
@@ -51,16 +50,19 @@ var getInvokeOpts = function getInvokeOpts(key, action, source) {
|
|
|
51
50
|
};
|
|
52
51
|
};
|
|
53
52
|
|
|
54
|
-
export var extractPreviewAction = function extractPreviewAction() {
|
|
55
|
-
var extensionKey =
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
53
|
+
export var extractPreviewAction = function extractPreviewAction(_ref) {
|
|
54
|
+
var _ref$extensionKey = _ref.extensionKey,
|
|
55
|
+
extensionKey = _ref$extensionKey === void 0 ? 'empty-object-provider' : _ref$extensionKey,
|
|
56
|
+
viewProps = _ref.viewProps,
|
|
57
|
+
jsonLd = _ref.jsonLd,
|
|
58
|
+
handleInvoke = _ref.handleInvoke,
|
|
59
|
+
testId = _ref.testId,
|
|
60
|
+
platform = _ref.platform,
|
|
61
|
+
origin = _ref.origin,
|
|
62
|
+
_ref$source = _ref.source,
|
|
63
|
+
source = _ref$source === void 0 ? 'block' : _ref$source,
|
|
64
|
+
featureFlags = _ref.featureFlags,
|
|
65
|
+
analytics = _ref.analytics;
|
|
64
66
|
// Extract metadata from view props & raw JSON-LD.
|
|
65
67
|
var metadataFromJsonLd = getMetadataFromJsonLd(jsonLd, platform);
|
|
66
68
|
var metadataFromViewProps = getMetadataFromResolvedProps(viewProps);
|
|
@@ -72,14 +74,10 @@ export var extractPreviewAction = function extractPreviewAction() {
|
|
|
72
74
|
// Build action using instrumentation hooks.
|
|
73
75
|
var key = extensionKey;
|
|
74
76
|
var previewAction = PreviewAction(_objectSpread(_objectSpread({}, metadata), {}, {
|
|
77
|
+
analytics: analytics,
|
|
78
|
+
origin: origin,
|
|
75
79
|
featureFlags: featureFlags,
|
|
76
80
|
testId: testId,
|
|
77
|
-
onOpen: function onOpen() {
|
|
78
|
-
handleAnalytics(uiRenderSuccessEvent('preview', 'resolved', key));
|
|
79
|
-
},
|
|
80
|
-
onOpenFailed: function onOpenFailed(error, errorInfo) {
|
|
81
|
-
handleAnalytics(uiRenderFailedEvent('preview', error, errorInfo));
|
|
82
|
-
},
|
|
83
81
|
onDownloadActionClick: function onDownloadActionClick() {
|
|
84
82
|
handleInvoke(getInvokeOpts(key, 'DownloadAction'));
|
|
85
83
|
},
|
|
@@ -89,7 +87,7 @@ export var extractPreviewAction = function extractPreviewAction() {
|
|
|
89
87
|
})); // Setup props to go through proper Redux 'invocation' flow
|
|
90
88
|
// for analytics, further state management if required in future.
|
|
91
89
|
|
|
92
|
-
var previewActionProps = getInvokeOpts(key, 'PreviewAction', source
|
|
90
|
+
var previewActionProps = getInvokeOpts(key, 'PreviewAction', source); // - Promise invoked by the action invocation handler; open preview.
|
|
93
91
|
|
|
94
92
|
previewActionProps.action.promise = previewAction.promise; // - Promise invoked on click of `Preview` on block card; trigger above promise.
|
|
95
93
|
|