@contentful/field-editor-reference 5.18.0 → 5.20.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/__fixtures__/FakeSdk.js +3 -3
- package/dist/cjs/__fixtures__/asset/index.js +10 -10
- package/dist/cjs/__fixtures__/content-type/index.js +1 -1
- package/dist/cjs/__fixtures__/entry/index.js +7 -7
- package/dist/cjs/__fixtures__/fixtures.js +8 -6
- package/dist/cjs/__fixtures__/locale/index.js +2 -2
- package/dist/cjs/__fixtures__/space/index.js +1 -1
- package/dist/cjs/assets/MultipleMediaEditor.js +7 -5
- package/dist/cjs/assets/SingleMediaEditor.js +6 -4
- package/dist/cjs/assets/WrappedAssetCard/AssetCardActions.js +21 -19
- package/dist/cjs/assets/WrappedAssetCard/FetchingWrappedAssetCard.js +18 -11
- package/dist/cjs/assets/WrappedAssetCard/WrappedAssetCard.js +20 -11
- package/dist/cjs/assets/WrappedAssetCard/WrappedAssetLink.js +12 -9
- package/dist/cjs/assets/index.js +3 -3
- package/dist/cjs/common/EntityStore.js +53 -53
- package/dist/cjs/common/MultipleReferenceEditor.js +20 -11
- package/dist/cjs/common/ReferenceEditor.js +7 -5
- package/dist/cjs/common/SingleReferenceEditor.js +11 -7
- package/dist/cjs/common/SortableLinkList.js +14 -14
- package/dist/cjs/common/customCardTypes.js +4 -2
- package/dist/cjs/common/queryClient.js +102 -0
- package/dist/cjs/common/useContentTypePermissions.js +3 -1
- package/dist/cjs/common/useEditorPermissions.js +15 -3
- package/dist/cjs/common/useEditorPermissions.spec.js +13 -12
- package/dist/cjs/components/AssetThumbnail/AssetThumbnail.js +5 -3
- package/dist/cjs/components/CreateEntryLinkButton/CreateEntryLinkButton.js +13 -9
- package/dist/cjs/components/CreateEntryLinkButton/CreateEntryLinkButton.spec.js +17 -15
- package/dist/cjs/components/CreateEntryLinkButton/CreateEntryMenuTrigger.js +29 -19
- package/dist/cjs/components/CreateEntryLinkButton/CreateEntryMenuTrigger.spec.js +14 -12
- package/dist/cjs/components/LinkActions/CombinedLinkActions.js +28 -21
- package/dist/cjs/components/LinkActions/LinkActions.js +17 -15
- package/dist/cjs/components/LinkActions/LinkEntityActions.js +26 -17
- package/dist/cjs/components/LinkActions/NoLinkPermissionsInfo.js +5 -3
- package/dist/cjs/components/LinkActions/helpers.js +10 -5
- package/dist/cjs/components/LinkActions/redesignStyles.js +4 -4
- package/dist/cjs/components/LinkActions/styles.js +1 -1
- package/dist/cjs/components/MissingEntityCard/MissingEntityCard.js +11 -9
- package/dist/cjs/components/ResourceEntityErrorCard/ResourceEntityErrorCard.js +6 -4
- package/dist/cjs/components/ResourceEntityErrorCard/UnsupportedEntityCard.js +6 -4
- package/dist/cjs/components/ScheduledIconWithTooltip/ScheduleTooltip.js +10 -8
- package/dist/cjs/components/ScheduledIconWithTooltip/ScheduledIconWithTooltip.js +9 -4
- package/dist/cjs/components/ScheduledIconWithTooltip/formatDateAndTime.js +5 -4
- package/dist/cjs/components/SpaceName/SpaceName.js +10 -8
- package/dist/cjs/components/index.js +12 -12
- package/dist/cjs/entries/MultipleEntryReferenceEditor.js +9 -7
- package/dist/cjs/entries/SingleEntryReferenceEditor.js +7 -5
- package/dist/cjs/entries/WrappedEntryCard/FetchingWrappedEntryCard.js +20 -11
- package/dist/cjs/entries/WrappedEntryCard/WrappedEntryCard.js +23 -17
- package/dist/cjs/entries/index.js +3 -3
- package/dist/cjs/index.js +38 -34
- package/dist/cjs/resources/Cards/ContentfulEntryCard.js +13 -4
- package/dist/cjs/resources/Cards/ResourceCard.js +16 -12
- package/dist/cjs/resources/Cards/ResourceCard.spec.js +20 -17
- package/dist/cjs/resources/MultipleResourceReferenceEditor.js +20 -17
- package/dist/cjs/resources/MultipleResourceReferenceEditor.spec.js +34 -13
- package/dist/cjs/resources/SingleResourceReferenceEditor.js +11 -9
- package/dist/cjs/resources/SingleResourceReferenceEditor.spec.js +13 -6
- package/dist/cjs/resources/testHelpers/resourceEditorHelpers.js +12 -5
- package/dist/cjs/resources/useResourceLinkActions.js +11 -2
- package/dist/cjs/types.js +3 -3
- package/dist/cjs/utils/fromFieldValidations.js +2 -1
- package/dist/cjs/utils/useSortIDs.js +6 -4
- package/dist/esm/__fixtures__/FakeSdk.js +3 -3
- package/dist/esm/assets/MultipleMediaEditor.js +3 -3
- package/dist/esm/assets/SingleMediaEditor.js +2 -2
- package/dist/esm/assets/WrappedAssetCard/AssetCardActions.js +12 -12
- package/dist/esm/assets/WrappedAssetCard/FetchingWrappedAssetCard.js +14 -9
- package/dist/esm/assets/WrappedAssetCard/WrappedAssetCard.js +15 -7
- package/dist/esm/assets/WrappedAssetCard/WrappedAssetLink.js +7 -6
- package/dist/esm/common/EntityStore.js +40 -42
- package/dist/esm/common/MultipleReferenceEditor.js +16 -9
- package/dist/esm/common/ReferenceEditor.js +2 -2
- package/dist/esm/common/SingleReferenceEditor.js +7 -5
- package/dist/esm/common/SortableLinkList.js +12 -12
- package/dist/esm/common/queryClient.js +44 -0
- package/dist/esm/common/useContentTypePermissions.js +3 -1
- package/dist/esm/common/useEditorPermissions.js +15 -3
- package/dist/esm/common/useEditorPermissions.spec.js +13 -12
- package/dist/esm/components/AssetThumbnail/AssetThumbnail.js +1 -1
- package/dist/esm/components/CreateEntryLinkButton/CreateEntryLinkButton.js +7 -5
- package/dist/esm/components/CreateEntryLinkButton/CreateEntryLinkButton.spec.js +12 -12
- package/dist/esm/components/CreateEntryLinkButton/CreateEntryMenuTrigger.js +23 -15
- package/dist/esm/components/CreateEntryLinkButton/CreateEntryMenuTrigger.spec.js +9 -8
- package/dist/esm/components/LinkActions/CombinedLinkActions.js +30 -19
- package/dist/esm/components/LinkActions/LinkActions.js +9 -9
- package/dist/esm/components/LinkActions/LinkEntityActions.js +18 -11
- package/dist/esm/components/LinkActions/NoLinkPermissionsInfo.js +1 -1
- package/dist/esm/components/LinkActions/helpers.js +7 -2
- package/dist/esm/components/MissingEntityCard/MissingEntityCard.js +6 -6
- package/dist/esm/components/ResourceEntityErrorCard/ResourceEntityErrorCard.js +2 -2
- package/dist/esm/components/ResourceEntityErrorCard/UnsupportedEntityCard.js +2 -2
- package/dist/esm/components/ScheduledIconWithTooltip/ScheduleTooltip.js +3 -3
- package/dist/esm/components/ScheduledIconWithTooltip/ScheduledIconWithTooltip.js +5 -2
- package/dist/esm/components/ScheduledIconWithTooltip/formatDateAndTime.js +11 -2
- package/dist/esm/components/SpaceName/SpaceName.js +5 -5
- package/dist/esm/entries/MultipleEntryReferenceEditor.js +5 -5
- package/dist/esm/entries/SingleEntryReferenceEditor.js +3 -3
- package/dist/esm/entries/WrappedEntryCard/FetchingWrappedEntryCard.js +15 -8
- package/dist/esm/entries/WrappedEntryCard/WrappedEntryCard.js +18 -14
- package/dist/esm/index.js +1 -0
- package/dist/esm/resources/Cards/ContentfulEntryCard.js +9 -2
- package/dist/esm/resources/Cards/ResourceCard.js +12 -10
- package/dist/esm/resources/Cards/ResourceCard.spec.js +12 -11
- package/dist/esm/resources/MultipleResourceReferenceEditor.js +14 -13
- package/dist/esm/resources/MultipleResourceReferenceEditor.spec.js +30 -11
- package/dist/esm/resources/SingleResourceReferenceEditor.js +6 -6
- package/dist/esm/resources/SingleResourceReferenceEditor.spec.js +9 -4
- package/dist/esm/resources/testHelpers/resourceEditorHelpers.js +9 -2
- package/dist/esm/resources/useResourceLinkActions.js +11 -2
- package/dist/esm/utils/fromFieldValidations.js +1 -0
- package/dist/esm/utils/useSortIDs.js +2 -2
- package/dist/types/common/EntityStore.d.ts +1 -1
- package/dist/types/common/queryClient.d.ts +9 -0
- package/dist/types/index.d.ts +1 -0
- package/package.json +2 -2
|
@@ -10,9 +10,9 @@ import { CombinedLinkEntityActions } from '../components/LinkActions/LinkEntityA
|
|
|
10
10
|
import { ResourceCard } from './Cards/ResourceCard';
|
|
11
11
|
import { useResourceLinkActions } from './useResourceLinkActions';
|
|
12
12
|
function ResourceEditor(props) {
|
|
13
|
-
const { setValue
|
|
13
|
+
const { setValue, items, apiUrl } = props;
|
|
14
14
|
const onSortStart = ()=>noop();
|
|
15
|
-
const onSortEnd = useCallback(({ oldIndex
|
|
15
|
+
const onSortEnd = useCallback(({ oldIndex, newIndex })=>{
|
|
16
16
|
const newItems = arrayMove(items, oldIndex, newIndex);
|
|
17
17
|
setValue(newItems);
|
|
18
18
|
}, [
|
|
@@ -32,24 +32,25 @@ function ResourceEditor(props) {
|
|
|
32
32
|
items,
|
|
33
33
|
setValue
|
|
34
34
|
]);
|
|
35
|
-
const { dialogs
|
|
35
|
+
const { dialogs, field } = props.sdk;
|
|
36
36
|
const linkActionsProps = useResourceLinkActions({
|
|
37
37
|
dialogs,
|
|
38
38
|
field,
|
|
39
39
|
apiUrl
|
|
40
40
|
});
|
|
41
|
-
return React.createElement(React.Fragment, null, props.children({
|
|
41
|
+
return /*#__PURE__*/ React.createElement(React.Fragment, null, props.children({
|
|
42
42
|
...props,
|
|
43
43
|
onSortStart,
|
|
44
44
|
onSortEnd,
|
|
45
45
|
onMove,
|
|
46
46
|
onRemoteItemAtIndex
|
|
47
|
-
}), React.createElement(CombinedLinkEntityActions, {
|
|
47
|
+
}), /*#__PURE__*/ React.createElement(CombinedLinkEntityActions, {
|
|
48
48
|
...linkActionsProps,
|
|
49
49
|
renderCustomActions: props.renderCustomActions
|
|
50
50
|
}));
|
|
51
51
|
}
|
|
52
|
-
|
|
52
|
+
// provides memoized callbacks bound to a given item
|
|
53
|
+
function WithPerItemCallbacks({ listLength, index, onMove, onRemoteItemAtIndex, children }) {
|
|
53
54
|
const handleMoveTop = React.useMemo(()=>index > 0 ? ()=>onMove(index, 0) : undefined, [
|
|
54
55
|
index,
|
|
55
56
|
onMove
|
|
@@ -63,7 +64,7 @@ function WithPerItemCallbacks({ listLength , index , onMove , onRemoteItemAtInde
|
|
|
63
64
|
index,
|
|
64
65
|
onRemoteItemAtIndex
|
|
65
66
|
]);
|
|
66
|
-
return React.createElement(React.Fragment, null, children({
|
|
67
|
+
return /*#__PURE__*/ React.createElement(React.Fragment, null, children({
|
|
67
68
|
onMoveBottom: handleMoveBottom,
|
|
68
69
|
onMoveTop: handleMoveTop,
|
|
69
70
|
onRemove: handleRemove
|
|
@@ -71,28 +72,28 @@ function WithPerItemCallbacks({ listLength , index , onMove , onRemoteItemAtInde
|
|
|
71
72
|
}
|
|
72
73
|
const EMPTY_ARRAY = [];
|
|
73
74
|
export function MultipleResourceReferenceEditor(props) {
|
|
74
|
-
return React.createElement(EntityProvider, {
|
|
75
|
+
return /*#__PURE__*/ React.createElement(EntityProvider, {
|
|
75
76
|
sdk: props.sdk
|
|
76
|
-
}, React.createElement(FieldConnector, {
|
|
77
|
+
}, /*#__PURE__*/ React.createElement(FieldConnector, {
|
|
77
78
|
debounce: 0,
|
|
78
79
|
field: props.sdk.field,
|
|
79
80
|
isInitiallyDisabled: props.isInitiallyDisabled,
|
|
80
81
|
isEqualValues: deepEqual
|
|
81
|
-
}, ({ value
|
|
82
|
-
return React.createElement(ResourceEditor, {
|
|
82
|
+
}, ({ value, disabled, setValue, externalReset })=>{
|
|
83
|
+
return /*#__PURE__*/ React.createElement(ResourceEditor, {
|
|
83
84
|
...props,
|
|
84
85
|
items: value || EMPTY_ARRAY,
|
|
85
86
|
isDisabled: disabled,
|
|
86
87
|
setValue: setValue,
|
|
87
88
|
renderCustomActions: props.renderCustomActions,
|
|
88
89
|
key: `${externalReset}-list`
|
|
89
|
-
}, (editorProps)
|
|
90
|
+
}, (editorProps)=>/*#__PURE__*/ React.createElement(SortableLinkList, editorProps, ({ item, isDisabled, DragHandle, index })=>/*#__PURE__*/ React.createElement(WithPerItemCallbacks, {
|
|
90
91
|
key: index,
|
|
91
92
|
index: index,
|
|
92
93
|
onMove: editorProps.onMove,
|
|
93
94
|
onRemoteItemAtIndex: editorProps.onRemoteItemAtIndex,
|
|
94
95
|
listLength: value?.length || 0
|
|
95
|
-
}, ({ onMoveBottom
|
|
96
|
+
}, ({ onMoveBottom, onMoveTop, onRemove })=>/*#__PURE__*/ React.createElement(ResourceCard, {
|
|
96
97
|
key: index,
|
|
97
98
|
index: index,
|
|
98
99
|
resourceLink: item,
|
|
@@ -46,16 +46,18 @@ const fieldDefinition = {
|
|
|
46
46
|
describe('Multiple resource editor', ()=>{
|
|
47
47
|
it('renders the action button when no value is set', async ()=>{
|
|
48
48
|
const sdk = mockSdkForField(fieldDefinition);
|
|
49
|
-
render(React.createElement(MultipleResourceReferenceEditor, {
|
|
49
|
+
render(/*#__PURE__*/ React.createElement(MultipleResourceReferenceEditor, {
|
|
50
50
|
isInitiallyDisabled: false,
|
|
51
51
|
sdk: sdk,
|
|
52
52
|
hasCardEditActions: true,
|
|
53
53
|
viewType: "card",
|
|
54
|
+
// @ts-expect-error unused...
|
|
54
55
|
parameters: {}
|
|
55
56
|
}));
|
|
56
57
|
const button = await screen.findByText('Add existing content');
|
|
57
58
|
expect(button).toBeDefined();
|
|
58
59
|
fireEvent.click(button);
|
|
60
|
+
// @ts-expect-error wait app-sdk version update
|
|
59
61
|
const dialogFn = sdk.dialogs.selectMultipleResourceEntries;
|
|
60
62
|
expect(dialogFn).toHaveBeenCalledTimes(1);
|
|
61
63
|
const options = dialogFn.mock.calls[0][0];
|
|
@@ -65,13 +67,14 @@ describe('Multiple resource editor', ()=>{
|
|
|
65
67
|
});
|
|
66
68
|
it('renders custom actions when passed', async ()=>{
|
|
67
69
|
const sdk = mockSdkForField(fieldDefinition);
|
|
68
|
-
render(React.createElement(MultipleResourceReferenceEditor, {
|
|
70
|
+
render(/*#__PURE__*/ React.createElement(MultipleResourceReferenceEditor, {
|
|
69
71
|
isInitiallyDisabled: false,
|
|
70
72
|
sdk: sdk,
|
|
71
73
|
hasCardEditActions: true,
|
|
72
74
|
viewType: "card",
|
|
75
|
+
// @ts-expect-error unused...
|
|
73
76
|
parameters: {},
|
|
74
|
-
renderCustomActions: ()
|
|
77
|
+
renderCustomActions: ()=>/*#__PURE__*/ React.createElement("div", {
|
|
75
78
|
"data-testid": "custom-actions"
|
|
76
79
|
})
|
|
77
80
|
}));
|
|
@@ -80,22 +83,24 @@ describe('Multiple resource editor', ()=>{
|
|
|
80
83
|
});
|
|
81
84
|
describe('with value', ()=>{
|
|
82
85
|
it('renders the cards', async ()=>{
|
|
83
|
-
const { entryLinks
|
|
86
|
+
const { entryLinks, entryInfos } = generateMultipleTestResources();
|
|
84
87
|
mockedResources = {};
|
|
85
88
|
for (const [spaceId, link] of Object.entries(entryLinks)){
|
|
86
89
|
mockedResources[`${link.sys.linkType}.${link.sys.urn}`] = entryInfos[spaceId];
|
|
87
90
|
}
|
|
88
91
|
const sdk = mockSdkForField(fieldDefinition, Object.values(entryLinks));
|
|
89
|
-
render(React.createElement(MultipleResourceReferenceEditor, {
|
|
92
|
+
render(/*#__PURE__*/ React.createElement(MultipleResourceReferenceEditor, {
|
|
90
93
|
isInitiallyDisabled: false,
|
|
91
94
|
sdk: sdk,
|
|
92
95
|
hasCardEditActions: true,
|
|
93
96
|
viewType: "card",
|
|
94
97
|
apiUrl: "test-contentful",
|
|
95
98
|
getEntryRouteHref: ()=>'',
|
|
99
|
+
// @ts-expect-error unused...
|
|
96
100
|
parameters: {}
|
|
97
101
|
}));
|
|
98
102
|
expect(useResource).toHaveBeenCalledTimes(Object.values(entryInfos).length);
|
|
103
|
+
// ensure the card is rendered for every value
|
|
99
104
|
const cards = [];
|
|
100
105
|
const entriesArray = Object.values(entryInfos);
|
|
101
106
|
for (const info of Array.from(entriesArray.values())){
|
|
@@ -107,49 +112,58 @@ describe('Multiple resource editor', ()=>{
|
|
|
107
112
|
});
|
|
108
113
|
describe('card actions', ()=>{
|
|
109
114
|
it('should have a move to top button', async ()=>{
|
|
110
|
-
const { entryLinks
|
|
115
|
+
const { entryLinks, entryInfos } = generateMultipleTestResources();
|
|
111
116
|
mockedResources = {};
|
|
112
117
|
for (const [spaceId, link] of Object.entries(entryLinks)){
|
|
113
118
|
mockedResources[`${link.sys.linkType}.${link.sys.urn}`] = entryInfos[spaceId];
|
|
114
119
|
}
|
|
115
120
|
const sdk = mockSdkForField(fieldDefinition, Object.values(entryLinks));
|
|
116
|
-
render(React.createElement(MultipleResourceReferenceEditor, {
|
|
121
|
+
render(/*#__PURE__*/ React.createElement(MultipleResourceReferenceEditor, {
|
|
117
122
|
isInitiallyDisabled: false,
|
|
118
123
|
sdk: sdk,
|
|
119
124
|
hasCardEditActions: true,
|
|
120
125
|
viewType: "card",
|
|
121
126
|
apiUrl: "test-contentful",
|
|
122
127
|
getEntryRouteHref: ()=>'',
|
|
128
|
+
// @ts-expect-error unused...
|
|
123
129
|
parameters: {}
|
|
124
130
|
}));
|
|
131
|
+
// expect(useResource).toHaveBeenCalledTimes(Object.values(entryInfos).length);
|
|
132
|
+
// linking more is available
|
|
125
133
|
const linkExistingBtn = screen.queryByText('Add existing content');
|
|
126
134
|
expect(linkExistingBtn).toBeInTheDocument();
|
|
135
|
+
// ensure the card is rendered for every value
|
|
127
136
|
const entriesArray = Object.values(entryInfos);
|
|
128
137
|
const firstItem = entriesArray[0];
|
|
129
138
|
await expectToNotHaveMoveButton(firstItem, 'Move to top');
|
|
130
139
|
const allButFirst = entriesArray.slice(1);
|
|
140
|
+
// move actions are available
|
|
131
141
|
for (const info of allButFirst){
|
|
132
142
|
await expectToHaveMoveButton(info, 'Move to top');
|
|
133
143
|
}
|
|
134
144
|
});
|
|
135
145
|
it('should have a move to bottom button', async ()=>{
|
|
136
|
-
const { entryLinks
|
|
146
|
+
const { entryLinks, entryInfos } = generateMultipleTestResources();
|
|
137
147
|
mockedResources = {};
|
|
138
148
|
for (const [spaceId, link] of Object.entries(entryLinks)){
|
|
139
149
|
mockedResources[`${link.sys.linkType}.${link.sys.urn}`] = entryInfos[spaceId];
|
|
140
150
|
}
|
|
141
151
|
const sdk = mockSdkForField(fieldDefinition, Object.values(entryLinks));
|
|
142
|
-
render(React.createElement(MultipleResourceReferenceEditor, {
|
|
152
|
+
render(/*#__PURE__*/ React.createElement(MultipleResourceReferenceEditor, {
|
|
143
153
|
isInitiallyDisabled: false,
|
|
144
154
|
sdk: sdk,
|
|
145
155
|
hasCardEditActions: true,
|
|
146
156
|
viewType: "card",
|
|
147
157
|
apiUrl: "test-contentful",
|
|
148
158
|
getEntryRouteHref: ()=>'',
|
|
159
|
+
// @ts-expect-error unused...
|
|
149
160
|
parameters: {}
|
|
150
161
|
}));
|
|
162
|
+
// expect(useResource).toHaveBeenCalledTimes(Object.values(entryInfos).length);
|
|
163
|
+
// linking more is available
|
|
151
164
|
const linkExistingBtn = screen.queryByText('Add existing content');
|
|
152
165
|
expect(linkExistingBtn).toBeInTheDocument();
|
|
166
|
+
// ensure the card is rendered for every value
|
|
153
167
|
const entriesArray = Object.values(entryInfos);
|
|
154
168
|
const lastItem = entriesArray[entriesArray.length - 1];
|
|
155
169
|
await expectToNotHaveMoveButton(lastItem, 'Move to bottom');
|
|
@@ -159,23 +173,27 @@ describe('Multiple resource editor', ()=>{
|
|
|
159
173
|
}
|
|
160
174
|
});
|
|
161
175
|
it('works when using remove action', async ()=>{
|
|
162
|
-
const { entryLinks
|
|
176
|
+
const { entryLinks, entryInfos } = generateMultipleTestResources();
|
|
163
177
|
mockedResources = {};
|
|
164
178
|
for (const [spaceId, link] of Object.entries(entryLinks)){
|
|
165
179
|
mockedResources[`${link.sys.linkType}.${link.sys.urn}`] = entryInfos[spaceId];
|
|
166
180
|
}
|
|
167
181
|
const sdk = mockSdkForField(fieldDefinition, Object.values(entryLinks));
|
|
168
|
-
render(React.createElement(MultipleResourceReferenceEditor, {
|
|
182
|
+
render(/*#__PURE__*/ React.createElement(MultipleResourceReferenceEditor, {
|
|
169
183
|
isInitiallyDisabled: false,
|
|
170
184
|
sdk: sdk,
|
|
171
185
|
hasCardEditActions: true,
|
|
172
186
|
viewType: "card",
|
|
173
187
|
apiUrl: "test-contentful",
|
|
174
188
|
getEntryRouteHref: ()=>'',
|
|
189
|
+
// @ts-expect-error unused...
|
|
175
190
|
parameters: {}
|
|
176
191
|
}));
|
|
192
|
+
// expect(useResource).toHaveBeenCalledTimes(Object.values(entryInfos).length);
|
|
193
|
+
// linking more is available
|
|
177
194
|
const linkExistingBtn = screen.queryByText('Add existing content');
|
|
178
195
|
expect(linkExistingBtn).toBeInTheDocument();
|
|
196
|
+
// ensure the card is rendered for every value
|
|
179
197
|
const entriesArray = Object.values(entryInfos);
|
|
180
198
|
for (const info of entriesArray){
|
|
181
199
|
await clickCardActionsButton(info);
|
|
@@ -184,6 +202,7 @@ describe('Multiple resource editor', ()=>{
|
|
|
184
202
|
});
|
|
185
203
|
fireEvent.click(removeBtn);
|
|
186
204
|
}
|
|
205
|
+
// all cards were deleted
|
|
187
206
|
expect(sdk.field.setValue).toHaveBeenCalledTimes(3);
|
|
188
207
|
expect(sdk.field.setValue).toHaveBeenCalledWith([]);
|
|
189
208
|
});
|
|
@@ -6,26 +6,26 @@ import { CombinedLinkEntityActions } from '../components/LinkActions/LinkEntityA
|
|
|
6
6
|
import { ResourceCard } from './Cards/ResourceCard';
|
|
7
7
|
import { useResourceLinkActions } from './useResourceLinkActions';
|
|
8
8
|
export function SingleResourceReferenceEditor(props) {
|
|
9
|
-
const { dialogs
|
|
9
|
+
const { dialogs, field } = props.sdk;
|
|
10
10
|
const linkActionsProps = useResourceLinkActions({
|
|
11
11
|
dialogs,
|
|
12
12
|
field,
|
|
13
13
|
apiUrl: props.apiUrl
|
|
14
14
|
});
|
|
15
|
-
return React.createElement(EntityProvider, {
|
|
15
|
+
return /*#__PURE__*/ React.createElement(EntityProvider, {
|
|
16
16
|
sdk: props.sdk
|
|
17
|
-
}, React.createElement(FieldConnector, {
|
|
17
|
+
}, /*#__PURE__*/ React.createElement(FieldConnector, {
|
|
18
18
|
debounce: 0,
|
|
19
19
|
field: props.sdk.field,
|
|
20
20
|
isInitiallyDisabled: props.isInitiallyDisabled,
|
|
21
21
|
isEqualValues: deepEqual
|
|
22
|
-
}, ({ value
|
|
23
|
-
return value ? React.createElement(ResourceCard, {
|
|
22
|
+
}, ({ value, disabled })=>{
|
|
23
|
+
return value ? /*#__PURE__*/ React.createElement(ResourceCard, {
|
|
24
24
|
onRemove: ()=>props.sdk.field.removeValue(),
|
|
25
25
|
resourceLink: value,
|
|
26
26
|
isDisabled: disabled,
|
|
27
27
|
getEntryRouteHref: props.getEntryRouteHref
|
|
28
|
-
}) : React.createElement(CombinedLinkEntityActions, {
|
|
28
|
+
}) : /*#__PURE__*/ React.createElement(CombinedLinkEntityActions, {
|
|
29
29
|
...linkActionsProps,
|
|
30
30
|
renderCustomActions: props.renderCustomActions
|
|
31
31
|
});
|
|
@@ -42,16 +42,18 @@ const fieldDefinition = {
|
|
|
42
42
|
describe('Single resource editor', ()=>{
|
|
43
43
|
it('renders the action button when no value is set', async ()=>{
|
|
44
44
|
const sdk = mockSdkForField(fieldDefinition);
|
|
45
|
-
render(React.createElement(SingleResourceReferenceEditor, {
|
|
45
|
+
render(/*#__PURE__*/ React.createElement(SingleResourceReferenceEditor, {
|
|
46
46
|
isInitiallyDisabled: false,
|
|
47
47
|
sdk: sdk,
|
|
48
48
|
hasCardEditActions: true,
|
|
49
49
|
viewType: "card",
|
|
50
|
+
// @ts-expect-error unused...
|
|
50
51
|
parameters: {}
|
|
51
52
|
}));
|
|
52
53
|
const button = await screen.findByText('Add existing content');
|
|
53
54
|
expect(button).toBeDefined();
|
|
54
55
|
fireEvent.click(button);
|
|
56
|
+
// @ts-expect-error wait app-sdk version update
|
|
55
57
|
const dialogFn = sdk.dialogs.selectSingleResourceEntry;
|
|
56
58
|
expect(dialogFn).toHaveBeenCalledTimes(1);
|
|
57
59
|
const options = dialogFn.mock.calls[0][0];
|
|
@@ -61,13 +63,14 @@ describe('Single resource editor', ()=>{
|
|
|
61
63
|
});
|
|
62
64
|
it('renders custom actions when passed', async ()=>{
|
|
63
65
|
const sdk = mockSdkForField(fieldDefinition);
|
|
64
|
-
render(React.createElement(SingleResourceReferenceEditor, {
|
|
66
|
+
render(/*#__PURE__*/ React.createElement(SingleResourceReferenceEditor, {
|
|
65
67
|
isInitiallyDisabled: false,
|
|
66
68
|
sdk: sdk,
|
|
67
69
|
hasCardEditActions: true,
|
|
68
70
|
viewType: "card",
|
|
71
|
+
// @ts-expect-error unused...
|
|
69
72
|
parameters: {},
|
|
70
|
-
renderCustomActions: ()
|
|
73
|
+
renderCustomActions: ()=>/*#__PURE__*/ React.createElement("div", {
|
|
71
74
|
"data-testid": "custom-actions"
|
|
72
75
|
})
|
|
73
76
|
}));
|
|
@@ -91,16 +94,18 @@ describe('Single resource editor', ()=>{
|
|
|
91
94
|
}
|
|
92
95
|
});
|
|
93
96
|
mockedResources[`Contentful:Entry.crn:test:::content:spaces/x-space/entries/linkedEntryId`] = info;
|
|
94
|
-
render(React.createElement(SingleResourceReferenceEditor, {
|
|
97
|
+
render(/*#__PURE__*/ React.createElement(SingleResourceReferenceEditor, {
|
|
95
98
|
isInitiallyDisabled: false,
|
|
96
99
|
sdk: sdk,
|
|
97
100
|
hasCardEditActions: true,
|
|
98
101
|
viewType: "card",
|
|
99
102
|
apiUrl: "test-contentful",
|
|
100
103
|
getEntryRouteHref: jest.fn(),
|
|
104
|
+
// @ts-expect-error unused...
|
|
101
105
|
parameters: {}
|
|
102
106
|
}));
|
|
103
107
|
expect(useResource).toHaveBeenCalled();
|
|
108
|
+
// ensure the card is rendered
|
|
104
109
|
const title = await screen.findByText('Title of linked entry');
|
|
105
110
|
await screen.findByText('X Space');
|
|
106
111
|
const theCard = title.closest('[data-test-id="cf-ui-entry-card"]');
|
|
@@ -4,13 +4,17 @@ export function mockSdkForField(fieldDefinition, fieldValue) {
|
|
|
4
4
|
getValue: jest.fn(()=>fieldValue),
|
|
5
5
|
setValue: jest.fn(()=>Promise.resolve(undefined)),
|
|
6
6
|
removeValue: jest.fn(),
|
|
7
|
+
// eslint-disable-next-line -- test helper
|
|
7
8
|
onSchemaErrorsChanged: ()=>{},
|
|
9
|
+
// eslint-disable-next-line -- test helper
|
|
8
10
|
onIsDisabledChanged: ()=>{},
|
|
11
|
+
// eslint-disable-next-line -- test helper
|
|
9
12
|
onValueChanged: ()=>{},
|
|
10
13
|
...fieldDefinition,
|
|
11
14
|
locale: 'en'
|
|
12
15
|
},
|
|
13
16
|
dialogs: {
|
|
17
|
+
// @ts-expect-error wait app-sdk version update
|
|
14
18
|
selectSingleResourceEntry: jest.fn().mockResolvedValue({
|
|
15
19
|
sys: {
|
|
16
20
|
type: 'Entry',
|
|
@@ -50,15 +54,18 @@ export function mockSdkForField(fieldDefinition, fieldValue) {
|
|
|
50
54
|
contentType: 'testCT'
|
|
51
55
|
},
|
|
52
56
|
space: {
|
|
57
|
+
// @ts-expect-error wait app-sdk version update
|
|
58
|
+
// eslint-disable-next-line -- test helper
|
|
53
59
|
onEntityChanged: ()=>{}
|
|
54
60
|
},
|
|
61
|
+
// @ts-expect-error
|
|
55
62
|
navigator: {
|
|
56
63
|
onSlideInNavigation: ()=>()=>({})
|
|
57
64
|
}
|
|
58
65
|
};
|
|
59
66
|
}
|
|
60
|
-
export const createFakeEntryResource = ({ title
|
|
61
|
-
const { id: spaceId
|
|
67
|
+
export const createFakeEntryResource = ({ title, id, space })=>{
|
|
68
|
+
const { id: spaceId, name: spaceName } = space;
|
|
62
69
|
return {
|
|
63
70
|
resource: {
|
|
64
71
|
sys: {
|
|
@@ -19,7 +19,7 @@ const getUpdatedValue = (field, entries, apiUrl)=>{
|
|
|
19
19
|
return toLinkItem(entries[0], apiUrl);
|
|
20
20
|
}
|
|
21
21
|
};
|
|
22
|
-
export function useResourceLinkActions({ dialogs
|
|
22
|
+
export function useResourceLinkActions({ dialogs, field, onAfterLink, apiUrl }) {
|
|
23
23
|
const handleAfterLink = useCallback((entries)=>{
|
|
24
24
|
if (!onAfterLink) {
|
|
25
25
|
return;
|
|
@@ -41,10 +41,14 @@ export function useResourceLinkActions({ dialogs , field , onAfterLink , apiUrl
|
|
|
41
41
|
]);
|
|
42
42
|
const multiple = field.type === 'Array';
|
|
43
43
|
const onLinkExisting = useMemo(()=>{
|
|
44
|
-
const promptSelection = multiple ? async ()
|
|
44
|
+
const promptSelection = multiple ? async ()=>// @ts-expect-error wait for update of app-sdk version
|
|
45
|
+
await dialogs.selectMultipleResourceEntries({
|
|
46
|
+
// @ts-expect-error wait for update of app-sdk version
|
|
45
47
|
allowedResources: field.allowedResources
|
|
46
48
|
}) : async ()=>[
|
|
49
|
+
// @ts-expect-error wait for update of app-sdk version
|
|
47
50
|
await dialogs.selectSingleResourceEntry({
|
|
51
|
+
// @ts-expect-error wait for update of app-sdk version
|
|
48
52
|
allowedResources: field.allowedResources
|
|
49
53
|
})
|
|
50
54
|
];
|
|
@@ -55,6 +59,7 @@ export function useResourceLinkActions({ dialogs , field , onAfterLink , apiUrl
|
|
|
55
59
|
}
|
|
56
60
|
onLinkedExisting(res);
|
|
57
61
|
};
|
|
62
|
+
// @ts-expect-error wait for update of app-sdk version
|
|
58
63
|
}, [
|
|
59
64
|
dialogs,
|
|
60
65
|
field.allowedResources,
|
|
@@ -63,7 +68,9 @@ export function useResourceLinkActions({ dialogs , field , onAfterLink , apiUrl
|
|
|
63
68
|
]);
|
|
64
69
|
return {
|
|
65
70
|
onLinkExisting,
|
|
71
|
+
// @ts-expect-error
|
|
66
72
|
onLinkedExisting,
|
|
73
|
+
// hardcoded values to match interface for standard reference field actions
|
|
67
74
|
entityType: 'Entry',
|
|
68
75
|
contentTypes: [],
|
|
69
76
|
canCreateEntity: false,
|
|
@@ -72,7 +79,9 @@ export function useResourceLinkActions({ dialogs , field , onAfterLink , apiUrl
|
|
|
72
79
|
isDisabled: false,
|
|
73
80
|
isEmpty: false,
|
|
74
81
|
isFull: false,
|
|
82
|
+
// eslint-disable-next-line -- hardcoded values to match interface for standard reference field actions
|
|
75
83
|
onCreate: async ()=>{},
|
|
84
|
+
// eslint-disable-next-line -- hardcoded values to match interface for standard reference field actions
|
|
76
85
|
onCreated: ()=>{}
|
|
77
86
|
};
|
|
78
87
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import isNumber from 'lodash/isNumber';
|
|
2
2
|
export function fromFieldValidations(field) {
|
|
3
|
+
// eslint-disable-next-line -- TODO: describe this disable @typescript-eslint/no-explicit-any
|
|
3
4
|
const validations = [
|
|
4
5
|
...field.validations,
|
|
5
6
|
...field.type === 'Array' ? field.items?.validations ?? [] : []
|
|
@@ -2,7 +2,7 @@ import React, { useCallback, useState } from 'react';
|
|
|
2
2
|
import { arrayMove } from '@dnd-kit/sortable';
|
|
3
3
|
export const useSortIDs = (items)=>{
|
|
4
4
|
const ids = (items || []).map((item, index)=>{
|
|
5
|
-
const { type
|
|
5
|
+
const { type } = item.sys;
|
|
6
6
|
return {
|
|
7
7
|
id: type === 'ResourceLink' ? `${item.sys.urn}-${index}` : `${item.sys.id}-${index}`
|
|
8
8
|
};
|
|
@@ -11,7 +11,7 @@ export const useSortIDs = (items)=>{
|
|
|
11
11
|
React.useEffect(()=>{
|
|
12
12
|
if (items.length !== sortIDs.length) {
|
|
13
13
|
const ids = items.map((item, index)=>{
|
|
14
|
-
const { type
|
|
14
|
+
const { type } = item.sys;
|
|
15
15
|
return {
|
|
16
16
|
id: type === 'ResourceLink' ? `${item.sys.urn}-${index}` : `${item.sys.id}-${index}`
|
|
17
17
|
};
|
|
@@ -54,7 +54,7 @@ declare const useEntityLoader: () => {
|
|
|
54
54
|
};
|
|
55
55
|
export declare function useEntity<E extends FetchableEntity>(entityType: FetchableEntityType, entityId: string, options?: UseEntityOptions): UseEntityResult<E>;
|
|
56
56
|
export declare function useResource(resourceType: ResourceType, urn: string, options?: UseResourceOptions): {
|
|
57
|
-
status: "
|
|
57
|
+
status: "error" | "success" | "loading";
|
|
58
58
|
data: ResourceInfo<Resource> | undefined;
|
|
59
59
|
error: unknown;
|
|
60
60
|
};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { QueryClient, useQuery as useRQ } from '@tanstack/react-query';
|
|
3
|
+
export declare function useQueryClient(): QueryClient;
|
|
4
|
+
export declare const useQuery: typeof useRQ;
|
|
5
|
+
/**
|
|
6
|
+
* Provides access to a query client either by sharing an existing client or
|
|
7
|
+
* creating a new one.
|
|
8
|
+
*/
|
|
9
|
+
export declare function SharedQueryClientProvider({ children }: React.PropsWithChildren<{}>): React.JSX.Element;
|
package/dist/types/index.d.ts
CHANGED
|
@@ -5,6 +5,7 @@ export type { CustomActionProps } from './common/ReferenceEditor';
|
|
|
5
5
|
export type { CustomEntityCardProps, DefaultCardRenderer, MissingEntityCardProps, RenderCustomMissingEntityCard, } from './common/customCardTypes';
|
|
6
6
|
export { SortableLinkList } from './common/SortableLinkList';
|
|
7
7
|
export { EntityProvider, useEntityLoader, useEntity, useResource } from './common/EntityStore';
|
|
8
|
+
export { SharedQueryClientProvider as EntityCacheProvider } from './common/queryClient';
|
|
8
9
|
export type { ResourceInfo } from './common/EntityStore';
|
|
9
10
|
export { SingleResourceReferenceEditor, MultipleResourceReferenceEditor } from './resources';
|
|
10
11
|
export * from './types';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@contentful/field-editor-reference",
|
|
3
|
-
"version": "5.
|
|
3
|
+
"version": "5.20.0",
|
|
4
4
|
"main": "dist/cjs/index.js",
|
|
5
5
|
"module": "dist/esm/index.js",
|
|
6
6
|
"types": "dist/types/index.d.ts",
|
|
@@ -64,5 +64,5 @@
|
|
|
64
64
|
"@contentful/app-sdk": "^4.17.1",
|
|
65
65
|
"react": ">=16.8.0"
|
|
66
66
|
},
|
|
67
|
-
"gitHead": "
|
|
67
|
+
"gitHead": "122ef199250b6d84b4df4a595e6ce938716193fb"
|
|
68
68
|
}
|