@atlaskit/smart-card 20.0.6 → 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 +29 -0
- package/dist/cjs/state/actions/constants.js +4 -2
- package/dist/cjs/state/actions/index.js +51 -19
- 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 +2 -0
- package/dist/cjs/view/EmbedCard/index.js +29 -0
- package/dist/cjs/view/FlexibleCard/index.js +34 -7
- package/dist/cjs/view/HoverCard/components/HoverCardContent.js +9 -1
- 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/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 +2 -0
- package/dist/es2019/view/EmbedCard/index.js +29 -0
- package/dist/es2019/view/FlexibleCard/index.js +32 -7
- package/dist/es2019/view/HoverCard/components/HoverCardContent.js +6 -0
- 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/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 +2 -0
- package/dist/esm/view/EmbedCard/index.js +29 -0
- package/dist/esm/view/FlexibleCard/index.js +33 -7
- package/dist/esm/view/HoverCard/components/HoverCardContent.js +8 -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/hooks/useSmartLink.d.ts +1 -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/types.d.ts +1 -0
- 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
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
import { useMemo, useCallback } from 'react';
|
|
2
2
|
import { auth } from '@atlaskit/outbound-auth-flow-client';
|
|
3
|
-
import { APIError } from '@atlaskit/linking-common';
|
|
4
3
|
import { useSmartLinkContext } from '@atlaskit/link-provider';
|
|
5
|
-
import { ACTION_PENDING, ACTION_RESOLVED, ACTION_ERROR, ACTION_ERROR_FALLBACK, ACTION_RELOADING, cardAction } from '@atlaskit/linking-common';
|
|
4
|
+
import { ACTION_PENDING, ACTION_RESOLVED, ACTION_ERROR, ACTION_ERROR_FALLBACK, ACTION_RELOADING, ACTION_UPDATE_METADATA_STATUS, cardAction, APIError } from '@atlaskit/linking-common';
|
|
6
5
|
import { getDefinitionId, getByDefinitionId, getServices, getStatus, getExtensionKey } from '../helpers';
|
|
7
|
-
import { ERROR_MESSAGE_OAUTH, ERROR_MESSAGE_FATAL } from './constants';
|
|
6
|
+
import { ERROR_MESSAGE_OAUTH, ERROR_MESSAGE_FATAL, ERROR_MESSAGE_METADATA } from './constants';
|
|
8
7
|
import * as measure from '../../utils/performance';
|
|
9
8
|
import { getUnauthorizedJsonLd } from '../../utils/jsonld';
|
|
10
9
|
import { addMetadataToExperience } from '../analytics';
|
|
@@ -20,14 +19,26 @@ export const useSmartCardActions = (id, url, analytics) => {
|
|
|
20
19
|
} = store;
|
|
21
20
|
const {
|
|
22
21
|
details,
|
|
23
|
-
status
|
|
22
|
+
status,
|
|
23
|
+
metadataStatus
|
|
24
24
|
} = getState()[url] || {
|
|
25
25
|
status: 'pending',
|
|
26
26
|
details: undefined
|
|
27
27
|
};
|
|
28
28
|
const hasAuthFlowSupported = config.authFlow !== 'disabled';
|
|
29
29
|
const hasData = !!(details && details.data);
|
|
30
|
-
const
|
|
30
|
+
const setMetadataStatus = useCallback(metadataStatus => {
|
|
31
|
+
dispatch(cardAction(ACTION_UPDATE_METADATA_STATUS, {
|
|
32
|
+
url
|
|
33
|
+
}, undefined, undefined, metadataStatus));
|
|
34
|
+
}, [dispatch, url]);
|
|
35
|
+
const handleResolvedLinkError = useCallback((url, error, response, isMetadataRequest) => {
|
|
36
|
+
// If metadata request then set metadata status, return and do not alter link status
|
|
37
|
+
if (isMetadataRequest) {
|
|
38
|
+
setMetadataStatus('errored');
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
|
|
31
42
|
if (error.kind === 'fatal') {
|
|
32
43
|
// If there's no previous data in the store for this URL, then bail
|
|
33
44
|
// out and let the editor handle fallbacks (returns to a blue link).
|
|
@@ -64,24 +75,32 @@ export const useSmartCardActions = (id, url, analytics) => {
|
|
|
64
75
|
}, undefined, error));
|
|
65
76
|
}
|
|
66
77
|
}
|
|
67
|
-
}, [hasData, status, dispatch, details]);
|
|
68
|
-
const handleResolvedLinkResponse = useCallback((resourceUrl, response, isReloading = false) => {
|
|
78
|
+
}, [setMetadataStatus, hasData, status, dispatch, details]);
|
|
79
|
+
const handleResolvedLinkResponse = useCallback((resourceUrl, response, isReloading = false, isMetadataRequest) => {
|
|
69
80
|
const hostname = new URL(resourceUrl).hostname;
|
|
70
81
|
const nextStatus = response ? getStatus(response) : 'fatal'; // If we require authorization & do not have an authFlow available,
|
|
71
82
|
// throw an error and render as a normal blue link.
|
|
72
83
|
|
|
73
84
|
if ((nextStatus === 'unauthorized' || nextStatus === 'forbidden') && !hasAuthFlowSupported) {
|
|
74
|
-
handleResolvedLinkError(resourceUrl, new APIError('fallback', hostname, ERROR_MESSAGE_OAUTH), response);
|
|
85
|
+
handleResolvedLinkError(resourceUrl, new APIError('fallback', hostname, ERROR_MESSAGE_OAUTH), response, isMetadataRequest);
|
|
75
86
|
return;
|
|
76
87
|
} // Handle any other errors
|
|
77
88
|
|
|
78
89
|
|
|
79
90
|
if (nextStatus === 'fatal') {
|
|
80
|
-
handleResolvedLinkError(resourceUrl, new APIError('fatal', hostname, ERROR_MESSAGE_FATAL));
|
|
91
|
+
handleResolvedLinkError(resourceUrl, new APIError('fatal', hostname, ERROR_MESSAGE_FATAL), undefined, isMetadataRequest);
|
|
81
92
|
return;
|
|
82
|
-
} //
|
|
93
|
+
} // Handle errors of any other kind in the metadata request response
|
|
83
94
|
|
|
84
95
|
|
|
96
|
+
if (isMetadataRequest && nextStatus !== 'resolved') {
|
|
97
|
+
handleResolvedLinkError(resourceUrl, new APIError('error', hostname, ERROR_MESSAGE_METADATA), response, isMetadataRequest);
|
|
98
|
+
return;
|
|
99
|
+
} //if a link resolves normally, metadata will also always be resolved
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
setMetadataStatus('resolved'); // Dispatch Analytics and resolved card action - including unauthorized states.
|
|
103
|
+
|
|
85
104
|
if (isReloading) {
|
|
86
105
|
dispatch(cardAction(ACTION_RELOADING, {
|
|
87
106
|
url: resourceUrl
|
|
@@ -89,15 +108,15 @@ export const useSmartCardActions = (id, url, analytics) => {
|
|
|
89
108
|
} else {
|
|
90
109
|
dispatch(cardAction(ACTION_RESOLVED, {
|
|
91
110
|
url: resourceUrl
|
|
92
|
-
}, response));
|
|
111
|
+
}, response, undefined, undefined, isMetadataRequest));
|
|
93
112
|
}
|
|
94
|
-
}, [dispatch, handleResolvedLinkError, hasAuthFlowSupported]);
|
|
95
|
-
const resolve = useCallback(async (resourceUrl = url, isReloading = false) => {
|
|
113
|
+
}, [dispatch, handleResolvedLinkError, hasAuthFlowSupported, setMetadataStatus]);
|
|
114
|
+
const resolve = useCallback(async (resourceUrl = url, isReloading = false, isMetadataRequest = false) => {
|
|
96
115
|
// Request JSON-LD data for the card from ORS, iff it has extended
|
|
97
116
|
// its cache lifespan OR there is no data for it currently. Once the data
|
|
98
117
|
// has come back asynchronously, dispatch the resolved action for the card.
|
|
99
|
-
if (isReloading || !hasData) {
|
|
100
|
-
return connections.client.fetchData(resourceUrl).then(response => handleResolvedLinkResponse(resourceUrl, response, isReloading)).catch(error => handleResolvedLinkError(resourceUrl, error));
|
|
118
|
+
if (isReloading || !hasData || isMetadataRequest) {
|
|
119
|
+
return connections.client.fetchData(resourceUrl).then(response => handleResolvedLinkResponse(resourceUrl, response, isReloading, isMetadataRequest)).catch(error => handleResolvedLinkError(resourceUrl, error, undefined, isMetadataRequest));
|
|
101
120
|
} else {
|
|
102
121
|
addMetadataToExperience('smart-link-rendered', id, {
|
|
103
122
|
cached: true
|
|
@@ -109,10 +128,11 @@ export const useSmartCardActions = (id, url, analytics) => {
|
|
|
109
128
|
dispatch(cardAction(ACTION_PENDING, {
|
|
110
129
|
url
|
|
111
130
|
}));
|
|
131
|
+
setMetadataStatus('pending');
|
|
112
132
|
}
|
|
113
133
|
|
|
114
134
|
return resolve();
|
|
115
|
-
}, [
|
|
135
|
+
}, [details, resolve, dispatch, url, setMetadataStatus]);
|
|
116
136
|
const reload = useCallback(() => {
|
|
117
137
|
const definitionId = getDefinitionId(details);
|
|
118
138
|
|
|
@@ -122,6 +142,13 @@ export const useSmartCardActions = (id, url, analytics) => {
|
|
|
122
142
|
resolve(url, true);
|
|
123
143
|
}
|
|
124
144
|
}, [url, details, getState, resolve]);
|
|
145
|
+
const loadMetadata = useCallback(() => {
|
|
146
|
+
//metadataStatus will be undefined for SSR links only
|
|
147
|
+
if (metadataStatus === undefined) {
|
|
148
|
+
setMetadataStatus('pending');
|
|
149
|
+
return resolve(url, false, true);
|
|
150
|
+
}
|
|
151
|
+
}, [metadataStatus, resolve, setMetadataStatus, url]);
|
|
125
152
|
const authorize = useCallback(appearance => {
|
|
126
153
|
const definitionId = getDefinitionId(details);
|
|
127
154
|
const extensionKey = getExtensionKey(details);
|
|
@@ -187,6 +214,7 @@ export const useSmartCardActions = (id, url, analytics) => {
|
|
|
187
214
|
register,
|
|
188
215
|
reload,
|
|
189
216
|
authorize,
|
|
190
|
-
invoke
|
|
191
|
-
|
|
217
|
+
invoke,
|
|
218
|
+
loadMetadata
|
|
219
|
+
}), [register, reload, authorize, invoke, loadMetadata]);
|
|
192
220
|
};
|
package/dist/es2019/version.json
CHANGED
|
@@ -30,6 +30,7 @@ export const BlockCard = ({
|
|
|
30
30
|
renderers,
|
|
31
31
|
isSelected,
|
|
32
32
|
onResolve,
|
|
33
|
+
onError,
|
|
33
34
|
testId,
|
|
34
35
|
showActions,
|
|
35
36
|
platform
|
|
@@ -70,6 +71,13 @@ export const BlockCard = ({
|
|
|
70
71
|
}));
|
|
71
72
|
|
|
72
73
|
case 'unauthorized':
|
|
74
|
+
if (onError) {
|
|
75
|
+
onError({
|
|
76
|
+
url,
|
|
77
|
+
status
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
|
|
73
81
|
const unauthorizedViewProps = extractBlockProps(data, meta, extractorOpts);
|
|
74
82
|
return /*#__PURE__*/React.createElement(BlockCardUnauthorisedView, _extends({}, unauthorizedViewProps, {
|
|
75
83
|
isSelected: isSelected,
|
|
@@ -80,6 +88,13 @@ export const BlockCard = ({
|
|
|
80
88
|
}));
|
|
81
89
|
|
|
82
90
|
case 'forbidden':
|
|
91
|
+
if (onError) {
|
|
92
|
+
onError({
|
|
93
|
+
url,
|
|
94
|
+
status
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
|
|
83
98
|
const forbiddenViewProps = extractBlockProps(data, meta, extractorOpts);
|
|
84
99
|
const cardMetadata = (_details$meta = details === null || details === void 0 ? void 0 : details.meta) !== null && _details$meta !== void 0 ? _details$meta : getUnauthorizedJsonLd().meta;
|
|
85
100
|
const requestAccessContext = extractRequestAccessContext({
|
|
@@ -96,6 +111,13 @@ export const BlockCard = ({
|
|
|
96
111
|
}));
|
|
97
112
|
|
|
98
113
|
case 'not_found':
|
|
114
|
+
if (onError) {
|
|
115
|
+
onError({
|
|
116
|
+
url,
|
|
117
|
+
status
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
|
|
99
121
|
const notFoundViewProps = extractBlockProps(data, meta, extractorOpts);
|
|
100
122
|
return /*#__PURE__*/React.createElement(BlockCardNotFoundView, _extends({}, notFoundViewProps, {
|
|
101
123
|
isSelected: isSelected,
|
|
@@ -105,6 +127,13 @@ export const BlockCard = ({
|
|
|
105
127
|
|
|
106
128
|
case 'fallback':
|
|
107
129
|
case 'errored':
|
|
130
|
+
if (onError) {
|
|
131
|
+
onError({
|
|
132
|
+
url,
|
|
133
|
+
status
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
|
|
108
137
|
if (authFlow && authFlow === 'disabled') {
|
|
109
138
|
return /*#__PURE__*/React.createElement(CardLinkView, {
|
|
110
139
|
link: url,
|
|
@@ -20,6 +20,7 @@ export function CardWithUrlContent({
|
|
|
20
20
|
appearance,
|
|
21
21
|
dispatchAnalytics,
|
|
22
22
|
onResolve,
|
|
23
|
+
onError,
|
|
23
24
|
testId,
|
|
24
25
|
showActions,
|
|
25
26
|
inheritDimensions,
|
|
@@ -91,7 +92,7 @@ export function CardWithUrlContent({
|
|
|
91
92
|
if (isFinalState(state.status)) {
|
|
92
93
|
analytics.ui.renderSuccessEvent(appearance, state.status, id, definitionId, extensionKey);
|
|
93
94
|
}
|
|
94
|
-
}, [appearance, state.
|
|
95
|
+
}, [appearance, state.status, url, definitionId, extensionKey, analytics.ui, id]);
|
|
95
96
|
|
|
96
97
|
if (isFlexibleUi) {
|
|
97
98
|
let cardState = state;
|
|
@@ -115,7 +116,8 @@ export function CardWithUrlContent({
|
|
|
115
116
|
ui: ui,
|
|
116
117
|
url: url,
|
|
117
118
|
testId: testId,
|
|
118
|
-
onResolve: onResolve
|
|
119
|
+
onResolve: onResolve,
|
|
120
|
+
onError: onError
|
|
119
121
|
}, children);
|
|
120
122
|
} // We have to keep this last to prevent hook order from being violated
|
|
121
123
|
|
|
@@ -135,6 +137,7 @@ export function CardWithUrlContent({
|
|
|
135
137
|
handleFrameClick: handleClickWrapper,
|
|
136
138
|
isSelected: isSelected,
|
|
137
139
|
onResolve: onResolve,
|
|
140
|
+
onError: onError,
|
|
138
141
|
testId: testId,
|
|
139
142
|
inlinePreloaderStyle: inlinePreloaderStyle,
|
|
140
143
|
showHoverPreview: showHoverPreview
|
|
@@ -154,6 +157,7 @@ export function CardWithUrlContent({
|
|
|
154
157
|
handleAnalytics: dispatchAnalytics,
|
|
155
158
|
isSelected: isSelected,
|
|
156
159
|
onResolve: onResolve,
|
|
160
|
+
onError: onError,
|
|
157
161
|
testId: testId,
|
|
158
162
|
showActions: showActions,
|
|
159
163
|
platform: platform
|
|
@@ -173,6 +177,7 @@ export function CardWithUrlContent({
|
|
|
173
177
|
isFrameVisible: isFrameVisible,
|
|
174
178
|
platform: platform,
|
|
175
179
|
onResolve: onResolve,
|
|
180
|
+
onError: onError,
|
|
176
181
|
testId: testId,
|
|
177
182
|
inheritDimensions: inheritDimensions,
|
|
178
183
|
showActions: showActions,
|
|
@@ -25,6 +25,7 @@ export function CardWithURLRenderer(props) {
|
|
|
25
25
|
onClick,
|
|
26
26
|
container,
|
|
27
27
|
onResolve,
|
|
28
|
+
onError,
|
|
28
29
|
testId,
|
|
29
30
|
showActions,
|
|
30
31
|
inheritDimensions,
|
|
@@ -85,6 +86,7 @@ export function CardWithURLRenderer(props) {
|
|
|
85
86
|
dispatchAnalytics,
|
|
86
87
|
container,
|
|
87
88
|
onResolve,
|
|
89
|
+
onError,
|
|
88
90
|
testId,
|
|
89
91
|
showActions,
|
|
90
92
|
inheritDimensions,
|
|
@@ -29,6 +29,7 @@ export const EmbedCard = /*#__PURE__*/React.forwardRef(({
|
|
|
29
29
|
isFrameVisible,
|
|
30
30
|
platform,
|
|
31
31
|
onResolve,
|
|
32
|
+
onError,
|
|
32
33
|
testId,
|
|
33
34
|
inheritDimensions
|
|
34
35
|
}, iframeRef) => {
|
|
@@ -91,6 +92,13 @@ export const EmbedCard = /*#__PURE__*/React.forwardRef(({
|
|
|
91
92
|
}
|
|
92
93
|
|
|
93
94
|
case 'unauthorized':
|
|
95
|
+
if (onError) {
|
|
96
|
+
onError({
|
|
97
|
+
url,
|
|
98
|
+
status
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
|
|
94
102
|
const unauthorisedViewProps = extractEmbedProps(data, meta, platform);
|
|
95
103
|
return /*#__PURE__*/React.createElement(EmbedCardUnauthorisedView, _extends({}, unauthorisedViewProps, {
|
|
96
104
|
isSelected: isSelected,
|
|
@@ -100,6 +108,13 @@ export const EmbedCard = /*#__PURE__*/React.forwardRef(({
|
|
|
100
108
|
}));
|
|
101
109
|
|
|
102
110
|
case 'forbidden':
|
|
111
|
+
if (onError) {
|
|
112
|
+
onError({
|
|
113
|
+
url,
|
|
114
|
+
status
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
|
|
103
118
|
const forbiddenViewProps = extractEmbedProps(data, meta, platform);
|
|
104
119
|
const cardMetadata = (_details$meta = details === null || details === void 0 ? void 0 : details.meta) !== null && _details$meta !== void 0 ? _details$meta : getUnauthorizedJsonLd().meta;
|
|
105
120
|
const requestAccessContext = extractRequestAccessContext({
|
|
@@ -116,6 +131,13 @@ export const EmbedCard = /*#__PURE__*/React.forwardRef(({
|
|
|
116
131
|
}));
|
|
117
132
|
|
|
118
133
|
case 'not_found':
|
|
134
|
+
if (onError) {
|
|
135
|
+
onError({
|
|
136
|
+
url,
|
|
137
|
+
status
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
|
|
119
141
|
const notFoundViewProps = extractEmbedProps(data, meta, platform);
|
|
120
142
|
return /*#__PURE__*/React.createElement(EmbedCardNotFoundView, _extends({}, notFoundViewProps, {
|
|
121
143
|
isSelected: isSelected,
|
|
@@ -125,6 +147,13 @@ export const EmbedCard = /*#__PURE__*/React.forwardRef(({
|
|
|
125
147
|
|
|
126
148
|
case 'fallback':
|
|
127
149
|
case 'errored':
|
|
150
|
+
if (onError) {
|
|
151
|
+
onError({
|
|
152
|
+
url,
|
|
153
|
+
status
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
|
|
128
157
|
return /*#__PURE__*/React.createElement(EmbedCardErroredView, {
|
|
129
158
|
onRetry: handleErrorRetry,
|
|
130
159
|
inheritDimensions: inheritDimensions,
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import _extends from "@babel/runtime/helpers/extends";
|
|
2
2
|
import React, { useEffect } from 'react';
|
|
3
|
+
import { SmartLinkStatus } from '../../constants';
|
|
3
4
|
import Container from './components/container';
|
|
4
5
|
import { FlexibleUiContext } from '../../state/flexible-ui-context';
|
|
5
6
|
import { getContextByStatus, getRetryOptions } from './utils';
|
|
@@ -14,12 +15,13 @@ const FlexibleCard = ({
|
|
|
14
15
|
cardState,
|
|
15
16
|
children,
|
|
16
17
|
onAuthorize,
|
|
18
|
+
onError,
|
|
19
|
+
onResolve,
|
|
17
20
|
renderers,
|
|
18
21
|
ui,
|
|
19
22
|
url,
|
|
20
23
|
onClick,
|
|
21
|
-
testId
|
|
22
|
-
onResolve
|
|
24
|
+
testId
|
|
23
25
|
}) => {
|
|
24
26
|
const {
|
|
25
27
|
status: cardType,
|
|
@@ -28,13 +30,36 @@ const FlexibleCard = ({
|
|
|
28
30
|
const status = cardType;
|
|
29
31
|
const context = getContextByStatus(url, status, details, renderers);
|
|
30
32
|
const retry = getRetryOptions(url, status, details, onAuthorize);
|
|
33
|
+
const {
|
|
34
|
+
title
|
|
35
|
+
} = context || {};
|
|
31
36
|
useEffect(() => {
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
37
|
+
switch (status) {
|
|
38
|
+
case SmartLinkStatus.Resolved:
|
|
39
|
+
if (onResolve) {
|
|
40
|
+
onResolve({
|
|
41
|
+
title,
|
|
42
|
+
url
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
break;
|
|
47
|
+
|
|
48
|
+
case SmartLinkStatus.Errored:
|
|
49
|
+
case SmartLinkStatus.Fallback:
|
|
50
|
+
case SmartLinkStatus.Forbidden:
|
|
51
|
+
case SmartLinkStatus.NotFound:
|
|
52
|
+
case SmartLinkStatus.Unauthorized:
|
|
53
|
+
if (onError) {
|
|
54
|
+
onError({
|
|
55
|
+
status,
|
|
56
|
+
url
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
break;
|
|
36
61
|
}
|
|
37
|
-
}, [onResolve, status, url]);
|
|
62
|
+
}, [onError, onResolve, status, title, url]);
|
|
38
63
|
return /*#__PURE__*/React.createElement(FlexibleUiContext.Provider, {
|
|
39
64
|
value: context
|
|
40
65
|
}, /*#__PURE__*/React.createElement(Container, _extends({
|
|
@@ -4,6 +4,7 @@ import React, { useCallback, useEffect, useMemo } from 'react';
|
|
|
4
4
|
import { ActionName, SmartLinkPosition, SmartLinkSize } from '../../../constants';
|
|
5
5
|
import extractPreview from '../../../extractors/flexible/extract-preview';
|
|
6
6
|
import { extractMetadata } from '../../../extractors/hover/extractMetadata';
|
|
7
|
+
import { useSmartCardActions } from '../../../state/actions';
|
|
7
8
|
import { getExtensionKey } from '../../../state/helpers';
|
|
8
9
|
import { isSpecialEvent } from '../../../utils';
|
|
9
10
|
import FlexibleCard from '../../FlexibleCard';
|
|
@@ -41,6 +42,7 @@ export const toFooterActions = (cardActions, onActionClick) => cardActions.map(a
|
|
|
41
42
|
}));
|
|
42
43
|
|
|
43
44
|
const HoverCardContent = ({
|
|
45
|
+
id = '',
|
|
44
46
|
analytics,
|
|
45
47
|
cardActions = [],
|
|
46
48
|
cardState,
|
|
@@ -51,6 +53,10 @@ const HoverCardContent = ({
|
|
|
51
53
|
}) => {
|
|
52
54
|
var _cardState$details;
|
|
53
55
|
|
|
56
|
+
const actions = useSmartCardActions(id, url, analytics);
|
|
57
|
+
useEffect(() => {
|
|
58
|
+
actions.loadMetadata();
|
|
59
|
+
}, [actions]);
|
|
54
60
|
useEffect(() => {
|
|
55
61
|
// Since hover preview only render on resolved status,
|
|
56
62
|
// there is no need to check for statuses.
|
|
@@ -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
|
};
|
package/dist/esm/version.json
CHANGED