@contentful/field-editor-reference 5.19.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 +9 -7
- 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 +4 -4
- 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
|
@@ -3,20 +3,20 @@ import { Card, Flex, IconButton, SectionHeading } from '@contentful/f36-componen
|
|
|
3
3
|
import { CloseIcon } from '@contentful/f36-icons';
|
|
4
4
|
import * as styles from './styles';
|
|
5
5
|
export function MissingEntityCard(props) {
|
|
6
|
-
return React.createElement(Card, {
|
|
6
|
+
return /*#__PURE__*/ React.createElement(Card, {
|
|
7
7
|
className: styles.card,
|
|
8
8
|
testId: "cf-ui-missing-entry-card",
|
|
9
9
|
isSelected: props.isSelected
|
|
10
|
-
}, React.createElement(Flex, {
|
|
10
|
+
}, /*#__PURE__*/ React.createElement(Flex, {
|
|
11
11
|
alignItems: "center",
|
|
12
12
|
justifyContent: "space-between"
|
|
13
|
-
}, React.createElement("div", {
|
|
13
|
+
}, /*#__PURE__*/ React.createElement("div", {
|
|
14
14
|
className: props.asSquare ? styles.squareCard : ''
|
|
15
|
-
}, React.createElement(SectionHeading, {
|
|
15
|
+
}, /*#__PURE__*/ React.createElement(SectionHeading, {
|
|
16
16
|
marginBottom: "none"
|
|
17
|
-
}, props.entityType, " is missing or inaccessible")), !props.isDisabled && props.onRemove && React.createElement(IconButton, {
|
|
17
|
+
}, props.entityType, " is missing or inaccessible")), !props.isDisabled && props.onRemove && /*#__PURE__*/ React.createElement(IconButton, {
|
|
18
18
|
variant: "transparent",
|
|
19
|
-
icon: React.createElement(CloseIcon, {
|
|
19
|
+
icon: /*#__PURE__*/ React.createElement(CloseIcon, {
|
|
20
20
|
variant: "muted"
|
|
21
21
|
}),
|
|
22
22
|
"aria-label": "Delete",
|
|
@@ -4,12 +4,12 @@ import { MissingEntityCard } from '../MissingEntityCard/MissingEntityCard';
|
|
|
4
4
|
import { UnsupportedEntityCard } from './UnsupportedEntityCard';
|
|
5
5
|
export function ResourceEntityErrorCard(props) {
|
|
6
6
|
if (isUnsupportedError(props.error)) {
|
|
7
|
-
return React.createElement(UnsupportedEntityCard, {
|
|
7
|
+
return /*#__PURE__*/ React.createElement(UnsupportedEntityCard, {
|
|
8
8
|
linkType: props.linkType,
|
|
9
9
|
isSelected: props.isSelected
|
|
10
10
|
});
|
|
11
11
|
}
|
|
12
|
-
return React.createElement(MissingEntityCard, {
|
|
12
|
+
return /*#__PURE__*/ React.createElement(MissingEntityCard, {
|
|
13
13
|
entityType: "Entry",
|
|
14
14
|
isDisabled: props.isDisabled,
|
|
15
15
|
isSelected: props.isSelected,
|
|
@@ -7,10 +7,10 @@ const styles = {
|
|
|
7
7
|
})
|
|
8
8
|
};
|
|
9
9
|
export function UnsupportedEntityCard(props) {
|
|
10
|
-
return React.createElement(Card, {
|
|
10
|
+
return /*#__PURE__*/ React.createElement(Card, {
|
|
11
11
|
className: styles.card,
|
|
12
12
|
isSelected: props.isSelected
|
|
13
|
-
}, React.createElement(SectionHeading, {
|
|
13
|
+
}, /*#__PURE__*/ React.createElement(SectionHeading, {
|
|
14
14
|
marginBottom: "none"
|
|
15
15
|
}, "Resource type ", props.linkType, " is currently not supported"));
|
|
16
16
|
}
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
2
|
import { Tooltip } from '@contentful/f36-components';
|
|
3
3
|
import { formatDateAndTime } from './formatDateAndTime';
|
|
4
|
-
export const getScheduleTooltipContent = ({ job
|
|
4
|
+
export const getScheduleTooltipContent = ({ job, jobsCount })=>{
|
|
5
5
|
return `Will ${job.action.toLowerCase()} ${formatDateAndTime(job.scheduledFor.datetime).toLowerCase()}
|
|
6
6
|
${jobsCount > 1 ? `+ ${jobsCount - 1} more` : ''}`;
|
|
7
7
|
};
|
|
8
|
-
export const ScheduleTooltip = ({ job
|
|
9
|
-
return React.createElement(Tooltip, {
|
|
8
|
+
export const ScheduleTooltip = ({ job, jobsCount, children })=>{
|
|
9
|
+
return /*#__PURE__*/ React.createElement(Tooltip, {
|
|
10
10
|
placement: "top",
|
|
11
11
|
testId: job.sys.id,
|
|
12
12
|
as: "div",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
2
|
import { ScheduleTooltip } from './ScheduleTooltip';
|
|
3
|
-
export const ScheduledIconWithTooltip = ({ entityType
|
|
3
|
+
export const ScheduledIconWithTooltip = ({ entityType, entityId, getEntityScheduledActions, children })=>{
|
|
4
4
|
const [status, setStatus] = React.useState({
|
|
5
5
|
type: 'loading'
|
|
6
6
|
});
|
|
@@ -16,6 +16,9 @@ export const ScheduledIconWithTooltip = ({ entityType , entityId , getEntitySche
|
|
|
16
16
|
error: e
|
|
17
17
|
});
|
|
18
18
|
});
|
|
19
|
+
// This should only be ever called once. Following the eslint hint to add used
|
|
20
|
+
// dependencies will cause page freeze (infinite loop)
|
|
21
|
+
// eslint-disable-next-line -- TODO: describe this disable
|
|
19
22
|
}, []);
|
|
20
23
|
if (status.type === 'loading' || status.type === 'error') {
|
|
21
24
|
return null;
|
|
@@ -25,7 +28,7 @@ export const ScheduledIconWithTooltip = ({ entityType , entityId , getEntitySche
|
|
|
25
28
|
return null;
|
|
26
29
|
}
|
|
27
30
|
const mostRelevantJob = jobs[0];
|
|
28
|
-
return React.createElement(ScheduleTooltip, {
|
|
31
|
+
return /*#__PURE__*/ React.createElement(ScheduleTooltip, {
|
|
29
32
|
job: mostRelevantJob,
|
|
30
33
|
jobsCount: jobs.length
|
|
31
34
|
}, children);
|
|
@@ -1,5 +1,9 @@
|
|
|
1
|
+
// eslint-disable-next-line -- TODO: describe this disable no-restricted-imports
|
|
1
2
|
import moment from 'moment';
|
|
2
|
-
|
|
3
|
+
/**
|
|
4
|
+
* @param {Date|string} date A valid constructor argument for moment()
|
|
5
|
+
* @param {boolean=} short Render only Today/Tomorrow/Yesterday if valid. Defaults to false
|
|
6
|
+
*/ export const formatDate = (date, short)=>{
|
|
3
7
|
switch(moment().startOf('day').diff(moment(date).startOf('day'), 'days')){
|
|
4
8
|
case 0:
|
|
5
9
|
return short ? 'Today' : `Today, ${moment(date).format('DD MMM YYYY')}`;
|
|
@@ -11,7 +15,12 @@ export const formatDate = (date, short)=>{
|
|
|
11
15
|
return moment(date).format('ddd, DD MMM YYYY');
|
|
12
16
|
}
|
|
13
17
|
};
|
|
14
|
-
|
|
18
|
+
/**
|
|
19
|
+
* Returns the time portion of a date in the local time in the format H:MM AM/PM
|
|
20
|
+
*
|
|
21
|
+
* == Examples
|
|
22
|
+
* * `T15:36:45.000Z` => 3:36 PM (if in +0:00 offset)
|
|
23
|
+
*/ export const formatTime = (date)=>{
|
|
15
24
|
return moment.utc(date).local().format('h:mm A');
|
|
16
25
|
};
|
|
17
26
|
export const formatDateAndTime = (date, short)=>{
|
|
@@ -21,19 +21,19 @@ const styles = {
|
|
|
21
21
|
export function SpaceName(props) {
|
|
22
22
|
let content = `Space: ${props.spaceName}`;
|
|
23
23
|
if (props.environmentName) content += ` (Env.: ${props.environmentName})`;
|
|
24
|
-
return React.createElement(Tooltip, {
|
|
24
|
+
return /*#__PURE__*/ React.createElement(Tooltip, {
|
|
25
25
|
placement: "top",
|
|
26
26
|
as: "div",
|
|
27
27
|
content: content
|
|
28
|
-
}, React.createElement(Flex, {
|
|
28
|
+
}, /*#__PURE__*/ React.createElement(Flex, {
|
|
29
29
|
alignItems: "center",
|
|
30
30
|
gap: "spacingXs",
|
|
31
31
|
marginRight: "spacingS"
|
|
32
|
-
}, React.createElement(FolderOpenTrimmedIcon, {
|
|
32
|
+
}, /*#__PURE__*/ React.createElement(FolderOpenTrimmedIcon, {
|
|
33
33
|
className: styles.spaceIcon,
|
|
34
34
|
size: "tiny",
|
|
35
35
|
"aria-label": "Source space"
|
|
36
|
-
}), React.createElement(Text, {
|
|
36
|
+
}), /*#__PURE__*/ React.createElement(Text, {
|
|
37
37
|
className: styles.spaceName
|
|
38
38
|
}, props.spaceName)));
|
|
39
39
|
}
|
|
@@ -5,20 +5,20 @@ import { SortableLinkList } from '../common/SortableLinkList';
|
|
|
5
5
|
import { FetchingWrappedEntryCard } from './WrappedEntryCard/FetchingWrappedEntryCard';
|
|
6
6
|
export function MultipleEntryReferenceEditor(props) {
|
|
7
7
|
const [indexToUpdate, setIndexToUpdate] = React.useState(undefined);
|
|
8
|
-
const updateBeforeSortStart = ({ index
|
|
8
|
+
const updateBeforeSortStart = ({ index })=>{
|
|
9
9
|
setIndexToUpdate(index);
|
|
10
10
|
};
|
|
11
|
-
return React.createElement(MultipleReferenceEditor, {
|
|
11
|
+
return /*#__PURE__*/ React.createElement(MultipleReferenceEditor, {
|
|
12
12
|
...props,
|
|
13
13
|
entityType: "Entry",
|
|
14
14
|
setIndexToUpdate: setIndexToUpdate
|
|
15
|
-
}, (childrenProps)
|
|
15
|
+
}, (childrenProps)=>/*#__PURE__*/ React.createElement(SortableLinkList, {
|
|
16
16
|
...childrenProps,
|
|
17
17
|
sortingStrategy: verticalListSortingStrategy,
|
|
18
18
|
updateBeforeSortStart: updateBeforeSortStart
|
|
19
|
-
}, ({ items
|
|
19
|
+
}, ({ items, item, index, isDisabled, DragHandle })=>{
|
|
20
20
|
const lastIndex = items.length - 1;
|
|
21
|
-
return React.createElement(FetchingWrappedEntryCard, {
|
|
21
|
+
return /*#__PURE__*/ React.createElement(FetchingWrappedEntryCard, {
|
|
22
22
|
...childrenProps,
|
|
23
23
|
key: `${item.sys.id}-${index}`,
|
|
24
24
|
index: index,
|
|
@@ -2,11 +2,11 @@ import * as React from 'react';
|
|
|
2
2
|
import { SingleReferenceEditor } from '../common/SingleReferenceEditor';
|
|
3
3
|
import { FetchingWrappedEntryCard } from './WrappedEntryCard/FetchingWrappedEntryCard';
|
|
4
4
|
export function SingleEntryReferenceEditor(props) {
|
|
5
|
-
return React.createElement(SingleReferenceEditor, {
|
|
5
|
+
return /*#__PURE__*/ React.createElement(SingleReferenceEditor, {
|
|
6
6
|
...props,
|
|
7
7
|
entityType: "Entry"
|
|
8
|
-
}, ({ allContentTypes
|
|
9
|
-
return React.createElement(FetchingWrappedEntryCard, {
|
|
8
|
+
}, ({ allContentTypes, isDisabled, entityId, setValue, renderCustomCard, hasCardRemoveActions, hasCardEditActions })=>{
|
|
9
|
+
return /*#__PURE__*/ React.createElement(FetchingWrappedEntryCard, {
|
|
10
10
|
...props,
|
|
11
11
|
allContentTypes: allContentTypes,
|
|
12
12
|
isDisabled: isDisabled,
|
|
@@ -15,7 +15,10 @@ async function openEntry(sdk, entryId, options) {
|
|
|
15
15
|
});
|
|
16
16
|
slide = result.slide;
|
|
17
17
|
return slide;
|
|
18
|
-
} catch (e) {
|
|
18
|
+
} catch (e) {
|
|
19
|
+
// we don't allow to open multiple bulk editors for performance reasons
|
|
20
|
+
// proceed with a default openEntry
|
|
21
|
+
}
|
|
19
22
|
}
|
|
20
23
|
const result = await sdk.navigator.openEntry(entryId, {
|
|
21
24
|
slideIn: true
|
|
@@ -24,14 +27,14 @@ async function openEntry(sdk, entryId, options) {
|
|
|
24
27
|
return slide;
|
|
25
28
|
}
|
|
26
29
|
export function FetchingWrappedEntryCard(props) {
|
|
27
|
-
const { data: entry
|
|
28
|
-
const { getEntityScheduledActions
|
|
30
|
+
const { data: entry, status } = useEntity('Entry', props.entryId);
|
|
31
|
+
const { getEntityScheduledActions } = useEntityLoader();
|
|
29
32
|
const loadEntityScheduledActions = React.useCallback(()=>getEntityScheduledActions('Entry', props.entryId), [
|
|
30
33
|
getEntityScheduledActions,
|
|
31
34
|
props.entryId
|
|
32
35
|
]);
|
|
33
36
|
const size = props.viewType === 'link' ? 'small' : 'default';
|
|
34
|
-
const { getEntity
|
|
37
|
+
const { getEntity } = useEntityLoader();
|
|
35
38
|
const getAsset = (assetId)=>getEntity('Asset', assetId);
|
|
36
39
|
const onEdit = async ()=>{
|
|
37
40
|
const slide = await openEntry(props.sdk, props.entryId, {
|
|
@@ -62,12 +65,13 @@ export function FetchingWrappedEntryCard(props) {
|
|
|
62
65
|
entity: 'Entry'
|
|
63
66
|
});
|
|
64
67
|
}
|
|
68
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps -- TODO: Evaluate the dependencies
|
|
65
69
|
}, [
|
|
66
70
|
entry
|
|
67
71
|
]);
|
|
68
72
|
return React.useMemo(()=>{
|
|
69
73
|
if (status === 'error') {
|
|
70
|
-
const card = React.createElement(MissingEntityCard, {
|
|
74
|
+
const card = /*#__PURE__*/ React.createElement(MissingEntityCard, {
|
|
71
75
|
entityType: "Entry",
|
|
72
76
|
isDisabled: props.isDisabled,
|
|
73
77
|
onRemove: onRemoveEntry
|
|
@@ -84,7 +88,7 @@ export function FetchingWrappedEntryCard(props) {
|
|
|
84
88
|
return card;
|
|
85
89
|
}
|
|
86
90
|
if (status === 'loading') {
|
|
87
|
-
return React.createElement(EntryCard, {
|
|
91
|
+
return /*#__PURE__*/ React.createElement(EntryCard, {
|
|
88
92
|
size: size,
|
|
89
93
|
isLoading: true
|
|
90
94
|
});
|
|
@@ -105,7 +109,7 @@ export function FetchingWrappedEntryCard(props) {
|
|
|
105
109
|
onMoveBottom: props.onMoveBottom,
|
|
106
110
|
isBeingDragged: props.isBeingDragged
|
|
107
111
|
};
|
|
108
|
-
const { hasCardEditActions
|
|
112
|
+
const { hasCardEditActions, hasCardMoveActions, hasCardRemoveActions } = props;
|
|
109
113
|
function renderDefaultCard(props) {
|
|
110
114
|
const builtinCardProps = {
|
|
111
115
|
...sharedCardProps,
|
|
@@ -118,15 +122,18 @@ export function FetchingWrappedEntryCard(props) {
|
|
|
118
122
|
entry: (props?.entity) || sharedCardProps.entity,
|
|
119
123
|
entryUrl: props?.entityUrl || sharedCardProps.entityUrl
|
|
120
124
|
};
|
|
121
|
-
return React.createElement(WrappedEntryCard, builtinCardProps);
|
|
125
|
+
return /*#__PURE__*/ React.createElement(WrappedEntryCard, builtinCardProps);
|
|
122
126
|
}
|
|
123
127
|
if (props.renderCustomCard) {
|
|
128
|
+
// LinkActionsProps are injected higher SingleReferenceEditor/MultipleReferenceEditor
|
|
124
129
|
const renderedCustomCard = props.renderCustomCard(sharedCardProps, {}, renderDefaultCard);
|
|
130
|
+
// Only `false` indicates to render the original card. E.g. `null` would result in no card.
|
|
125
131
|
if (renderedCustomCard !== false) {
|
|
126
132
|
return renderedCustomCard;
|
|
127
133
|
}
|
|
128
134
|
}
|
|
129
135
|
return renderDefaultCard();
|
|
136
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps -- TODO: Evaluate the dependencies
|
|
130
137
|
}, [
|
|
131
138
|
props,
|
|
132
139
|
status,
|
|
@@ -6,7 +6,7 @@ import { entityHelpers, isValidImage } from '@contentful/field-editor-shared';
|
|
|
6
6
|
import { css } from 'emotion';
|
|
7
7
|
import { AssetThumbnail, MissingEntityCard, ScheduledIconWithTooltip } from '../../components';
|
|
8
8
|
import { SpaceName } from '../../components/SpaceName/SpaceName';
|
|
9
|
-
const { getEntryTitle
|
|
9
|
+
const { getEntryTitle, getEntityDescription, getEntryStatus, getEntryImage } = entityHelpers;
|
|
10
10
|
const styles = {
|
|
11
11
|
scheduleIcon: css({
|
|
12
12
|
marginRight: tokens.spacing2Xs
|
|
@@ -20,7 +20,7 @@ const defaultProps = {
|
|
|
20
20
|
};
|
|
21
21
|
export function WrappedEntryCard(props) {
|
|
22
22
|
const [file, setFile] = React.useState(null);
|
|
23
|
-
const { contentType
|
|
23
|
+
const { contentType } = props;
|
|
24
24
|
React.useEffect(()=>{
|
|
25
25
|
if (props.entry) {
|
|
26
26
|
getEntryImage({
|
|
@@ -43,7 +43,7 @@ export function WrappedEntryCard(props) {
|
|
|
43
43
|
]);
|
|
44
44
|
const status = getEntryStatus(props.entry?.sys);
|
|
45
45
|
if (status === 'deleted') {
|
|
46
|
-
return React.createElement(MissingEntityCard, {
|
|
46
|
+
return /*#__PURE__*/ React.createElement(MissingEntityCard, {
|
|
47
47
|
entityType: "Entry",
|
|
48
48
|
isDisabled: props.isDisabled,
|
|
49
49
|
onRemove: props.onRemove
|
|
@@ -62,7 +62,7 @@ export function WrappedEntryCard(props) {
|
|
|
62
62
|
localeCode: props.localeCode,
|
|
63
63
|
defaultLocaleCode: props.defaultLocaleCode
|
|
64
64
|
});
|
|
65
|
-
return React.createElement(EntryCard, {
|
|
65
|
+
return /*#__PURE__*/ React.createElement(EntryCard, {
|
|
66
66
|
as: props.entryUrl ? 'a' : 'article',
|
|
67
67
|
href: props.entryUrl,
|
|
68
68
|
title: title,
|
|
@@ -71,54 +71,58 @@ export function WrappedEntryCard(props) {
|
|
|
71
71
|
size: props.size,
|
|
72
72
|
isSelected: props.isSelected,
|
|
73
73
|
status: status,
|
|
74
|
-
icon: props.spaceName ? React.createElement(SpaceName, {
|
|
74
|
+
icon: props.spaceName ? /*#__PURE__*/ React.createElement(SpaceName, {
|
|
75
75
|
spaceName: props.spaceName,
|
|
76
76
|
environmentName: props.entry.sys.environment.sys.id
|
|
77
|
-
}) : React.createElement(ScheduledIconWithTooltip, {
|
|
77
|
+
}) : /*#__PURE__*/ React.createElement(ScheduledIconWithTooltip, {
|
|
78
78
|
getEntityScheduledActions: props.getEntityScheduledActions,
|
|
79
79
|
entityType: "Entry",
|
|
80
80
|
entityId: props.entry.sys.id
|
|
81
|
-
}, React.createElement(ClockIcon, {
|
|
81
|
+
}, /*#__PURE__*/ React.createElement(ClockIcon, {
|
|
82
82
|
className: styles.scheduleIcon,
|
|
83
83
|
size: "small",
|
|
84
84
|
variant: "muted",
|
|
85
85
|
testId: "schedule-icon"
|
|
86
86
|
})),
|
|
87
|
-
thumbnailElement: file && isValidImage(file) ? React.createElement(AssetThumbnail, {
|
|
87
|
+
thumbnailElement: file && isValidImage(file) ? /*#__PURE__*/ React.createElement(AssetThumbnail, {
|
|
88
88
|
file: file
|
|
89
89
|
}) : undefined,
|
|
90
90
|
dragHandleRender: props.renderDragHandle,
|
|
91
91
|
withDragHandle: !!props.renderDragHandle,
|
|
92
92
|
actions: props.onEdit || props.onRemove ? [
|
|
93
|
-
props.hasCardEditActions && props.onEdit ? React.createElement(MenuItem, {
|
|
93
|
+
props.hasCardEditActions && props.onEdit ? /*#__PURE__*/ React.createElement(MenuItem, {
|
|
94
94
|
key: "edit",
|
|
95
95
|
testId: "edit",
|
|
96
96
|
onClick: ()=>{
|
|
97
97
|
props.onEdit && props.onEdit();
|
|
98
98
|
}
|
|
99
99
|
}, "Edit") : null,
|
|
100
|
-
props.hasCardRemoveActions && props.onRemove ? React.createElement(MenuItem, {
|
|
100
|
+
props.hasCardRemoveActions && props.onRemove ? /*#__PURE__*/ React.createElement(MenuItem, {
|
|
101
101
|
key: "delete",
|
|
102
102
|
testId: "delete",
|
|
103
103
|
onClick: ()=>{
|
|
104
104
|
props.onRemove && props.onRemove();
|
|
105
105
|
}
|
|
106
106
|
}, "Remove") : null,
|
|
107
|
-
props.hasCardMoveActions && (props.onMoveTop || props.onMoveBottom) ? React.createElement(MenuDivider, {
|
|
107
|
+
props.hasCardMoveActions && (props.onMoveTop || props.onMoveBottom) ? /*#__PURE__*/ React.createElement(MenuDivider, {
|
|
108
108
|
key: "divider"
|
|
109
109
|
}) : null,
|
|
110
|
-
props.hasCardMoveActions && props.onMoveTop ? React.createElement(MenuItem, {
|
|
110
|
+
props.hasCardMoveActions && props.onMoveTop ? /*#__PURE__*/ React.createElement(MenuItem, {
|
|
111
111
|
key: "move-top",
|
|
112
112
|
onClick: ()=>props.onMoveTop && props.onMoveTop(),
|
|
113
113
|
testId: "move-top"
|
|
114
114
|
}, "Move to top") : null,
|
|
115
|
-
props.hasCardMoveActions && props.onMoveBottom ? React.createElement(MenuItem, {
|
|
115
|
+
props.hasCardMoveActions && props.onMoveBottom ? /*#__PURE__*/ React.createElement(MenuItem, {
|
|
116
116
|
key: "move-bottom",
|
|
117
117
|
onClick: ()=>props.onMoveBottom && props.onMoveBottom(),
|
|
118
118
|
testId: "move-bottom"
|
|
119
119
|
}, "Move to bottom") : null
|
|
120
120
|
].filter((item)=>item) : [],
|
|
121
|
-
onClick:
|
|
121
|
+
onClick: // Providing an onClick handler messes up with some rich text
|
|
122
|
+
// features e.g. pressing ENTER on a card to add a new paragraph
|
|
123
|
+
// underneath. It's crucial not to pass a custom handler when
|
|
124
|
+
// isClickable is disabled which in the case of RT it's.
|
|
125
|
+
props.isClickable ? (e)=>{
|
|
122
126
|
e.preventDefault();
|
|
123
127
|
if (props.onClick) return props.onClick(e);
|
|
124
128
|
props.onEdit && props.onEdit();
|
package/dist/esm/index.js
CHANGED
|
@@ -3,5 +3,6 @@ export { SingleEntryReferenceEditor, MultipleEntryReferenceEditor, WrappedEntryC
|
|
|
3
3
|
export { SingleMediaEditor, MultipleMediaEditor, WrappedAssetCard } from './assets';
|
|
4
4
|
export { SortableLinkList } from './common/SortableLinkList';
|
|
5
5
|
export { EntityProvider, useEntityLoader, useEntity, useResource } from './common/EntityStore';
|
|
6
|
+
export { SharedQueryClientProvider as EntityCacheProvider } from './common/queryClient';
|
|
6
7
|
export { SingleResourceReferenceEditor, MultipleResourceReferenceEditor } from './resources';
|
|
7
8
|
export * from './types';
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
2
|
import { WrappedEntryCard } from '../../entries';
|
|
3
|
+
// assets are not shown for small cards (which we hardcode currently)
|
|
3
4
|
const resolveAsset = ()=>Promise.resolve();
|
|
5
|
+
// we don't want to show scheduled actions for resources
|
|
4
6
|
const resolveScheduledActions = ()=>Promise.resolve([]);
|
|
5
|
-
export function ContentfulEntryCard({ info
|
|
7
|
+
export function ContentfulEntryCard({ info, isDisabled, renderDragHandle, onRemove, onMoveTop, onMoveBottom, getEntryRouteHref }) {
|
|
6
8
|
const resourceSys = info.resource.sys;
|
|
7
9
|
const spaceId = resourceSys.space.sys.id;
|
|
8
10
|
const environmentId = resourceSys.environment.sys.id;
|
|
@@ -12,14 +14,19 @@ export function ContentfulEntryCard({ info , isDisabled , renderDragHandle , onR
|
|
|
12
14
|
environmentId,
|
|
13
15
|
entryId
|
|
14
16
|
});
|
|
17
|
+
// TODO: move this into `sdk.navigator.openEntry()`, note that it's signature only include the entry id (not a space or environment)
|
|
15
18
|
const openEntryDetail = ()=>{
|
|
16
19
|
window.open(resourceHref, '_blank', 'noopener,noreferrer');
|
|
17
20
|
};
|
|
18
|
-
return React.createElement(WrappedEntryCard, {
|
|
21
|
+
return /*#__PURE__*/ React.createElement(WrappedEntryCard, {
|
|
19
22
|
entry: info.resource,
|
|
20
23
|
isDisabled: isDisabled,
|
|
21
24
|
hasCardEditActions: false,
|
|
22
25
|
contentType: info.contentType,
|
|
26
|
+
// we use the default locale from the space the entry belongs to
|
|
27
|
+
// as we assume this gives a more consistent behaviour.
|
|
28
|
+
// locales will inevitably differ from space to space, so it's likely
|
|
29
|
+
// that the current locale does not exist in the "remote" space
|
|
23
30
|
localeCode: info.defaultLocaleCode,
|
|
24
31
|
defaultLocaleCode: info.defaultLocaleCode,
|
|
25
32
|
size: "small",
|
|
@@ -5,28 +5,29 @@ import { useResource } from '../../common/EntityStore';
|
|
|
5
5
|
import { ResourceEntityErrorCard } from '../../components';
|
|
6
6
|
import { ContentfulEntryCard } from './ContentfulEntryCard';
|
|
7
7
|
function ResourceCardSkeleton() {
|
|
8
|
-
return React.createElement(EntryCard, {
|
|
8
|
+
return /*#__PURE__*/ React.createElement(EntryCard, {
|
|
9
9
|
size: "small",
|
|
10
10
|
isLoading: true
|
|
11
11
|
});
|
|
12
12
|
}
|
|
13
13
|
function ExistingResourceCard(props) {
|
|
14
|
-
const { resourceLink
|
|
14
|
+
const { resourceLink, inView, index = 0 } = props;
|
|
15
15
|
const resourceOptions = {
|
|
16
16
|
priority: index * -1,
|
|
17
17
|
enabled: inView
|
|
18
18
|
};
|
|
19
|
-
const { data
|
|
19
|
+
const { data, error } = useResource(resourceLink.sys.linkType, resourceLink.sys.urn, resourceOptions);
|
|
20
20
|
if (!data && !error) {
|
|
21
|
-
return React.createElement(ResourceCardSkeleton, null);
|
|
21
|
+
return /*#__PURE__*/ React.createElement(ResourceCardSkeleton, null);
|
|
22
22
|
}
|
|
23
23
|
if (data) {
|
|
24
|
-
|
|
24
|
+
// @ts-expect-error
|
|
25
|
+
return /*#__PURE__*/ React.createElement(ContentfulEntryCard, {
|
|
25
26
|
info: data,
|
|
26
27
|
...props
|
|
27
28
|
});
|
|
28
29
|
}
|
|
29
|
-
return React.createElement(ResourceEntityErrorCard, {
|
|
30
|
+
return /*#__PURE__*/ React.createElement(ResourceEntityErrorCard, {
|
|
30
31
|
linkType: resourceLink.sys.linkType,
|
|
31
32
|
error: error,
|
|
32
33
|
isDisabled: props.isDisabled,
|
|
@@ -37,20 +38,21 @@ function ResourceCardWrapper(props) {
|
|
|
37
38
|
if (!props.resourceLink) {
|
|
38
39
|
return null;
|
|
39
40
|
}
|
|
40
|
-
return React.createElement(ExistingResourceCard, {
|
|
41
|
+
return /*#__PURE__*/ React.createElement(ExistingResourceCard, {
|
|
41
42
|
...props,
|
|
42
43
|
resourceLink: props.resourceLink,
|
|
43
44
|
getEntryRouteHref: props.getEntryRouteHref
|
|
44
45
|
});
|
|
45
46
|
}
|
|
46
47
|
export function ResourceCard(props) {
|
|
47
|
-
const { ref
|
|
48
|
+
const { ref, inView } = useInView({
|
|
48
49
|
triggerOnce: true,
|
|
49
50
|
rootMargin: '300px 0px 0px 300px'
|
|
50
51
|
});
|
|
51
|
-
|
|
52
|
+
// Forma does not offer us to pass refs, so we need an additional wrapper here
|
|
53
|
+
return /*#__PURE__*/ React.createElement("div", {
|
|
52
54
|
ref: ref
|
|
53
|
-
}, React.createElement(ResourceCardWrapper, {
|
|
55
|
+
}, /*#__PURE__*/ React.createElement(ResourceCardWrapper, {
|
|
54
56
|
...props,
|
|
55
57
|
inView: inView
|
|
56
58
|
}));
|
|
@@ -14,6 +14,7 @@ configure({
|
|
|
14
14
|
jest.mock('react-intersection-observer', ()=>({
|
|
15
15
|
useInView: jest.fn().mockReturnValue({})
|
|
16
16
|
}));
|
|
17
|
+
// explicit master
|
|
17
18
|
const resolvableEntryUrn = 'crn:contentful:::content:spaces/space-id/entries/linked-entry-urn';
|
|
18
19
|
const resolvableEntryUrnWithExplicitMaster = 'crn:contentful:::content:spaces/space-id/environments/master/entries/linked-entry-urn';
|
|
19
20
|
const resolvableEntryUrnWithAnotherEnvironment = 'crn:contentful:::content:spaces/space-id/environments/my-test-environment/entries/linked-entry-urn';
|
|
@@ -27,7 +28,7 @@ const sdk = {
|
|
|
27
28
|
get: jest.fn().mockReturnValue(publishedCT)
|
|
28
29
|
},
|
|
29
30
|
Entry: {
|
|
30
|
-
get: jest.fn().mockImplementation(({ spaceId
|
|
31
|
+
get: jest.fn().mockImplementation(({ spaceId, environmentId, entryId })=>{
|
|
31
32
|
if (spaceId === 'space-id' && environmentId === 'master' && entryId === 'linked-entry-urn') {
|
|
32
33
|
return Promise.resolve(publishedEntry);
|
|
33
34
|
}
|
|
@@ -66,10 +67,10 @@ const sdk = {
|
|
|
66
67
|
environment: 'environment-id'
|
|
67
68
|
}
|
|
68
69
|
};
|
|
69
|
-
function renderResourceCard({ linkType ='Contentful:Entry'
|
|
70
|
-
return render(React.createElement(EntityProvider, {
|
|
70
|
+
function renderResourceCard({ linkType = 'Contentful:Entry', entryUrn = resolvableEntryUrn } = {}) {
|
|
71
|
+
return render(/*#__PURE__*/ React.createElement(EntityProvider, {
|
|
71
72
|
sdk: sdk
|
|
72
|
-
}, React.createElement(ResourceCard, {
|
|
73
|
+
}, /*#__PURE__*/ React.createElement(ResourceCard, {
|
|
73
74
|
isDisabled: false,
|
|
74
75
|
getEntryRouteHref: ()=>'',
|
|
75
76
|
resourceLink: {
|
|
@@ -83,7 +84,7 @@ function renderResourceCard({ linkType ='Contentful:Entry' , entryUrn =resolvabl
|
|
|
83
84
|
}
|
|
84
85
|
describe('ResourceCard', ()=>{
|
|
85
86
|
it('renders entry card with implicit master crn', async ()=>{
|
|
86
|
-
const { getByTestId
|
|
87
|
+
const { getByTestId, getByText } = renderResourceCard();
|
|
87
88
|
const tooltipContent = `Space: ${space.name} (Env.: ${publishedEntry.sys.environment.sys.id})`;
|
|
88
89
|
await waitFor(()=>expect(getByTestId('cf-ui-entry-card')).toBeDefined());
|
|
89
90
|
expect(getByText(publishedEntry.fields.exField['en-US'])).toBeDefined();
|
|
@@ -92,7 +93,7 @@ describe('ResourceCard', ()=>{
|
|
|
92
93
|
await waitFor(()=>expect(getByText(tooltipContent)).toBeDefined());
|
|
93
94
|
});
|
|
94
95
|
it('renders entry card with explicit master crn', async ()=>{
|
|
95
|
-
const { getByTestId
|
|
96
|
+
const { getByTestId, getByText } = renderResourceCard({
|
|
96
97
|
entryUrn: resolvableEntryUrnWithExplicitMaster
|
|
97
98
|
});
|
|
98
99
|
const tooltipContent = `Space: ${space.name} (Env.: ${publishedEntry.sys.environment.sys.id})`;
|
|
@@ -103,7 +104,7 @@ describe('ResourceCard', ()=>{
|
|
|
103
104
|
await waitFor(()=>expect(getByText(tooltipContent)).toBeDefined());
|
|
104
105
|
});
|
|
105
106
|
it('renders entry card with a non master environment', async ()=>{
|
|
106
|
-
const { getByTestId
|
|
107
|
+
const { getByTestId, getByText } = renderResourceCard({
|
|
107
108
|
entryUrn: resolvableEntryUrnWithAnotherEnvironment
|
|
108
109
|
});
|
|
109
110
|
await waitFor(()=>expect(getByTestId('cf-ui-entry-card')).toBeDefined());
|
|
@@ -114,23 +115,23 @@ describe('ResourceCard', ()=>{
|
|
|
114
115
|
await waitFor(()=>expect(getByText(tooltipContent)).toBeDefined());
|
|
115
116
|
});
|
|
116
117
|
it('renders skeleton when no data is provided', ()=>{
|
|
117
|
-
const { getByTestId
|
|
118
|
+
const { getByTestId } = renderResourceCard();
|
|
118
119
|
expect(getByTestId('cf-ui-skeleton-form')).toBeDefined();
|
|
119
120
|
});
|
|
120
121
|
it('renders unsupported entity card when unsupported link is passed', async ()=>{
|
|
121
|
-
const { getByText
|
|
122
|
+
const { getByText } = renderResourceCard({
|
|
122
123
|
linkType: 'Contentful:UnsupportedLink'
|
|
123
124
|
});
|
|
124
125
|
await waitFor(()=>expect(getByText('Resource type Contentful:UnsupportedLink is currently not supported')).toBeDefined());
|
|
125
126
|
});
|
|
126
127
|
it('renders missing entity card when unknown error is returned', async ()=>{
|
|
127
|
-
const { getByTestId
|
|
128
|
+
const { getByTestId } = renderResourceCard({
|
|
128
129
|
entryUrn: unknownEntryUrn
|
|
129
130
|
});
|
|
130
131
|
await waitFor(()=>expect(getByTestId('cf-ui-missing-entry-card')).toBeDefined());
|
|
131
132
|
});
|
|
132
133
|
it('renders missing entity card when crn is invalid', async ()=>{
|
|
133
|
-
const { getByTestId
|
|
134
|
+
const { getByTestId } = renderResourceCard({
|
|
134
135
|
entryUrn: ''
|
|
135
136
|
});
|
|
136
137
|
await waitFor(()=>expect(getByTestId('cf-ui-missing-entry-card')).toBeDefined());
|