@atlaskit/smart-card 20.0.4 → 20.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +41 -0
- package/dist/cjs/state/actions/constants.js +4 -2
- package/dist/cjs/state/actions/index.js +51 -19
- package/dist/cjs/state/analytics/useSmartLinkAnalytics.js +26 -6
- package/dist/cjs/version.json +1 -1
- package/dist/cjs/view/BlockCard/index.js +29 -0
- package/dist/cjs/view/CardWithUrl/component.js +7 -2
- package/dist/cjs/view/CardWithUrl/loader.js +7 -9
- package/dist/cjs/view/EmbedCard/index.js +29 -0
- package/dist/cjs/view/FlexibleCard/components/blocks/element-group/index.js +2 -2
- package/dist/cjs/view/FlexibleCard/index.js +34 -7
- package/dist/cjs/view/HoverCard/components/HoverCardComponent.js +143 -0
- package/dist/cjs/view/HoverCard/components/{hover-card-content.js → HoverCardContent.js} +29 -25
- package/dist/cjs/view/HoverCard/index.js +25 -126
- package/dist/cjs/view/HoverCard/styled.js +11 -1
- package/dist/cjs/view/HoverCard/utils.js +3 -3
- package/dist/cjs/view/InlineCard/index.js +29 -0
- package/dist/es2019/state/actions/constants.js +2 -1
- package/dist/es2019/state/actions/index.js +46 -18
- package/dist/es2019/state/analytics/useSmartLinkAnalytics.js +24 -7
- package/dist/es2019/version.json +1 -1
- package/dist/es2019/view/BlockCard/index.js +29 -0
- package/dist/es2019/view/CardWithUrl/component.js +7 -2
- package/dist/es2019/view/CardWithUrl/loader.js +8 -10
- package/dist/es2019/view/EmbedCard/index.js +29 -0
- package/dist/es2019/view/FlexibleCard/components/blocks/element-group/index.js +4 -0
- package/dist/es2019/view/FlexibleCard/index.js +32 -7
- package/dist/es2019/view/HoverCard/components/HoverCardComponent.js +102 -0
- package/dist/es2019/view/HoverCard/components/{hover-card-content.js → HoverCardContent.js} +18 -21
- package/dist/es2019/view/HoverCard/index.js +26 -97
- package/dist/es2019/view/HoverCard/styled.js +8 -0
- package/dist/es2019/view/HoverCard/utils.js +1 -1
- package/dist/es2019/view/InlineCard/index.js +29 -0
- package/dist/esm/state/actions/constants.js +2 -1
- package/dist/esm/state/actions/index.js +51 -20
- package/dist/esm/state/analytics/useSmartLinkAnalytics.js +27 -7
- package/dist/esm/version.json +1 -1
- package/dist/esm/view/BlockCard/index.js +29 -0
- package/dist/esm/view/CardWithUrl/component.js +7 -2
- package/dist/esm/view/CardWithUrl/loader.js +8 -10
- package/dist/esm/view/EmbedCard/index.js +29 -0
- package/dist/esm/view/FlexibleCard/components/blocks/element-group/index.js +2 -2
- package/dist/esm/view/FlexibleCard/index.js +33 -7
- package/dist/esm/view/HoverCard/components/HoverCardComponent.js +114 -0
- package/dist/esm/view/HoverCard/components/{hover-card-content.js → HoverCardContent.js} +20 -22
- package/dist/esm/view/HoverCard/index.js +24 -109
- package/dist/esm/view/HoverCard/styled.js +8 -0
- package/dist/esm/view/HoverCard/utils.js +1 -1
- package/dist/esm/view/InlineCard/index.js +29 -0
- package/dist/types/state/actions/constants.d.ts +1 -0
- package/dist/types/state/actions/index.d.ts +1 -0
- package/dist/types/state/analytics/useSmartLinkAnalytics.d.ts +9 -0
- package/dist/types/state/hooks/useSmartLink.d.ts +3 -0
- package/dist/types/view/BlockCard/types.d.ts +2 -0
- package/dist/types/view/Card/index.d.ts +1 -1
- package/dist/types/view/Card/types.d.ts +2 -1
- package/dist/types/view/CardWithUrl/component.d.ts +1 -1
- package/dist/types/view/CardWithUrl/types.d.ts +2 -1
- package/dist/types/view/EmbedCard/components/styled.d.ts +16 -16
- package/dist/types/view/EmbedCard/types.d.ts +2 -0
- package/dist/types/view/FlexibleCard/types.d.ts +9 -4
- package/dist/types/view/HoverCard/components/HoverCardComponent.d.ts +4 -0
- package/dist/types/view/HoverCard/components/HoverCardContent.d.ts +9 -0
- package/dist/types/view/HoverCard/index.d.ts +2 -4
- package/dist/types/view/HoverCard/styled.d.ts +2 -0
- package/dist/types/view/HoverCard/types.d.ts +8 -0
- package/dist/types/view/HoverCard/utils.d.ts +1 -1
- package/dist/types/view/InlineCard/Frame/styled.d.ts +1 -1
- package/dist/types/view/InlineCard/Icon.d.ts +3 -3
- package/dist/types/view/InlineCard/IconAndTitleLayout/styled.d.ts +9 -9
- package/dist/types/view/InlineCard/ResolvingView/styled.d.ts +13 -5
- package/dist/types/view/InlineCard/styled.d.ts +8 -4
- package/dist/types/view/InlineCard/types.d.ts +2 -1
- package/dist/types/view/types.d.ts +6 -0
- package/package.json +4 -4
- package/dist/types/view/HoverCard/components/hover-card-content.d.ts +0 -4
|
@@ -1,24 +1,17 @@
|
|
|
1
|
+
import ShortcutIcon from '@atlaskit/icon/glyph/shortcut';
|
|
2
|
+
import { extractType } from '@atlaskit/linking-common/extractors';
|
|
1
3
|
import React, { useCallback, useEffect, useMemo } from 'react';
|
|
2
|
-
import {
|
|
3
|
-
import { getSimulatedMetadata, HOVER_CARD_ANALYTICS_DISPLAY } from '../utils';
|
|
4
|
+
import { ActionName, SmartLinkPosition, SmartLinkSize } from '../../../constants';
|
|
4
5
|
import extractPreview from '../../../extractors/flexible/extract-preview';
|
|
5
|
-
import {
|
|
6
|
+
import { extractMetadata } from '../../../extractors/hover/extractMetadata';
|
|
7
|
+
import { useSmartCardActions } from '../../../state/actions';
|
|
8
|
+
import { getExtensionKey } from '../../../state/helpers';
|
|
9
|
+
import { isSpecialEvent } from '../../../utils';
|
|
6
10
|
import FlexibleCard from '../../FlexibleCard';
|
|
7
11
|
import { FooterBlock, MetadataBlock, PreviewBlock, SnippetBlock, TitleBlock } from '../../FlexibleCard/components/blocks';
|
|
8
|
-
import {
|
|
9
|
-
import
|
|
10
|
-
|
|
11
|
-
import { titleBlockCss, metadataBlockCss, footerBlockCss } from '../styled';
|
|
12
|
-
import { extractType } from '@atlaskit/linking-common/extractors';
|
|
13
|
-
const flexibleUiOptions = {
|
|
14
|
-
hideElevation: true,
|
|
15
|
-
size: SmartLinkSize.Medium,
|
|
16
|
-
// eslint-disable-next-line @atlaskit/design-system/ensure-design-token-usage
|
|
17
|
-
theme: SmartLinkTheme.Black,
|
|
18
|
-
hidePadding: true
|
|
19
|
-
};
|
|
20
|
-
|
|
21
|
-
const getOpenAction = (url, analytics, onActionClick) => ({
|
|
12
|
+
import { flexibleUiOptions, footerBlockCss, metadataBlockCss, titleBlockCss } from '../styled';
|
|
13
|
+
import { getSimulatedMetadata, SMART_CARD_ANALYTICS_DISPLAY } from '../utils';
|
|
14
|
+
export const getOpenAction = (url, analytics, onActionClick) => ({
|
|
22
15
|
name: ActionName.CustomAction,
|
|
23
16
|
icon: /*#__PURE__*/React.createElement(ShortcutIcon, {
|
|
24
17
|
label: "open in new tab",
|
|
@@ -35,8 +28,7 @@ const getOpenAction = (url, analytics, onActionClick) => ({
|
|
|
35
28
|
},
|
|
36
29
|
testId: 'hover-card-open-button'
|
|
37
30
|
});
|
|
38
|
-
|
|
39
|
-
const toFooterActions = (cardActions, onActionClick) => cardActions.map(action => ({
|
|
31
|
+
export const toFooterActions = (cardActions, onActionClick) => cardActions.map(action => ({
|
|
40
32
|
content: action.text,
|
|
41
33
|
name: ActionName.CustomAction,
|
|
42
34
|
onClick: () => {
|
|
@@ -50,6 +42,7 @@ const toFooterActions = (cardActions, onActionClick) => cardActions.map(action =
|
|
|
50
42
|
}));
|
|
51
43
|
|
|
52
44
|
const HoverCardContent = ({
|
|
45
|
+
id = '',
|
|
53
46
|
analytics,
|
|
54
47
|
cardActions = [],
|
|
55
48
|
cardState,
|
|
@@ -60,15 +53,19 @@ const HoverCardContent = ({
|
|
|
60
53
|
}) => {
|
|
61
54
|
var _cardState$details;
|
|
62
55
|
|
|
56
|
+
const actions = useSmartCardActions(id, url, analytics);
|
|
57
|
+
useEffect(() => {
|
|
58
|
+
actions.loadMetadata();
|
|
59
|
+
}, [actions]);
|
|
63
60
|
useEffect(() => {
|
|
64
61
|
// Since hover preview only render on resolved status,
|
|
65
62
|
// there is no need to check for statuses.
|
|
66
|
-
analytics.ui.renderSuccessEvent(
|
|
63
|
+
analytics.ui.renderSuccessEvent(SMART_CARD_ANALYTICS_DISPLAY, cardState.status);
|
|
67
64
|
}, [analytics.ui, cardState.status]);
|
|
68
65
|
const extensionKey = useMemo(() => getExtensionKey(cardState.details), [cardState.details]);
|
|
69
66
|
const onClick = useCallback(event => {
|
|
70
67
|
const isModifierKeyPressed = isSpecialEvent(event);
|
|
71
|
-
analytics.ui.cardClickedEvent(undefined,
|
|
68
|
+
analytics.ui.cardClickedEvent(undefined, SMART_CARD_ANALYTICS_DISPLAY, cardState.status, undefined, undefined, isModifierKeyPressed, undefined, undefined, undefined, 'titleGoToLink');
|
|
72
69
|
}, [cardState.status, analytics.ui]);
|
|
73
70
|
const titleActions = useMemo(() => [getOpenAction(url, analytics, onActionClick)], [url, analytics, onActionClick]);
|
|
74
71
|
const footerActions = useMemo(() => toFooterActions(cardActions, onActionClick), [cardActions, onActionClick]);
|
|
@@ -1,109 +1,38 @@
|
|
|
1
1
|
import _extends from "@babel/runtime/helpers/extends";
|
|
2
2
|
|
|
3
3
|
/** @jsx jsx */
|
|
4
|
-
import { jsx } from '@emotion/core';
|
|
5
|
-
import React, { useCallback, useRef } from 'react';
|
|
6
|
-
import Popup from '@atlaskit/popup';
|
|
7
|
-
import { useSmartLinkActions } from '../../state/hooks-external/useSmartLinkActions';
|
|
8
|
-
import { HoverCardContainer } from './styled';
|
|
9
4
|
import { withAnalyticsContext, withAnalyticsEvents } from '@atlaskit/analytics-next';
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
5
|
+
import { jsx } from '@emotion/core';
|
|
6
|
+
import { useCallback } from 'react';
|
|
7
|
+
import { ErrorBoundary } from 'react-error-boundary';
|
|
12
8
|
import { useSmartLinkAnalytics } from '../../state/analytics';
|
|
13
|
-
import {
|
|
14
|
-
import
|
|
15
|
-
import {
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
9
|
+
import { fireSmartLinkEvent } from '../../utils/analytics';
|
|
10
|
+
import { HoverCardComponent } from './components/HoverCardComponent';
|
|
11
|
+
import { SMART_CARD_ANALYTICS_DISPLAY } from './utils';
|
|
12
|
+
|
|
13
|
+
const HoverCardWithErrorBoundary = props => {
|
|
14
|
+
const {
|
|
15
|
+
url,
|
|
16
|
+
id,
|
|
17
|
+
children,
|
|
18
|
+
createAnalyticsEvent
|
|
19
|
+
} = props;
|
|
23
20
|
const analyticsHandler = useCallback(analyticsPayload => {
|
|
24
21
|
fireSmartLinkEvent(analyticsPayload, createAnalyticsEvent);
|
|
25
22
|
}, [createAnalyticsEvent]);
|
|
26
|
-
const delay = 300;
|
|
27
|
-
const [isOpen, setIsOpen] = React.useState(false);
|
|
28
|
-
const fadeOutTimeoutId = useRef();
|
|
29
|
-
const fadeInTimeoutId = useRef();
|
|
30
|
-
const cardOpenTime = useRef();
|
|
31
|
-
const renderers = useSmartLinkRenderers();
|
|
32
|
-
const linkState = useLinkState(url);
|
|
33
23
|
const analytics = useSmartLinkAnalytics(url, analyticsHandler, id);
|
|
34
|
-
const
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
if (fadeInTimeoutId.current) {
|
|
45
|
-
clearTimeout(fadeInTimeoutId.current);
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
fadeOutTimeoutId.current = setTimeout(() => hideCard(), delay);
|
|
49
|
-
}, [hideCard]);
|
|
50
|
-
const initShowCard = useCallback(() => {
|
|
51
|
-
if (fadeOutTimeoutId.current) {
|
|
52
|
-
clearTimeout(fadeOutTimeoutId.current);
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
fadeInTimeoutId.current = setTimeout(() => {
|
|
56
|
-
//Check if its previously closed to avoid firing events when moving between the child and hover card components
|
|
57
|
-
if (isOpen === false) {
|
|
58
|
-
cardOpenTime.current = Date.now();
|
|
59
|
-
analytics.ui.hoverCardViewedEvent('card', 'mouse_hover');
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
setIsOpen(true);
|
|
63
|
-
}, delay);
|
|
64
|
-
}, [delay, isOpen, analytics.ui]);
|
|
65
|
-
const linkActions = useSmartLinkActions({
|
|
66
|
-
url,
|
|
67
|
-
appearance: HOVER_CARD_ANALYTICS_DISPLAY,
|
|
68
|
-
analyticsHandler
|
|
69
|
-
});
|
|
70
|
-
const onActionClick = useCallback(actionId => {
|
|
71
|
-
if (actionId === 'preview-content') {
|
|
72
|
-
hideCard();
|
|
73
|
-
}
|
|
74
|
-
}, [hideCard]); // Stop hover preview content to propagate event to parent.
|
|
75
|
-
|
|
76
|
-
const onClick = useCallback(e => e.stopPropagation(), []);
|
|
77
|
-
return jsx(Popup, {
|
|
78
|
-
testId: "hover-card",
|
|
79
|
-
isOpen: isOpen,
|
|
80
|
-
onClose: hideCard,
|
|
81
|
-
placement: "bottom-start",
|
|
82
|
-
content: ({
|
|
83
|
-
update
|
|
84
|
-
}) => jsx("div", {
|
|
85
|
-
onMouseEnter: initShowCard,
|
|
86
|
-
onMouseLeave: initHideCard,
|
|
87
|
-
className: hoverCardClassName,
|
|
88
|
-
css: HoverCardContainer,
|
|
89
|
-
onClick: onClick
|
|
90
|
-
}, jsx(HoverCardContent, {
|
|
91
|
-
analytics: analytics,
|
|
92
|
-
cardActions: linkActions,
|
|
93
|
-
cardState: linkState,
|
|
94
|
-
onActionClick: onActionClick,
|
|
95
|
-
onResolve: update,
|
|
96
|
-
renderers: renderers,
|
|
97
|
-
url: url
|
|
98
|
-
})),
|
|
99
|
-
trigger: triggerProps => jsx("span", _extends({}, triggerProps, {
|
|
100
|
-
onMouseEnter: initShowCard,
|
|
101
|
-
onMouseLeave: initHideCard
|
|
102
|
-
}), children),
|
|
103
|
-
zIndex: 511 // Temporary fix for Confluence inline comment on editor mod has z-index of 500, Jira issue view has z-index of 510
|
|
104
|
-
|
|
105
|
-
});
|
|
24
|
+
const onError = useCallback((error, info) => {
|
|
25
|
+
analytics.ui.renderFailedEvent(SMART_CARD_ANALYTICS_DISPLAY, id, error, info);
|
|
26
|
+
}, [analytics.ui, id]);
|
|
27
|
+
return jsx(ErrorBoundary, {
|
|
28
|
+
fallback: children,
|
|
29
|
+
onError: onError
|
|
30
|
+
}, jsx(HoverCardComponent, _extends({}, props, {
|
|
31
|
+
analyticsHandler: analyticsHandler,
|
|
32
|
+
analytics: analytics
|
|
33
|
+
}), children));
|
|
106
34
|
};
|
|
35
|
+
|
|
107
36
|
export const HoverCard = withAnalyticsContext({
|
|
108
37
|
source: 'smartLinkPreviewHoverCard'
|
|
109
|
-
})(withAnalyticsEvents()(
|
|
38
|
+
})(withAnalyticsEvents()(HoverCardWithErrorBoundary));
|
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
import { css } from '@emotion/core';
|
|
2
2
|
import { loadingPlaceholderClassName } from '../../index';
|
|
3
|
+
import { SmartLinkSize, SmartLinkTheme } from '../../constants';
|
|
4
|
+
export const flexibleUiOptions = {
|
|
5
|
+
hideElevation: true,
|
|
6
|
+
size: SmartLinkSize.Medium,
|
|
7
|
+
// eslint-disable-next-line @atlaskit/design-system/ensure-design-token-usage
|
|
8
|
+
theme: SmartLinkTheme.Black,
|
|
9
|
+
hidePadding: true
|
|
10
|
+
};
|
|
3
11
|
const blockGap = '0.5rem';
|
|
4
12
|
const elementGap = '0.5rem';
|
|
5
13
|
const separatorCss = css`
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ElementName } from '../../constants';
|
|
2
|
-
export const
|
|
2
|
+
export const SMART_CARD_ANALYTICS_DISPLAY = 'flexible';
|
|
3
3
|
export const getSimulatedMetadata = (extensionKey = '', types = []) => {
|
|
4
4
|
switch (extensionKey) {
|
|
5
5
|
case 'bitbucket-object-provider':
|
|
@@ -20,6 +20,7 @@ export const InlineCard = ({
|
|
|
20
20
|
isSelected,
|
|
21
21
|
renderers,
|
|
22
22
|
onResolve,
|
|
23
|
+
onError,
|
|
23
24
|
testId,
|
|
24
25
|
inlinePreloaderStyle,
|
|
25
26
|
showHoverPreview
|
|
@@ -64,6 +65,13 @@ export const InlineCard = ({
|
|
|
64
65
|
}));
|
|
65
66
|
|
|
66
67
|
case 'unauthorized':
|
|
68
|
+
if (onError) {
|
|
69
|
+
onError({
|
|
70
|
+
url,
|
|
71
|
+
status
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
|
|
67
75
|
const provider = extractProvider(cardDetails);
|
|
68
76
|
return /*#__PURE__*/React.createElement(InlineCardUnauthorizedView, {
|
|
69
77
|
icon: provider && provider.icon,
|
|
@@ -75,6 +83,13 @@ export const InlineCard = ({
|
|
|
75
83
|
});
|
|
76
84
|
|
|
77
85
|
case 'forbidden':
|
|
86
|
+
if (onError) {
|
|
87
|
+
onError({
|
|
88
|
+
url,
|
|
89
|
+
status
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
|
|
78
93
|
const providerForbidden = extractProvider(cardDetails);
|
|
79
94
|
const cardMetadata = (_details$meta = details === null || details === void 0 ? void 0 : details.meta) !== null && _details$meta !== void 0 ? _details$meta : getUnauthorizedJsonLd().meta;
|
|
80
95
|
const requestAccessContext = extractRequestAccessContext({
|
|
@@ -94,6 +109,13 @@ export const InlineCard = ({
|
|
|
94
109
|
});
|
|
95
110
|
|
|
96
111
|
case 'not_found':
|
|
112
|
+
if (onError) {
|
|
113
|
+
onError({
|
|
114
|
+
url,
|
|
115
|
+
status
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
|
|
97
119
|
const providerNotFound = extractProvider(cardDetails);
|
|
98
120
|
return /*#__PURE__*/React.createElement(InlineCardErroredView, {
|
|
99
121
|
url: url,
|
|
@@ -106,6 +128,13 @@ export const InlineCard = ({
|
|
|
106
128
|
|
|
107
129
|
case 'fallback':
|
|
108
130
|
case 'errored':
|
|
131
|
+
if (onError) {
|
|
132
|
+
onError({
|
|
133
|
+
url,
|
|
134
|
+
status
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
|
|
109
138
|
return /*#__PURE__*/React.createElement(CardLinkView, {
|
|
110
139
|
link: url,
|
|
111
140
|
isSelected: isSelected,
|
|
@@ -2,4 +2,5 @@ export var ANALYTICS_RESOLVING = 'resolving';
|
|
|
2
2
|
export var ANALYTICS_ERROR = 'errored';
|
|
3
3
|
export var ANALYTICS_FALLBACK = 'fallback';
|
|
4
4
|
export var ERROR_MESSAGE_OAUTH = 'Provider.authFlow is not set to OAuth2.';
|
|
5
|
-
export var ERROR_MESSAGE_FATAL = 'Fatal error resolving URL';
|
|
5
|
+
export var ERROR_MESSAGE_FATAL = 'Fatal error resolving URL';
|
|
6
|
+
export var ERROR_MESSAGE_METADATA = 'Error resolving metadata.';
|
|
@@ -2,11 +2,10 @@ import _asyncToGenerator from "@babel/runtime/helpers/asyncToGenerator";
|
|
|
2
2
|
import _regeneratorRuntime from "@babel/runtime/regenerator";
|
|
3
3
|
import { useMemo, useCallback } from 'react';
|
|
4
4
|
import { auth } from '@atlaskit/outbound-auth-flow-client';
|
|
5
|
-
import { APIError } from '@atlaskit/linking-common';
|
|
6
5
|
import { useSmartLinkContext } from '@atlaskit/link-provider';
|
|
7
|
-
import { ACTION_PENDING, ACTION_RESOLVED, ACTION_ERROR, ACTION_ERROR_FALLBACK, ACTION_RELOADING, cardAction } from '@atlaskit/linking-common';
|
|
6
|
+
import { ACTION_PENDING, ACTION_RESOLVED, ACTION_ERROR, ACTION_ERROR_FALLBACK, ACTION_RELOADING, ACTION_UPDATE_METADATA_STATUS, cardAction, APIError } from '@atlaskit/linking-common';
|
|
8
7
|
import { getDefinitionId, getByDefinitionId, getServices, getStatus, getExtensionKey } from '../helpers';
|
|
9
|
-
import { ERROR_MESSAGE_OAUTH, ERROR_MESSAGE_FATAL } from './constants';
|
|
8
|
+
import { ERROR_MESSAGE_OAUTH, ERROR_MESSAGE_FATAL, ERROR_MESSAGE_METADATA } from './constants';
|
|
10
9
|
import * as measure from '../../utils/performance';
|
|
11
10
|
import { getUnauthorizedJsonLd } from '../../utils/jsonld';
|
|
12
11
|
import { addMetadataToExperience } from '../analytics';
|
|
@@ -24,11 +23,23 @@ export var useSmartCardActions = function useSmartCardActions(id, url, analytics
|
|
|
24
23
|
details: undefined
|
|
25
24
|
},
|
|
26
25
|
details = _ref.details,
|
|
27
|
-
status = _ref.status
|
|
26
|
+
status = _ref.status,
|
|
27
|
+
metadataStatus = _ref.metadataStatus;
|
|
28
28
|
|
|
29
29
|
var hasAuthFlowSupported = config.authFlow !== 'disabled';
|
|
30
30
|
var hasData = !!(details && details.data);
|
|
31
|
-
var
|
|
31
|
+
var setMetadataStatus = useCallback(function (metadataStatus) {
|
|
32
|
+
dispatch(cardAction(ACTION_UPDATE_METADATA_STATUS, {
|
|
33
|
+
url: url
|
|
34
|
+
}, undefined, undefined, metadataStatus));
|
|
35
|
+
}, [dispatch, url]);
|
|
36
|
+
var handleResolvedLinkError = useCallback(function (url, error, response, isMetadataRequest) {
|
|
37
|
+
// If metadata request then set metadata status, return and do not alter link status
|
|
38
|
+
if (isMetadataRequest) {
|
|
39
|
+
setMetadataStatus('errored');
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
|
|
32
43
|
if (error.kind === 'fatal') {
|
|
33
44
|
// If there's no previous data in the store for this URL, then bail
|
|
34
45
|
// out and let the editor handle fallbacks (returns to a blue link).
|
|
@@ -65,25 +76,34 @@ export var useSmartCardActions = function useSmartCardActions(id, url, analytics
|
|
|
65
76
|
}, undefined, error));
|
|
66
77
|
}
|
|
67
78
|
}
|
|
68
|
-
}, [hasData, status, dispatch, details]);
|
|
79
|
+
}, [setMetadataStatus, hasData, status, dispatch, details]);
|
|
69
80
|
var handleResolvedLinkResponse = useCallback(function (resourceUrl, response) {
|
|
70
81
|
var isReloading = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
|
|
82
|
+
var isMetadataRequest = arguments.length > 3 ? arguments[3] : undefined;
|
|
71
83
|
var hostname = new URL(resourceUrl).hostname;
|
|
72
84
|
var nextStatus = response ? getStatus(response) : 'fatal'; // If we require authorization & do not have an authFlow available,
|
|
73
85
|
// throw an error and render as a normal blue link.
|
|
74
86
|
|
|
75
87
|
if ((nextStatus === 'unauthorized' || nextStatus === 'forbidden') && !hasAuthFlowSupported) {
|
|
76
|
-
handleResolvedLinkError(resourceUrl, new APIError('fallback', hostname, ERROR_MESSAGE_OAUTH), response);
|
|
88
|
+
handleResolvedLinkError(resourceUrl, new APIError('fallback', hostname, ERROR_MESSAGE_OAUTH), response, isMetadataRequest);
|
|
77
89
|
return;
|
|
78
90
|
} // Handle any other errors
|
|
79
91
|
|
|
80
92
|
|
|
81
93
|
if (nextStatus === 'fatal') {
|
|
82
|
-
handleResolvedLinkError(resourceUrl, new APIError('fatal', hostname, ERROR_MESSAGE_FATAL));
|
|
94
|
+
handleResolvedLinkError(resourceUrl, new APIError('fatal', hostname, ERROR_MESSAGE_FATAL), undefined, isMetadataRequest);
|
|
95
|
+
return;
|
|
96
|
+
} // Handle errors of any other kind in the metadata request response
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
if (isMetadataRequest && nextStatus !== 'resolved') {
|
|
100
|
+
handleResolvedLinkError(resourceUrl, new APIError('error', hostname, ERROR_MESSAGE_METADATA), response, isMetadataRequest);
|
|
83
101
|
return;
|
|
84
|
-
} //
|
|
102
|
+
} //if a link resolves normally, metadata will also always be resolved
|
|
85
103
|
|
|
86
104
|
|
|
105
|
+
setMetadataStatus('resolved'); // Dispatch Analytics and resolved card action - including unauthorized states.
|
|
106
|
+
|
|
87
107
|
if (isReloading) {
|
|
88
108
|
dispatch(cardAction(ACTION_RELOADING, {
|
|
89
109
|
url: resourceUrl
|
|
@@ -91,12 +111,13 @@ export var useSmartCardActions = function useSmartCardActions(id, url, analytics
|
|
|
91
111
|
} else {
|
|
92
112
|
dispatch(cardAction(ACTION_RESOLVED, {
|
|
93
113
|
url: resourceUrl
|
|
94
|
-
}, response));
|
|
114
|
+
}, response, undefined, undefined, isMetadataRequest));
|
|
95
115
|
}
|
|
96
|
-
}, [dispatch, handleResolvedLinkError, hasAuthFlowSupported]);
|
|
116
|
+
}, [dispatch, handleResolvedLinkError, hasAuthFlowSupported, setMetadataStatus]);
|
|
97
117
|
var resolve = useCallback( /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee() {
|
|
98
118
|
var resourceUrl,
|
|
99
119
|
isReloading,
|
|
120
|
+
isMetadataRequest,
|
|
100
121
|
_args = arguments;
|
|
101
122
|
return _regeneratorRuntime.wrap(function _callee$(_context) {
|
|
102
123
|
while (1) {
|
|
@@ -104,24 +125,25 @@ export var useSmartCardActions = function useSmartCardActions(id, url, analytics
|
|
|
104
125
|
case 0:
|
|
105
126
|
resourceUrl = _args.length > 0 && _args[0] !== undefined ? _args[0] : url;
|
|
106
127
|
isReloading = _args.length > 1 && _args[1] !== undefined ? _args[1] : false;
|
|
128
|
+
isMetadataRequest = _args.length > 2 && _args[2] !== undefined ? _args[2] : false;
|
|
107
129
|
|
|
108
|
-
if (!(isReloading || !hasData)) {
|
|
109
|
-
_context.next =
|
|
130
|
+
if (!(isReloading || !hasData || isMetadataRequest)) {
|
|
131
|
+
_context.next = 7;
|
|
110
132
|
break;
|
|
111
133
|
}
|
|
112
134
|
|
|
113
135
|
return _context.abrupt("return", connections.client.fetchData(resourceUrl).then(function (response) {
|
|
114
|
-
return handleResolvedLinkResponse(resourceUrl, response, isReloading);
|
|
136
|
+
return handleResolvedLinkResponse(resourceUrl, response, isReloading, isMetadataRequest);
|
|
115
137
|
}).catch(function (error) {
|
|
116
|
-
return handleResolvedLinkError(resourceUrl, error);
|
|
138
|
+
return handleResolvedLinkError(resourceUrl, error, undefined, isMetadataRequest);
|
|
117
139
|
}));
|
|
118
140
|
|
|
119
|
-
case
|
|
141
|
+
case 7:
|
|
120
142
|
addMetadataToExperience('smart-link-rendered', id, {
|
|
121
143
|
cached: true
|
|
122
144
|
});
|
|
123
145
|
|
|
124
|
-
case
|
|
146
|
+
case 8:
|
|
125
147
|
case "end":
|
|
126
148
|
return _context.stop();
|
|
127
149
|
}
|
|
@@ -133,10 +155,11 @@ export var useSmartCardActions = function useSmartCardActions(id, url, analytics
|
|
|
133
155
|
dispatch(cardAction(ACTION_PENDING, {
|
|
134
156
|
url: url
|
|
135
157
|
}));
|
|
158
|
+
setMetadataStatus('pending');
|
|
136
159
|
}
|
|
137
160
|
|
|
138
161
|
return resolve();
|
|
139
|
-
}, [
|
|
162
|
+
}, [details, resolve, dispatch, url, setMetadataStatus]);
|
|
140
163
|
var reload = useCallback(function () {
|
|
141
164
|
var definitionId = getDefinitionId(details);
|
|
142
165
|
|
|
@@ -148,6 +171,13 @@ export var useSmartCardActions = function useSmartCardActions(id, url, analytics
|
|
|
148
171
|
resolve(url, true);
|
|
149
172
|
}
|
|
150
173
|
}, [url, details, getState, resolve]);
|
|
174
|
+
var loadMetadata = useCallback(function () {
|
|
175
|
+
//metadataStatus will be undefined for SSR links only
|
|
176
|
+
if (metadataStatus === undefined) {
|
|
177
|
+
setMetadataStatus('pending');
|
|
178
|
+
return resolve(url, false, true);
|
|
179
|
+
}
|
|
180
|
+
}, [metadataStatus, resolve, setMetadataStatus, url]);
|
|
151
181
|
var authorize = useCallback(function (appearance) {
|
|
152
182
|
var definitionId = getDefinitionId(details);
|
|
153
183
|
var extensionKey = getExtensionKey(details);
|
|
@@ -243,7 +273,8 @@ export var useSmartCardActions = function useSmartCardActions(id, url, analytics
|
|
|
243
273
|
register: register,
|
|
244
274
|
reload: reload,
|
|
245
275
|
authorize: authorize,
|
|
246
|
-
invoke: invoke
|
|
276
|
+
invoke: invoke,
|
|
277
|
+
loadMetadata: loadMetadata
|
|
247
278
|
};
|
|
248
|
-
}, [register, reload, authorize, invoke]);
|
|
279
|
+
}, [register, reload, authorize, invoke, loadMetadata]);
|
|
249
280
|
};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { useMemo } from 'react';
|
|
2
2
|
import { getUrl } from '@atlaskit/linking-common';
|
|
3
|
-
import { uiAuthEvent, uiAuthAlternateAccountEvent, uiCardClickedEvent, uiActionClickedEvent, uiClosedAuthEvent, uiRenderSuccessEvent, uiHoverCardViewedEvent, uiHoverCardDismissedEvent, uiHoverCardOpenLinkClickedEvent, invokeSucceededEvent as _invokeSucceededEvent, invokeFailedEvent as _invokeFailedEvent, connectSucceededEvent as _connectSucceededEvent, connectFailedEvent as _connectFailedEvent, trackAppAccountConnected, screenAuthPopupEvent, instrumentEvent } from '../../utils/analytics';
|
|
3
|
+
import { uiAuthEvent, uiAuthAlternateAccountEvent, uiCardClickedEvent, uiActionClickedEvent, uiClosedAuthEvent, uiRenderSuccessEvent, uiRenderFailedEvent, uiHoverCardViewedEvent, uiHoverCardDismissedEvent, uiHoverCardOpenLinkClickedEvent, invokeSucceededEvent as _invokeSucceededEvent, invokeFailedEvent as _invokeFailedEvent, connectSucceededEvent as _connectSucceededEvent, connectFailedEvent as _connectFailedEvent, trackAppAccountConnected, screenAuthPopupEvent, instrumentEvent } from '../../utils/analytics';
|
|
4
4
|
import { failUfoExperience, startUfoExperience, succeedUfoExperience } from './ufoExperiences';
|
|
5
5
|
import { getDefinitionId, getExtensionKey, getResourceType, getSubproduct, getProduct } from '../helpers';
|
|
6
6
|
import { useSmartLinkContext } from '@atlaskit/link-provider';
|
|
@@ -20,12 +20,13 @@ export var useSmartLinkAnalytics = function useSmartLinkAnalytics(url, dispatchA
|
|
|
20
20
|
var _useSmartLinkContext = useSmartLinkContext(),
|
|
21
21
|
store = _useSmartLinkContext.store;
|
|
22
22
|
|
|
23
|
-
var state = getUrl(store, url);
|
|
24
|
-
var
|
|
25
|
-
var
|
|
26
|
-
var
|
|
27
|
-
var
|
|
28
|
-
var
|
|
23
|
+
var state = store ? getUrl(store, url) : undefined;
|
|
24
|
+
var details = state ? state.details : undefined;
|
|
25
|
+
var extractedDefinitionId = getDefinitionId(details);
|
|
26
|
+
var extractedExtensionKey = getExtensionKey(details);
|
|
27
|
+
var extractedResourceType = getResourceType(details);
|
|
28
|
+
var extractedSubproduct = getSubproduct(details);
|
|
29
|
+
var extractedProduct = getProduct(details);
|
|
29
30
|
/** Contains all ui analytics events */
|
|
30
31
|
|
|
31
32
|
var ui = useMemo(function () {
|
|
@@ -160,6 +161,25 @@ export var useSmartLinkAnalytics = function useSmartLinkAnalytics(url, dispatchA
|
|
|
160
161
|
dispatchAnalytics(uiRenderSuccessEvent(display, status, definitionId, extensionKey));
|
|
161
162
|
},
|
|
162
163
|
|
|
164
|
+
/**
|
|
165
|
+
* This fires an event that represents when a Smart Link renders unsuccessfuly.
|
|
166
|
+
* @param display Whether the card was an Inline, Block, Embed or Flexible UI.
|
|
167
|
+
* @param id The unique ID for this Smart Link.
|
|
168
|
+
* @param error: An error representing why the Smart Link render failed.
|
|
169
|
+
* @param errorInfo: Additional details about the error including the stack trace.
|
|
170
|
+
*/
|
|
171
|
+
renderFailedEvent: function renderFailedEvent(display) {
|
|
172
|
+
var id = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : defaultId;
|
|
173
|
+
var error = arguments.length > 2 ? arguments[2] : undefined;
|
|
174
|
+
var errorInfo = arguments.length > 3 ? arguments[3] : undefined;
|
|
175
|
+
// Start and fail the smart-link-rendered experience. If it has already
|
|
176
|
+
// been started nothing happens.
|
|
177
|
+
startUfoExperience('smart-link-rendered', id);
|
|
178
|
+
failUfoExperience('smart-link-rendered', id);
|
|
179
|
+
failUfoExperience('smart-link-authenticated', id);
|
|
180
|
+
dispatchAnalytics(uiRenderFailedEvent(display, error, errorInfo));
|
|
181
|
+
},
|
|
182
|
+
|
|
163
183
|
/**
|
|
164
184
|
* This fires an event that represents a hover preview being opened.
|
|
165
185
|
* @param hoverDisplay Whether the hover preview was displayed as a card or embed.
|
package/dist/esm/version.json
CHANGED
|
@@ -31,6 +31,7 @@ export var BlockCard = function BlockCard(_ref) {
|
|
|
31
31
|
renderers = _ref.renderers,
|
|
32
32
|
isSelected = _ref.isSelected,
|
|
33
33
|
onResolve = _ref.onResolve,
|
|
34
|
+
onError = _ref.onError,
|
|
34
35
|
testId = _ref.testId,
|
|
35
36
|
showActions = _ref.showActions,
|
|
36
37
|
platform = _ref.platform;
|
|
@@ -68,6 +69,13 @@ export var BlockCard = function BlockCard(_ref) {
|
|
|
68
69
|
}));
|
|
69
70
|
|
|
70
71
|
case 'unauthorized':
|
|
72
|
+
if (onError) {
|
|
73
|
+
onError({
|
|
74
|
+
url: url,
|
|
75
|
+
status: status
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
|
|
71
79
|
var unauthorizedViewProps = extractBlockProps(data, meta, extractorOpts);
|
|
72
80
|
return /*#__PURE__*/React.createElement(BlockCardUnauthorisedView, _extends({}, unauthorizedViewProps, {
|
|
73
81
|
isSelected: isSelected,
|
|
@@ -78,6 +86,13 @@ export var BlockCard = function BlockCard(_ref) {
|
|
|
78
86
|
}));
|
|
79
87
|
|
|
80
88
|
case 'forbidden':
|
|
89
|
+
if (onError) {
|
|
90
|
+
onError({
|
|
91
|
+
url: url,
|
|
92
|
+
status: status
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
|
|
81
96
|
var forbiddenViewProps = extractBlockProps(data, meta, extractorOpts);
|
|
82
97
|
var cardMetadata = (_details$meta = details === null || details === void 0 ? void 0 : details.meta) !== null && _details$meta !== void 0 ? _details$meta : getUnauthorizedJsonLd().meta;
|
|
83
98
|
var requestAccessContext = extractRequestAccessContext({
|
|
@@ -94,6 +109,13 @@ export var BlockCard = function BlockCard(_ref) {
|
|
|
94
109
|
}));
|
|
95
110
|
|
|
96
111
|
case 'not_found':
|
|
112
|
+
if (onError) {
|
|
113
|
+
onError({
|
|
114
|
+
url: url,
|
|
115
|
+
status: status
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
|
|
97
119
|
var notFoundViewProps = extractBlockProps(data, meta, extractorOpts);
|
|
98
120
|
return /*#__PURE__*/React.createElement(BlockCardNotFoundView, _extends({}, notFoundViewProps, {
|
|
99
121
|
isSelected: isSelected,
|
|
@@ -103,6 +125,13 @@ export var BlockCard = function BlockCard(_ref) {
|
|
|
103
125
|
|
|
104
126
|
case 'fallback':
|
|
105
127
|
case 'errored':
|
|
128
|
+
if (onError) {
|
|
129
|
+
onError({
|
|
130
|
+
url: url,
|
|
131
|
+
status: status
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
|
|
106
135
|
if (authFlow && authFlow === 'disabled') {
|
|
107
136
|
return /*#__PURE__*/React.createElement(CardLinkView, {
|
|
108
137
|
link: url,
|
|
@@ -20,6 +20,7 @@ export function CardWithUrlContent(_ref) {
|
|
|
20
20
|
appearance = _ref.appearance,
|
|
21
21
|
dispatchAnalytics = _ref.dispatchAnalytics,
|
|
22
22
|
onResolve = _ref.onResolve,
|
|
23
|
+
onError = _ref.onError,
|
|
23
24
|
testId = _ref.testId,
|
|
24
25
|
showActions = _ref.showActions,
|
|
25
26
|
inheritDimensions = _ref.inheritDimensions,
|
|
@@ -97,7 +98,7 @@ export function CardWithUrlContent(_ref) {
|
|
|
97
98
|
if (isFinalState(state.status)) {
|
|
98
99
|
analytics.ui.renderSuccessEvent(appearance, state.status, id, definitionId, extensionKey);
|
|
99
100
|
}
|
|
100
|
-
}, [appearance, state.
|
|
101
|
+
}, [appearance, state.status, url, definitionId, extensionKey, analytics.ui, id]);
|
|
101
102
|
|
|
102
103
|
if (isFlexibleUi) {
|
|
103
104
|
var cardState = state;
|
|
@@ -121,7 +122,8 @@ export function CardWithUrlContent(_ref) {
|
|
|
121
122
|
ui: ui,
|
|
122
123
|
url: url,
|
|
123
124
|
testId: testId,
|
|
124
|
-
onResolve: onResolve
|
|
125
|
+
onResolve: onResolve,
|
|
126
|
+
onError: onError
|
|
125
127
|
}, children);
|
|
126
128
|
} // We have to keep this last to prevent hook order from being violated
|
|
127
129
|
|
|
@@ -141,6 +143,7 @@ export function CardWithUrlContent(_ref) {
|
|
|
141
143
|
handleFrameClick: handleClickWrapper,
|
|
142
144
|
isSelected: isSelected,
|
|
143
145
|
onResolve: onResolve,
|
|
146
|
+
onError: onError,
|
|
144
147
|
testId: testId,
|
|
145
148
|
inlinePreloaderStyle: inlinePreloaderStyle,
|
|
146
149
|
showHoverPreview: showHoverPreview
|
|
@@ -160,6 +163,7 @@ export function CardWithUrlContent(_ref) {
|
|
|
160
163
|
handleAnalytics: dispatchAnalytics,
|
|
161
164
|
isSelected: isSelected,
|
|
162
165
|
onResolve: onResolve,
|
|
166
|
+
onError: onError,
|
|
163
167
|
testId: testId,
|
|
164
168
|
showActions: showActions,
|
|
165
169
|
platform: platform
|
|
@@ -179,6 +183,7 @@ export function CardWithUrlContent(_ref) {
|
|
|
179
183
|
isFrameVisible: isFrameVisible,
|
|
180
184
|
platform: platform,
|
|
181
185
|
onResolve: onResolve,
|
|
186
|
+
onError: onError,
|
|
182
187
|
testId: testId,
|
|
183
188
|
inheritDimensions: inheritDimensions,
|
|
184
189
|
showActions: showActions,
|