@contentful/field-editor-reference 5.22.6 → 5.23.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/dist/cjs/common/EntityStore.js +51 -3
- package/dist/cjs/resources/Cards/ResourceCard.js +18 -10
- package/dist/cjs/resources/Cards/ResourceCard.spec.js +48 -7
- package/dist/cjs/resources/ExternalResourceCard/ExternalResourceCard.js +14 -22
- package/dist/esm/common/EntityStore.js +48 -3
- package/dist/esm/resources/Cards/ResourceCard.js +19 -11
- package/dist/esm/resources/Cards/ResourceCard.spec.js +48 -7
- package/dist/esm/resources/ExternalResourceCard/ExternalResourceCard.js +14 -22
- package/dist/types/common/EntityStore.d.ts +15 -7
- package/dist/types/resources/Cards/ResourceCard.d.ts +1 -1
- package/dist/types/resources/ExternalResourceCard/ExternalResourceCard.d.ts +4 -32
- package/dist/types/types.d.ts +40 -5
- package/dist/types/utils/useSortIDs.d.ts +1 -1
- package/package.json +2 -2
|
@@ -15,6 +15,9 @@ _export(exports, {
|
|
|
15
15
|
UnsupportedError: function() {
|
|
16
16
|
return UnsupportedError;
|
|
17
17
|
},
|
|
18
|
+
isContentfulResourceInfo: function() {
|
|
19
|
+
return isContentfulResourceInfo;
|
|
20
|
+
},
|
|
18
21
|
isUnsupportedError: function() {
|
|
19
22
|
return isUnsupportedError;
|
|
20
23
|
},
|
|
@@ -92,6 +95,9 @@ function _interop_require_wildcard(obj, nodeInterop) {
|
|
|
92
95
|
}
|
|
93
96
|
return newObj;
|
|
94
97
|
}
|
|
98
|
+
function isContentfulResourceInfo(info) {
|
|
99
|
+
return info.resource.sys.type === 'Entry';
|
|
100
|
+
}
|
|
95
101
|
const globalQueue = new _pqueue.default({
|
|
96
102
|
concurrency: 50
|
|
97
103
|
});
|
|
@@ -108,8 +114,7 @@ function isUnsupportedError(value) {
|
|
|
108
114
|
const isEntityQueryKey = (queryKey)=>{
|
|
109
115
|
return Array.isArray(queryKey) && (queryKey[0] === 'Entry' || queryKey[0] === 'Asset') && queryKey.length === 4;
|
|
110
116
|
};
|
|
111
|
-
async function fetchContentfulEntry(
|
|
112
|
-
const { urn, fetch, options } = params;
|
|
117
|
+
async function fetchContentfulEntry({ urn, fetch, options }) {
|
|
113
118
|
const resourceId = urn.split(':', 6)[5];
|
|
114
119
|
const ENTITY_RESOURCE_ID_REGEX = RegExp("^spaces\\/(?<spaceId>[^/]+)(?:\\/environments\\/(?<environmentId>[^/]+))?\\/entries\\/(?<entityId>[^/]+)$");
|
|
115
120
|
const resourceIdMatch = resourceId.match(ENTITY_RESOURCE_ID_REGEX);
|
|
@@ -172,6 +177,37 @@ async function fetchContentfulEntry(params) {
|
|
|
172
177
|
contentType: contentType
|
|
173
178
|
};
|
|
174
179
|
}
|
|
180
|
+
async function fetchExternalResource({ urn, fetch, options, spaceId, environmentId, resourceType }) {
|
|
181
|
+
const [resource, resourceTypes] = await Promise.all([
|
|
182
|
+
fetch([
|
|
183
|
+
'resource',
|
|
184
|
+
spaceId,
|
|
185
|
+
environmentId,
|
|
186
|
+
resourceType,
|
|
187
|
+
urn
|
|
188
|
+
], ({ cmaClient })=>cmaClient.raw.get(`/spaces/${spaceId}/environments/${environmentId}/resource_types/${resourceType}/resources`, {
|
|
189
|
+
params: {
|
|
190
|
+
'sys.urn[in]': urn
|
|
191
|
+
}
|
|
192
|
+
}).then(({ items })=>items[0] ?? null), options),
|
|
193
|
+
fetch([
|
|
194
|
+
'resource-types',
|
|
195
|
+
spaceId,
|
|
196
|
+
environmentId
|
|
197
|
+
], ({ cmaClient })=>cmaClient.raw.get(`/spaces/${spaceId}/environments/${environmentId}/resource_types`).then(({ items })=>items))
|
|
198
|
+
]);
|
|
199
|
+
const resourceTypeEntity = resourceTypes.find((rt)=>rt.sys.id === resourceType);
|
|
200
|
+
if (!resourceTypeEntity) {
|
|
201
|
+
throw new UnsupportedError('Unsupported resource type');
|
|
202
|
+
}
|
|
203
|
+
if (!resource) {
|
|
204
|
+
throw new Error('Missing resource');
|
|
205
|
+
}
|
|
206
|
+
return {
|
|
207
|
+
resource,
|
|
208
|
+
resourceType: resourceTypeEntity
|
|
209
|
+
};
|
|
210
|
+
}
|
|
175
211
|
const [InternalServiceProvider, useFetch, useEntityLoader, useCurrentIds] = (0, _constate.default)(function useInitServices(props) {
|
|
176
212
|
const currentSpaceId = props.sdk.ids.space;
|
|
177
213
|
const currentEnvironmentId = props.sdk.ids.environmentAlias ?? props.sdk.ids.environment;
|
|
@@ -288,9 +324,21 @@ const [InternalServiceProvider, useFetch, useEntityLoader, useCurrentIds] = (0,
|
|
|
288
324
|
options
|
|
289
325
|
});
|
|
290
326
|
}
|
|
291
|
-
|
|
327
|
+
if (!options?.allowExternal) {
|
|
328
|
+
throw new UnsupportedError('Unsupported resource type');
|
|
329
|
+
}
|
|
330
|
+
return fetchExternalResource({
|
|
331
|
+
fetch,
|
|
332
|
+
urn,
|
|
333
|
+
options,
|
|
334
|
+
resourceType,
|
|
335
|
+
spaceId: currentSpaceId,
|
|
336
|
+
environmentId: currentEnvironmentId
|
|
337
|
+
});
|
|
292
338
|
}, options);
|
|
293
339
|
}, [
|
|
340
|
+
currentEnvironmentId,
|
|
341
|
+
currentSpaceId,
|
|
294
342
|
fetch
|
|
295
343
|
]);
|
|
296
344
|
const isSameSpaceEntityQueryKey = (0, _react.useCallback)((queryKey)=>{
|
|
@@ -13,6 +13,7 @@ const _reactintersectionobserver = require("react-intersection-observer");
|
|
|
13
13
|
const _f36components = require("@contentful/f36-components");
|
|
14
14
|
const _EntityStore = require("../../common/EntityStore");
|
|
15
15
|
const _components = require("../../components");
|
|
16
|
+
const _ExternalResourceCard = require("../ExternalResourceCard/ExternalResourceCard");
|
|
16
17
|
const _ContentfulEntryCard = require("./ContentfulEntryCard");
|
|
17
18
|
function _getRequireWildcardCache(nodeInterop) {
|
|
18
19
|
if (typeof WeakMap !== "function") return null;
|
|
@@ -65,23 +66,30 @@ function ExistingResourceCard(props) {
|
|
|
65
66
|
const { resourceLink, inView, index = 0 } = props;
|
|
66
67
|
const resourceOptions = {
|
|
67
68
|
priority: index * -1,
|
|
68
|
-
enabled: inView
|
|
69
|
+
enabled: inView,
|
|
70
|
+
allowExternal: true
|
|
69
71
|
};
|
|
70
|
-
const { data, error } = (0, _EntityStore.useResource)(resourceLink.sys.linkType, resourceLink.sys.urn, resourceOptions);
|
|
71
|
-
if (!
|
|
72
|
+
const { data: info, error } = (0, _EntityStore.useResource)(resourceLink.sys.linkType, resourceLink.sys.urn, resourceOptions);
|
|
73
|
+
if (!info && !error) {
|
|
72
74
|
return _react.createElement(ResourceCardSkeleton, null);
|
|
73
75
|
}
|
|
74
|
-
if (
|
|
76
|
+
if (!info) {
|
|
77
|
+
return _react.createElement(_components.ResourceEntityErrorCard, {
|
|
78
|
+
linkType: resourceLink.sys.linkType,
|
|
79
|
+
error: error,
|
|
80
|
+
isDisabled: props.isDisabled,
|
|
81
|
+
onRemove: props.onRemove
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
if ((0, _EntityStore.isContentfulResourceInfo)(info)) {
|
|
75
85
|
return _react.createElement(_ContentfulEntryCard.ContentfulEntryCard, {
|
|
76
|
-
info:
|
|
86
|
+
info: info,
|
|
77
87
|
...props
|
|
78
88
|
});
|
|
79
89
|
}
|
|
80
|
-
return _react.createElement(
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
isDisabled: props.isDisabled,
|
|
84
|
-
onRemove: props.onRemove
|
|
90
|
+
return _react.createElement(_ExternalResourceCard.ExternalResourceCard, {
|
|
91
|
+
info: info,
|
|
92
|
+
...props
|
|
85
93
|
});
|
|
86
94
|
}
|
|
87
95
|
function ResourceCardWrapper(props) {
|
|
@@ -9,6 +9,8 @@ const _react1 = require("@testing-library/react");
|
|
|
9
9
|
const _published_content_typejson = _interop_require_default(require("../../__fixtures__/content-type/published_content_type.json"));
|
|
10
10
|
const _published_entry_non_masterjson = _interop_require_default(require("../../__fixtures__/entry/published_entry_non_master.json"));
|
|
11
11
|
const _published_entryjson = _interop_require_default(require("../../__fixtures__/entry/published_entry.json"));
|
|
12
|
+
const _resourcetypejson = _interop_require_default(require("../../__fixtures__/resource-type/resource-type.json"));
|
|
13
|
+
const _resourcejson = _interop_require_default(require("../../__fixtures__/resource/resource.json"));
|
|
12
14
|
const _indifferent_spacejson = _interop_require_default(require("../../__fixtures__/space/indifferent_space.json"));
|
|
13
15
|
const _EntityStore = require("../../common/EntityStore");
|
|
14
16
|
const _ResourceCard = require("./ResourceCard");
|
|
@@ -68,6 +70,8 @@ const resolvableEntryUrn = 'crn:contentful:::content:spaces/space-id/entries/lin
|
|
|
68
70
|
const resolvableEntryUrnWithExplicitMaster = 'crn:contentful:::content:spaces/space-id/environments/master/entries/linked-entry-urn';
|
|
69
71
|
const resolvableEntryUrnWithAnotherEnvironment = 'crn:contentful:::content:spaces/space-id/environments/my-test-environment/entries/linked-entry-urn';
|
|
70
72
|
const unknownEntryUrn = 'crn:contentful:::content:spaces/space-id/entries/unknown-entry-urn';
|
|
73
|
+
const resolvableExternalResourceType = 'External:ResourceType';
|
|
74
|
+
const resolvableExternalEntityUrn = 'external:entity-urn';
|
|
71
75
|
const sdk = {
|
|
72
76
|
locales: {
|
|
73
77
|
default: 'en-US'
|
|
@@ -87,6 +91,27 @@ const sdk = {
|
|
|
87
91
|
return Promise.reject(new Error());
|
|
88
92
|
})
|
|
89
93
|
},
|
|
94
|
+
Http: {
|
|
95
|
+
get: jest.fn().mockImplementation(({ url, config })=>{
|
|
96
|
+
if (url === '/spaces/space-id/environments/environment-id/resource_types') {
|
|
97
|
+
return Promise.resolve({
|
|
98
|
+
items: [
|
|
99
|
+
_resourcetypejson.default
|
|
100
|
+
]
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
if (url === `/spaces/space-id/environments/environment-id/resource_types/${resolvableExternalResourceType}/resources` && config.params['sys.urn[in]'] === resolvableExternalEntityUrn) {
|
|
104
|
+
return Promise.resolve({
|
|
105
|
+
items: [
|
|
106
|
+
_resourcejson.default
|
|
107
|
+
]
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
return Promise.resolve({
|
|
111
|
+
items: []
|
|
112
|
+
});
|
|
113
|
+
})
|
|
114
|
+
},
|
|
90
115
|
Locale: {
|
|
91
116
|
getMany: jest.fn().mockResolvedValue({
|
|
92
117
|
items: [
|
|
@@ -116,7 +141,7 @@ const sdk = {
|
|
|
116
141
|
environment: 'environment-id'
|
|
117
142
|
}
|
|
118
143
|
};
|
|
119
|
-
function renderResourceCard({ linkType = 'Contentful:Entry',
|
|
144
|
+
function renderResourceCard({ linkType = 'Contentful:Entry', entityUrn = resolvableEntryUrn } = {}) {
|
|
120
145
|
return (0, _react1.render)(_react.createElement(_EntityStore.EntityProvider, {
|
|
121
146
|
sdk: sdk
|
|
122
147
|
}, _react.createElement(_ResourceCard.ResourceCard, {
|
|
@@ -126,7 +151,7 @@ function renderResourceCard({ linkType = 'Contentful:Entry', entryUrn = resolvab
|
|
|
126
151
|
sys: {
|
|
127
152
|
type: 'ResourceLink',
|
|
128
153
|
linkType: linkType,
|
|
129
|
-
urn:
|
|
154
|
+
urn: entityUrn
|
|
130
155
|
}
|
|
131
156
|
}
|
|
132
157
|
})));
|
|
@@ -143,7 +168,7 @@ describe('ResourceCard', ()=>{
|
|
|
143
168
|
});
|
|
144
169
|
it('renders entry card with explicit master crn', async ()=>{
|
|
145
170
|
const { getByTestId, getByText } = renderResourceCard({
|
|
146
|
-
|
|
171
|
+
entityUrn: resolvableEntryUrnWithExplicitMaster
|
|
147
172
|
});
|
|
148
173
|
const tooltipContent = `Space: ${_indifferent_spacejson.default.name} (Env.: ${_published_entryjson.default.sys.environment.sys.id})`;
|
|
149
174
|
await (0, _react1.waitFor)(()=>expect(getByTestId('cf-ui-entry-card')).toBeDefined());
|
|
@@ -154,7 +179,7 @@ describe('ResourceCard', ()=>{
|
|
|
154
179
|
});
|
|
155
180
|
it('renders entry card with a non master environment', async ()=>{
|
|
156
181
|
const { getByTestId, getByText } = renderResourceCard({
|
|
157
|
-
|
|
182
|
+
entityUrn: resolvableEntryUrnWithAnotherEnvironment
|
|
158
183
|
});
|
|
159
184
|
await (0, _react1.waitFor)(()=>expect(getByTestId('cf-ui-entry-card')).toBeDefined());
|
|
160
185
|
const tooltipContent = `Space: ${_indifferent_spacejson.default.name} (Env.: ${_published_entry_non_masterjson.default.sys.environment.sys.id})`;
|
|
@@ -167,7 +192,7 @@ describe('ResourceCard', ()=>{
|
|
|
167
192
|
const { getByTestId } = renderResourceCard();
|
|
168
193
|
expect(getByTestId('cf-ui-skeleton-form')).toBeDefined();
|
|
169
194
|
});
|
|
170
|
-
it('renders unsupported entity card when
|
|
195
|
+
it('renders unsupported entity card when resource type is unknown', async ()=>{
|
|
171
196
|
const { getByText } = renderResourceCard({
|
|
172
197
|
linkType: 'Contentful:UnsupportedLink'
|
|
173
198
|
});
|
|
@@ -175,14 +200,30 @@ describe('ResourceCard', ()=>{
|
|
|
175
200
|
});
|
|
176
201
|
it('renders missing entity card when unknown error is returned', async ()=>{
|
|
177
202
|
const { getByTestId } = renderResourceCard({
|
|
178
|
-
|
|
203
|
+
entityUrn: unknownEntryUrn
|
|
179
204
|
});
|
|
180
205
|
await (0, _react1.waitFor)(()=>expect(getByTestId('cf-ui-missing-entry-card')).toBeDefined());
|
|
181
206
|
});
|
|
182
207
|
it('renders missing entity card when crn is invalid', async ()=>{
|
|
183
208
|
const { getByTestId } = renderResourceCard({
|
|
184
|
-
|
|
209
|
+
entityUrn: ''
|
|
210
|
+
});
|
|
211
|
+
await (0, _react1.waitFor)(()=>expect(getByTestId('cf-ui-missing-entry-card')).toBeDefined());
|
|
212
|
+
});
|
|
213
|
+
it('renders missing entity card when external urn is invalid', async ()=>{
|
|
214
|
+
const { getByTestId } = renderResourceCard({
|
|
215
|
+
linkType: resolvableExternalResourceType,
|
|
216
|
+
entityUrn: ''
|
|
185
217
|
});
|
|
186
218
|
await (0, _react1.waitFor)(()=>expect(getByTestId('cf-ui-missing-entry-card')).toBeDefined());
|
|
187
219
|
});
|
|
220
|
+
it('renders entry card for external resource', async ()=>{
|
|
221
|
+
const { getByTestId, getByText } = renderResourceCard({
|
|
222
|
+
linkType: resolvableExternalResourceType,
|
|
223
|
+
entityUrn: resolvableExternalEntityUrn
|
|
224
|
+
});
|
|
225
|
+
await (0, _react1.waitFor)(()=>expect(getByTestId('cf-ui-entry-card')).toBeDefined());
|
|
226
|
+
expect(getByText(_resourcejson.default.fields.title)).toBeDefined();
|
|
227
|
+
expect(getByText(_resourcetypejson.default.name)).toBeDefined();
|
|
228
|
+
});
|
|
188
229
|
});
|
|
@@ -53,40 +53,32 @@ function _interop_require_wildcard(obj, nodeInterop) {
|
|
|
53
53
|
}
|
|
54
54
|
const defaultProps = {
|
|
55
55
|
isClickable: true,
|
|
56
|
-
hasCardEditActions: true,
|
|
57
56
|
hasCardMoveActions: true,
|
|
58
57
|
hasCardRemoveActions: true
|
|
59
58
|
};
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
suspended: 'negative'
|
|
65
|
-
};
|
|
66
|
-
function ExternalEntityBadge(entityStatus) {
|
|
67
|
-
const variant = statusMap[entityStatus];
|
|
68
|
-
return _react.createElement(_f36components.Badge, {
|
|
69
|
-
variant: variant
|
|
70
|
-
}, entityStatus);
|
|
59
|
+
function ExternalEntityBadge(badge) {
|
|
60
|
+
return badge ? _react.createElement(_f36components.Badge, {
|
|
61
|
+
variant: badge.variant
|
|
62
|
+
}, badge.label) : null;
|
|
71
63
|
}
|
|
72
|
-
function ExternalResourceCard({
|
|
73
|
-
const
|
|
74
|
-
const badge =
|
|
64
|
+
function ExternalResourceCard({ info, isClickable, onEdit, onRemove, onMoveTop, onMoveBottom, hasCardEditActions, hasCardMoveActions, hasCardRemoveActions, renderDragHandle, onClick }) {
|
|
65
|
+
const { resource: entity, resourceType } = info;
|
|
66
|
+
const badge = ExternalEntityBadge(entity.fields.badge);
|
|
75
67
|
return _react.createElement(_f36components.EntryCard, {
|
|
76
68
|
as: entity.fields.externalUrl ? 'a' : 'article',
|
|
77
69
|
href: entity.fields.externalUrl,
|
|
78
70
|
title: entity.fields.title,
|
|
79
71
|
description: entity.fields.description,
|
|
80
|
-
contentType: resourceType,
|
|
81
|
-
size:
|
|
82
|
-
thumbnailElement: entity.fields.image
|
|
83
|
-
alt: entity.fields.image.
|
|
72
|
+
contentType: resourceType.name,
|
|
73
|
+
size: 'auto',
|
|
74
|
+
thumbnailElement: entity.fields.image?.url ? _react.createElement("img", {
|
|
75
|
+
alt: entity.fields.image.altText,
|
|
84
76
|
src: entity.fields.image.url
|
|
85
77
|
}) : undefined,
|
|
86
78
|
dragHandleRender: renderDragHandle,
|
|
87
79
|
withDragHandle: !!renderDragHandle,
|
|
88
80
|
badge: badge,
|
|
89
|
-
actions:
|
|
81
|
+
actions: [
|
|
90
82
|
hasCardEditActions && onEdit ? _react.createElement(_f36components.MenuItem, {
|
|
91
83
|
key: "edit",
|
|
92
84
|
testId: "edit",
|
|
@@ -101,7 +93,7 @@ function ExternalResourceCard({ entity, resourceType, size, isClickable, onEdit,
|
|
|
101
93
|
onRemove && onRemove();
|
|
102
94
|
}
|
|
103
95
|
}, "Remove") : null,
|
|
104
|
-
hasCardMoveActions && (onMoveTop || onMoveBottom) ? _react.createElement(_f36components.MenuDivider, {
|
|
96
|
+
hasCardMoveActions && (onEdit || onRemove) && (onMoveTop || onMoveBottom) ? _react.createElement(_f36components.MenuDivider, {
|
|
105
97
|
key: "divider"
|
|
106
98
|
}) : null,
|
|
107
99
|
hasCardMoveActions && onMoveTop ? _react.createElement(_f36components.MenuItem, {
|
|
@@ -114,7 +106,7 @@ function ExternalResourceCard({ entity, resourceType, size, isClickable, onEdit,
|
|
|
114
106
|
onClick: ()=>onMoveBottom && onMoveBottom(),
|
|
115
107
|
testId: "move-bottom"
|
|
116
108
|
}, "Move to bottom") : null
|
|
117
|
-
].filter((item)=>item)
|
|
109
|
+
].filter((item)=>item),
|
|
118
110
|
onClick: isClickable ? (e)=>{
|
|
119
111
|
e.preventDefault();
|
|
120
112
|
if (onClick) return onClick(e);
|
|
@@ -16,6 +16,9 @@ import constate from 'constate';
|
|
|
16
16
|
import { createClient } from 'contentful-management';
|
|
17
17
|
import PQueue from 'p-queue';
|
|
18
18
|
import { SharedQueryClientProvider, useQuery, useQueryClient } from './queryClient';
|
|
19
|
+
export function isContentfulResourceInfo(info) {
|
|
20
|
+
return info.resource.sys.type === 'Entry';
|
|
21
|
+
}
|
|
19
22
|
const globalQueue = new PQueue({
|
|
20
23
|
concurrency: 50
|
|
21
24
|
});
|
|
@@ -32,8 +35,7 @@ export function isUnsupportedError(value) {
|
|
|
32
35
|
const isEntityQueryKey = (queryKey)=>{
|
|
33
36
|
return Array.isArray(queryKey) && (queryKey[0] === 'Entry' || queryKey[0] === 'Asset') && queryKey.length === 4;
|
|
34
37
|
};
|
|
35
|
-
async function fetchContentfulEntry(
|
|
36
|
-
const { urn, fetch, options } = params;
|
|
38
|
+
async function fetchContentfulEntry({ urn, fetch, options }) {
|
|
37
39
|
const resourceId = urn.split(':', 6)[5];
|
|
38
40
|
const ENTITY_RESOURCE_ID_REGEX = RegExp("^spaces\\/(?<spaceId>[^/]+)(?:\\/environments\\/(?<environmentId>[^/]+))?\\/entries\\/(?<entityId>[^/]+)$");
|
|
39
41
|
const resourceIdMatch = resourceId.match(ENTITY_RESOURCE_ID_REGEX);
|
|
@@ -96,6 +98,37 @@ async function fetchContentfulEntry(params) {
|
|
|
96
98
|
contentType: contentType
|
|
97
99
|
};
|
|
98
100
|
}
|
|
101
|
+
async function fetchExternalResource({ urn, fetch, options, spaceId, environmentId, resourceType }) {
|
|
102
|
+
const [resource, resourceTypes] = await Promise.all([
|
|
103
|
+
fetch([
|
|
104
|
+
'resource',
|
|
105
|
+
spaceId,
|
|
106
|
+
environmentId,
|
|
107
|
+
resourceType,
|
|
108
|
+
urn
|
|
109
|
+
], ({ cmaClient })=>cmaClient.raw.get(`/spaces/${spaceId}/environments/${environmentId}/resource_types/${resourceType}/resources`, {
|
|
110
|
+
params: {
|
|
111
|
+
'sys.urn[in]': urn
|
|
112
|
+
}
|
|
113
|
+
}).then(({ items })=>items[0] ?? null), options),
|
|
114
|
+
fetch([
|
|
115
|
+
'resource-types',
|
|
116
|
+
spaceId,
|
|
117
|
+
environmentId
|
|
118
|
+
], ({ cmaClient })=>cmaClient.raw.get(`/spaces/${spaceId}/environments/${environmentId}/resource_types`).then(({ items })=>items))
|
|
119
|
+
]);
|
|
120
|
+
const resourceTypeEntity = resourceTypes.find((rt)=>rt.sys.id === resourceType);
|
|
121
|
+
if (!resourceTypeEntity) {
|
|
122
|
+
throw new UnsupportedError('Unsupported resource type');
|
|
123
|
+
}
|
|
124
|
+
if (!resource) {
|
|
125
|
+
throw new Error('Missing resource');
|
|
126
|
+
}
|
|
127
|
+
return {
|
|
128
|
+
resource,
|
|
129
|
+
resourceType: resourceTypeEntity
|
|
130
|
+
};
|
|
131
|
+
}
|
|
99
132
|
const [InternalServiceProvider, useFetch, useEntityLoader, useCurrentIds] = constate(function useInitServices(props) {
|
|
100
133
|
const currentSpaceId = props.sdk.ids.space;
|
|
101
134
|
const currentEnvironmentId = props.sdk.ids.environmentAlias ?? props.sdk.ids.environment;
|
|
@@ -212,9 +245,21 @@ const [InternalServiceProvider, useFetch, useEntityLoader, useCurrentIds] = cons
|
|
|
212
245
|
options
|
|
213
246
|
});
|
|
214
247
|
}
|
|
215
|
-
|
|
248
|
+
if (!options?.allowExternal) {
|
|
249
|
+
throw new UnsupportedError('Unsupported resource type');
|
|
250
|
+
}
|
|
251
|
+
return fetchExternalResource({
|
|
252
|
+
fetch,
|
|
253
|
+
urn,
|
|
254
|
+
options,
|
|
255
|
+
resourceType,
|
|
256
|
+
spaceId: currentSpaceId,
|
|
257
|
+
environmentId: currentEnvironmentId
|
|
258
|
+
});
|
|
216
259
|
}, options);
|
|
217
260
|
}, [
|
|
261
|
+
currentEnvironmentId,
|
|
262
|
+
currentSpaceId,
|
|
218
263
|
fetch
|
|
219
264
|
]);
|
|
220
265
|
const isSameSpaceEntityQueryKey = useCallback((queryKey)=>{
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
2
|
import { useInView } from 'react-intersection-observer';
|
|
3
3
|
import { EntryCard } from '@contentful/f36-components';
|
|
4
|
-
import { useResource } from '../../common/EntityStore';
|
|
4
|
+
import { isContentfulResourceInfo, useResource } from '../../common/EntityStore';
|
|
5
5
|
import { ResourceEntityErrorCard } from '../../components';
|
|
6
|
+
import { ExternalResourceCard } from '../ExternalResourceCard/ExternalResourceCard';
|
|
6
7
|
import { ContentfulEntryCard } from './ContentfulEntryCard';
|
|
7
8
|
function ResourceCardSkeleton() {
|
|
8
9
|
return React.createElement(EntryCard, {
|
|
@@ -14,23 +15,30 @@ function ExistingResourceCard(props) {
|
|
|
14
15
|
const { resourceLink, inView, index = 0 } = props;
|
|
15
16
|
const resourceOptions = {
|
|
16
17
|
priority: index * -1,
|
|
17
|
-
enabled: inView
|
|
18
|
+
enabled: inView,
|
|
19
|
+
allowExternal: true
|
|
18
20
|
};
|
|
19
|
-
const { data, error } = useResource(resourceLink.sys.linkType, resourceLink.sys.urn, resourceOptions);
|
|
20
|
-
if (!
|
|
21
|
+
const { data: info, error } = useResource(resourceLink.sys.linkType, resourceLink.sys.urn, resourceOptions);
|
|
22
|
+
if (!info && !error) {
|
|
21
23
|
return React.createElement(ResourceCardSkeleton, null);
|
|
22
24
|
}
|
|
23
|
-
if (
|
|
25
|
+
if (!info) {
|
|
26
|
+
return React.createElement(ResourceEntityErrorCard, {
|
|
27
|
+
linkType: resourceLink.sys.linkType,
|
|
28
|
+
error: error,
|
|
29
|
+
isDisabled: props.isDisabled,
|
|
30
|
+
onRemove: props.onRemove
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
if (isContentfulResourceInfo(info)) {
|
|
24
34
|
return React.createElement(ContentfulEntryCard, {
|
|
25
|
-
info:
|
|
35
|
+
info: info,
|
|
26
36
|
...props
|
|
27
37
|
});
|
|
28
38
|
}
|
|
29
|
-
return React.createElement(
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
isDisabled: props.isDisabled,
|
|
33
|
-
onRemove: props.onRemove
|
|
39
|
+
return React.createElement(ExternalResourceCard, {
|
|
40
|
+
info: info,
|
|
41
|
+
...props
|
|
34
42
|
});
|
|
35
43
|
}
|
|
36
44
|
function ResourceCardWrapper(props) {
|
|
@@ -5,6 +5,8 @@ import { configure, fireEvent, render, waitFor } from '@testing-library/react';
|
|
|
5
5
|
import publishedCT from '../../__fixtures__/content-type/published_content_type.json';
|
|
6
6
|
import publishedEntryNonMasterEnvironment from '../../__fixtures__/entry/published_entry_non_master.json';
|
|
7
7
|
import publishedEntry from '../../__fixtures__/entry/published_entry.json';
|
|
8
|
+
import resourceType from '../../__fixtures__/resource-type/resource-type.json';
|
|
9
|
+
import resource from '../../__fixtures__/resource/resource.json';
|
|
8
10
|
import space from '../../__fixtures__/space/indifferent_space.json';
|
|
9
11
|
import { EntityProvider } from '../../common/EntityStore';
|
|
10
12
|
import { ResourceCard } from './ResourceCard';
|
|
@@ -18,6 +20,8 @@ const resolvableEntryUrn = 'crn:contentful:::content:spaces/space-id/entries/lin
|
|
|
18
20
|
const resolvableEntryUrnWithExplicitMaster = 'crn:contentful:::content:spaces/space-id/environments/master/entries/linked-entry-urn';
|
|
19
21
|
const resolvableEntryUrnWithAnotherEnvironment = 'crn:contentful:::content:spaces/space-id/environments/my-test-environment/entries/linked-entry-urn';
|
|
20
22
|
const unknownEntryUrn = 'crn:contentful:::content:spaces/space-id/entries/unknown-entry-urn';
|
|
23
|
+
const resolvableExternalResourceType = 'External:ResourceType';
|
|
24
|
+
const resolvableExternalEntityUrn = 'external:entity-urn';
|
|
21
25
|
const sdk = {
|
|
22
26
|
locales: {
|
|
23
27
|
default: 'en-US'
|
|
@@ -37,6 +41,27 @@ const sdk = {
|
|
|
37
41
|
return Promise.reject(new Error());
|
|
38
42
|
})
|
|
39
43
|
},
|
|
44
|
+
Http: {
|
|
45
|
+
get: jest.fn().mockImplementation(({ url, config })=>{
|
|
46
|
+
if (url === '/spaces/space-id/environments/environment-id/resource_types') {
|
|
47
|
+
return Promise.resolve({
|
|
48
|
+
items: [
|
|
49
|
+
resourceType
|
|
50
|
+
]
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
if (url === `/spaces/space-id/environments/environment-id/resource_types/${resolvableExternalResourceType}/resources` && config.params['sys.urn[in]'] === resolvableExternalEntityUrn) {
|
|
54
|
+
return Promise.resolve({
|
|
55
|
+
items: [
|
|
56
|
+
resource
|
|
57
|
+
]
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
return Promise.resolve({
|
|
61
|
+
items: []
|
|
62
|
+
});
|
|
63
|
+
})
|
|
64
|
+
},
|
|
40
65
|
Locale: {
|
|
41
66
|
getMany: jest.fn().mockResolvedValue({
|
|
42
67
|
items: [
|
|
@@ -66,7 +91,7 @@ const sdk = {
|
|
|
66
91
|
environment: 'environment-id'
|
|
67
92
|
}
|
|
68
93
|
};
|
|
69
|
-
function renderResourceCard({ linkType = 'Contentful:Entry',
|
|
94
|
+
function renderResourceCard({ linkType = 'Contentful:Entry', entityUrn = resolvableEntryUrn } = {}) {
|
|
70
95
|
return render(React.createElement(EntityProvider, {
|
|
71
96
|
sdk: sdk
|
|
72
97
|
}, React.createElement(ResourceCard, {
|
|
@@ -76,7 +101,7 @@ function renderResourceCard({ linkType = 'Contentful:Entry', entryUrn = resolvab
|
|
|
76
101
|
sys: {
|
|
77
102
|
type: 'ResourceLink',
|
|
78
103
|
linkType: linkType,
|
|
79
|
-
urn:
|
|
104
|
+
urn: entityUrn
|
|
80
105
|
}
|
|
81
106
|
}
|
|
82
107
|
})));
|
|
@@ -93,7 +118,7 @@ describe('ResourceCard', ()=>{
|
|
|
93
118
|
});
|
|
94
119
|
it('renders entry card with explicit master crn', async ()=>{
|
|
95
120
|
const { getByTestId, getByText } = renderResourceCard({
|
|
96
|
-
|
|
121
|
+
entityUrn: resolvableEntryUrnWithExplicitMaster
|
|
97
122
|
});
|
|
98
123
|
const tooltipContent = `Space: ${space.name} (Env.: ${publishedEntry.sys.environment.sys.id})`;
|
|
99
124
|
await waitFor(()=>expect(getByTestId('cf-ui-entry-card')).toBeDefined());
|
|
@@ -104,7 +129,7 @@ describe('ResourceCard', ()=>{
|
|
|
104
129
|
});
|
|
105
130
|
it('renders entry card with a non master environment', async ()=>{
|
|
106
131
|
const { getByTestId, getByText } = renderResourceCard({
|
|
107
|
-
|
|
132
|
+
entityUrn: resolvableEntryUrnWithAnotherEnvironment
|
|
108
133
|
});
|
|
109
134
|
await waitFor(()=>expect(getByTestId('cf-ui-entry-card')).toBeDefined());
|
|
110
135
|
const tooltipContent = `Space: ${space.name} (Env.: ${publishedEntryNonMasterEnvironment.sys.environment.sys.id})`;
|
|
@@ -117,7 +142,7 @@ describe('ResourceCard', ()=>{
|
|
|
117
142
|
const { getByTestId } = renderResourceCard();
|
|
118
143
|
expect(getByTestId('cf-ui-skeleton-form')).toBeDefined();
|
|
119
144
|
});
|
|
120
|
-
it('renders unsupported entity card when
|
|
145
|
+
it('renders unsupported entity card when resource type is unknown', async ()=>{
|
|
121
146
|
const { getByText } = renderResourceCard({
|
|
122
147
|
linkType: 'Contentful:UnsupportedLink'
|
|
123
148
|
});
|
|
@@ -125,14 +150,30 @@ describe('ResourceCard', ()=>{
|
|
|
125
150
|
});
|
|
126
151
|
it('renders missing entity card when unknown error is returned', async ()=>{
|
|
127
152
|
const { getByTestId } = renderResourceCard({
|
|
128
|
-
|
|
153
|
+
entityUrn: unknownEntryUrn
|
|
129
154
|
});
|
|
130
155
|
await waitFor(()=>expect(getByTestId('cf-ui-missing-entry-card')).toBeDefined());
|
|
131
156
|
});
|
|
132
157
|
it('renders missing entity card when crn is invalid', async ()=>{
|
|
133
158
|
const { getByTestId } = renderResourceCard({
|
|
134
|
-
|
|
159
|
+
entityUrn: ''
|
|
160
|
+
});
|
|
161
|
+
await waitFor(()=>expect(getByTestId('cf-ui-missing-entry-card')).toBeDefined());
|
|
162
|
+
});
|
|
163
|
+
it('renders missing entity card when external urn is invalid', async ()=>{
|
|
164
|
+
const { getByTestId } = renderResourceCard({
|
|
165
|
+
linkType: resolvableExternalResourceType,
|
|
166
|
+
entityUrn: ''
|
|
135
167
|
});
|
|
136
168
|
await waitFor(()=>expect(getByTestId('cf-ui-missing-entry-card')).toBeDefined());
|
|
137
169
|
});
|
|
170
|
+
it('renders entry card for external resource', async ()=>{
|
|
171
|
+
const { getByTestId, getByText } = renderResourceCard({
|
|
172
|
+
linkType: resolvableExternalResourceType,
|
|
173
|
+
entityUrn: resolvableExternalEntityUrn
|
|
174
|
+
});
|
|
175
|
+
await waitFor(()=>expect(getByTestId('cf-ui-entry-card')).toBeDefined());
|
|
176
|
+
expect(getByText(resource.fields.title)).toBeDefined();
|
|
177
|
+
expect(getByText(resourceType.name)).toBeDefined();
|
|
178
|
+
});
|
|
138
179
|
});
|
|
@@ -2,40 +2,32 @@ import * as React from 'react';
|
|
|
2
2
|
import { Badge, EntryCard, MenuItem, MenuDivider } from '@contentful/f36-components';
|
|
3
3
|
const defaultProps = {
|
|
4
4
|
isClickable: true,
|
|
5
|
-
hasCardEditActions: true,
|
|
6
5
|
hasCardMoveActions: true,
|
|
7
6
|
hasCardRemoveActions: true
|
|
8
7
|
};
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
suspended: 'negative'
|
|
14
|
-
};
|
|
15
|
-
function ExternalEntityBadge(entityStatus) {
|
|
16
|
-
const variant = statusMap[entityStatus];
|
|
17
|
-
return React.createElement(Badge, {
|
|
18
|
-
variant: variant
|
|
19
|
-
}, entityStatus);
|
|
8
|
+
function ExternalEntityBadge(badge) {
|
|
9
|
+
return badge ? React.createElement(Badge, {
|
|
10
|
+
variant: badge.variant
|
|
11
|
+
}, badge.label) : null;
|
|
20
12
|
}
|
|
21
|
-
export function ExternalResourceCard({
|
|
22
|
-
const
|
|
23
|
-
const badge =
|
|
13
|
+
export function ExternalResourceCard({ info, isClickable, onEdit, onRemove, onMoveTop, onMoveBottom, hasCardEditActions, hasCardMoveActions, hasCardRemoveActions, renderDragHandle, onClick }) {
|
|
14
|
+
const { resource: entity, resourceType } = info;
|
|
15
|
+
const badge = ExternalEntityBadge(entity.fields.badge);
|
|
24
16
|
return React.createElement(EntryCard, {
|
|
25
17
|
as: entity.fields.externalUrl ? 'a' : 'article',
|
|
26
18
|
href: entity.fields.externalUrl,
|
|
27
19
|
title: entity.fields.title,
|
|
28
20
|
description: entity.fields.description,
|
|
29
|
-
contentType: resourceType,
|
|
30
|
-
size:
|
|
31
|
-
thumbnailElement: entity.fields.image
|
|
32
|
-
alt: entity.fields.image.
|
|
21
|
+
contentType: resourceType.name,
|
|
22
|
+
size: 'auto',
|
|
23
|
+
thumbnailElement: entity.fields.image?.url ? React.createElement("img", {
|
|
24
|
+
alt: entity.fields.image.altText,
|
|
33
25
|
src: entity.fields.image.url
|
|
34
26
|
}) : undefined,
|
|
35
27
|
dragHandleRender: renderDragHandle,
|
|
36
28
|
withDragHandle: !!renderDragHandle,
|
|
37
29
|
badge: badge,
|
|
38
|
-
actions:
|
|
30
|
+
actions: [
|
|
39
31
|
hasCardEditActions && onEdit ? React.createElement(MenuItem, {
|
|
40
32
|
key: "edit",
|
|
41
33
|
testId: "edit",
|
|
@@ -50,7 +42,7 @@ export function ExternalResourceCard({ entity, resourceType, size, isClickable,
|
|
|
50
42
|
onRemove && onRemove();
|
|
51
43
|
}
|
|
52
44
|
}, "Remove") : null,
|
|
53
|
-
hasCardMoveActions && (onMoveTop || onMoveBottom) ? React.createElement(MenuDivider, {
|
|
45
|
+
hasCardMoveActions && (onEdit || onRemove) && (onMoveTop || onMoveBottom) ? React.createElement(MenuDivider, {
|
|
54
46
|
key: "divider"
|
|
55
47
|
}) : null,
|
|
56
48
|
hasCardMoveActions && onMoveTop ? React.createElement(MenuItem, {
|
|
@@ -63,7 +55,7 @@ export function ExternalResourceCard({ entity, resourceType, size, isClickable,
|
|
|
63
55
|
onClick: ()=>onMoveBottom && onMoveBottom(),
|
|
64
56
|
testId: "move-bottom"
|
|
65
57
|
}, "Move to bottom") : null
|
|
66
|
-
].filter((item)=>item)
|
|
58
|
+
].filter((item)=>item),
|
|
67
59
|
onClick: isClickable ? (e)=>{
|
|
68
60
|
e.preventDefault();
|
|
69
61
|
if (onClick) return onClick(e);
|
|
@@ -1,12 +1,18 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { BaseAppSDK } from '@contentful/app-sdk';
|
|
3
|
-
import { Asset, ContentType, Entry, Resource, ResourceType, ScheduledAction, Space } from '../types';
|
|
4
|
-
export type
|
|
5
|
-
resource:
|
|
3
|
+
import { Asset, ContentType, Entry, ExternalResource, Resource, ResourceType, ScheduledAction, Space } from '../types';
|
|
4
|
+
export type ContentfulResourceInfo = {
|
|
5
|
+
resource: Entry;
|
|
6
6
|
defaultLocaleCode: string;
|
|
7
7
|
contentType: ContentType;
|
|
8
8
|
space: Space;
|
|
9
9
|
};
|
|
10
|
+
export type ExternalResourceInfo = {
|
|
11
|
+
resource: ExternalResource;
|
|
12
|
+
resourceType: ResourceType;
|
|
13
|
+
};
|
|
14
|
+
export type ResourceInfo<R extends Resource = Resource> = R extends Entry ? ContentfulResourceInfo : ExternalResourceInfo;
|
|
15
|
+
export declare function isContentfulResourceInfo(info: ResourceInfo): info is ContentfulResourceInfo;
|
|
10
16
|
type EntityStoreProps = {
|
|
11
17
|
sdk: BaseAppSDK;
|
|
12
18
|
queryConcurrency?: number;
|
|
@@ -22,7 +28,9 @@ type UseEntityOptions = GetEntityOptions & {
|
|
|
22
28
|
enabled?: boolean;
|
|
23
29
|
};
|
|
24
30
|
type QueryEntityResult<E> = Promise<E>;
|
|
25
|
-
type GetResourceOptions = GetOptions
|
|
31
|
+
type GetResourceOptions = GetOptions & {
|
|
32
|
+
allowExternal?: boolean;
|
|
33
|
+
};
|
|
26
34
|
type QueryResourceResult<R extends Resource = Resource> = QueryEntityResult<ResourceInfo<R>>;
|
|
27
35
|
type UseResourceOptions = GetResourceOptions & {
|
|
28
36
|
enabled?: boolean;
|
|
@@ -48,14 +56,14 @@ export declare class UnsupportedError extends Error {
|
|
|
48
56
|
}
|
|
49
57
|
export declare function isUnsupportedError(value: unknown): value is UnsupportedError;
|
|
50
58
|
declare const useEntityLoader: () => {
|
|
51
|
-
getResource: <R extends Resource = Resource>(resourceType:
|
|
59
|
+
getResource: <R extends Resource = Resource>(resourceType: string, urn: string, options?: GetResourceOptions) => QueryResourceResult<R>;
|
|
52
60
|
getEntity: <E extends FetchableEntity>(entityType: FetchableEntityType, entityId: string, options?: GetEntityOptions) => QueryEntityResult<E>;
|
|
53
61
|
getEntityScheduledActions: (entityType: FetchableEntityType, entityId: string, options?: GetEntityOptions) => QueryEntityResult<ScheduledAction[]>;
|
|
54
62
|
};
|
|
55
63
|
export declare function useEntity<E extends FetchableEntity>(entityType: FetchableEntityType, entityId: string, options?: UseEntityOptions): UseEntityResult<E>;
|
|
56
|
-
export declare function useResource(resourceType:
|
|
64
|
+
export declare function useResource<R extends Resource = Resource>(resourceType: string, urn: string, options?: UseResourceOptions): {
|
|
57
65
|
status: "error" | "success" | "loading";
|
|
58
|
-
data: ResourceInfo<
|
|
66
|
+
data: ResourceInfo<R> | undefined;
|
|
59
67
|
error: unknown;
|
|
60
68
|
};
|
|
61
69
|
declare function EntityProvider({ children, ...props }: React.PropsWithChildren<EntityStoreProps>): JSX.Element;
|
|
@@ -3,7 +3,7 @@ import { RenderDragFn, ResourceLink } from '../../types';
|
|
|
3
3
|
import { CardActionsHandlers, EntryRoute } from './ContentfulEntryCard';
|
|
4
4
|
type ResourceCardProps = {
|
|
5
5
|
index?: number;
|
|
6
|
-
resourceLink?: ResourceLink
|
|
6
|
+
resourceLink?: ResourceLink<string>;
|
|
7
7
|
isDisabled: boolean;
|
|
8
8
|
renderDragHandle?: RenderDragFn;
|
|
9
9
|
getEntryRouteHref: (entryRoute: EntryRoute) => string;
|
|
@@ -1,35 +1,9 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
|
+
import { ExternalResourceInfo } from '../../common/EntityStore';
|
|
2
3
|
import { RenderDragFn } from '../../types';
|
|
3
|
-
type SysExternalResource<T extends string> = {
|
|
4
|
-
sys: {
|
|
5
|
-
type: 'Link';
|
|
6
|
-
linkType: T;
|
|
7
|
-
id: string;
|
|
8
|
-
};
|
|
9
|
-
};
|
|
10
|
-
interface ExternalResource {
|
|
11
|
-
sys: {
|
|
12
|
-
type: string;
|
|
13
|
-
id: string;
|
|
14
|
-
resourceProvider: SysExternalResource<'ResourceProvider'>;
|
|
15
|
-
resourceType: SysExternalResource<'ResourceType'>;
|
|
16
|
-
};
|
|
17
|
-
fields: {
|
|
18
|
-
title: string;
|
|
19
|
-
description?: string;
|
|
20
|
-
externalUrl?: string;
|
|
21
|
-
image?: {
|
|
22
|
-
url?: string;
|
|
23
|
-
description?: string;
|
|
24
|
-
};
|
|
25
|
-
additionalData: any;
|
|
26
|
-
};
|
|
27
|
-
}
|
|
28
4
|
export interface ExternalResourceCardProps {
|
|
29
|
-
|
|
30
|
-
resourceType: string;
|
|
5
|
+
info: ExternalResourceInfo;
|
|
31
6
|
isDisabled: boolean;
|
|
32
|
-
size: 'small' | 'default' | 'auto';
|
|
33
7
|
isSelected?: boolean;
|
|
34
8
|
onRemove?: () => void;
|
|
35
9
|
onEdit?: () => void;
|
|
@@ -38,17 +12,15 @@ export interface ExternalResourceCardProps {
|
|
|
38
12
|
isClickable?: boolean;
|
|
39
13
|
onMoveTop?: () => void;
|
|
40
14
|
onMoveBottom?: () => void;
|
|
41
|
-
hasCardEditActions
|
|
15
|
+
hasCardEditActions?: boolean;
|
|
42
16
|
hasCardMoveActions?: boolean;
|
|
43
17
|
hasCardRemoveActions?: boolean;
|
|
44
18
|
}
|
|
45
|
-
export declare function ExternalResourceCard({
|
|
19
|
+
export declare function ExternalResourceCard({ info, isClickable, onEdit, onRemove, onMoveTop, onMoveBottom, hasCardEditActions, hasCardMoveActions, hasCardRemoveActions, renderDragHandle, onClick, }: ExternalResourceCardProps): JSX.Element;
|
|
46
20
|
export declare namespace ExternalResourceCard {
|
|
47
21
|
var defaultProps: {
|
|
48
22
|
isClickable: boolean;
|
|
49
|
-
hasCardEditActions: boolean;
|
|
50
23
|
hasCardMoveActions: boolean;
|
|
51
24
|
hasCardRemoveActions: boolean;
|
|
52
25
|
};
|
|
53
26
|
}
|
|
54
|
-
export {};
|
package/dist/types/types.d.ts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import { NavigatorSlideInfo, ContentEntityType } from '@contentful/app-sdk';
|
|
3
3
|
import { Entry, Asset } from '@contentful/field-editor-shared';
|
|
4
4
|
export type { BaseAppSDK, FieldAppSDK, ContentType, ContentTypeField, Link, ContentEntityType, NavigatorSlideInfo, ScheduledAction, } from '@contentful/app-sdk';
|
|
5
|
-
export type { SpaceProps as Space } from 'contentful-management';
|
|
5
|
+
export type { SpaceProps as Space, ResourceLink } from 'contentful-management';
|
|
6
6
|
export { Entry, File, Asset } from '@contentful/field-editor-shared';
|
|
7
7
|
export type { ResourceInfo } from './common/EntityStore';
|
|
8
8
|
export type Entity = Entry | Asset;
|
|
@@ -21,9 +21,45 @@ export type AssetLink = {
|
|
|
21
21
|
};
|
|
22
22
|
};
|
|
23
23
|
export type EntityLink = EntryLink | AssetLink;
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
24
|
+
type SysExternalResource<T extends string> = {
|
|
25
|
+
sys: {
|
|
26
|
+
type: 'Link';
|
|
27
|
+
linkType: T;
|
|
28
|
+
id: string;
|
|
29
|
+
};
|
|
30
|
+
};
|
|
31
|
+
export type ResourceType = {
|
|
32
|
+
sys: {
|
|
33
|
+
type: 'ResourceType';
|
|
34
|
+
id: string;
|
|
35
|
+
resourceProvider: SysExternalResource<'ResourceProvider'>;
|
|
36
|
+
};
|
|
37
|
+
name: string;
|
|
38
|
+
};
|
|
39
|
+
export interface ExternalResource {
|
|
40
|
+
sys: {
|
|
41
|
+
type: 'Resource';
|
|
42
|
+
id: string;
|
|
43
|
+
resourceProvider: SysExternalResource<'ResourceProvider'>;
|
|
44
|
+
resourceType: SysExternalResource<'ResourceType'>;
|
|
45
|
+
};
|
|
46
|
+
fields: {
|
|
47
|
+
title: string;
|
|
48
|
+
subtitle?: string;
|
|
49
|
+
description?: string;
|
|
50
|
+
externalUrl?: string;
|
|
51
|
+
badge?: {
|
|
52
|
+
label: string;
|
|
53
|
+
variant: 'negative' | 'positive' | 'primary' | 'secondary' | 'warning';
|
|
54
|
+
};
|
|
55
|
+
image?: {
|
|
56
|
+
url: string;
|
|
57
|
+
altText?: string;
|
|
58
|
+
};
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
export type Resource = Entry | ExternalResource;
|
|
62
|
+
export type EntityType = 'Entry' | 'Asset' | string;
|
|
27
63
|
export type SysResourceLink<T extends string> = {
|
|
28
64
|
sys: {
|
|
29
65
|
type: 'ResourceLink';
|
|
@@ -32,7 +68,6 @@ export type SysResourceLink<T extends string> = {
|
|
|
32
68
|
};
|
|
33
69
|
};
|
|
34
70
|
export type ContentfulEntryLink = SysResourceLink<'Contentful:Entry'>;
|
|
35
|
-
export type ResourceLink = ContentfulEntryLink;
|
|
36
71
|
/**
|
|
37
72
|
* @deprecated use `EntityLink` type
|
|
38
73
|
*/
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@contentful/field-editor-reference",
|
|
3
|
-
"version": "5.
|
|
3
|
+
"version": "5.23.0",
|
|
4
4
|
"main": "dist/cjs/index.js",
|
|
5
5
|
"module": "dist/esm/index.js",
|
|
6
6
|
"types": "dist/types/index.d.ts",
|
|
@@ -67,5 +67,5 @@
|
|
|
67
67
|
"publishConfig": {
|
|
68
68
|
"registry": "https://npm.pkg.github.com/"
|
|
69
69
|
},
|
|
70
|
-
"gitHead": "
|
|
70
|
+
"gitHead": "7018fb86df27fcb2e0d4bdb475549367fe6ee87d"
|
|
71
71
|
}
|