@contentful/field-editor-reference 5.9.0 → 5.11.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 +183 -0
- package/dist/cjs/__fixtures__/asset/index.js +37 -0
- package/dist/cjs/__fixtures__/content-type/index.js +16 -0
- package/dist/cjs/__fixtures__/entry/index.js +33 -0
- package/dist/cjs/__fixtures__/fixtures.js +71 -0
- package/dist/cjs/__fixtures__/locale/index.js +40 -0
- package/dist/cjs/__fixtures__/space/index.js +16 -0
- package/dist/cjs/assets/MultipleMediaEditor.js +86 -0
- package/dist/cjs/assets/SingleMediaEditor.js +69 -0
- package/dist/cjs/assets/WrappedAssetCard/AssetCardActions.js +125 -0
- package/dist/cjs/assets/WrappedAssetCard/FetchingWrappedAssetCard.js +171 -0
- package/dist/cjs/assets/WrappedAssetCard/WrappedAssetCard.js +159 -0
- package/dist/cjs/assets/WrappedAssetCard/WrappedAssetLink.js +130 -0
- package/dist/cjs/assets/index.js +24 -0
- package/dist/cjs/common/EntityStore.js +420 -0
- package/dist/cjs/common/MultipleReferenceEditor.js +164 -0
- package/dist/cjs/common/ReferenceEditor.js +74 -0
- package/dist/cjs/common/SingleReferenceEditor.js +118 -0
- package/dist/cjs/common/SortableLinkList.js +95 -0
- package/dist/cjs/common/customCardTypes.js +44 -0
- package/dist/cjs/common/useAccessApi.js +19 -0
- package/dist/cjs/common/useContentTypePermissions.js +54 -0
- package/dist/cjs/common/useEditorPermissions.js +77 -0
- package/dist/cjs/common/useEditorPermissions.spec.js +205 -0
- package/dist/cjs/components/AssetThumbnail/AssetThumbnail.js +62 -0
- package/dist/cjs/components/CreateEntryLinkButton/CreateEntryLinkButton.js +102 -0
- package/dist/cjs/components/CreateEntryLinkButton/CreateEntryLinkButton.spec.js +254 -0
- package/dist/cjs/components/CreateEntryLinkButton/CreateEntryMenuTrigger.js +199 -0
- package/dist/cjs/components/CreateEntryLinkButton/CreateEntryMenuTrigger.spec.js +190 -0
- package/dist/cjs/components/CreateEntryLinkButton/useGlobalMouseUp.js +19 -0
- package/dist/cjs/components/LinkActions/CombinedLinkActions.js +167 -0
- package/dist/cjs/components/LinkActions/LinkActions.js +123 -0
- package/dist/cjs/components/LinkActions/LinkEntityActions.js +186 -0
- package/dist/cjs/components/LinkActions/NoLinkPermissionsInfo.js +54 -0
- package/dist/cjs/components/LinkActions/helpers.js +78 -0
- package/dist/cjs/components/LinkActions/redesignStyles.js +44 -0
- package/dist/cjs/components/LinkActions/styles.js +33 -0
- package/dist/cjs/components/MissingEntityCard/MissingEntityCard.js +75 -0
- package/dist/cjs/components/MissingEntityCard/styles.js +29 -0
- package/dist/cjs/components/ScheduledIconWithTooltip/ScheduleTooltip.js +75 -0
- package/dist/cjs/components/ScheduledIconWithTooltip/ScheduledIconWithTooltip.js +81 -0
- package/dist/cjs/components/ScheduledIconWithTooltip/formatDateAndTime.js +45 -0
- package/dist/cjs/components/SpaceName/SpaceName.js +91 -0
- package/dist/cjs/components/index.js +44 -0
- package/dist/cjs/entries/MultipleEntryReferenceEditor.js +86 -0
- package/dist/cjs/entries/SingleEntryReferenceEditor.js +74 -0
- package/dist/cjs/entries/WrappedEntryCard/FetchingWrappedEntryCard.js +189 -0
- package/dist/cjs/entries/WrappedEntryCard/WrappedEntryCard.js +181 -0
- package/dist/cjs/entries/index.js +24 -0
- package/dist/cjs/index.js +92 -0
- package/dist/cjs/resources/Cards/ContentfulEntryCard.js +87 -0
- package/dist/cjs/resources/Cards/ResourceCard.js +111 -0
- package/dist/cjs/resources/Cards/UnsupportedEntityCard.js +64 -0
- package/dist/cjs/resources/MultipleResourceReferenceEditor.js +157 -0
- package/dist/cjs/resources/MultipleResourceReferenceEditor.spec.js +297 -0
- package/dist/cjs/resources/SingleResourceReferenceEditor.js +87 -0
- package/dist/cjs/resources/SingleResourceReferenceEditor.spec.js +161 -0
- package/dist/cjs/resources/index.js +19 -0
- package/dist/cjs/resources/testHelpers/resourceEditorHelpers.js +121 -0
- package/dist/cjs/resources/useResourceLinkActions.js +88 -0
- package/dist/cjs/types.js +22 -0
- package/dist/cjs/utils/fromFieldValidations.js +54 -0
- package/dist/esm/__fixtures__/FakeSdk.js +173 -0
- package/dist/esm/__fixtures__/asset/index.js +6 -0
- package/dist/esm/__fixtures__/content-type/index.js +2 -0
- package/dist/esm/__fixtures__/entry/index.js +5 -0
- package/dist/esm/__fixtures__/fixtures.js +6 -0
- package/dist/esm/__fixtures__/locale/index.js +15 -0
- package/dist/esm/__fixtures__/space/index.js +2 -0
- package/dist/esm/assets/MultipleMediaEditor.js +37 -0
- package/dist/esm/assets/SingleMediaEditor.js +20 -0
- package/dist/esm/assets/WrappedAssetCard/AssetCardActions.js +63 -0
- package/dist/esm/assets/WrappedAssetCard/FetchingWrappedAssetCard.js +122 -0
- package/dist/esm/assets/WrappedAssetCard/WrappedAssetCard.js +105 -0
- package/dist/esm/assets/WrappedAssetCard/WrappedAssetLink.js +76 -0
- package/dist/esm/assets/index.js +3 -0
- package/dist/esm/common/EntityStore.js +347 -0
- package/dist/esm/common/MultipleReferenceEditor.js +111 -0
- package/dist/esm/common/ReferenceEditor.js +20 -0
- package/dist/esm/common/SingleReferenceEditor.js +70 -0
- package/dist/esm/common/SortableLinkList.js +41 -0
- package/dist/esm/common/customCardTypes.js +1 -0
- package/dist/esm/common/useAccessApi.js +9 -0
- package/dist/esm/common/useContentTypePermissions.js +44 -0
- package/dist/esm/common/useEditorPermissions.js +67 -0
- package/dist/esm/common/useEditorPermissions.spec.js +201 -0
- package/dist/esm/components/AssetThumbnail/AssetThumbnail.js +13 -0
- package/dist/esm/components/CreateEntryLinkButton/CreateEntryLinkButton.js +48 -0
- package/dist/esm/components/CreateEntryLinkButton/CreateEntryLinkButton.spec.js +206 -0
- package/dist/esm/components/CreateEntryLinkButton/CreateEntryMenuTrigger.js +145 -0
- package/dist/esm/components/CreateEntryLinkButton/CreateEntryMenuTrigger.spec.js +142 -0
- package/dist/esm/components/CreateEntryLinkButton/useGlobalMouseUp.js +9 -0
- package/dist/esm/components/LinkActions/CombinedLinkActions.js +118 -0
- package/dist/esm/components/LinkActions/LinkActions.js +66 -0
- package/dist/esm/components/LinkActions/LinkEntityActions.js +127 -0
- package/dist/esm/components/LinkActions/NoLinkPermissionsInfo.js +5 -0
- package/dist/esm/components/LinkActions/helpers.js +57 -0
- package/dist/esm/components/LinkActions/redesignStyles.js +18 -0
- package/dist/esm/components/LinkActions/styles.js +10 -0
- package/dist/esm/components/MissingEntityCard/MissingEntityCard.js +26 -0
- package/dist/esm/components/MissingEntityCard/styles.js +11 -0
- package/dist/esm/components/ScheduledIconWithTooltip/ScheduleTooltip.js +18 -0
- package/dist/esm/components/ScheduledIconWithTooltip/ScheduledIconWithTooltip.js +32 -0
- package/dist/esm/components/ScheduledIconWithTooltip/formatDateAndTime.js +19 -0
- package/dist/esm/components/SpaceName/SpaceName.js +37 -0
- package/dist/esm/components/index.js +8 -0
- package/dist/esm/entries/MultipleEntryReferenceEditor.js +37 -0
- package/dist/esm/entries/SingleEntryReferenceEditor.js +25 -0
- package/dist/esm/entries/WrappedEntryCard/FetchingWrappedEntryCard.js +135 -0
- package/dist/esm/entries/WrappedEntryCard/WrappedEntryCard.js +127 -0
- package/dist/esm/entries/index.js +3 -0
- package/dist/esm/index.js +7 -0
- package/dist/esm/resources/Cards/ContentfulEntryCard.js +38 -0
- package/dist/esm/resources/Cards/ResourceCard.js +62 -0
- package/dist/esm/resources/Cards/UnsupportedEntityCard.js +15 -0
- package/dist/esm/resources/MultipleResourceReferenceEditor.js +104 -0
- package/dist/esm/resources/MultipleResourceReferenceEditor.spec.js +254 -0
- package/dist/esm/resources/SingleResourceReferenceEditor.js +33 -0
- package/dist/esm/resources/SingleResourceReferenceEditor.spec.js +118 -0
- package/dist/esm/resources/index.js +2 -0
- package/dist/esm/resources/testHelpers/resourceEditorHelpers.js +103 -0
- package/dist/esm/resources/useResourceLinkActions.js +78 -0
- package/dist/esm/types.js +1 -0
- package/dist/esm/utils/fromFieldValidations.js +39 -0
- package/dist/{__fixtures__ → types/__fixtures__}/FakeSdk.d.ts +8 -8
- package/dist/{__fixtures__ → types/__fixtures__}/asset/index.d.ts +6 -6
- package/dist/{__fixtures__ → types/__fixtures__}/content-type/index.d.ts +2 -2
- package/dist/{__fixtures__ → types/__fixtures__}/entry/index.d.ts +5 -5
- package/dist/{__fixtures__ → types/__fixtures__}/fixtures.d.ts +6 -6
- package/dist/{__fixtures__ → types/__fixtures__}/locale/index.d.ts +42 -42
- package/dist/{__fixtures__ → types/__fixtures__}/space/index.d.ts +2 -2
- package/dist/{assets → types/assets}/MultipleMediaEditor.d.ts +10 -10
- package/dist/types/assets/SingleMediaEditor.d.ts +10 -0
- package/dist/{assets → types/assets}/WrappedAssetCard/AssetCardActions.d.ts +11 -11
- package/dist/{assets → types/assets}/WrappedAssetCard/FetchingWrappedAssetCard.d.ts +17 -17
- package/dist/{assets → types/assets}/WrappedAssetCard/WrappedAssetCard.d.ts +24 -24
- package/dist/{assets → types/assets}/WrappedAssetCard/WrappedAssetLink.d.ts +16 -16
- package/dist/{assets → types/assets}/index.d.ts +3 -3
- package/dist/{common → types/common}/EntityStore.d.ts +62 -62
- package/dist/{common → types/common}/MultipleReferenceEditor.d.ts +25 -25
- package/dist/{common → types/common}/ReferenceEditor.d.ts +46 -46
- package/dist/{common → types/common}/SingleReferenceEditor.d.ts +24 -24
- package/dist/{common → types/common}/SortableLinkList.d.ts +19 -19
- package/dist/{common → types/common}/customCardTypes.d.ts +29 -29
- package/dist/types/common/useAccessApi.d.ts +16 -0
- package/dist/{common → types/common}/useContentTypePermissions.d.ts +17 -17
- package/dist/{common → types/common}/useEditorPermissions.d.ts +17 -17
- package/dist/types/common/useEditorPermissions.spec.d.ts +1 -0
- package/dist/{components → types/components}/AssetThumbnail/AssetThumbnail.d.ts +7 -7
- package/dist/{components → types/components}/CreateEntryLinkButton/CreateEntryLinkButton.d.ts +19 -19
- package/dist/types/components/CreateEntryLinkButton/CreateEntryLinkButton.spec.d.ts +1 -0
- package/dist/{components → types/components}/CreateEntryLinkButton/CreateEntryMenuTrigger.d.ts +31 -31
- package/dist/types/components/CreateEntryLinkButton/CreateEntryMenuTrigger.spec.d.ts +1 -0
- package/dist/{components → types/components}/CreateEntryLinkButton/useGlobalMouseUp.d.ts +1 -1
- package/dist/{components → types/components}/LinkActions/CombinedLinkActions.d.ts +10 -10
- package/dist/{components → types/components}/LinkActions/LinkActions.d.ts +26 -26
- package/dist/{components → types/components}/LinkActions/LinkEntityActions.d.ts +24 -24
- package/dist/types/components/LinkActions/NoLinkPermissionsInfo.d.ts +2 -0
- package/dist/{components → types/components}/LinkActions/helpers.d.ts +26 -26
- package/dist/{components → types/components}/LinkActions/redesignStyles.d.ts +3 -3
- package/dist/{components → types/components}/LinkActions/styles.d.ts +2 -2
- package/dist/{components → types/components}/MissingEntityCard/MissingEntityCard.d.ts +8 -8
- package/dist/{components → types/components}/MissingEntityCard/styles.d.ts +2 -2
- package/dist/{components → types/components}/ScheduledIconWithTooltip/ScheduleTooltip.d.ts +11 -11
- package/dist/{components → types/components}/ScheduledIconWithTooltip/ScheduledIconWithTooltip.d.ts +10 -10
- package/dist/{components → types/components}/ScheduledIconWithTooltip/formatDateAndTime.d.ts +15 -15
- package/dist/types/components/SpaceName/SpaceName.d.ts +6 -0
- package/dist/{components → types/components}/index.d.ts +9 -9
- package/dist/{entries → types/entries}/MultipleEntryReferenceEditor.d.ts +3 -3
- package/dist/{entries → types/entries}/SingleEntryReferenceEditor.d.ts +8 -8
- package/dist/{entries → types/entries}/WrappedEntryCard/FetchingWrappedEntryCard.d.ts +18 -18
- package/dist/{entries → types/entries}/WrappedEntryCard/WrappedEntryCard.d.ts +35 -35
- package/dist/{entries → types/entries}/index.d.ts +3 -3
- package/dist/{index.d.ts → types/index.d.ts} +10 -8
- package/dist/{resources → types/resources}/Cards/ContentfulEntryCard.d.ts +21 -21
- package/dist/{resources → types/resources}/Cards/ResourceCard.d.ts +12 -12
- package/dist/{resources → types/resources}/Cards/UnsupportedEntityCard.d.ts +4 -4
- package/dist/{resources → types/resources}/MultipleResourceReferenceEditor.d.ts +7 -7
- package/dist/types/resources/MultipleResourceReferenceEditor.spec.d.ts +1 -0
- package/dist/{resources → types/resources}/SingleResourceReferenceEditor.d.ts +7 -7
- package/dist/types/resources/SingleResourceReferenceEditor.spec.d.ts +1 -0
- package/dist/{resources → types/resources}/index.d.ts +2 -2
- package/dist/{resources → types/resources}/testHelpers/resourceEditorHelpers.d.ts +50 -50
- package/dist/{resources → types/resources}/useResourceLinkActions.d.ts +7 -7
- package/dist/{types.d.ts → types/types.d.ts} +104 -104
- package/dist/{utils → types/utils}/fromFieldValidations.d.ts +21 -21
- package/package.json +25 -11
- package/CHANGELOG.md +0 -860
- package/dist/assets/SingleMediaEditor.d.ts +0 -10
- package/dist/common/useAccessApi.d.ts +0 -16
- package/dist/components/LinkActions/NoLinkPermissionsInfo.d.ts +0 -2
- package/dist/components/SpaceName/SpaceName.d.ts +0 -6
- package/dist/field-editor-reference.cjs.development.js +0 -2753
- package/dist/field-editor-reference.cjs.development.js.map +0 -1
- package/dist/field-editor-reference.cjs.production.min.js +0 -2
- package/dist/field-editor-reference.cjs.production.min.js.map +0 -1
- package/dist/field-editor-reference.esm.js +0 -2727
- package/dist/field-editor-reference.esm.js.map +0 -1
- package/dist/index.js +0 -8
|
@@ -1,2727 +0,0 @@
|
|
|
1
|
-
import React__default, { useState, useRef, useEffect, createElement, Fragment, useMemo, useCallback } from 'react';
|
|
2
|
-
import { Menu, TextInput, Button, Paragraph, Card, Flex, SectionHeading, IconButton, Tooltip, Text, EntryCard, MenuItem, MenuDivider, AssetCard } from '@contentful/f36-components';
|
|
3
|
-
import { SearchIcon, PlusIcon, ChevronDownIcon, LinkIcon, CloseIcon, FolderOpenTrimmedIcon, ClockIcon } from '@contentful/f36-icons';
|
|
4
|
-
import tokens from '@contentful/f36-tokens';
|
|
5
|
-
import { css, cx } from 'emotion';
|
|
6
|
-
import get from 'lodash-es/get';
|
|
7
|
-
import moment from 'moment';
|
|
8
|
-
import { FieldConnector, isValidImage, entityHelpers, shortenStorageUnit } from '@contentful/field-editor-shared';
|
|
9
|
-
import deepEqual from 'deep-equal';
|
|
10
|
-
import { useQueryClient, useQuery, QueryCache, QueryClient, QueryClientProvider } from '@tanstack/react-query';
|
|
11
|
-
import constate from 'constate';
|
|
12
|
-
import { createClient } from 'contentful-management';
|
|
13
|
-
import PQueue from 'p-queue';
|
|
14
|
-
import isNumber from 'lodash-es/isNumber';
|
|
15
|
-
import arrayMove from 'array-move';
|
|
16
|
-
import { SortableContainer, SortableHandle, SortableElement } from 'react-sortable-hoc';
|
|
17
|
-
import mimetype from '@contentful/mimetype';
|
|
18
|
-
import { useInView } from 'react-intersection-observer';
|
|
19
|
-
|
|
20
|
-
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
21
|
-
const MAX_ITEMS_WITHOUT_SEARCH = 5;
|
|
22
|
-
const menuPlacementMap = {
|
|
23
|
-
'bottom-left': 'bottom-start',
|
|
24
|
-
'bottom-right': 'bottom-end'
|
|
25
|
-
};
|
|
26
|
-
const styles = {
|
|
27
|
-
wrapper: /*#__PURE__*/css({
|
|
28
|
-
position: 'relative'
|
|
29
|
-
}),
|
|
30
|
-
inputWrapper: /*#__PURE__*/css({
|
|
31
|
-
position: 'relative',
|
|
32
|
-
padding: `0 ${tokens.spacing2Xs}`
|
|
33
|
-
}),
|
|
34
|
-
searchInput: /*#__PURE__*/css({
|
|
35
|
-
paddingRight: tokens.spacingXl,
|
|
36
|
-
textOverflow: 'ellipsis'
|
|
37
|
-
}),
|
|
38
|
-
searchIcon: /*#__PURE__*/css({
|
|
39
|
-
position: 'absolute',
|
|
40
|
-
right: tokens.spacingM,
|
|
41
|
-
top: tokens.spacingS,
|
|
42
|
-
zIndex: /*#__PURE__*/Number(tokens.zIndexDefault),
|
|
43
|
-
fill: tokens.gray600
|
|
44
|
-
}),
|
|
45
|
-
separator: /*#__PURE__*/css({
|
|
46
|
-
background: tokens.gray200,
|
|
47
|
-
margin: '10px 0'
|
|
48
|
-
}),
|
|
49
|
-
dropdownList: /*#__PURE__*/css({
|
|
50
|
-
borderColor: tokens.gray200
|
|
51
|
-
})
|
|
52
|
-
};
|
|
53
|
-
const CreateEntryMenuTrigger = ({
|
|
54
|
-
contentTypes,
|
|
55
|
-
suggestedContentTypeId,
|
|
56
|
-
contentTypesLabel,
|
|
57
|
-
onSelect,
|
|
58
|
-
testId,
|
|
59
|
-
dropdownSettings = {
|
|
60
|
-
position: 'bottom-left'
|
|
61
|
-
},
|
|
62
|
-
customDropdownItems,
|
|
63
|
-
children
|
|
64
|
-
}) => {
|
|
65
|
-
const [isOpen, setOpen] = useState(false);
|
|
66
|
-
const [isSelecting, setSelecting] = useState(false);
|
|
67
|
-
const [searchInput, setSearchInput] = useState('');
|
|
68
|
-
const wrapper = useRef(null);
|
|
69
|
-
const textField = useRef(null);
|
|
70
|
-
const menuListRef = useRef(null);
|
|
71
|
-
/*
|
|
72
|
-
By default, dropdown wraps it's content, so it's width = the width of the widest item
|
|
73
|
-
During search, menu items change, and so the widest menu item can change
|
|
74
|
-
This leads to menu always changing it's width
|
|
75
|
-
To prevent this, we get the width of the menu item after the first mount of a dropdown (when all the content is displayed)
|
|
76
|
-
And hardcode it through the class name. This way we ensure that even during search the menu will keep that max width
|
|
77
|
-
That it had on initial mount and that fits any menu item in has
|
|
78
|
-
*/
|
|
79
|
-
|
|
80
|
-
const [dropdownWidth, setDropdownWidth] = useState();
|
|
81
|
-
const hasDropdown = contentTypes.length > 1 || !!customDropdownItems;
|
|
82
|
-
|
|
83
|
-
const closeMenu = () => setOpen(false);
|
|
84
|
-
|
|
85
|
-
useEffect(() => {
|
|
86
|
-
if (isOpen) {
|
|
87
|
-
setTimeout(() => {
|
|
88
|
-
var _textField$current, _textField$current$qu;
|
|
89
|
-
|
|
90
|
-
(_textField$current = textField.current) == null ? void 0 : (_textField$current$qu = _textField$current.querySelector('input')) == null ? void 0 : _textField$current$qu.focus({
|
|
91
|
-
preventScroll: true
|
|
92
|
-
});
|
|
93
|
-
}, 200);
|
|
94
|
-
}
|
|
95
|
-
}, [isOpen]);
|
|
96
|
-
useEffect(() => {
|
|
97
|
-
if (isOpen && !dropdownWidth) {
|
|
98
|
-
var _menuListRef$current;
|
|
99
|
-
|
|
100
|
-
setDropdownWidth((_menuListRef$current = menuListRef.current) == null ? void 0 : _menuListRef$current.clientWidth);
|
|
101
|
-
}
|
|
102
|
-
}, [isOpen, dropdownWidth]);
|
|
103
|
-
|
|
104
|
-
const handleSelect = item => {
|
|
105
|
-
closeMenu();
|
|
106
|
-
const res = onSelect(item.sys.id); // TODO: Convert to controllable component.
|
|
107
|
-
|
|
108
|
-
if (res && typeof res.then === 'function') {
|
|
109
|
-
setSelecting(true);
|
|
110
|
-
res.then(() => setSelecting(false), () => setSelecting(false));
|
|
111
|
-
}
|
|
112
|
-
};
|
|
113
|
-
|
|
114
|
-
const handleMenuOpen = () => {
|
|
115
|
-
if (hasDropdown) {
|
|
116
|
-
setOpen(true);
|
|
117
|
-
} else {
|
|
118
|
-
handleSelect(contentTypes[0]);
|
|
119
|
-
}
|
|
120
|
-
};
|
|
121
|
-
|
|
122
|
-
useEffect(() => {
|
|
123
|
-
if (!isOpen) {
|
|
124
|
-
setSearchInput('');
|
|
125
|
-
}
|
|
126
|
-
}, [isOpen]);
|
|
127
|
-
|
|
128
|
-
const renderSearchResultsCount = resultsLength => resultsLength ? React__default.createElement(Menu.SectionTitle, {
|
|
129
|
-
testId: "add-entru-menu-search-results"
|
|
130
|
-
}, resultsLength, " result", resultsLength > 1 ? 's' : '') : null;
|
|
131
|
-
|
|
132
|
-
const isSearchable = contentTypes.length > MAX_ITEMS_WITHOUT_SEARCH;
|
|
133
|
-
const maxDropdownHeight = suggestedContentTypeId ? 300 : 250;
|
|
134
|
-
const suggestedContentType = contentTypes.find(ct => ct.sys.id === suggestedContentTypeId);
|
|
135
|
-
const filteredContentTypes = contentTypes.filter(ct => !searchInput || get(ct, 'name', 'Untitled').toLowerCase().includes(searchInput.toLowerCase()));
|
|
136
|
-
return React__default.createElement("span", {
|
|
137
|
-
className: styles.wrapper,
|
|
138
|
-
ref: wrapper,
|
|
139
|
-
"data-test-id": testId
|
|
140
|
-
}, React__default.createElement(Menu, {
|
|
141
|
-
placement: menuPlacementMap[dropdownSettings.position],
|
|
142
|
-
isAutoalignmentEnabled: dropdownSettings.isAutoalignmentEnabled,
|
|
143
|
-
isOpen: isOpen,
|
|
144
|
-
onClose: closeMenu,
|
|
145
|
-
onOpen: handleMenuOpen
|
|
146
|
-
}, React__default.createElement(Menu.Trigger, null, children({
|
|
147
|
-
isOpen,
|
|
148
|
-
isSelecting
|
|
149
|
-
})), isOpen && React__default.createElement(Menu.List, {
|
|
150
|
-
className: styles.dropdownList,
|
|
151
|
-
style: {
|
|
152
|
-
width: dropdownWidth != undefined ? `${dropdownWidth}px` : undefined,
|
|
153
|
-
maxHeight: `${maxDropdownHeight}px`
|
|
154
|
-
},
|
|
155
|
-
ref: menuListRef,
|
|
156
|
-
testId: "add-entry-menu"
|
|
157
|
-
}, Boolean(customDropdownItems) && React__default.createElement(React__default.Fragment, null, customDropdownItems, React__default.createElement(Menu.Divider, null)), isSearchable && React__default.createElement(React__default.Fragment, null, React__default.createElement("div", {
|
|
158
|
-
ref: textField,
|
|
159
|
-
className: styles.inputWrapper
|
|
160
|
-
}, React__default.createElement(TextInput, {
|
|
161
|
-
className: styles.searchInput,
|
|
162
|
-
placeholder: "Search all content types",
|
|
163
|
-
testId: "add-entry-menu-search",
|
|
164
|
-
value: searchInput,
|
|
165
|
-
onChange: e => setSearchInput(e.target.value)
|
|
166
|
-
}), React__default.createElement(SearchIcon, {
|
|
167
|
-
className: styles.searchIcon
|
|
168
|
-
})), React__default.createElement(Menu.Divider, null)), searchInput && renderSearchResultsCount(filteredContentTypes.length), suggestedContentType && !searchInput && React__default.createElement(React__default.Fragment, null, React__default.createElement(Menu.SectionTitle, null, "Suggested Content Type"), React__default.createElement(Menu.Item, {
|
|
169
|
-
testId: "suggested",
|
|
170
|
-
onClick: () => handleSelect(suggestedContentType)
|
|
171
|
-
}, get(suggestedContentType, 'name')), React__default.createElement(Menu.Divider, null)), !searchInput && React__default.createElement(Menu.SectionTitle, null, contentTypesLabel), filteredContentTypes.length ? filteredContentTypes.map((contentType, i) => React__default.createElement(Menu.Item, {
|
|
172
|
-
testId: "contentType",
|
|
173
|
-
key: `${get(contentType, 'name')}-${i}`,
|
|
174
|
-
onClick: () => handleSelect(contentType)
|
|
175
|
-
}, get(contentType, 'name', 'Untitled'))) : React__default.createElement(Menu.Item, {
|
|
176
|
-
testId: "add-entru-menu-search-results"
|
|
177
|
-
}, "No results found"))));
|
|
178
|
-
};
|
|
179
|
-
CreateEntryMenuTrigger.defaultProps = {
|
|
180
|
-
testId: 'create-entry-button-menu-trigger',
|
|
181
|
-
contentTypesLabel: 'All Content Types'
|
|
182
|
-
};
|
|
183
|
-
|
|
184
|
-
const standardStyles = {
|
|
185
|
-
spinnerMargin: /*#__PURE__*/css({
|
|
186
|
-
marginRight: tokens.spacingXs
|
|
187
|
-
}),
|
|
188
|
-
action: undefined
|
|
189
|
-
};
|
|
190
|
-
const redesignStyles = { ...standardStyles,
|
|
191
|
-
action: /*#__PURE__*/css({
|
|
192
|
-
textDecoration: 'none',
|
|
193
|
-
fontWeight: 'bold',
|
|
194
|
-
maxWidth: '300px'
|
|
195
|
-
})
|
|
196
|
-
};
|
|
197
|
-
const CreateEntryLinkButton = ({
|
|
198
|
-
contentTypes,
|
|
199
|
-
onSelect,
|
|
200
|
-
customDropdownItems,
|
|
201
|
-
text,
|
|
202
|
-
testId,
|
|
203
|
-
hasPlusIcon = false,
|
|
204
|
-
useExperimentalStyles,
|
|
205
|
-
suggestedContentTypeId,
|
|
206
|
-
dropdownSettings,
|
|
207
|
-
disabled = false
|
|
208
|
-
}) => {
|
|
209
|
-
contentTypes = contentTypes.sort((a, b) => a.name.localeCompare(b.name));
|
|
210
|
-
const suggestedContentType = contentTypes.find(ct => ct.sys.id === suggestedContentTypeId);
|
|
211
|
-
const buttonText = text || `Add ${get(suggestedContentType || (contentTypes.length === 1 ? contentTypes[0] : {}), 'name', 'entry')}`;
|
|
212
|
-
const hasDropdown = contentTypes.length > 1 || customDropdownItems; // TODO: Introduce `icon: string` and remove `hasPlusIcon` or remove "Plus" if we keep new layout.
|
|
213
|
-
|
|
214
|
-
const plusIcon = hasPlusIcon ? React__default.createElement(PlusIcon, null) : undefined; // TODO: Always use "New content" here if we fully switch to new layout.
|
|
215
|
-
|
|
216
|
-
const contentTypesLabel = useExperimentalStyles ? 'New content' : undefined;
|
|
217
|
-
const styles = useExperimentalStyles ? redesignStyles : standardStyles;
|
|
218
|
-
return React__default.createElement(CreateEntryMenuTrigger, {
|
|
219
|
-
contentTypes: contentTypes,
|
|
220
|
-
suggestedContentTypeId: suggestedContentTypeId,
|
|
221
|
-
contentTypesLabel: contentTypesLabel,
|
|
222
|
-
onSelect: onSelect,
|
|
223
|
-
testId: testId,
|
|
224
|
-
dropdownSettings: dropdownSettings,
|
|
225
|
-
customDropdownItems: customDropdownItems
|
|
226
|
-
}, ({
|
|
227
|
-
isSelecting
|
|
228
|
-
}) => React__default.createElement(Button, {
|
|
229
|
-
endIcon: hasDropdown ? React__default.createElement(ChevronDownIcon, null) : undefined,
|
|
230
|
-
variant: "secondary",
|
|
231
|
-
className: styles.action,
|
|
232
|
-
isDisabled: disabled || isSelecting,
|
|
233
|
-
startIcon: isSelecting ? undefined : plusIcon,
|
|
234
|
-
size: "small",
|
|
235
|
-
testId: "create-entry-link-button",
|
|
236
|
-
isLoading: isSelecting
|
|
237
|
-
}, buttonText));
|
|
238
|
-
};
|
|
239
|
-
|
|
240
|
-
function NoLinkPermissionsInfo() {
|
|
241
|
-
return React__default.createElement(Paragraph, null, "You don't have permission to view this content or this field is not correctly configured. Contact your administrator for help.");
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
const container = /*#__PURE__*/css({
|
|
245
|
-
display: 'flex',
|
|
246
|
-
width: '100%',
|
|
247
|
-
marginTop: tokens.spacingS
|
|
248
|
-
});
|
|
249
|
-
const separator = /*#__PURE__*/css({
|
|
250
|
-
marginRight: tokens.spacingXl
|
|
251
|
-
});
|
|
252
|
-
|
|
253
|
-
const defaultEntryLabels = {
|
|
254
|
-
createNew: props => props != null && props.contentType ? `Create new ${props.contentType} and link` : 'Create new entry and link',
|
|
255
|
-
linkExisting: props => props != null && props.canLinkMultiple ? 'Link existing entries' : 'Link existing entry'
|
|
256
|
-
};
|
|
257
|
-
const defaultAssetLabels = {
|
|
258
|
-
createNew: () => `Create new asset and link`,
|
|
259
|
-
linkExisting: props => props != null && props.canLinkMultiple ? 'Link existing assets' : 'Link existing asset'
|
|
260
|
-
};
|
|
261
|
-
const testIds = {
|
|
262
|
-
dropdown: 'linkEditor.dropdown',
|
|
263
|
-
createAndLink: 'linkEditor.createAndLink',
|
|
264
|
-
createAndLinkWrapper: 'create-entry-button-menu-trigger',
|
|
265
|
-
linkExisting: 'linkEditor.linkExisting'
|
|
266
|
-
};
|
|
267
|
-
function LinkActions(props) {
|
|
268
|
-
if (props.isFull) {
|
|
269
|
-
return null; // Don't render link actions if we reached max allowed links.
|
|
270
|
-
}
|
|
271
|
-
|
|
272
|
-
const defaultLabels = props.entityType === 'Entry' ? defaultEntryLabels : defaultAssetLabels;
|
|
273
|
-
const labels = { ...defaultLabels,
|
|
274
|
-
...props.actionLabels
|
|
275
|
-
};
|
|
276
|
-
return createElement("div", {
|
|
277
|
-
className: container
|
|
278
|
-
}, props.canCreateEntity && createElement(Fragment, null, props.entityType === 'Entry' && createElement(CreateEntryLinkButton, {
|
|
279
|
-
testId: testIds.createAndLink,
|
|
280
|
-
disabled: props.isDisabled,
|
|
281
|
-
text: labels.createNew({
|
|
282
|
-
contentType: props.contentTypes.length === 1 ? props.contentTypes[0].name : undefined
|
|
283
|
-
}),
|
|
284
|
-
contentTypes: props.contentTypes,
|
|
285
|
-
hasPlusIcon: true,
|
|
286
|
-
onSelect: contentTypeId => {
|
|
287
|
-
return contentTypeId ? props.onCreate(contentTypeId, props.itemsLength) : Promise.resolve();
|
|
288
|
-
}
|
|
289
|
-
}), props.entityType === 'Asset' && createElement(Button, {
|
|
290
|
-
isDisabled: props.isDisabled,
|
|
291
|
-
testId: testIds.createAndLink,
|
|
292
|
-
onClick: () => {
|
|
293
|
-
props.onCreate(undefined, props.itemsLength);
|
|
294
|
-
},
|
|
295
|
-
variant: "secondary",
|
|
296
|
-
startIcon: createElement(PlusIcon, null),
|
|
297
|
-
size: "small"
|
|
298
|
-
}, labels.createNew()), createElement("span", {
|
|
299
|
-
className: separator
|
|
300
|
-
})), props.canLinkEntity && createElement(Button, {
|
|
301
|
-
isDisabled: props.isDisabled,
|
|
302
|
-
testId: testIds.linkExisting,
|
|
303
|
-
onClick: () => {
|
|
304
|
-
props.onLinkExisting();
|
|
305
|
-
},
|
|
306
|
-
variant: "secondary",
|
|
307
|
-
startIcon: createElement(LinkIcon, null),
|
|
308
|
-
size: "small"
|
|
309
|
-
}, labels.linkExisting({
|
|
310
|
-
canLinkMultiple: props.canLinkMultiple
|
|
311
|
-
})), !props.canCreateEntity && !props.canLinkEntity && createElement(NoLinkPermissionsInfo, null));
|
|
312
|
-
}
|
|
313
|
-
|
|
314
|
-
const container$1 = /*#__PURE__*/css({
|
|
315
|
-
display: 'flex',
|
|
316
|
-
border: `1px dashed ${tokens.gray500}`,
|
|
317
|
-
borderRadius: tokens.borderRadiusMedium,
|
|
318
|
-
justifyContent: 'center',
|
|
319
|
-
padding: tokens.spacingXl
|
|
320
|
-
});
|
|
321
|
-
const action = /*#__PURE__*/css({
|
|
322
|
-
textDecoration: 'none',
|
|
323
|
-
fontWeight: 'bold'
|
|
324
|
-
});
|
|
325
|
-
|
|
326
|
-
const testIds$1 = { ...testIds,
|
|
327
|
-
actionsWrapper: 'link-actions-menu-trigger'
|
|
328
|
-
};
|
|
329
|
-
/**
|
|
330
|
-
* Alternative, experimental alternative to <LinkActions /> that is planned to
|
|
331
|
-
* replace the current default LinkActions in reference and media editors.
|
|
332
|
-
*
|
|
333
|
-
* Places both actions to create and link new, as well as link existing, behind
|
|
334
|
-
* one action dropdown and introduces new copy for action labels.
|
|
335
|
-
*/
|
|
336
|
-
|
|
337
|
-
function CombinedLinkActions(props) {
|
|
338
|
-
if (props.isFull) {
|
|
339
|
-
return null; // Don't render link actions if we reached max allowed links.
|
|
340
|
-
} // We don't want to render a spacious container in case there are are already
|
|
341
|
-
// assets linked (in case of entries, always show it) as the border wouldn't be
|
|
342
|
-
// nicely aligned with asset cards.
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
const hideEmptyCard = props.entityType === 'Asset' && !props.isEmpty;
|
|
346
|
-
return createElement("div", {
|
|
347
|
-
className: hideEmptyCard ? '' : container$1
|
|
348
|
-
}, !props.canCreateEntity && !props.canLinkEntity && createElement(NoLinkPermissionsInfo, null), props.entityType === 'Entry' && createElement(CombinedEntryLinkActions, { ...props
|
|
349
|
-
}), props.entityType === 'Asset' && createElement(CombinedAssetLinkActions, { ...props
|
|
350
|
-
}));
|
|
351
|
-
}
|
|
352
|
-
|
|
353
|
-
function CombinedEntryLinkActions(props) {
|
|
354
|
-
if (props.canCreateEntity) {
|
|
355
|
-
return createElement(CreateEntryLinkButton, {
|
|
356
|
-
testId: testIds$1.actionsWrapper,
|
|
357
|
-
disabled: props.isDisabled,
|
|
358
|
-
text: props.combinedActionsLabel || 'Add content',
|
|
359
|
-
contentTypes: props.contentTypes,
|
|
360
|
-
hasPlusIcon: true,
|
|
361
|
-
useExperimentalStyles: true,
|
|
362
|
-
dropdownSettings: {
|
|
363
|
-
position: 'bottom-left'
|
|
364
|
-
},
|
|
365
|
-
onSelect: contentTypeId => {
|
|
366
|
-
return contentTypeId ? props.onCreate(contentTypeId) : Promise.resolve();
|
|
367
|
-
},
|
|
368
|
-
customDropdownItems: props.canLinkEntity ? createElement(Menu.Item, {
|
|
369
|
-
testId: testIds$1.linkExisting,
|
|
370
|
-
onClick: () => {
|
|
371
|
-
props.onLinkExisting();
|
|
372
|
-
}
|
|
373
|
-
}, "Add existing content") : undefined
|
|
374
|
-
});
|
|
375
|
-
} else if (props.canLinkEntity) {
|
|
376
|
-
return createElement(Button, {
|
|
377
|
-
isDisabled: props.isDisabled,
|
|
378
|
-
testId: testIds$1.linkExisting,
|
|
379
|
-
className: action,
|
|
380
|
-
onClick: () => {
|
|
381
|
-
props.onLinkExisting();
|
|
382
|
-
},
|
|
383
|
-
variant: "secondary",
|
|
384
|
-
startIcon: createElement(LinkIcon, null),
|
|
385
|
-
size: "small"
|
|
386
|
-
}, "Add existing content");
|
|
387
|
-
}
|
|
388
|
-
|
|
389
|
-
return null;
|
|
390
|
-
}
|
|
391
|
-
|
|
392
|
-
function CombinedAssetLinkActions(props) {
|
|
393
|
-
const [isOpen, setOpen] = useState(false);
|
|
394
|
-
|
|
395
|
-
if (!props.canLinkEntity || !props.canCreateEntity) {
|
|
396
|
-
if (props.canLinkEntity) {
|
|
397
|
-
return createElement(Button, {
|
|
398
|
-
isDisabled: props.isDisabled,
|
|
399
|
-
testId: testIds$1.linkExisting,
|
|
400
|
-
className: action,
|
|
401
|
-
onClick: () => {
|
|
402
|
-
props.onLinkExisting();
|
|
403
|
-
},
|
|
404
|
-
variant: "secondary",
|
|
405
|
-
startIcon: createElement(PlusIcon, null),
|
|
406
|
-
size: "small"
|
|
407
|
-
}, "Add existing media");
|
|
408
|
-
}
|
|
409
|
-
|
|
410
|
-
if (props.canCreateEntity) {
|
|
411
|
-
return createElement(Button, {
|
|
412
|
-
isDisabled: props.isDisabled,
|
|
413
|
-
testId: testIds$1.createAndLink,
|
|
414
|
-
className: action,
|
|
415
|
-
onClick: () => {
|
|
416
|
-
props.onCreate();
|
|
417
|
-
},
|
|
418
|
-
variant: "secondary",
|
|
419
|
-
startIcon: createElement(PlusIcon, null),
|
|
420
|
-
size: "small"
|
|
421
|
-
}, "Add media");
|
|
422
|
-
}
|
|
423
|
-
|
|
424
|
-
return null;
|
|
425
|
-
} // TODO: If we fully switch to this new layout, make a more generic `CreateEntityLinkButton`
|
|
426
|
-
// that works without content types to cover asset use-case.
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
return createElement(Menu, {
|
|
430
|
-
isOpen: isOpen,
|
|
431
|
-
onClose: () => {
|
|
432
|
-
setOpen(false);
|
|
433
|
-
},
|
|
434
|
-
onOpen: () => {
|
|
435
|
-
setOpen(true);
|
|
436
|
-
}
|
|
437
|
-
}, createElement(Menu.Trigger, null, createElement(Button, {
|
|
438
|
-
endIcon: createElement(ChevronDownIcon, null),
|
|
439
|
-
isDisabled: props.isDisabled,
|
|
440
|
-
testId: testIds$1.actionsWrapper,
|
|
441
|
-
className: action,
|
|
442
|
-
variant: "secondary",
|
|
443
|
-
startIcon: createElement(PlusIcon, null),
|
|
444
|
-
size: "small"
|
|
445
|
-
}, "Add media")), isOpen && createElement(Menu.List, {
|
|
446
|
-
testId: testIds$1.dropdown
|
|
447
|
-
}, createElement(Menu.Item, {
|
|
448
|
-
testId: testIds$1.linkExisting,
|
|
449
|
-
onClick: () => {
|
|
450
|
-
props.onLinkExisting();
|
|
451
|
-
}
|
|
452
|
-
}, "Add existing media"), createElement(Menu.Item, {
|
|
453
|
-
testId: testIds$1.createAndLink,
|
|
454
|
-
onClick: () => {
|
|
455
|
-
props.onCreate();
|
|
456
|
-
}
|
|
457
|
-
}, "Add new media")));
|
|
458
|
-
}
|
|
459
|
-
|
|
460
|
-
const card = /*#__PURE__*/css({
|
|
461
|
-
position: 'relative'
|
|
462
|
-
});
|
|
463
|
-
const squareCard = /*#__PURE__*/css({
|
|
464
|
-
display: 'flex',
|
|
465
|
-
alignItems: 'center',
|
|
466
|
-
width: '135px',
|
|
467
|
-
height: '160px',
|
|
468
|
-
textAlign: 'center'
|
|
469
|
-
});
|
|
470
|
-
|
|
471
|
-
function MissingEntityCard(props) {
|
|
472
|
-
return React__default.createElement(Card, {
|
|
473
|
-
className: card,
|
|
474
|
-
testId: "cf-ui-missing-entry-card"
|
|
475
|
-
}, React__default.createElement(Flex, {
|
|
476
|
-
alignItems: "center",
|
|
477
|
-
justifyContent: "space-between"
|
|
478
|
-
}, React__default.createElement("div", {
|
|
479
|
-
className: props.asSquare ? squareCard : ''
|
|
480
|
-
}, React__default.createElement(SectionHeading, {
|
|
481
|
-
marginBottom: "none"
|
|
482
|
-
}, props.entityType, " is missing or inaccessible")), !props.isDisabled && props.onRemove && React__default.createElement(IconButton, {
|
|
483
|
-
variant: "transparent",
|
|
484
|
-
icon: React__default.createElement(CloseIcon, {
|
|
485
|
-
variant: "muted"
|
|
486
|
-
}),
|
|
487
|
-
"aria-label": "Delete",
|
|
488
|
-
onClick: () => {
|
|
489
|
-
props.onRemove && props.onRemove();
|
|
490
|
-
}
|
|
491
|
-
})));
|
|
492
|
-
}
|
|
493
|
-
|
|
494
|
-
const getContentTypeIds = contentTypes => contentTypes.map(ct => ct.sys.id);
|
|
495
|
-
|
|
496
|
-
async function createEntity(props) {
|
|
497
|
-
if (props.entityType === 'Entry') {
|
|
498
|
-
if (!props.contentTypeId) {
|
|
499
|
-
return {};
|
|
500
|
-
}
|
|
501
|
-
|
|
502
|
-
const {
|
|
503
|
-
entity,
|
|
504
|
-
slide
|
|
505
|
-
} = await props.sdk.navigator.openNewEntry(props.contentTypeId, {
|
|
506
|
-
slideIn: true
|
|
507
|
-
});
|
|
508
|
-
return {
|
|
509
|
-
entity,
|
|
510
|
-
slide
|
|
511
|
-
};
|
|
512
|
-
} else {
|
|
513
|
-
const {
|
|
514
|
-
entity,
|
|
515
|
-
slide
|
|
516
|
-
} = await props.sdk.navigator.openNewAsset({
|
|
517
|
-
slideIn: true
|
|
518
|
-
});
|
|
519
|
-
return {
|
|
520
|
-
entity,
|
|
521
|
-
slide
|
|
522
|
-
};
|
|
523
|
-
}
|
|
524
|
-
}
|
|
525
|
-
async function selectSingleEntity(props) {
|
|
526
|
-
if (props.entityType === 'Entry') {
|
|
527
|
-
return await props.sdk.dialogs.selectSingleEntry({
|
|
528
|
-
locale: props.sdk.field.locale,
|
|
529
|
-
contentTypes: getContentTypeIds(props.editorPermissions.readableContentTypes)
|
|
530
|
-
});
|
|
531
|
-
} else {
|
|
532
|
-
return props.sdk.dialogs.selectSingleAsset({
|
|
533
|
-
locale: props.sdk.field.locale,
|
|
534
|
-
mimetypeGroups: props.editorPermissions.validations.mimetypeGroups
|
|
535
|
-
});
|
|
536
|
-
}
|
|
537
|
-
}
|
|
538
|
-
async function selectMultipleEntities(props) {
|
|
539
|
-
var _props$editorPermissi, _props$editorPermissi2;
|
|
540
|
-
|
|
541
|
-
const value = props.sdk.field.getValue();
|
|
542
|
-
const linkCount = Array.isArray(value) ? value.length : value ? 1 : 0; // TODO: Why not always set `min: 1` by default? Does it make sense to enforce
|
|
543
|
-
// user to select as many entities as the field's "min" requires? What if e.g.
|
|
544
|
-
// "min" is 4 and the user wants to insert 2 entities first, then create 2 new ones?
|
|
545
|
-
|
|
546
|
-
const min = Math.max((((_props$editorPermissi = props.editorPermissions.validations.numberOfLinks) == null ? void 0 : _props$editorPermissi.min) || 1) - linkCount, 1); // TODO: Consider same for max. If e.g. "max" is 4, we disable the button if the
|
|
547
|
-
// user wants to select 5 but we show no information why the button is disabled.
|
|
548
|
-
|
|
549
|
-
const max = (((_props$editorPermissi2 = props.editorPermissions.validations.numberOfLinks) == null ? void 0 : _props$editorPermissi2.max) || +Infinity) - linkCount;
|
|
550
|
-
|
|
551
|
-
if (props.entityType === 'Entry') {
|
|
552
|
-
return await props.sdk.dialogs.selectMultipleEntries({
|
|
553
|
-
locale: props.sdk.field.locale,
|
|
554
|
-
contentTypes: getContentTypeIds(props.editorPermissions.readableContentTypes),
|
|
555
|
-
min,
|
|
556
|
-
max
|
|
557
|
-
});
|
|
558
|
-
} else {
|
|
559
|
-
return props.sdk.dialogs.selectMultipleAssets({
|
|
560
|
-
locale: props.sdk.field.locale,
|
|
561
|
-
mimetypeGroups: props.editorPermissions.validations.mimetypeGroups,
|
|
562
|
-
min,
|
|
563
|
-
max
|
|
564
|
-
});
|
|
565
|
-
}
|
|
566
|
-
}
|
|
567
|
-
|
|
568
|
-
function useLinkActionsProps(props) {
|
|
569
|
-
var _editorPermissions$va;
|
|
570
|
-
|
|
571
|
-
const {
|
|
572
|
-
sdk,
|
|
573
|
-
editorPermissions,
|
|
574
|
-
entityType,
|
|
575
|
-
canLinkMultiple,
|
|
576
|
-
isDisabled,
|
|
577
|
-
actionLabels,
|
|
578
|
-
itemsLength
|
|
579
|
-
} = props;
|
|
580
|
-
const maxLinksCount = (_editorPermissions$va = editorPermissions.validations.numberOfLinks) == null ? void 0 : _editorPermissions$va.max;
|
|
581
|
-
const value = sdk.field.getValue();
|
|
582
|
-
const linkCount = Array.isArray(value) ? value.length : value ? 1 : 0;
|
|
583
|
-
const isFull = !!maxLinksCount && maxLinksCount <= linkCount;
|
|
584
|
-
const isEmpty = linkCount === 0;
|
|
585
|
-
const onCreated = useCallback((entity, index = itemsLength, slide) => {
|
|
586
|
-
props.onCreate(entity.sys.id, index);
|
|
587
|
-
props.onAction && props.onAction({
|
|
588
|
-
type: 'create_and_link',
|
|
589
|
-
entity: entityType,
|
|
590
|
-
entityData: entity,
|
|
591
|
-
slide,
|
|
592
|
-
index
|
|
593
|
-
});
|
|
594
|
-
}, // eslint-disable-next-line react-hooks/exhaustive-deps -- TODO: Evaluate the dependencies
|
|
595
|
-
[entityType, props.onCreate, props.onAction]);
|
|
596
|
-
const onLinkedExisting = useCallback((entities, index = itemsLength) => {
|
|
597
|
-
props.onLink(entities.map(item => item.sys.id), index);
|
|
598
|
-
entities.forEach((entity, i) => {
|
|
599
|
-
props.onAction && props.onAction({
|
|
600
|
-
type: 'select_and_link',
|
|
601
|
-
entity: entityType,
|
|
602
|
-
entityData: entity,
|
|
603
|
-
index: index === undefined ? undefined : index + i
|
|
604
|
-
});
|
|
605
|
-
});
|
|
606
|
-
}, // eslint-disable-next-line react-hooks/exhaustive-deps -- TODO: Evaluate the dependencies
|
|
607
|
-
[entityType, props.onLink, props.onAction]);
|
|
608
|
-
const onCreate = useCallback(async (contentTypeId, index) => {
|
|
609
|
-
const {
|
|
610
|
-
entity,
|
|
611
|
-
slide
|
|
612
|
-
} = await createEntity({
|
|
613
|
-
sdk,
|
|
614
|
-
entityType,
|
|
615
|
-
contentTypeId
|
|
616
|
-
});
|
|
617
|
-
|
|
618
|
-
if (!entity) {
|
|
619
|
-
return;
|
|
620
|
-
}
|
|
621
|
-
|
|
622
|
-
onCreated(entity, index, slide);
|
|
623
|
-
}, [sdk, entityType, onCreated]);
|
|
624
|
-
const onLinkExisting = useCallback(async index => {
|
|
625
|
-
const entity = await selectSingleEntity({
|
|
626
|
-
sdk,
|
|
627
|
-
entityType,
|
|
628
|
-
editorPermissions
|
|
629
|
-
});
|
|
630
|
-
|
|
631
|
-
if (!entity) {
|
|
632
|
-
return;
|
|
633
|
-
}
|
|
634
|
-
|
|
635
|
-
onLinkedExisting([entity], index);
|
|
636
|
-
}, // eslint-disable-next-line react-hooks/exhaustive-deps -- TODO: Evaluate the dependencies
|
|
637
|
-
[sdk, entityType, onLinkedExisting]);
|
|
638
|
-
const onLinkSeveralExisting = useCallback(async index => {
|
|
639
|
-
const entities = await selectMultipleEntities({
|
|
640
|
-
sdk,
|
|
641
|
-
entityType,
|
|
642
|
-
editorPermissions
|
|
643
|
-
});
|
|
644
|
-
|
|
645
|
-
if (!entities || entities.length === 0) {
|
|
646
|
-
return;
|
|
647
|
-
}
|
|
648
|
-
|
|
649
|
-
onLinkedExisting(entities, index);
|
|
650
|
-
}, // eslint-disable-next-line react-hooks/exhaustive-deps -- TODO: Evaluate the dependencies
|
|
651
|
-
[sdk, entityType, onLinkedExisting]); // FIXME: The memoization might rerun every time due to the always changing callback identities above
|
|
652
|
-
|
|
653
|
-
return useMemo(() => ({
|
|
654
|
-
entityType,
|
|
655
|
-
canLinkMultiple,
|
|
656
|
-
isDisabled,
|
|
657
|
-
isEmpty,
|
|
658
|
-
isFull,
|
|
659
|
-
canCreateEntity: editorPermissions.canCreateEntity,
|
|
660
|
-
canLinkEntity: editorPermissions.canLinkEntity,
|
|
661
|
-
contentTypes: editorPermissions.creatableContentTypes,
|
|
662
|
-
onCreate,
|
|
663
|
-
onLinkExisting: canLinkMultiple ? onLinkSeveralExisting : onLinkExisting,
|
|
664
|
-
actionLabels,
|
|
665
|
-
onCreated,
|
|
666
|
-
onLinkedExisting,
|
|
667
|
-
itemsLength
|
|
668
|
-
}), // eslint-disable-next-line react-hooks/exhaustive-deps -- TODO: Evaluate the dependencies
|
|
669
|
-
[entityType, canLinkMultiple, isDisabled, isEmpty, isFull, editorPermissions.canCreateEntity, editorPermissions.canLinkEntity, actionLabels, // eslint-disable-next-line react-hooks/exhaustive-deps -- TODO: Evaluate the dependencies
|
|
670
|
-
editorPermissions.creatableContentTypes.map(ct => ct.sys.id).join(':'), onCreate, onLinkExisting, onLinkSeveralExisting, onCreated, onLinkedExisting, itemsLength]);
|
|
671
|
-
}
|
|
672
|
-
function LinkEntityActions({
|
|
673
|
-
renderCustomActions,
|
|
674
|
-
...props
|
|
675
|
-
}) {
|
|
676
|
-
return renderCustomActions ? renderCustomActions(props) : createElement(LinkActions, { ...props
|
|
677
|
-
});
|
|
678
|
-
}
|
|
679
|
-
function CombinedLinkEntityActions({
|
|
680
|
-
renderCustomActions,
|
|
681
|
-
...props
|
|
682
|
-
}) {
|
|
683
|
-
return renderCustomActions ? renderCustomActions(props) : createElement(CombinedLinkActions, { ...props
|
|
684
|
-
});
|
|
685
|
-
}
|
|
686
|
-
|
|
687
|
-
// eslint-disable-next-line -- TODO: describe this disable no-restricted-imports
|
|
688
|
-
/**
|
|
689
|
-
* @param {Date|string} date A valid constructor argument for moment()
|
|
690
|
-
* @param {boolean=} short Render only Today/Tomorrow/Yesterday if valid. Defaults to false
|
|
691
|
-
*/
|
|
692
|
-
|
|
693
|
-
const formatDate = (date, short) => {
|
|
694
|
-
switch (moment().startOf('day').diff(moment(date).startOf('day'), 'days')) {
|
|
695
|
-
case 0:
|
|
696
|
-
return short ? 'Today' : `Today, ${moment(date).format('DD MMM YYYY')}`;
|
|
697
|
-
|
|
698
|
-
case -1:
|
|
699
|
-
return short ? 'Tomorrow' : `Tomorrow, ${moment(date).format('DD MMM YYYY')}`;
|
|
700
|
-
|
|
701
|
-
case 1:
|
|
702
|
-
return short ? 'Yesterday' : `Yesterday, ${moment(date).format('DD MMM YYYY')}`;
|
|
703
|
-
|
|
704
|
-
default:
|
|
705
|
-
return moment(date).format('ddd, DD MMM YYYY');
|
|
706
|
-
}
|
|
707
|
-
};
|
|
708
|
-
/**
|
|
709
|
-
* Returns the time portion of a date in the local time in the format H:MM AM/PM
|
|
710
|
-
*
|
|
711
|
-
* == Examples
|
|
712
|
-
* * `T15:36:45.000Z` => 3:36 PM (if in +0:00 offset)
|
|
713
|
-
*/
|
|
714
|
-
|
|
715
|
-
const formatTime = date => {
|
|
716
|
-
return moment.utc(date).local().format('h:mm A');
|
|
717
|
-
};
|
|
718
|
-
const formatDateAndTime = (date, short) => {
|
|
719
|
-
return `${formatDate(date, short)} at ${formatTime(date)}`;
|
|
720
|
-
};
|
|
721
|
-
|
|
722
|
-
const getScheduleTooltipContent = ({
|
|
723
|
-
job,
|
|
724
|
-
jobsCount
|
|
725
|
-
}) => {
|
|
726
|
-
return `Will ${job.action.toLowerCase()} ${formatDateAndTime(job.scheduledFor.datetime).toLowerCase()}
|
|
727
|
-
${jobsCount > 1 ? `+ ${jobsCount - 1} more` : ''}`;
|
|
728
|
-
};
|
|
729
|
-
const ScheduleTooltip = ({
|
|
730
|
-
job,
|
|
731
|
-
jobsCount,
|
|
732
|
-
children
|
|
733
|
-
}) => {
|
|
734
|
-
return React__default.createElement(Tooltip, {
|
|
735
|
-
placement: "top",
|
|
736
|
-
testId: job.sys.id,
|
|
737
|
-
as: "div",
|
|
738
|
-
content: getScheduleTooltipContent({
|
|
739
|
-
job,
|
|
740
|
-
jobsCount
|
|
741
|
-
})
|
|
742
|
-
}, children);
|
|
743
|
-
};
|
|
744
|
-
|
|
745
|
-
const ScheduledIconWithTooltip = ({
|
|
746
|
-
entityType,
|
|
747
|
-
entityId,
|
|
748
|
-
getEntityScheduledActions,
|
|
749
|
-
children
|
|
750
|
-
}) => {
|
|
751
|
-
const [status, setStatus] = React__default.useState({
|
|
752
|
-
type: 'loading'
|
|
753
|
-
});
|
|
754
|
-
React__default.useEffect(() => {
|
|
755
|
-
getEntityScheduledActions(entityType, entityId).then(data => {
|
|
756
|
-
setStatus({
|
|
757
|
-
type: 'loaded',
|
|
758
|
-
jobs: data
|
|
759
|
-
});
|
|
760
|
-
}).catch(e => {
|
|
761
|
-
setStatus({
|
|
762
|
-
type: 'error',
|
|
763
|
-
error: e
|
|
764
|
-
});
|
|
765
|
-
}); // This should only be ever called once. Following the eslint hint to add used
|
|
766
|
-
// dependencies will cause page freeze (infinite loop)
|
|
767
|
-
// eslint-disable-next-line -- TODO: describe this disable
|
|
768
|
-
}, []);
|
|
769
|
-
|
|
770
|
-
if (status.type === 'loading' || status.type === 'error') {
|
|
771
|
-
return null;
|
|
772
|
-
}
|
|
773
|
-
|
|
774
|
-
const jobs = status.jobs ?? [];
|
|
775
|
-
|
|
776
|
-
if (jobs.length === 0) {
|
|
777
|
-
return null;
|
|
778
|
-
}
|
|
779
|
-
|
|
780
|
-
const mostRelevantJob = jobs[0];
|
|
781
|
-
return React__default.createElement(ScheduleTooltip, {
|
|
782
|
-
job: mostRelevantJob,
|
|
783
|
-
jobsCount: jobs.length
|
|
784
|
-
}, children);
|
|
785
|
-
};
|
|
786
|
-
|
|
787
|
-
const dimensions = {
|
|
788
|
-
width: 70,
|
|
789
|
-
height: 70
|
|
790
|
-
};
|
|
791
|
-
function AssetThumbnail(props) {
|
|
792
|
-
return React__default.createElement("img", {
|
|
793
|
-
alt: props.file.fileName,
|
|
794
|
-
src: `${props.file.url}?w=${dimensions.width}&h=${dimensions.height}&fit=thumb`,
|
|
795
|
-
height: dimensions.height,
|
|
796
|
-
width: dimensions.width
|
|
797
|
-
});
|
|
798
|
-
}
|
|
799
|
-
|
|
800
|
-
const globalQueue = /*#__PURE__*/new PQueue({
|
|
801
|
-
concurrency: 50
|
|
802
|
-
});
|
|
803
|
-
class UnsupportedError extends Error {
|
|
804
|
-
constructor(message) {
|
|
805
|
-
super(message);
|
|
806
|
-
this.isUnsupportedError = void 0;
|
|
807
|
-
this.isUnsupportedError = true;
|
|
808
|
-
}
|
|
809
|
-
|
|
810
|
-
}
|
|
811
|
-
function isUnsupportedError(value) {
|
|
812
|
-
return typeof value === 'object' && (value == null ? void 0 : value.isUnsupportedError) === true;
|
|
813
|
-
}
|
|
814
|
-
|
|
815
|
-
const isEntityQueryKey = queryKey => {
|
|
816
|
-
return Array.isArray(queryKey) && (queryKey[0] === 'Entry' || queryKey[0] === 'Asset') && queryKey.length === 4;
|
|
817
|
-
};
|
|
818
|
-
|
|
819
|
-
async function fetchContentfulEntry(params) {
|
|
820
|
-
const {
|
|
821
|
-
urn,
|
|
822
|
-
fetch,
|
|
823
|
-
options
|
|
824
|
-
} = params;
|
|
825
|
-
const resourceId = urn.split(':', 6)[5];
|
|
826
|
-
const [, spaceId,, entryId] = resourceId.split('/');
|
|
827
|
-
const environmentId = 'master';
|
|
828
|
-
const [space, entry] = await Promise.all([fetch(['space', spaceId], ({
|
|
829
|
-
cmaClient
|
|
830
|
-
}) => cmaClient.space.get({
|
|
831
|
-
spaceId
|
|
832
|
-
}), options), fetch(['entry', spaceId, environmentId, entryId], ({
|
|
833
|
-
cmaClient
|
|
834
|
-
}) => cmaClient.entry.get({
|
|
835
|
-
spaceId,
|
|
836
|
-
environmentId,
|
|
837
|
-
entryId
|
|
838
|
-
}), options)]);
|
|
839
|
-
const contentTypeId = entry.sys.contentType.sys.id;
|
|
840
|
-
const [contentType, defaultLocaleCode] = await Promise.all([fetch(['contentType', spaceId, environmentId, contentTypeId], ({
|
|
841
|
-
cmaClient
|
|
842
|
-
}) => cmaClient.contentType.get({
|
|
843
|
-
contentTypeId,
|
|
844
|
-
spaceId,
|
|
845
|
-
environmentId
|
|
846
|
-
}), options), fetch(['defaultLocale', spaceId, environmentId], async ({
|
|
847
|
-
cmaClient
|
|
848
|
-
}) => {
|
|
849
|
-
var _locales$items$find;
|
|
850
|
-
|
|
851
|
-
const locales = await cmaClient.locale.getMany({
|
|
852
|
-
spaceId,
|
|
853
|
-
environmentId,
|
|
854
|
-
query: {
|
|
855
|
-
limit: 100
|
|
856
|
-
}
|
|
857
|
-
});
|
|
858
|
-
const defaultLocaleCode = (_locales$items$find = locales.items.find(locale => locale.default)) == null ? void 0 : _locales$items$find.code;
|
|
859
|
-
return defaultLocaleCode;
|
|
860
|
-
}, options)]);
|
|
861
|
-
return {
|
|
862
|
-
defaultLocaleCode,
|
|
863
|
-
resource: entry,
|
|
864
|
-
space: space,
|
|
865
|
-
contentType: contentType
|
|
866
|
-
};
|
|
867
|
-
}
|
|
868
|
-
|
|
869
|
-
const [InternalServiceProvider, useFetch, useEntityLoader, useCurrentIds] = /*#__PURE__*/constate(function useInitServices(props) {
|
|
870
|
-
const currentSpaceId = props.sdk.ids.space;
|
|
871
|
-
const currentEnvironmentId = props.sdk.ids.environmentAlias ?? props.sdk.ids.environment;
|
|
872
|
-
const environmentIds = useMemo(() => [props.sdk.ids.environmentAlias, props.sdk.ids.environment], [props.sdk.ids.environmentAlias, props.sdk.ids.environment]);
|
|
873
|
-
const queryClient = useQueryClient();
|
|
874
|
-
const queryCache = queryClient.getQueryCache();
|
|
875
|
-
const entityChangeUnsubscribers = useRef({});
|
|
876
|
-
const cmaClient = useMemo(() => createClient({
|
|
877
|
-
apiAdapter: props.sdk.cmaAdapter
|
|
878
|
-
}, {
|
|
879
|
-
type: 'plain'
|
|
880
|
-
}), [props.sdk.cmaAdapter]);
|
|
881
|
-
const queryQueue = useMemo(() => {
|
|
882
|
-
if (props.queryConcurrency) {
|
|
883
|
-
return new PQueue({
|
|
884
|
-
concurrency: props.queryConcurrency
|
|
885
|
-
});
|
|
886
|
-
}
|
|
887
|
-
|
|
888
|
-
return globalQueue;
|
|
889
|
-
}, [props.queryConcurrency]);
|
|
890
|
-
const fetch = useCallback(function fetch(queryKey, fn, options = {}) {
|
|
891
|
-
const {
|
|
892
|
-
priority,
|
|
893
|
-
...queryOptions
|
|
894
|
-
} = options;
|
|
895
|
-
return queryClient.fetchQuery(queryKey, () => queryQueue.add(() => fn({
|
|
896
|
-
cmaClient
|
|
897
|
-
}), {
|
|
898
|
-
priority
|
|
899
|
-
}), queryOptions);
|
|
900
|
-
}, [queryClient, queryQueue, cmaClient]);
|
|
901
|
-
const getEntity = useCallback(function getEntity(entityType, entityId, options) {
|
|
902
|
-
const spaceId = (options == null ? void 0 : options.spaceId) ?? currentSpaceId;
|
|
903
|
-
const environmentId = (options == null ? void 0 : options.environmentId) ?? currentEnvironmentId;
|
|
904
|
-
const queryKey = [entityType, entityId, spaceId, environmentId];
|
|
905
|
-
return fetch(queryKey, ({
|
|
906
|
-
cmaClient
|
|
907
|
-
}) => {
|
|
908
|
-
if (entityType === 'Entry') {
|
|
909
|
-
return cmaClient.entry.get({
|
|
910
|
-
entryId: entityId,
|
|
911
|
-
spaceId,
|
|
912
|
-
environmentId
|
|
913
|
-
});
|
|
914
|
-
}
|
|
915
|
-
|
|
916
|
-
if (entityType === 'Asset') {
|
|
917
|
-
return cmaClient.asset.get({
|
|
918
|
-
assetId: entityId,
|
|
919
|
-
spaceId,
|
|
920
|
-
environmentId
|
|
921
|
-
});
|
|
922
|
-
}
|
|
923
|
-
|
|
924
|
-
throw new UnsupportedError('Unsupported entity type');
|
|
925
|
-
}, options);
|
|
926
|
-
}, [fetch, currentSpaceId, currentEnvironmentId]);
|
|
927
|
-
/**
|
|
928
|
-
* Fetch all scheduled actions for a given entity.
|
|
929
|
-
* This function fetches all schedules for all entries and then returns
|
|
930
|
-
* a filtered result based on the entityID provided.
|
|
931
|
-
*
|
|
932
|
-
* The result is then reused/cached for subsequent calls to this function.
|
|
933
|
-
*/
|
|
934
|
-
|
|
935
|
-
const getEntityScheduledActions = useCallback(function getEntityScheduledActions(entityType, entityId, options) {
|
|
936
|
-
// This is fixed to force the cache to reuse previous results
|
|
937
|
-
const fixedEntityCacheId = 'scheduledActionEntityId'; // A space+environment combo can only have up to 500 scheduled actions
|
|
938
|
-
// With this request we fetch all schedules and can reuse the results.
|
|
939
|
-
// See https://www.contentful.com/developers/docs/references/content-management-api/#/reference/scheduled-actions/limitations
|
|
940
|
-
|
|
941
|
-
const maxScheduledActions = 500;
|
|
942
|
-
const spaceId = (options == null ? void 0 : options.spaceId) ?? currentSpaceId;
|
|
943
|
-
const environmentId = (options == null ? void 0 : options.environmentId) ?? currentEnvironmentId;
|
|
944
|
-
const queryKey = ['scheduled-actions', entityType, fixedEntityCacheId, spaceId, environmentId]; // Fetch + Filter by entity ID in the end
|
|
945
|
-
|
|
946
|
-
return fetch(queryKey, async ({
|
|
947
|
-
cmaClient
|
|
948
|
-
}) => {
|
|
949
|
-
const response = await cmaClient.scheduledActions.getMany({
|
|
950
|
-
spaceId,
|
|
951
|
-
query: {
|
|
952
|
-
'environment.sys.id': environmentId,
|
|
953
|
-
'sys.status[in]': 'scheduled',
|
|
954
|
-
order: 'scheduledFor.datetime',
|
|
955
|
-
limit: maxScheduledActions
|
|
956
|
-
}
|
|
957
|
-
});
|
|
958
|
-
return response.items;
|
|
959
|
-
}, options).then(items => items.filter(action => action.entity.sys.id === entityId));
|
|
960
|
-
}, [fetch, currentSpaceId, currentEnvironmentId]);
|
|
961
|
-
const getResource = useCallback(function getResource(resourceType, urn, options) {
|
|
962
|
-
const queryKey = ['Resource', resourceType, urn];
|
|
963
|
-
return fetch(queryKey, () => {
|
|
964
|
-
if (resourceType === 'Contentful:Entry') {
|
|
965
|
-
return fetchContentfulEntry({
|
|
966
|
-
fetch,
|
|
967
|
-
urn,
|
|
968
|
-
options
|
|
969
|
-
});
|
|
970
|
-
}
|
|
971
|
-
|
|
972
|
-
throw new UnsupportedError('Unsupported resource type');
|
|
973
|
-
}, options);
|
|
974
|
-
}, [fetch]);
|
|
975
|
-
const isSameSpaceEntityQueryKey = useCallback(queryKey => {
|
|
976
|
-
const isEntityKey = isEntityQueryKey(queryKey);
|
|
977
|
-
const isSameSpaceEntityKey = isEntityKey && queryKey[2] === currentSpaceId && environmentIds.includes(queryKey[3]);
|
|
978
|
-
return isSameSpaceEntityKey;
|
|
979
|
-
}, [currentSpaceId, environmentIds]); // @ts-expect-error ...
|
|
980
|
-
|
|
981
|
-
const onEntityChanged = props.sdk.space.onEntityChanged;
|
|
982
|
-
const onSlideInNavigation = props.sdk.navigator.onSlideInNavigation;
|
|
983
|
-
useEffect(() => {
|
|
984
|
-
function findSameSpaceQueries() {
|
|
985
|
-
return queryCache.findAll({
|
|
986
|
-
type: 'active',
|
|
987
|
-
predicate: query => isSameSpaceEntityQueryKey(query.queryKey)
|
|
988
|
-
});
|
|
989
|
-
}
|
|
990
|
-
|
|
991
|
-
if (typeof onEntityChanged !== 'function') {
|
|
992
|
-
return onSlideInNavigation(({
|
|
993
|
-
oldSlideLevel,
|
|
994
|
-
newSlideLevel
|
|
995
|
-
}) => {
|
|
996
|
-
if (oldSlideLevel > newSlideLevel) {
|
|
997
|
-
findSameSpaceQueries().forEach(query => {
|
|
998
|
-
// automatically refetches the query
|
|
999
|
-
void queryClient.invalidateQueries(query.queryKey);
|
|
1000
|
-
});
|
|
1001
|
-
}
|
|
1002
|
-
});
|
|
1003
|
-
}
|
|
1004
|
-
|
|
1005
|
-
const subscribeQuery = ({
|
|
1006
|
-
queryKey,
|
|
1007
|
-
queryHash
|
|
1008
|
-
}) => {
|
|
1009
|
-
const [entityType, entityId] = queryKey;
|
|
1010
|
-
entityChangeUnsubscribers.current[queryHash] = onEntityChanged(entityType, entityId, data => {
|
|
1011
|
-
queryClient.setQueryData(queryKey, data);
|
|
1012
|
-
});
|
|
1013
|
-
};
|
|
1014
|
-
|
|
1015
|
-
findSameSpaceQueries().forEach(subscribeQuery);
|
|
1016
|
-
const unsubscribe = queryCache.subscribe(event => {
|
|
1017
|
-
if (!event) {
|
|
1018
|
-
return;
|
|
1019
|
-
}
|
|
1020
|
-
|
|
1021
|
-
const {
|
|
1022
|
-
type,
|
|
1023
|
-
query
|
|
1024
|
-
} = event;
|
|
1025
|
-
const {
|
|
1026
|
-
queryKey,
|
|
1027
|
-
queryHash
|
|
1028
|
-
} = query;
|
|
1029
|
-
|
|
1030
|
-
if (!isSameSpaceEntityQueryKey(queryKey)) {
|
|
1031
|
-
return;
|
|
1032
|
-
}
|
|
1033
|
-
|
|
1034
|
-
if (type === 'added') {
|
|
1035
|
-
subscribeQuery(query);
|
|
1036
|
-
}
|
|
1037
|
-
|
|
1038
|
-
if (type === 'removed') {
|
|
1039
|
-
var _entityChangeUnsubscr, _entityChangeUnsubscr2;
|
|
1040
|
-
|
|
1041
|
-
// calling unsubscribe
|
|
1042
|
-
(_entityChangeUnsubscr = (_entityChangeUnsubscr2 = entityChangeUnsubscribers.current)[queryHash]) == null ? void 0 : _entityChangeUnsubscr.call(_entityChangeUnsubscr2);
|
|
1043
|
-
}
|
|
1044
|
-
});
|
|
1045
|
-
return () => {
|
|
1046
|
-
unsubscribe();
|
|
1047
|
-
Object.values(entityChangeUnsubscribers.current).forEach(off => off());
|
|
1048
|
-
entityChangeUnsubscribers.current = {};
|
|
1049
|
-
};
|
|
1050
|
-
}, [onEntityChanged, queryCache, isSameSpaceEntityQueryKey, queryClient, getEntity, onSlideInNavigation]);
|
|
1051
|
-
return {
|
|
1052
|
-
ids: props.sdk.ids,
|
|
1053
|
-
cmaClient,
|
|
1054
|
-
fetch,
|
|
1055
|
-
getResource,
|
|
1056
|
-
getEntity,
|
|
1057
|
-
getEntityScheduledActions
|
|
1058
|
-
};
|
|
1059
|
-
}, ({
|
|
1060
|
-
fetch
|
|
1061
|
-
}) => fetch, ({
|
|
1062
|
-
getResource,
|
|
1063
|
-
getEntity,
|
|
1064
|
-
getEntityScheduledActions
|
|
1065
|
-
}) => ({
|
|
1066
|
-
getResource,
|
|
1067
|
-
getEntity,
|
|
1068
|
-
getEntityScheduledActions
|
|
1069
|
-
}), ({
|
|
1070
|
-
ids
|
|
1071
|
-
}) => ({
|
|
1072
|
-
environment: ids.environmentAlias ?? ids.environment,
|
|
1073
|
-
space: ids.space
|
|
1074
|
-
}));
|
|
1075
|
-
function useEntity(entityType, entityId, options) {
|
|
1076
|
-
const {
|
|
1077
|
-
space,
|
|
1078
|
-
environment
|
|
1079
|
-
} = useCurrentIds();
|
|
1080
|
-
const {
|
|
1081
|
-
getEntity
|
|
1082
|
-
} = useEntityLoader();
|
|
1083
|
-
const queryKey = [entityType, entityId, (options == null ? void 0 : options.spaceId) ?? space, (options == null ? void 0 : options.environmentId) ?? environment];
|
|
1084
|
-
const {
|
|
1085
|
-
status,
|
|
1086
|
-
data
|
|
1087
|
-
} = useQuery(queryKey, () => getEntity(entityType, entityId, options), {
|
|
1088
|
-
enabled: options == null ? void 0 : options.enabled
|
|
1089
|
-
});
|
|
1090
|
-
return {
|
|
1091
|
-
status,
|
|
1092
|
-
data
|
|
1093
|
-
};
|
|
1094
|
-
}
|
|
1095
|
-
function useResource(resourceType, urn, options) {
|
|
1096
|
-
const queryKey = ['Resource', resourceType, urn];
|
|
1097
|
-
const {
|
|
1098
|
-
getResource
|
|
1099
|
-
} = useEntityLoader();
|
|
1100
|
-
const {
|
|
1101
|
-
status,
|
|
1102
|
-
data,
|
|
1103
|
-
error
|
|
1104
|
-
} = useQuery(queryKey, () => getResource(resourceType, urn, options), {
|
|
1105
|
-
enabled: options == null ? void 0 : options.enabled
|
|
1106
|
-
});
|
|
1107
|
-
return {
|
|
1108
|
-
status,
|
|
1109
|
-
data,
|
|
1110
|
-
error
|
|
1111
|
-
};
|
|
1112
|
-
}
|
|
1113
|
-
|
|
1114
|
-
function EntityProvider({
|
|
1115
|
-
children,
|
|
1116
|
-
...props
|
|
1117
|
-
}) {
|
|
1118
|
-
const reactQueryClient = useMemo(() => {
|
|
1119
|
-
const queryCache = new QueryCache();
|
|
1120
|
-
const queryClient = new QueryClient({
|
|
1121
|
-
queryCache,
|
|
1122
|
-
defaultOptions: {
|
|
1123
|
-
queries: {
|
|
1124
|
-
useErrorBoundary: false,
|
|
1125
|
-
refetchOnWindowFocus: false,
|
|
1126
|
-
refetchOnReconnect: true,
|
|
1127
|
-
refetchOnMount: false,
|
|
1128
|
-
staleTime: Infinity,
|
|
1129
|
-
retry: false
|
|
1130
|
-
}
|
|
1131
|
-
}
|
|
1132
|
-
});
|
|
1133
|
-
return queryClient;
|
|
1134
|
-
}, []);
|
|
1135
|
-
return React__default.createElement(QueryClientProvider, {
|
|
1136
|
-
client: reactQueryClient
|
|
1137
|
-
}, React__default.createElement(InternalServiceProvider, { ...props
|
|
1138
|
-
}, children));
|
|
1139
|
-
}
|
|
1140
|
-
|
|
1141
|
-
function ReferenceEditor(props) {
|
|
1142
|
-
return createElement(EntityProvider, {
|
|
1143
|
-
sdk: props.sdk
|
|
1144
|
-
}, createElement(FieldConnector, {
|
|
1145
|
-
throttle: 0,
|
|
1146
|
-
field: props.sdk.field,
|
|
1147
|
-
isInitiallyDisabled: props.isInitiallyDisabled,
|
|
1148
|
-
isEqualValues: (value1, value2) => {
|
|
1149
|
-
return deepEqual(value1, value2);
|
|
1150
|
-
}
|
|
1151
|
-
}, props.children));
|
|
1152
|
-
}
|
|
1153
|
-
ReferenceEditor.defaultProps = {
|
|
1154
|
-
isInitiallyDisabled: true,
|
|
1155
|
-
hasCardEditActions: true
|
|
1156
|
-
};
|
|
1157
|
-
|
|
1158
|
-
function fromFieldValidations(field) {
|
|
1159
|
-
var _field$items;
|
|
1160
|
-
|
|
1161
|
-
// eslint-disable-next-line -- TODO: describe this disable @typescript-eslint/no-explicit-any
|
|
1162
|
-
const validations = [...field.validations, ...(((_field$items = field.items) == null ? void 0 : _field$items.validations) ?? [])];
|
|
1163
|
-
const linkContentTypeValidations = validations.find(v => 'linkContentType' in v);
|
|
1164
|
-
const linkMimetypeGroupValidations = validations.find(v => 'linkMimetypeGroup' in v);
|
|
1165
|
-
const sizeValidations = validations.find(v => 'size' in v);
|
|
1166
|
-
const size = sizeValidations && sizeValidations.size || {};
|
|
1167
|
-
const min = size.min;
|
|
1168
|
-
const max = size.max;
|
|
1169
|
-
let numberOfLinks = undefined;
|
|
1170
|
-
|
|
1171
|
-
if (isNumber(min) && isNumber(max)) {
|
|
1172
|
-
numberOfLinks = {
|
|
1173
|
-
type: 'min-max',
|
|
1174
|
-
min,
|
|
1175
|
-
max
|
|
1176
|
-
};
|
|
1177
|
-
} else if (isNumber(min)) {
|
|
1178
|
-
numberOfLinks = {
|
|
1179
|
-
type: 'min',
|
|
1180
|
-
min,
|
|
1181
|
-
max: undefined
|
|
1182
|
-
};
|
|
1183
|
-
} else if (isNumber(max)) {
|
|
1184
|
-
numberOfLinks = {
|
|
1185
|
-
type: 'max',
|
|
1186
|
-
max,
|
|
1187
|
-
min: undefined
|
|
1188
|
-
};
|
|
1189
|
-
}
|
|
1190
|
-
|
|
1191
|
-
const result = {
|
|
1192
|
-
contentTypes: (linkContentTypeValidations == null ? void 0 : linkContentTypeValidations.linkContentType) ?? undefined,
|
|
1193
|
-
mimetypeGroups: (linkMimetypeGroupValidations == null ? void 0 : linkMimetypeGroupValidations.linkMimetypeGroup) ?? undefined,
|
|
1194
|
-
numberOfLinks // todo: there are multiple BE problems that need to be solved first, for now we don't want to apply size constraints
|
|
1195
|
-
// linkedFileSize: findValidation(field, 'assetFileSize', {}),
|
|
1196
|
-
// linkedImageDimensions: findValidation(field, 'assetImageDimensions', {})
|
|
1197
|
-
|
|
1198
|
-
};
|
|
1199
|
-
return result;
|
|
1200
|
-
}
|
|
1201
|
-
|
|
1202
|
-
const AllowActionsOnContentType = () => Promise.resolve(true);
|
|
1203
|
-
|
|
1204
|
-
function useAccessApi(accessApi) {
|
|
1205
|
-
const canPerformAction = accessApi.can;
|
|
1206
|
-
const canPerformActionOnEntryOfType = accessApi.canPerformActionOnEntryOfType ?? AllowActionsOnContentType;
|
|
1207
|
-
return {
|
|
1208
|
-
canPerformAction,
|
|
1209
|
-
canPerformActionOnEntryOfType
|
|
1210
|
-
};
|
|
1211
|
-
}
|
|
1212
|
-
|
|
1213
|
-
async function filter(arr, predicate) {
|
|
1214
|
-
// intentionally parallel as we assume it's cached in the implementation of the access api
|
|
1215
|
-
const fail = Symbol();
|
|
1216
|
-
const results = await Promise.all(arr.map(async item => (await predicate(item)) ? item : fail));
|
|
1217
|
-
return results.filter(x => x !== fail);
|
|
1218
|
-
}
|
|
1219
|
-
|
|
1220
|
-
function useContentTypePermissions(props) {
|
|
1221
|
-
const availableContentTypes = useMemo(() => {
|
|
1222
|
-
if (props.entityType === 'Asset') {
|
|
1223
|
-
return [];
|
|
1224
|
-
}
|
|
1225
|
-
|
|
1226
|
-
if (props.validations.contentTypes) {
|
|
1227
|
-
return props.allContentTypes.filter(ct => {
|
|
1228
|
-
var _props$validations$co;
|
|
1229
|
-
|
|
1230
|
-
return (_props$validations$co = props.validations.contentTypes) == null ? void 0 : _props$validations$co.includes(ct.sys.id);
|
|
1231
|
-
});
|
|
1232
|
-
}
|
|
1233
|
-
|
|
1234
|
-
return props.allContentTypes;
|
|
1235
|
-
}, [props.allContentTypes, props.validations.contentTypes, props.entityType]);
|
|
1236
|
-
const [creatableContentTypes, setCreatableContentTypes] = useState(availableContentTypes);
|
|
1237
|
-
const [readableContentTypes, setReadableContentTypes] = useState(availableContentTypes);
|
|
1238
|
-
const {
|
|
1239
|
-
canPerformActionOnEntryOfType
|
|
1240
|
-
} = useAccessApi(props.sdk.access);
|
|
1241
|
-
useEffect(() => {
|
|
1242
|
-
function getContentTypes(action) {
|
|
1243
|
-
return filter(availableContentTypes, ct => canPerformActionOnEntryOfType(action, ct.sys.id));
|
|
1244
|
-
}
|
|
1245
|
-
|
|
1246
|
-
async function checkContentTypeAccess() {
|
|
1247
|
-
const creatable = await getContentTypes('create');
|
|
1248
|
-
const readable = await getContentTypes('read');
|
|
1249
|
-
setCreatableContentTypes(creatable);
|
|
1250
|
-
setReadableContentTypes(readable);
|
|
1251
|
-
}
|
|
1252
|
-
|
|
1253
|
-
void checkContentTypeAccess(); // eslint-disable-next-line react-hooks/exhaustive-deps -- TODO: Evaluate the dependencies
|
|
1254
|
-
}, [availableContentTypes]);
|
|
1255
|
-
return {
|
|
1256
|
-
creatableContentTypes,
|
|
1257
|
-
readableContentTypes,
|
|
1258
|
-
availableContentTypes
|
|
1259
|
-
};
|
|
1260
|
-
}
|
|
1261
|
-
|
|
1262
|
-
function useEditorPermissions(props) {
|
|
1263
|
-
const {
|
|
1264
|
-
sdk,
|
|
1265
|
-
entityType,
|
|
1266
|
-
parameters
|
|
1267
|
-
} = props;
|
|
1268
|
-
const validations = useMemo(() => fromFieldValidations(props.sdk.field), [props.sdk.field]);
|
|
1269
|
-
const [canCreateEntity, setCanCreateEntity] = useState(true);
|
|
1270
|
-
const [canLinkEntity, setCanLinkEntity] = useState(true);
|
|
1271
|
-
const {
|
|
1272
|
-
creatableContentTypes,
|
|
1273
|
-
readableContentTypes,
|
|
1274
|
-
availableContentTypes
|
|
1275
|
-
} = useContentTypePermissions({ ...props,
|
|
1276
|
-
validations
|
|
1277
|
-
});
|
|
1278
|
-
const {
|
|
1279
|
-
canPerformAction
|
|
1280
|
-
} = useAccessApi(sdk.access);
|
|
1281
|
-
useEffect(() => {
|
|
1282
|
-
if (parameters.instance.showCreateEntityAction === false) {
|
|
1283
|
-
setCanCreateEntity(false);
|
|
1284
|
-
return;
|
|
1285
|
-
}
|
|
1286
|
-
|
|
1287
|
-
async function checkCreateAccess() {
|
|
1288
|
-
if (entityType === 'Asset') {
|
|
1289
|
-
// Hardcoded `true` value following https://contentful.atlassian.net/browse/DANTE-486
|
|
1290
|
-
// TODO: refine permissions check in order to account for tags in rules
|
|
1291
|
-
const canCreate = (await canPerformAction('create', 'Asset')) || true;
|
|
1292
|
-
setCanCreateEntity(canCreate);
|
|
1293
|
-
}
|
|
1294
|
-
|
|
1295
|
-
if (entityType === 'Entry') {
|
|
1296
|
-
// Hardcoded `true` value following https://contentful.atlassian.net/browse/DANTE-486
|
|
1297
|
-
// TODO: refine permissions check in order to account for tags in rules
|
|
1298
|
-
const canCreate = creatableContentTypes.length > 0 || true;
|
|
1299
|
-
setCanCreateEntity(canCreate);
|
|
1300
|
-
}
|
|
1301
|
-
}
|
|
1302
|
-
|
|
1303
|
-
void checkCreateAccess(); // eslint-disable-next-line react-hooks/exhaustive-deps -- TODO: Evaluate the dependencies
|
|
1304
|
-
}, [entityType, parameters.instance, creatableContentTypes]);
|
|
1305
|
-
useEffect(() => {
|
|
1306
|
-
if (parameters.instance.showLinkEntityAction === false) {
|
|
1307
|
-
setCanLinkEntity(false);
|
|
1308
|
-
return;
|
|
1309
|
-
}
|
|
1310
|
-
|
|
1311
|
-
async function checkLinkAccess() {
|
|
1312
|
-
if (entityType === 'Asset') {
|
|
1313
|
-
// Hardcoded `true` value following https://contentful.atlassian.net/browse/DANTE-486
|
|
1314
|
-
// TODO: refine permissions check in order to account for tags in rules
|
|
1315
|
-
const canRead = (await canPerformAction('read', 'Asset')) || true;
|
|
1316
|
-
setCanLinkEntity(canRead);
|
|
1317
|
-
}
|
|
1318
|
-
|
|
1319
|
-
if (entityType === 'Entry') {
|
|
1320
|
-
// Hardcoded `true` value following https://contentful.atlassian.net/browse/DANTE-486
|
|
1321
|
-
// TODO: refine permissions check in order to account for tags in rules
|
|
1322
|
-
// TODO: always show every content type (it's just a filter) to avoid people not seeing
|
|
1323
|
-
// their (partly limited) content types
|
|
1324
|
-
const canRead = true;
|
|
1325
|
-
setCanLinkEntity(canRead);
|
|
1326
|
-
}
|
|
1327
|
-
}
|
|
1328
|
-
|
|
1329
|
-
void checkLinkAccess(); // eslint-disable-next-line react-hooks/exhaustive-deps -- TODO: Evaluate the dependencies
|
|
1330
|
-
}, [entityType, parameters.instance, readableContentTypes]);
|
|
1331
|
-
return {
|
|
1332
|
-
canCreateEntity,
|
|
1333
|
-
canLinkEntity,
|
|
1334
|
-
creatableContentTypes,
|
|
1335
|
-
readableContentTypes,
|
|
1336
|
-
availableContentTypes,
|
|
1337
|
-
validations
|
|
1338
|
-
};
|
|
1339
|
-
}
|
|
1340
|
-
|
|
1341
|
-
function Editor(props) {
|
|
1342
|
-
const {
|
|
1343
|
-
setValue,
|
|
1344
|
-
entityType
|
|
1345
|
-
} = props;
|
|
1346
|
-
const editorPermissions = useEditorPermissions(props);
|
|
1347
|
-
const onCreate = useCallback(id => void setValue({
|
|
1348
|
-
sys: {
|
|
1349
|
-
type: 'Link',
|
|
1350
|
-
linkType: entityType,
|
|
1351
|
-
id
|
|
1352
|
-
}
|
|
1353
|
-
}), [setValue, entityType]);
|
|
1354
|
-
const onLink = useCallback(ids => {
|
|
1355
|
-
const [id] = ids;
|
|
1356
|
-
setValue({
|
|
1357
|
-
sys: {
|
|
1358
|
-
type: 'Link',
|
|
1359
|
-
linkType: entityType,
|
|
1360
|
-
id
|
|
1361
|
-
}
|
|
1362
|
-
});
|
|
1363
|
-
}, [setValue, entityType]);
|
|
1364
|
-
const linkActionsProps = useLinkActionsProps({ ...props,
|
|
1365
|
-
canLinkMultiple: false,
|
|
1366
|
-
editorPermissions,
|
|
1367
|
-
onCreate,
|
|
1368
|
-
onLink
|
|
1369
|
-
}); // Inject card actions props into the given custom card renderer
|
|
1370
|
-
|
|
1371
|
-
const customCardRenderer = useCallback((cardProps, _, renderDefaultCard) => props.renderCustomCard ? props.renderCustomCard(cardProps, linkActionsProps, renderDefaultCard) : false, // eslint-disable-next-line react-hooks/exhaustive-deps -- TODO: Evaluate the dependencies
|
|
1372
|
-
[linkActionsProps]);
|
|
1373
|
-
|
|
1374
|
-
if (!props.entityId) {
|
|
1375
|
-
return createElement(LinkEntityActions, {
|
|
1376
|
-
renderCustomActions: props.renderCustomActions,
|
|
1377
|
-
...linkActionsProps
|
|
1378
|
-
});
|
|
1379
|
-
}
|
|
1380
|
-
|
|
1381
|
-
return props.children({ ...props,
|
|
1382
|
-
renderCustomCard: props.renderCustomCard && customCardRenderer
|
|
1383
|
-
});
|
|
1384
|
-
}
|
|
1385
|
-
|
|
1386
|
-
function SingleReferenceEditor(props) {
|
|
1387
|
-
const allContentTypes = props.sdk.space.getCachedContentTypes();
|
|
1388
|
-
return createElement(ReferenceEditor, { ...props
|
|
1389
|
-
}, ({
|
|
1390
|
-
value,
|
|
1391
|
-
setValue,
|
|
1392
|
-
disabled,
|
|
1393
|
-
externalReset
|
|
1394
|
-
}) => {
|
|
1395
|
-
return createElement(Editor, { ...props,
|
|
1396
|
-
key: `${externalReset}-reference`,
|
|
1397
|
-
entityId: value ? value.sys.id : '',
|
|
1398
|
-
isDisabled: disabled,
|
|
1399
|
-
setValue: setValue,
|
|
1400
|
-
allContentTypes: allContentTypes
|
|
1401
|
-
});
|
|
1402
|
-
});
|
|
1403
|
-
}
|
|
1404
|
-
SingleReferenceEditor.defaultProps = {
|
|
1405
|
-
hasCardEditActions: true,
|
|
1406
|
-
hasCardRemoveActions: true
|
|
1407
|
-
};
|
|
1408
|
-
|
|
1409
|
-
const styles$1 = {
|
|
1410
|
-
spaceIcon: /*#__PURE__*/css({
|
|
1411
|
-
flexShrink: 0,
|
|
1412
|
-
fill: tokens.purple600
|
|
1413
|
-
}),
|
|
1414
|
-
spaceName: /*#__PURE__*/css({
|
|
1415
|
-
color: tokens.gray700,
|
|
1416
|
-
fontSize: tokens.fontSizeS,
|
|
1417
|
-
fontWeight: tokens.fontWeightDemiBold,
|
|
1418
|
-
maxWidth: '80px',
|
|
1419
|
-
textOverflow: 'ellipsis',
|
|
1420
|
-
overflow: 'hidden',
|
|
1421
|
-
whiteSpace: 'nowrap'
|
|
1422
|
-
})
|
|
1423
|
-
};
|
|
1424
|
-
function SpaceName(props) {
|
|
1425
|
-
return createElement(Tooltip, {
|
|
1426
|
-
placement: "top",
|
|
1427
|
-
as: "div",
|
|
1428
|
-
content: `Space: ${props.spaceName}`
|
|
1429
|
-
}, createElement(Flex, {
|
|
1430
|
-
alignItems: "center",
|
|
1431
|
-
gap: "spacingXs",
|
|
1432
|
-
marginRight: "spacingS"
|
|
1433
|
-
}, createElement(FolderOpenTrimmedIcon, {
|
|
1434
|
-
className: styles$1.spaceIcon,
|
|
1435
|
-
size: "tiny",
|
|
1436
|
-
"aria-label": "Source space"
|
|
1437
|
-
}), createElement(Text, {
|
|
1438
|
-
className: styles$1.spaceName
|
|
1439
|
-
}, props.spaceName)));
|
|
1440
|
-
}
|
|
1441
|
-
|
|
1442
|
-
const {
|
|
1443
|
-
getEntryTitle,
|
|
1444
|
-
getEntityDescription,
|
|
1445
|
-
getEntryStatus,
|
|
1446
|
-
getEntryImage
|
|
1447
|
-
} = entityHelpers;
|
|
1448
|
-
const styles$2 = {
|
|
1449
|
-
scheduleIcon: /*#__PURE__*/css({
|
|
1450
|
-
marginRight: tokens.spacing2Xs
|
|
1451
|
-
})
|
|
1452
|
-
};
|
|
1453
|
-
const defaultProps = {
|
|
1454
|
-
isClickable: true,
|
|
1455
|
-
hasCardEditActions: true,
|
|
1456
|
-
hasCardMoveActions: true,
|
|
1457
|
-
hasCardRemoveActions: true
|
|
1458
|
-
};
|
|
1459
|
-
function WrappedEntryCard(props) {
|
|
1460
|
-
var _props$entry;
|
|
1461
|
-
|
|
1462
|
-
const [file, setFile] = useState(null);
|
|
1463
|
-
const {
|
|
1464
|
-
contentType
|
|
1465
|
-
} = props;
|
|
1466
|
-
useEffect(() => {
|
|
1467
|
-
if (props.entry) {
|
|
1468
|
-
getEntryImage({
|
|
1469
|
-
entry: props.entry,
|
|
1470
|
-
contentType,
|
|
1471
|
-
localeCode: props.localeCode,
|
|
1472
|
-
defaultLocaleCode: props.defaultLocaleCode
|
|
1473
|
-
}, props.getAsset).then(file => {
|
|
1474
|
-
setFile(file);
|
|
1475
|
-
}).catch(() => {
|
|
1476
|
-
setFile(null);
|
|
1477
|
-
});
|
|
1478
|
-
}
|
|
1479
|
-
}, [props.entry, props.getAsset, contentType, props.localeCode, props.defaultLocaleCode]);
|
|
1480
|
-
const status = getEntryStatus((_props$entry = props.entry) == null ? void 0 : _props$entry.sys);
|
|
1481
|
-
|
|
1482
|
-
if (status === 'deleted') {
|
|
1483
|
-
return createElement(MissingEntityCard, {
|
|
1484
|
-
entityType: "Entry",
|
|
1485
|
-
isDisabled: props.isDisabled,
|
|
1486
|
-
onRemove: props.onRemove
|
|
1487
|
-
});
|
|
1488
|
-
}
|
|
1489
|
-
|
|
1490
|
-
const title = getEntryTitle({
|
|
1491
|
-
entry: props.entry,
|
|
1492
|
-
contentType,
|
|
1493
|
-
localeCode: props.localeCode,
|
|
1494
|
-
defaultLocaleCode: props.defaultLocaleCode,
|
|
1495
|
-
defaultTitle: 'Untitled'
|
|
1496
|
-
});
|
|
1497
|
-
const description = getEntityDescription({
|
|
1498
|
-
entity: props.entry,
|
|
1499
|
-
contentType,
|
|
1500
|
-
localeCode: props.localeCode,
|
|
1501
|
-
defaultLocaleCode: props.defaultLocaleCode
|
|
1502
|
-
});
|
|
1503
|
-
return createElement(EntryCard, {
|
|
1504
|
-
as: props.entryUrl ? 'a' : 'article',
|
|
1505
|
-
href: props.entryUrl,
|
|
1506
|
-
title: title,
|
|
1507
|
-
description: description,
|
|
1508
|
-
contentType: contentType == null ? void 0 : contentType.name,
|
|
1509
|
-
size: props.size,
|
|
1510
|
-
isSelected: props.isSelected,
|
|
1511
|
-
status: status,
|
|
1512
|
-
icon: props.spaceName ? createElement(SpaceName, {
|
|
1513
|
-
spaceName: props.spaceName
|
|
1514
|
-
}) : createElement(ScheduledIconWithTooltip, {
|
|
1515
|
-
getEntityScheduledActions: props.getEntityScheduledActions,
|
|
1516
|
-
entityType: "Entry",
|
|
1517
|
-
entityId: props.entry.sys.id
|
|
1518
|
-
}, createElement(ClockIcon, {
|
|
1519
|
-
className: styles$2.scheduleIcon,
|
|
1520
|
-
size: "small",
|
|
1521
|
-
variant: "muted",
|
|
1522
|
-
testId: "schedule-icon"
|
|
1523
|
-
})),
|
|
1524
|
-
thumbnailElement: file && isValidImage(file) ? createElement(AssetThumbnail, {
|
|
1525
|
-
file: file
|
|
1526
|
-
}) : undefined,
|
|
1527
|
-
dragHandleRender: props.renderDragHandle,
|
|
1528
|
-
withDragHandle: !!props.renderDragHandle,
|
|
1529
|
-
actions: props.onEdit || props.onRemove ? [props.hasCardEditActions && props.onEdit ? createElement(MenuItem, {
|
|
1530
|
-
key: "edit",
|
|
1531
|
-
testId: "edit",
|
|
1532
|
-
onClick: () => {
|
|
1533
|
-
props.onEdit && props.onEdit();
|
|
1534
|
-
}
|
|
1535
|
-
}, "Edit") : null, props.hasCardRemoveActions && props.onRemove ? createElement(MenuItem, {
|
|
1536
|
-
key: "delete",
|
|
1537
|
-
testId: "delete",
|
|
1538
|
-
onClick: () => {
|
|
1539
|
-
props.onRemove && props.onRemove();
|
|
1540
|
-
}
|
|
1541
|
-
}, "Remove") : null, props.hasCardMoveActions && (props.onMoveTop || props.onMoveBottom) ? createElement(MenuDivider, {
|
|
1542
|
-
key: "divider"
|
|
1543
|
-
}) : null, props.hasCardMoveActions && props.onMoveTop ? createElement(MenuItem, {
|
|
1544
|
-
key: "move-top",
|
|
1545
|
-
onClick: () => props.onMoveTop && props.onMoveTop(),
|
|
1546
|
-
testId: "move-top"
|
|
1547
|
-
}, "Move to top") : null, props.hasCardMoveActions && props.onMoveBottom ? createElement(MenuItem, {
|
|
1548
|
-
key: "move-bottom",
|
|
1549
|
-
onClick: () => props.onMoveBottom && props.onMoveBottom(),
|
|
1550
|
-
testId: "move-bottom"
|
|
1551
|
-
}, "Move to bottom") : null].filter(item => item) : [],
|
|
1552
|
-
onClick: // Providing an onClick handler messes up with some rich text
|
|
1553
|
-
// features e.g. pressing ENTER on a card to add a new paragraph
|
|
1554
|
-
// underneath. It's crucial not to pass a custom handler when
|
|
1555
|
-
// isClickable is disabled which in the case of RT it's.
|
|
1556
|
-
props.isClickable ? e => {
|
|
1557
|
-
e.preventDefault();
|
|
1558
|
-
if (props.onClick) return props.onClick(e);
|
|
1559
|
-
props.onEdit && props.onEdit();
|
|
1560
|
-
} : undefined
|
|
1561
|
-
});
|
|
1562
|
-
}
|
|
1563
|
-
WrappedEntryCard.defaultProps = defaultProps;
|
|
1564
|
-
|
|
1565
|
-
async function openEntry(sdk, entryId, options) {
|
|
1566
|
-
let slide;
|
|
1567
|
-
|
|
1568
|
-
if (options.bulkEditing) {
|
|
1569
|
-
try {
|
|
1570
|
-
const result = await sdk.navigator.openBulkEditor(sdk.entry.getSys().id, {
|
|
1571
|
-
fieldId: sdk.field.id,
|
|
1572
|
-
locale: sdk.field.locale,
|
|
1573
|
-
index: options.index ?? 0
|
|
1574
|
-
});
|
|
1575
|
-
slide = result.slide;
|
|
1576
|
-
return slide;
|
|
1577
|
-
} catch (e) {// we don't allow to open multiple bulk editors for performance reasons
|
|
1578
|
-
// proceed with a default openEntry
|
|
1579
|
-
}
|
|
1580
|
-
}
|
|
1581
|
-
|
|
1582
|
-
const result = await sdk.navigator.openEntry(entryId, {
|
|
1583
|
-
slideIn: true
|
|
1584
|
-
});
|
|
1585
|
-
slide = result.slide;
|
|
1586
|
-
return slide;
|
|
1587
|
-
}
|
|
1588
|
-
|
|
1589
|
-
function FetchingWrappedEntryCard(props) {
|
|
1590
|
-
const {
|
|
1591
|
-
data: entry,
|
|
1592
|
-
status
|
|
1593
|
-
} = useEntity('Entry', props.entryId);
|
|
1594
|
-
const {
|
|
1595
|
-
getEntityScheduledActions
|
|
1596
|
-
} = useEntityLoader();
|
|
1597
|
-
const loadEntityScheduledActions = useCallback(() => getEntityScheduledActions('Entry', props.entryId), [getEntityScheduledActions, props.entryId]);
|
|
1598
|
-
const size = props.viewType === 'link' ? 'small' : 'default';
|
|
1599
|
-
const {
|
|
1600
|
-
getEntity
|
|
1601
|
-
} = useEntityLoader();
|
|
1602
|
-
|
|
1603
|
-
const getAsset = assetId => getEntity('Asset', assetId);
|
|
1604
|
-
|
|
1605
|
-
const onEdit = async () => {
|
|
1606
|
-
const slide = await openEntry(props.sdk, props.entryId, {
|
|
1607
|
-
bulkEditing: props.parameters.instance.bulkEditing,
|
|
1608
|
-
index: props.index
|
|
1609
|
-
});
|
|
1610
|
-
props.onAction && props.onAction({
|
|
1611
|
-
entity: 'Entry',
|
|
1612
|
-
type: 'edit',
|
|
1613
|
-
id: props.entryId,
|
|
1614
|
-
contentTypeId: get(entry, 'sys.contentType.sys.id'),
|
|
1615
|
-
slide
|
|
1616
|
-
});
|
|
1617
|
-
};
|
|
1618
|
-
|
|
1619
|
-
const onRemoveEntry = () => {
|
|
1620
|
-
props.onRemove();
|
|
1621
|
-
props.onAction && props.onAction({
|
|
1622
|
-
entity: 'Entry',
|
|
1623
|
-
type: 'delete',
|
|
1624
|
-
id: props.entryId,
|
|
1625
|
-
contentTypeId: get(entry, 'sys.contentType.sys.id')
|
|
1626
|
-
});
|
|
1627
|
-
};
|
|
1628
|
-
|
|
1629
|
-
useEffect(() => {
|
|
1630
|
-
if (entry) {
|
|
1631
|
-
props.onAction && props.onAction({
|
|
1632
|
-
type: 'rendered',
|
|
1633
|
-
entity: 'Entry'
|
|
1634
|
-
});
|
|
1635
|
-
} // eslint-disable-next-line react-hooks/exhaustive-deps -- TODO: Evaluate the dependencies
|
|
1636
|
-
|
|
1637
|
-
}, [entry]);
|
|
1638
|
-
return useMemo(() => {
|
|
1639
|
-
if (status === 'error') {
|
|
1640
|
-
const card = createElement(MissingEntityCard, {
|
|
1641
|
-
entityType: "Entry",
|
|
1642
|
-
isDisabled: props.isDisabled,
|
|
1643
|
-
onRemove: onRemoveEntry
|
|
1644
|
-
});
|
|
1645
|
-
|
|
1646
|
-
if (props.renderCustomMissingEntityCard) {
|
|
1647
|
-
return props.renderCustomMissingEntityCard({
|
|
1648
|
-
defaultCard: card,
|
|
1649
|
-
entity: {
|
|
1650
|
-
id: props.entryId,
|
|
1651
|
-
type: 'Entry'
|
|
1652
|
-
}
|
|
1653
|
-
});
|
|
1654
|
-
}
|
|
1655
|
-
|
|
1656
|
-
return card;
|
|
1657
|
-
}
|
|
1658
|
-
|
|
1659
|
-
if (status === 'loading') {
|
|
1660
|
-
return createElement(EntryCard, {
|
|
1661
|
-
size: size,
|
|
1662
|
-
isLoading: true
|
|
1663
|
-
});
|
|
1664
|
-
}
|
|
1665
|
-
|
|
1666
|
-
const sharedCardProps = {
|
|
1667
|
-
index: props.index,
|
|
1668
|
-
entity: entry,
|
|
1669
|
-
entityUrl: props.getEntityUrl && props.getEntityUrl(entry.sys.id),
|
|
1670
|
-
contentType: props.allContentTypes.find(contentType => contentType.sys.id === entry.sys.contentType.sys.id),
|
|
1671
|
-
isDisabled: props.isDisabled,
|
|
1672
|
-
size,
|
|
1673
|
-
localeCode: props.sdk.field.locale,
|
|
1674
|
-
defaultLocaleCode: props.sdk.locales.default,
|
|
1675
|
-
renderDragHandle: props.renderDragHandle,
|
|
1676
|
-
onEdit,
|
|
1677
|
-
onRemove: onRemoveEntry,
|
|
1678
|
-
onMoveTop: props.onMoveTop,
|
|
1679
|
-
onMoveBottom: props.onMoveBottom,
|
|
1680
|
-
isBeingDragged: props.isBeingDragged
|
|
1681
|
-
};
|
|
1682
|
-
const {
|
|
1683
|
-
hasCardEditActions,
|
|
1684
|
-
hasCardMoveActions,
|
|
1685
|
-
hasCardRemoveActions
|
|
1686
|
-
} = props;
|
|
1687
|
-
|
|
1688
|
-
function renderDefaultCard(props) {
|
|
1689
|
-
const builtinCardProps = { ...sharedCardProps,
|
|
1690
|
-
...props,
|
|
1691
|
-
hasCardEditActions,
|
|
1692
|
-
hasCardMoveActions,
|
|
1693
|
-
hasCardRemoveActions,
|
|
1694
|
-
getAsset,
|
|
1695
|
-
getEntityScheduledActions: loadEntityScheduledActions,
|
|
1696
|
-
entry: (props == null ? void 0 : props.entity) || sharedCardProps.entity,
|
|
1697
|
-
entryUrl: (props == null ? void 0 : props.entityUrl) || sharedCardProps.entityUrl
|
|
1698
|
-
};
|
|
1699
|
-
return createElement(WrappedEntryCard, { ...builtinCardProps
|
|
1700
|
-
});
|
|
1701
|
-
}
|
|
1702
|
-
|
|
1703
|
-
if (props.renderCustomCard) {
|
|
1704
|
-
// LinkActionsProps are injected higher SingleReferenceEditor/MultipleReferenceEditor
|
|
1705
|
-
const renderedCustomCard = props.renderCustomCard(sharedCardProps, {}, renderDefaultCard); // Only `false` indicates to render the original card. E.g. `null` would result in no card.
|
|
1706
|
-
|
|
1707
|
-
if (renderedCustomCard !== false) {
|
|
1708
|
-
return renderedCustomCard;
|
|
1709
|
-
}
|
|
1710
|
-
}
|
|
1711
|
-
|
|
1712
|
-
return renderDefaultCard(); // eslint-disable-next-line react-hooks/exhaustive-deps -- TODO: Evaluate the dependencies
|
|
1713
|
-
}, [props, status, entry]);
|
|
1714
|
-
}
|
|
1715
|
-
|
|
1716
|
-
function SingleEntryReferenceEditor(props) {
|
|
1717
|
-
return createElement(SingleReferenceEditor, { ...props,
|
|
1718
|
-
entityType: "Entry"
|
|
1719
|
-
}, ({
|
|
1720
|
-
allContentTypes,
|
|
1721
|
-
isDisabled,
|
|
1722
|
-
entityId,
|
|
1723
|
-
setValue,
|
|
1724
|
-
renderCustomCard,
|
|
1725
|
-
hasCardRemoveActions,
|
|
1726
|
-
hasCardEditActions
|
|
1727
|
-
}) => {
|
|
1728
|
-
return createElement(FetchingWrappedEntryCard, { ...props,
|
|
1729
|
-
allContentTypes: allContentTypes,
|
|
1730
|
-
isDisabled: isDisabled,
|
|
1731
|
-
entryId: entityId,
|
|
1732
|
-
renderCustomCard: renderCustomCard,
|
|
1733
|
-
hasCardEditActions: hasCardEditActions,
|
|
1734
|
-
hasCardRemoveActions: hasCardRemoveActions,
|
|
1735
|
-
onRemove: () => {
|
|
1736
|
-
setValue(null);
|
|
1737
|
-
}
|
|
1738
|
-
});
|
|
1739
|
-
});
|
|
1740
|
-
}
|
|
1741
|
-
SingleEntryReferenceEditor.defaultProps = {
|
|
1742
|
-
isInitiallyDisabled: true
|
|
1743
|
-
};
|
|
1744
|
-
|
|
1745
|
-
function onLinkOrCreate(setValue, entityType, items, ids, index = items.length) {
|
|
1746
|
-
const links = ids.map(id => ({
|
|
1747
|
-
sys: {
|
|
1748
|
-
type: 'Link',
|
|
1749
|
-
linkType: entityType,
|
|
1750
|
-
id
|
|
1751
|
-
}
|
|
1752
|
-
}));
|
|
1753
|
-
const newItems = Array.from(items);
|
|
1754
|
-
newItems.splice(index, 0, ...links);
|
|
1755
|
-
setValue(newItems);
|
|
1756
|
-
}
|
|
1757
|
-
|
|
1758
|
-
const emptyArray = [];
|
|
1759
|
-
const nullableValue = {
|
|
1760
|
-
sys: {
|
|
1761
|
-
id: 'null-value'
|
|
1762
|
-
}
|
|
1763
|
-
};
|
|
1764
|
-
|
|
1765
|
-
function Editor$1(props) {
|
|
1766
|
-
const {
|
|
1767
|
-
setValue,
|
|
1768
|
-
entityType,
|
|
1769
|
-
setIndexToUpdate
|
|
1770
|
-
} = props;
|
|
1771
|
-
const editorPermissions = useEditorPermissions(props);
|
|
1772
|
-
const items = useMemo(() => {
|
|
1773
|
-
return (props.items || []). // If null values have found their way into the persisted
|
|
1774
|
-
// value for the multiref field, replace them with an object
|
|
1775
|
-
// that has the shape of a Link to make the missing entry/asset
|
|
1776
|
-
// card render
|
|
1777
|
-
map(link => link || nullableValue);
|
|
1778
|
-
}, [props.items]);
|
|
1779
|
-
const onSortStart = useCallback((_, event) => {
|
|
1780
|
-
if (event instanceof MouseEvent) {
|
|
1781
|
-
document.body.classList.add('grabbing');
|
|
1782
|
-
}
|
|
1783
|
-
|
|
1784
|
-
event.preventDefault();
|
|
1785
|
-
}, []);
|
|
1786
|
-
const onSortEnd = useCallback(({
|
|
1787
|
-
oldIndex,
|
|
1788
|
-
newIndex
|
|
1789
|
-
}) => {
|
|
1790
|
-
// custom callback that is invoked *before* we sort the array
|
|
1791
|
-
// e.g. in Compose we want to sort the references in the referenceMap before re-rendering drag and drop
|
|
1792
|
-
props.onSortingEnd && props.onSortingEnd({
|
|
1793
|
-
oldIndex,
|
|
1794
|
-
newIndex
|
|
1795
|
-
});
|
|
1796
|
-
const newItems = arrayMove(items, oldIndex, newIndex);
|
|
1797
|
-
setValue(newItems);
|
|
1798
|
-
setIndexToUpdate && setIndexToUpdate(undefined);
|
|
1799
|
-
document.body.classList.remove('grabbing');
|
|
1800
|
-
}, [items, props, setIndexToUpdate, setValue]);
|
|
1801
|
-
const onMove = useCallback((oldIndex, newIndex) => {
|
|
1802
|
-
const newItems = arrayMove(items, oldIndex, newIndex);
|
|
1803
|
-
setValue(newItems);
|
|
1804
|
-
}, [items, setValue]);
|
|
1805
|
-
const onCreate = useCallback((id, index) => onLinkOrCreate(setValue, entityType, items, [id], index), [setValue, items, entityType]);
|
|
1806
|
-
const onLink = useCallback((ids, index) => onLinkOrCreate(setValue, entityType, items, ids, index), [setValue, items, entityType]);
|
|
1807
|
-
const linkActionsProps = useLinkActionsProps({ ...props,
|
|
1808
|
-
canLinkMultiple: true,
|
|
1809
|
-
editorPermissions,
|
|
1810
|
-
onCreate,
|
|
1811
|
-
onLink,
|
|
1812
|
-
itemsLength: items.length
|
|
1813
|
-
});
|
|
1814
|
-
const customCardRenderer = useCallback((cardProps, _, renderDefaultCard) => props.renderCustomCard ? props.renderCustomCard(cardProps, linkActionsProps, renderDefaultCard) : false, // eslint-disable-next-line react-hooks/exhaustive-deps -- TODO: Evaluate the dependencies
|
|
1815
|
-
[linkActionsProps]);
|
|
1816
|
-
return createElement(Fragment, null, props.children({ ...props,
|
|
1817
|
-
onSortStart: onSortStart,
|
|
1818
|
-
onSortEnd: onSortEnd,
|
|
1819
|
-
onMove,
|
|
1820
|
-
renderCustomCard: props.renderCustomCard && customCardRenderer
|
|
1821
|
-
}), createElement(LinkEntityActions, {
|
|
1822
|
-
renderCustomActions: props.renderCustomActions,
|
|
1823
|
-
...linkActionsProps
|
|
1824
|
-
}));
|
|
1825
|
-
}
|
|
1826
|
-
|
|
1827
|
-
function MultipleReferenceEditor(props) {
|
|
1828
|
-
const allContentTypes = props.sdk.space.getCachedContentTypes();
|
|
1829
|
-
return createElement(ReferenceEditor, { ...props
|
|
1830
|
-
}, ({
|
|
1831
|
-
value,
|
|
1832
|
-
disabled,
|
|
1833
|
-
setValue,
|
|
1834
|
-
externalReset
|
|
1835
|
-
}) => {
|
|
1836
|
-
return createElement(Editor$1, { ...props,
|
|
1837
|
-
items: value || emptyArray,
|
|
1838
|
-
isDisabled: disabled,
|
|
1839
|
-
setValue: setValue,
|
|
1840
|
-
key: `${externalReset}-list`,
|
|
1841
|
-
allContentTypes: allContentTypes
|
|
1842
|
-
});
|
|
1843
|
-
});
|
|
1844
|
-
}
|
|
1845
|
-
MultipleReferenceEditor.defaultProps = {
|
|
1846
|
-
hasCardEditActions: true
|
|
1847
|
-
};
|
|
1848
|
-
|
|
1849
|
-
const styles$3 = {
|
|
1850
|
-
container: /*#__PURE__*/css({
|
|
1851
|
-
position: 'relative'
|
|
1852
|
-
}),
|
|
1853
|
-
item: /*#__PURE__*/css({
|
|
1854
|
-
marginBottom: tokens.spacingM,
|
|
1855
|
-
zIndex: tokens.zIndexModal // setting this to an index above 99 fixes dragged item disappearing issue. Should not be higher than 100 so it does not overlap the asset modal.
|
|
1856
|
-
|
|
1857
|
-
})
|
|
1858
|
-
};
|
|
1859
|
-
|
|
1860
|
-
const DragHandle = props => {
|
|
1861
|
-
const SortableDragHandle = SortableHandle(() => props.drag);
|
|
1862
|
-
return React__default.createElement(SortableDragHandle, null);
|
|
1863
|
-
};
|
|
1864
|
-
|
|
1865
|
-
const SortableLink = /*#__PURE__*/SortableElement(props => React__default.createElement("div", {
|
|
1866
|
-
className: styles$3.item
|
|
1867
|
-
}, props.children));
|
|
1868
|
-
const SortableLinkListInternal = /*#__PURE__*/SortableContainer(props => {
|
|
1869
|
-
return React__default.createElement("div", {
|
|
1870
|
-
className: cx(styles$3.container, props.className)
|
|
1871
|
-
}, props.items.map((item, index) => React__default.createElement(SortableLink, {
|
|
1872
|
-
disabled: props.isDisabled,
|
|
1873
|
-
key: `${item.sys.urn ?? item.sys.id}-${index}`,
|
|
1874
|
-
index: index
|
|
1875
|
-
}, props.children({
|
|
1876
|
-
items: props.items,
|
|
1877
|
-
isDisabled: props.isDisabled,
|
|
1878
|
-
item,
|
|
1879
|
-
index,
|
|
1880
|
-
DragHandle: props.isDisabled ? undefined : DragHandle
|
|
1881
|
-
}))));
|
|
1882
|
-
}); // HOC does not support generics, so we mimic it via additional component
|
|
1883
|
-
|
|
1884
|
-
function SortableLinkList(props) {
|
|
1885
|
-
// with the default distance of 0 the drag start event is "confused" with the click event,
|
|
1886
|
-
// so the latter one isn't fired and click handlers on child elements don't work
|
|
1887
|
-
return React__default.createElement(SortableLinkListInternal, {
|
|
1888
|
-
distance: 1,
|
|
1889
|
-
...props
|
|
1890
|
-
}, props.children);
|
|
1891
|
-
}
|
|
1892
|
-
|
|
1893
|
-
function MultipleEntryReferenceEditor(props) {
|
|
1894
|
-
const [indexToUpdate, setIndexToUpdate] = useState(undefined);
|
|
1895
|
-
|
|
1896
|
-
const updateBeforeSortStart = ({
|
|
1897
|
-
index
|
|
1898
|
-
}) => {
|
|
1899
|
-
setIndexToUpdate(index);
|
|
1900
|
-
};
|
|
1901
|
-
|
|
1902
|
-
return createElement(MultipleReferenceEditor, { ...props,
|
|
1903
|
-
entityType: "Entry",
|
|
1904
|
-
setIndexToUpdate: setIndexToUpdate
|
|
1905
|
-
}, childrenProps => createElement(SortableLinkList, { ...childrenProps,
|
|
1906
|
-
axis: "y",
|
|
1907
|
-
useDragHandle: true,
|
|
1908
|
-
updateBeforeSortStart: updateBeforeSortStart
|
|
1909
|
-
}, ({
|
|
1910
|
-
items,
|
|
1911
|
-
item,
|
|
1912
|
-
index,
|
|
1913
|
-
isDisabled,
|
|
1914
|
-
DragHandle
|
|
1915
|
-
}) => {
|
|
1916
|
-
const lastIndex = items.length - 1;
|
|
1917
|
-
return createElement(FetchingWrappedEntryCard, { ...childrenProps,
|
|
1918
|
-
key: `${item.sys.id}-${index}`,
|
|
1919
|
-
index: index,
|
|
1920
|
-
allContentTypes: childrenProps.allContentTypes,
|
|
1921
|
-
isDisabled: isDisabled,
|
|
1922
|
-
entryId: item.sys.id,
|
|
1923
|
-
onRemove: () => {
|
|
1924
|
-
childrenProps.setValue(items.filter((_value, i) => i !== index));
|
|
1925
|
-
},
|
|
1926
|
-
onMoveTop: index !== 0 ? () => childrenProps.onMove(index, 0) : undefined,
|
|
1927
|
-
onMoveBottom: index !== lastIndex ? () => childrenProps.onMove(index, lastIndex) : undefined,
|
|
1928
|
-
renderDragHandle: DragHandle,
|
|
1929
|
-
isBeingDragged: index === indexToUpdate
|
|
1930
|
-
});
|
|
1931
|
-
}));
|
|
1932
|
-
}
|
|
1933
|
-
|
|
1934
|
-
function downloadAsset(url) {
|
|
1935
|
-
window.open(url, '_blank', 'noopener,noreferrer');
|
|
1936
|
-
}
|
|
1937
|
-
|
|
1938
|
-
function renderAssetInfo(props) {
|
|
1939
|
-
const {
|
|
1940
|
-
entityFile
|
|
1941
|
-
} = props;
|
|
1942
|
-
const fileName = get(entityFile, 'fileName');
|
|
1943
|
-
const mimeType = get(entityFile, 'contentType');
|
|
1944
|
-
const fileSize = get(entityFile, 'details.size');
|
|
1945
|
-
const image = get(entityFile, 'details.image');
|
|
1946
|
-
return [React__default.createElement(Menu.SectionTitle, {
|
|
1947
|
-
key: "file-section"
|
|
1948
|
-
}, "File info"), fileName && React__default.createElement(Menu.Item, {
|
|
1949
|
-
key: "file-name"
|
|
1950
|
-
}, React__default.createElement(Text, {
|
|
1951
|
-
isTruncated: true
|
|
1952
|
-
}, fileName)), mimeType && React__default.createElement(Menu.Item, {
|
|
1953
|
-
key: "file-type"
|
|
1954
|
-
}, React__default.createElement(Text, {
|
|
1955
|
-
isTruncated: true
|
|
1956
|
-
}, mimeType)), fileSize && React__default.createElement(Menu.Item, {
|
|
1957
|
-
key: "file-size"
|
|
1958
|
-
}, shortenStorageUnit(fileSize, 'B')), image && React__default.createElement(Menu.Item, {
|
|
1959
|
-
key: "file-dimentions"
|
|
1960
|
-
}, `${image.width} × ${image.height}`)].filter(item => item);
|
|
1961
|
-
}
|
|
1962
|
-
function renderActions(props) {
|
|
1963
|
-
const {
|
|
1964
|
-
entityFile,
|
|
1965
|
-
isDisabled,
|
|
1966
|
-
onEdit,
|
|
1967
|
-
onRemove
|
|
1968
|
-
} = props;
|
|
1969
|
-
return [React__default.createElement(Menu.SectionTitle, {
|
|
1970
|
-
key: "section-title"
|
|
1971
|
-
}, "Actions"), onEdit ? React__default.createElement(Menu.Item, {
|
|
1972
|
-
key: "edit",
|
|
1973
|
-
onClick: onEdit,
|
|
1974
|
-
testId: "card-action-edit"
|
|
1975
|
-
}, "Edit") : null, entityFile ? React__default.createElement(Menu.Item, {
|
|
1976
|
-
key: "download",
|
|
1977
|
-
onClick: () => {
|
|
1978
|
-
if (typeof entityFile.url === 'string') {
|
|
1979
|
-
downloadAsset(entityFile.url);
|
|
1980
|
-
}
|
|
1981
|
-
},
|
|
1982
|
-
testId: "card-action-download"
|
|
1983
|
-
}, "Download") : null, onRemove ? React__default.createElement(Menu.Item, {
|
|
1984
|
-
key: "remove",
|
|
1985
|
-
disabled: isDisabled,
|
|
1986
|
-
onClick: onRemove,
|
|
1987
|
-
testId: "card-action-remove"
|
|
1988
|
-
}, "Remove") : null].filter(item => item);
|
|
1989
|
-
}
|
|
1990
|
-
|
|
1991
|
-
const groupToIconMap = {
|
|
1992
|
-
image: 'image',
|
|
1993
|
-
video: 'video',
|
|
1994
|
-
audio: 'audio',
|
|
1995
|
-
richtext: 'richtext',
|
|
1996
|
-
presentation: 'presentation',
|
|
1997
|
-
spreadsheet: 'spreadsheet',
|
|
1998
|
-
pdfdocument: 'pdf',
|
|
1999
|
-
archive: 'archive',
|
|
2000
|
-
plaintext: 'plaintext',
|
|
2001
|
-
code: 'code',
|
|
2002
|
-
markup: 'markup'
|
|
2003
|
-
};
|
|
2004
|
-
const styles$4 = {
|
|
2005
|
-
scheduleIcon: /*#__PURE__*/css({
|
|
2006
|
-
marginRight: tokens.spacing2Xs
|
|
2007
|
-
})
|
|
2008
|
-
};
|
|
2009
|
-
const defaultProps$1 = {
|
|
2010
|
-
isClickable: true
|
|
2011
|
-
}; // eslint-disable-next-line -- TODO: describe this disable @typescript-eslint/no-explicit-any
|
|
2012
|
-
|
|
2013
|
-
function getFileType(file) {
|
|
2014
|
-
if (!file) {
|
|
2015
|
-
return 'archive';
|
|
2016
|
-
}
|
|
2017
|
-
|
|
2018
|
-
const groupName = mimetype.getGroupLabel({
|
|
2019
|
-
type: file.contentType,
|
|
2020
|
-
fallbackFileName: file.fileName
|
|
2021
|
-
});
|
|
2022
|
-
return groupToIconMap[groupName] || 'archive';
|
|
2023
|
-
}
|
|
2024
|
-
|
|
2025
|
-
const WrappedAssetCard = props => {
|
|
2026
|
-
const {
|
|
2027
|
-
className,
|
|
2028
|
-
onEdit,
|
|
2029
|
-
getAssetUrl,
|
|
2030
|
-
onRemove,
|
|
2031
|
-
size,
|
|
2032
|
-
isDisabled,
|
|
2033
|
-
isSelected,
|
|
2034
|
-
isClickable
|
|
2035
|
-
} = props;
|
|
2036
|
-
const status = entityHelpers.getEntryStatus(props.asset.sys);
|
|
2037
|
-
|
|
2038
|
-
if (status === 'deleted') {
|
|
2039
|
-
return React__default.createElement(MissingEntityCard, {
|
|
2040
|
-
entityType: "Asset",
|
|
2041
|
-
asSquare: true,
|
|
2042
|
-
isDisabled: props.isDisabled,
|
|
2043
|
-
onRemove: props.onRemove
|
|
2044
|
-
});
|
|
2045
|
-
}
|
|
2046
|
-
|
|
2047
|
-
const entityTitle = entityHelpers.getAssetTitle({
|
|
2048
|
-
asset: props.asset,
|
|
2049
|
-
localeCode: props.localeCode,
|
|
2050
|
-
defaultLocaleCode: props.defaultLocaleCode,
|
|
2051
|
-
defaultTitle: 'Untitled'
|
|
2052
|
-
});
|
|
2053
|
-
const entityFile = props.asset.fields.file ? props.asset.fields.file[props.localeCode] || props.asset.fields.file[props.defaultLocaleCode] : undefined;
|
|
2054
|
-
const href = getAssetUrl ? getAssetUrl(props.asset.sys.id) : undefined;
|
|
2055
|
-
return React__default.createElement(AssetCard, {
|
|
2056
|
-
as: href ? 'a' : 'article',
|
|
2057
|
-
type: getFileType(entityFile),
|
|
2058
|
-
title: entityTitle,
|
|
2059
|
-
className: className,
|
|
2060
|
-
isSelected: isSelected,
|
|
2061
|
-
href: href,
|
|
2062
|
-
status: status,
|
|
2063
|
-
icon: React__default.createElement(ScheduledIconWithTooltip, {
|
|
2064
|
-
getEntityScheduledActions: props.getEntityScheduledActions,
|
|
2065
|
-
entityType: "Asset",
|
|
2066
|
-
entityId: props.asset.sys.id
|
|
2067
|
-
}, React__default.createElement(ClockIcon, {
|
|
2068
|
-
className: styles$4.scheduleIcon,
|
|
2069
|
-
size: "small",
|
|
2070
|
-
variant: "muted",
|
|
2071
|
-
testId: "schedule-icon"
|
|
2072
|
-
})),
|
|
2073
|
-
src: entityFile && entityFile.url ? size === 'small' ? `${entityFile.url}?w=150&h=150&fit=thumb` : `${entityFile.url}?h=300` : '',
|
|
2074
|
-
onClick: // Providing an onClick handler messes up with some rich text
|
|
2075
|
-
// features e.g. pressing ENTER on a card to add a new paragraph
|
|
2076
|
-
// underneath. It's crucial not to pass a custom handler when
|
|
2077
|
-
// isClickable is disabled which in the case of RT it's.
|
|
2078
|
-
isClickable ? e => {
|
|
2079
|
-
e.preventDefault();
|
|
2080
|
-
onEdit && onEdit();
|
|
2081
|
-
} : undefined,
|
|
2082
|
-
|
|
2083
|
-
/* todo - remove this when onKeyDown is allowed as a prop for BaseCard in forma 36
|
|
2084
|
-
// @ts-expect-error */
|
|
2085
|
-
onKeyDown: isClickable ? e => {
|
|
2086
|
-
if (e.key === 'Enter' && onEdit) {
|
|
2087
|
-
e.preventDefault();
|
|
2088
|
-
onEdit();
|
|
2089
|
-
}
|
|
2090
|
-
} : undefined,
|
|
2091
|
-
dragHandleRender: props.renderDragHandle,
|
|
2092
|
-
withDragHandle: !!props.renderDragHandle,
|
|
2093
|
-
actions: [...renderActions({
|
|
2094
|
-
entityFile,
|
|
2095
|
-
isDisabled: isDisabled,
|
|
2096
|
-
onEdit,
|
|
2097
|
-
onRemove
|
|
2098
|
-
}), ...(entityFile ? renderAssetInfo({
|
|
2099
|
-
entityFile
|
|
2100
|
-
}) : [])].filter(item => item),
|
|
2101
|
-
size: size
|
|
2102
|
-
});
|
|
2103
|
-
};
|
|
2104
|
-
WrappedAssetCard.defaultProps = defaultProps$1;
|
|
2105
|
-
|
|
2106
|
-
const styles$5 = {
|
|
2107
|
-
scheduleIcon: /*#__PURE__*/css({
|
|
2108
|
-
marginRight: tokens.spacing2Xs
|
|
2109
|
-
})
|
|
2110
|
-
};
|
|
2111
|
-
const WrappedAssetLink = props => {
|
|
2112
|
-
const {
|
|
2113
|
-
className,
|
|
2114
|
-
href,
|
|
2115
|
-
onEdit,
|
|
2116
|
-
onRemove,
|
|
2117
|
-
isDisabled
|
|
2118
|
-
} = props;
|
|
2119
|
-
const status = entityHelpers.getEntryStatus(props.asset.sys);
|
|
2120
|
-
|
|
2121
|
-
if (status === 'deleted') {
|
|
2122
|
-
return React__default.createElement(MissingEntityCard, {
|
|
2123
|
-
entityType: "Asset",
|
|
2124
|
-
isDisabled: props.isDisabled,
|
|
2125
|
-
onRemove: props.onRemove
|
|
2126
|
-
});
|
|
2127
|
-
}
|
|
2128
|
-
|
|
2129
|
-
const entityTitle = entityHelpers.getAssetTitle({
|
|
2130
|
-
asset: props.asset,
|
|
2131
|
-
localeCode: props.localeCode,
|
|
2132
|
-
defaultLocaleCode: props.defaultLocaleCode,
|
|
2133
|
-
defaultTitle: 'Untitled'
|
|
2134
|
-
});
|
|
2135
|
-
const entityFile = props.asset.fields.file ? props.asset.fields.file[props.localeCode] || props.asset.fields.file[props.defaultLocaleCode] : undefined;
|
|
2136
|
-
return React__default.createElement(EntryCard, {
|
|
2137
|
-
as: href ? 'a' : 'article',
|
|
2138
|
-
contentType: "Asset",
|
|
2139
|
-
title: entityTitle,
|
|
2140
|
-
className: className,
|
|
2141
|
-
href: href,
|
|
2142
|
-
size: "small",
|
|
2143
|
-
status: status,
|
|
2144
|
-
thumbnailElement: entityFile && isValidImage(entityFile) ? React__default.createElement(AssetThumbnail, {
|
|
2145
|
-
file: entityFile
|
|
2146
|
-
}) : undefined,
|
|
2147
|
-
icon: React__default.createElement(ScheduledIconWithTooltip, {
|
|
2148
|
-
getEntityScheduledActions: props.getEntityScheduledActions,
|
|
2149
|
-
entityType: "Asset",
|
|
2150
|
-
entityId: props.asset.sys.id
|
|
2151
|
-
}, React__default.createElement(ClockIcon, {
|
|
2152
|
-
className: styles$5.scheduleIcon,
|
|
2153
|
-
size: "small",
|
|
2154
|
-
variant: "muted",
|
|
2155
|
-
testId: "schedule-icon"
|
|
2156
|
-
})),
|
|
2157
|
-
onClick: e => {
|
|
2158
|
-
e.preventDefault();
|
|
2159
|
-
onEdit();
|
|
2160
|
-
},
|
|
2161
|
-
onKeyDown: e => {
|
|
2162
|
-
if (e.key === 'Enter' && onEdit) {
|
|
2163
|
-
e.preventDefault();
|
|
2164
|
-
onEdit();
|
|
2165
|
-
}
|
|
2166
|
-
},
|
|
2167
|
-
dragHandleRender: props.renderDragHandle,
|
|
2168
|
-
withDragHandle: !!props.renderDragHandle,
|
|
2169
|
-
actions: [renderActions({
|
|
2170
|
-
entityFile,
|
|
2171
|
-
isDisabled: isDisabled,
|
|
2172
|
-
onEdit,
|
|
2173
|
-
onRemove
|
|
2174
|
-
}), entityFile ? renderAssetInfo({
|
|
2175
|
-
entityFile
|
|
2176
|
-
}) : null].filter(item => item)
|
|
2177
|
-
});
|
|
2178
|
-
};
|
|
2179
|
-
|
|
2180
|
-
function FetchingWrappedAssetCard(props) {
|
|
2181
|
-
const {
|
|
2182
|
-
data: asset,
|
|
2183
|
-
status
|
|
2184
|
-
} = useEntity('Asset', props.assetId);
|
|
2185
|
-
const {
|
|
2186
|
-
getEntityScheduledActions
|
|
2187
|
-
} = useEntityLoader();
|
|
2188
|
-
const loadEntityScheduledActions = useCallback(() => getEntityScheduledActions('Asset', props.assetId), [getEntityScheduledActions, props.assetId]);
|
|
2189
|
-
useEffect(() => {
|
|
2190
|
-
if (asset) {
|
|
2191
|
-
props.onAction && props.onAction({
|
|
2192
|
-
type: 'rendered',
|
|
2193
|
-
entity: 'Asset'
|
|
2194
|
-
});
|
|
2195
|
-
} // eslint-disable-next-line react-hooks/exhaustive-deps -- TODO: Evaluate the dependencies
|
|
2196
|
-
|
|
2197
|
-
}, [asset]);
|
|
2198
|
-
|
|
2199
|
-
const onEdit = async () => {
|
|
2200
|
-
const {
|
|
2201
|
-
slide
|
|
2202
|
-
} = await props.sdk.navigator.openAsset(props.assetId, {
|
|
2203
|
-
slideIn: true
|
|
2204
|
-
});
|
|
2205
|
-
props.onAction && props.onAction({
|
|
2206
|
-
entity: 'Asset',
|
|
2207
|
-
type: 'edit',
|
|
2208
|
-
id: props.assetId,
|
|
2209
|
-
contentTypeId: '',
|
|
2210
|
-
slide
|
|
2211
|
-
});
|
|
2212
|
-
};
|
|
2213
|
-
|
|
2214
|
-
const onRemove = () => {
|
|
2215
|
-
props.onRemove();
|
|
2216
|
-
props.onAction && props.onAction({
|
|
2217
|
-
entity: 'Asset',
|
|
2218
|
-
type: 'delete',
|
|
2219
|
-
id: props.assetId,
|
|
2220
|
-
contentTypeId: ''
|
|
2221
|
-
});
|
|
2222
|
-
};
|
|
2223
|
-
|
|
2224
|
-
return useMemo(() => {
|
|
2225
|
-
if (status === 'error') {
|
|
2226
|
-
const card = createElement(MissingEntityCard, {
|
|
2227
|
-
entityType: "Asset",
|
|
2228
|
-
asSquare: props.viewType !== 'link',
|
|
2229
|
-
isDisabled: props.isDisabled,
|
|
2230
|
-
onRemove: onRemove
|
|
2231
|
-
});
|
|
2232
|
-
|
|
2233
|
-
if (props.renderCustomMissingEntityCard) {
|
|
2234
|
-
return props.renderCustomMissingEntityCard({
|
|
2235
|
-
defaultCard: card,
|
|
2236
|
-
entity: {
|
|
2237
|
-
id: props.assetId,
|
|
2238
|
-
type: 'Asset'
|
|
2239
|
-
}
|
|
2240
|
-
});
|
|
2241
|
-
}
|
|
2242
|
-
|
|
2243
|
-
return card;
|
|
2244
|
-
}
|
|
2245
|
-
|
|
2246
|
-
const {
|
|
2247
|
-
getEntityUrl
|
|
2248
|
-
} = props;
|
|
2249
|
-
const size = props.viewType === 'big_card' ? 'default' : 'small';
|
|
2250
|
-
const commonProps = {
|
|
2251
|
-
asset,
|
|
2252
|
-
entityUrl: getEntityUrl && getEntityUrl(props.assetId),
|
|
2253
|
-
size: size,
|
|
2254
|
-
isDisabled: props.isDisabled,
|
|
2255
|
-
localeCode: props.sdk.field.locale,
|
|
2256
|
-
defaultLocaleCode: props.sdk.locales.default,
|
|
2257
|
-
renderDragHandle: props.renderDragHandle,
|
|
2258
|
-
onEdit,
|
|
2259
|
-
onRemove
|
|
2260
|
-
};
|
|
2261
|
-
|
|
2262
|
-
if (props.viewType === 'link') {
|
|
2263
|
-
if (status === 'loading') {
|
|
2264
|
-
return createElement(EntryCard, {
|
|
2265
|
-
size: "small",
|
|
2266
|
-
isLoading: true
|
|
2267
|
-
});
|
|
2268
|
-
}
|
|
2269
|
-
|
|
2270
|
-
return createElement(WrappedAssetLink, { ...commonProps,
|
|
2271
|
-
href: commonProps.entityUrl,
|
|
2272
|
-
getEntityScheduledActions: loadEntityScheduledActions
|
|
2273
|
-
});
|
|
2274
|
-
}
|
|
2275
|
-
|
|
2276
|
-
if (status === 'loading') {
|
|
2277
|
-
return createElement(AssetCard, {
|
|
2278
|
-
size: size,
|
|
2279
|
-
isLoading: true
|
|
2280
|
-
});
|
|
2281
|
-
}
|
|
2282
|
-
|
|
2283
|
-
function renderDefaultCard(props) {
|
|
2284
|
-
// isClickable has a default value, so omit it from the props
|
|
2285
|
-
const builtinCardProps = { ...commonProps,
|
|
2286
|
-
...props,
|
|
2287
|
-
getEntityScheduledActions: loadEntityScheduledActions,
|
|
2288
|
-
asset: (props == null ? void 0 : props.entity) || commonProps.asset,
|
|
2289
|
-
getAssetUrl: getEntityUrl
|
|
2290
|
-
};
|
|
2291
|
-
return createElement(WrappedAssetCard, { ...builtinCardProps
|
|
2292
|
-
});
|
|
2293
|
-
}
|
|
2294
|
-
|
|
2295
|
-
if (props.renderCustomCard) {
|
|
2296
|
-
const customProps = { ...commonProps,
|
|
2297
|
-
entity: commonProps.asset
|
|
2298
|
-
}; // LinkActionsProps are injected higher SingleReferenceEditor/MultipleReferenceEditor
|
|
2299
|
-
|
|
2300
|
-
const renderedCustomCard = props.renderCustomCard(customProps, {}, renderDefaultCard); // Only `false` indicates to render the original card. E.g. `null` would result in no card.
|
|
2301
|
-
|
|
2302
|
-
if (renderedCustomCard !== false) {
|
|
2303
|
-
return renderedCustomCard;
|
|
2304
|
-
}
|
|
2305
|
-
}
|
|
2306
|
-
|
|
2307
|
-
return renderDefaultCard(); // eslint-disable-next-line react-hooks/exhaustive-deps -- TODO: Evaluate the dependencies
|
|
2308
|
-
}, [props, status, asset]);
|
|
2309
|
-
}
|
|
2310
|
-
|
|
2311
|
-
function SingleMediaEditor(props) {
|
|
2312
|
-
return createElement(SingleReferenceEditor, { ...props,
|
|
2313
|
-
entityType: "Asset"
|
|
2314
|
-
}, ({
|
|
2315
|
-
entityId,
|
|
2316
|
-
isDisabled,
|
|
2317
|
-
setValue
|
|
2318
|
-
}) => createElement(FetchingWrappedAssetCard, { ...props,
|
|
2319
|
-
viewType: "big_card",
|
|
2320
|
-
assetId: entityId,
|
|
2321
|
-
isDisabled: isDisabled,
|
|
2322
|
-
onRemove: () => {
|
|
2323
|
-
setValue(null);
|
|
2324
|
-
}
|
|
2325
|
-
}));
|
|
2326
|
-
}
|
|
2327
|
-
SingleMediaEditor.defaultProps = {
|
|
2328
|
-
isInitiallyDisabled: true
|
|
2329
|
-
};
|
|
2330
|
-
|
|
2331
|
-
const styles$6 = {
|
|
2332
|
-
gridContainer: /*#__PURE__*/css({
|
|
2333
|
-
position: 'relative',
|
|
2334
|
-
display: 'flex',
|
|
2335
|
-
flexWrap: 'wrap'
|
|
2336
|
-
})
|
|
2337
|
-
};
|
|
2338
|
-
function MultipleMediaEditor(props) {
|
|
2339
|
-
return createElement(MultipleReferenceEditor, { ...props,
|
|
2340
|
-
entityType: "Asset"
|
|
2341
|
-
}, childrenProps => createElement(SortableLinkList, { ...childrenProps,
|
|
2342
|
-
className: cx({
|
|
2343
|
-
[styles$6.gridContainer]: childrenProps.viewType === 'card'
|
|
2344
|
-
}),
|
|
2345
|
-
axis: childrenProps.viewType === 'card' ? 'xy' : 'y',
|
|
2346
|
-
useDragHandle: true
|
|
2347
|
-
}, ({
|
|
2348
|
-
items,
|
|
2349
|
-
item,
|
|
2350
|
-
index,
|
|
2351
|
-
isDisabled,
|
|
2352
|
-
DragHandle
|
|
2353
|
-
}) => createElement(FetchingWrappedAssetCard, { ...childrenProps,
|
|
2354
|
-
isDisabled: isDisabled,
|
|
2355
|
-
key: `${item.sys.id}-${index}`,
|
|
2356
|
-
assetId: item.sys.id,
|
|
2357
|
-
onRemove: () => {
|
|
2358
|
-
childrenProps.setValue(items.filter((_value, i) => i !== index));
|
|
2359
|
-
},
|
|
2360
|
-
renderDragHandle: DragHandle
|
|
2361
|
-
})));
|
|
2362
|
-
}
|
|
2363
|
-
MultipleMediaEditor.defaultProps = {
|
|
2364
|
-
isInitiallyDisabled: true
|
|
2365
|
-
};
|
|
2366
|
-
|
|
2367
|
-
const resolveAsset = () => Promise.resolve(); // we don't want to show scheduled actions for resources
|
|
2368
|
-
|
|
2369
|
-
|
|
2370
|
-
const resolveScheduledActions = () => Promise.resolve([]);
|
|
2371
|
-
|
|
2372
|
-
function ContentfulEntryCard({
|
|
2373
|
-
info,
|
|
2374
|
-
isDisabled,
|
|
2375
|
-
renderDragHandle,
|
|
2376
|
-
onRemove,
|
|
2377
|
-
onMoveTop,
|
|
2378
|
-
onMoveBottom,
|
|
2379
|
-
getEntryRouteHref
|
|
2380
|
-
}) {
|
|
2381
|
-
const resourceSys = info.resource.sys;
|
|
2382
|
-
const spaceId = resourceSys.space.sys.id;
|
|
2383
|
-
const environmentId = resourceSys.environment.sys.id;
|
|
2384
|
-
const entryId = resourceSys.id;
|
|
2385
|
-
const resourceHref = getEntryRouteHref({
|
|
2386
|
-
spaceId,
|
|
2387
|
-
environmentId,
|
|
2388
|
-
entryId
|
|
2389
|
-
}); // TODO: move this into `sdk.navigator.openEntry()`, note that it's signature only include the entry id (not a space or environment)
|
|
2390
|
-
|
|
2391
|
-
const openEntryDetail = () => {
|
|
2392
|
-
window.open(resourceHref, '_blank', 'noopener,noreferrer');
|
|
2393
|
-
};
|
|
2394
|
-
|
|
2395
|
-
return createElement(WrappedEntryCard, {
|
|
2396
|
-
entry: info.resource,
|
|
2397
|
-
isDisabled: isDisabled,
|
|
2398
|
-
hasCardEditActions: false,
|
|
2399
|
-
contentType: info.contentType,
|
|
2400
|
-
// we use the default locale from the space the entry belongs to
|
|
2401
|
-
// as we assume this gives a more consistent behaviour.
|
|
2402
|
-
// locales will inevitably differ from space to space, so it's likely
|
|
2403
|
-
// that the current locale does not exist in the "remote" space
|
|
2404
|
-
localeCode: info.defaultLocaleCode,
|
|
2405
|
-
defaultLocaleCode: info.defaultLocaleCode,
|
|
2406
|
-
size: "small",
|
|
2407
|
-
getAsset: resolveAsset,
|
|
2408
|
-
getEntityScheduledActions: resolveScheduledActions,
|
|
2409
|
-
spaceName: info.space.name,
|
|
2410
|
-
renderDragHandle: renderDragHandle,
|
|
2411
|
-
isClickable: true,
|
|
2412
|
-
onEdit: openEntryDetail,
|
|
2413
|
-
hasCardRemoveActions: Boolean(onRemove),
|
|
2414
|
-
onRemove: onRemove,
|
|
2415
|
-
onMoveBottom: onMoveBottom,
|
|
2416
|
-
onMoveTop: onMoveTop,
|
|
2417
|
-
entryUrl: resourceHref
|
|
2418
|
-
});
|
|
2419
|
-
}
|
|
2420
|
-
|
|
2421
|
-
const styles$7 = {
|
|
2422
|
-
card: /*#__PURE__*/css({
|
|
2423
|
-
position: 'relative'
|
|
2424
|
-
})
|
|
2425
|
-
};
|
|
2426
|
-
function UnsupportedEntityCard(props) {
|
|
2427
|
-
return React__default.createElement(Card, {
|
|
2428
|
-
className: styles$7.card
|
|
2429
|
-
}, React__default.createElement(SectionHeading, {
|
|
2430
|
-
marginBottom: "none"
|
|
2431
|
-
}, "Resource type ", props.entityType, " is currently not supported"));
|
|
2432
|
-
}
|
|
2433
|
-
|
|
2434
|
-
function ResourceCardSkeleton() {
|
|
2435
|
-
return createElement(EntryCard, {
|
|
2436
|
-
size: "small",
|
|
2437
|
-
isLoading: true
|
|
2438
|
-
});
|
|
2439
|
-
}
|
|
2440
|
-
|
|
2441
|
-
function ExistingResourceCard(props) {
|
|
2442
|
-
const {
|
|
2443
|
-
resourceLink,
|
|
2444
|
-
inView,
|
|
2445
|
-
index = 0
|
|
2446
|
-
} = props;
|
|
2447
|
-
const resourceOptions = {
|
|
2448
|
-
priority: index * -1,
|
|
2449
|
-
enabled: inView
|
|
2450
|
-
};
|
|
2451
|
-
const {
|
|
2452
|
-
data,
|
|
2453
|
-
error
|
|
2454
|
-
} = useResource(resourceLink.sys.linkType, resourceLink.sys.urn, resourceOptions);
|
|
2455
|
-
|
|
2456
|
-
if (!data && !error) {
|
|
2457
|
-
return createElement(ResourceCardSkeleton, null);
|
|
2458
|
-
}
|
|
2459
|
-
|
|
2460
|
-
if (data) {
|
|
2461
|
-
return createElement(ContentfulEntryCard, {
|
|
2462
|
-
info: data,
|
|
2463
|
-
...props
|
|
2464
|
-
});
|
|
2465
|
-
}
|
|
2466
|
-
|
|
2467
|
-
if (isUnsupportedError(error)) {
|
|
2468
|
-
return createElement(UnsupportedEntityCard, {
|
|
2469
|
-
entityType: resourceLink.sys.linkType
|
|
2470
|
-
});
|
|
2471
|
-
}
|
|
2472
|
-
|
|
2473
|
-
return createElement(MissingEntityCard, {
|
|
2474
|
-
entityType: "Entry",
|
|
2475
|
-
isDisabled: props.isDisabled,
|
|
2476
|
-
onRemove: props.onRemove
|
|
2477
|
-
});
|
|
2478
|
-
}
|
|
2479
|
-
|
|
2480
|
-
function ResourceCardWrapper(props) {
|
|
2481
|
-
if (!props.resourceLink) {
|
|
2482
|
-
return null;
|
|
2483
|
-
}
|
|
2484
|
-
|
|
2485
|
-
return createElement(ExistingResourceCard, { ...props,
|
|
2486
|
-
resourceLink: props.resourceLink,
|
|
2487
|
-
getEntryRouteHref: props.getEntryRouteHref
|
|
2488
|
-
});
|
|
2489
|
-
}
|
|
2490
|
-
|
|
2491
|
-
function ResourceCard(props) {
|
|
2492
|
-
const {
|
|
2493
|
-
ref,
|
|
2494
|
-
inView
|
|
2495
|
-
} = useInView({
|
|
2496
|
-
triggerOnce: true,
|
|
2497
|
-
rootMargin: '300px 0px 0px 300px'
|
|
2498
|
-
}); // Forma does not offer us to pass refs, so we need an additional wrapper here
|
|
2499
|
-
|
|
2500
|
-
return createElement("div", {
|
|
2501
|
-
ref: ref
|
|
2502
|
-
}, createElement(ResourceCardWrapper, { ...props,
|
|
2503
|
-
inView: inView
|
|
2504
|
-
}));
|
|
2505
|
-
}
|
|
2506
|
-
|
|
2507
|
-
const toLinkItem = (entry, apiUrl) => ({
|
|
2508
|
-
sys: {
|
|
2509
|
-
type: 'ResourceLink',
|
|
2510
|
-
linkType: 'Contentful:Entry',
|
|
2511
|
-
urn: entry.sys.urn ?? `crn:${apiUrl}:::content:spaces/${entry.sys.space.sys.id}/entries/${entry.sys.id}`
|
|
2512
|
-
}
|
|
2513
|
-
});
|
|
2514
|
-
|
|
2515
|
-
const getUpdatedValue = (field, entries, apiUrl) => {
|
|
2516
|
-
const multiple = field.type === 'Array';
|
|
2517
|
-
|
|
2518
|
-
if (multiple) {
|
|
2519
|
-
const linkItems = entries.map(entry => toLinkItem(entry, apiUrl));
|
|
2520
|
-
const prevValue = field.getValue() || [];
|
|
2521
|
-
return [...prevValue, ...linkItems];
|
|
2522
|
-
} else {
|
|
2523
|
-
return toLinkItem(entries[0], apiUrl);
|
|
2524
|
-
}
|
|
2525
|
-
};
|
|
2526
|
-
|
|
2527
|
-
function useResourceLinkActions({
|
|
2528
|
-
dialogs,
|
|
2529
|
-
field,
|
|
2530
|
-
onAfterLink,
|
|
2531
|
-
apiUrl
|
|
2532
|
-
}) {
|
|
2533
|
-
const handleAfterLink = useCallback(entries => {
|
|
2534
|
-
if (!onAfterLink) {
|
|
2535
|
-
return;
|
|
2536
|
-
}
|
|
2537
|
-
|
|
2538
|
-
entries.forEach(onAfterLink);
|
|
2539
|
-
}, [onAfterLink]);
|
|
2540
|
-
const onLinkedExisting = useMemo(() => {
|
|
2541
|
-
return entries => {
|
|
2542
|
-
const updatedValue = getUpdatedValue(field, entries, apiUrl);
|
|
2543
|
-
field.setValue(updatedValue);
|
|
2544
|
-
handleAfterLink(entries);
|
|
2545
|
-
};
|
|
2546
|
-
}, [field, handleAfterLink, apiUrl]);
|
|
2547
|
-
const multiple = field.type === 'Array';
|
|
2548
|
-
const onLinkExisting = useMemo(() => {
|
|
2549
|
-
const promptSelection = multiple ? async () => // @ts-expect-error wait for update of app-sdk version
|
|
2550
|
-
await dialogs.selectMultipleResourceEntries({
|
|
2551
|
-
// @ts-expect-error wait for update of app-sdk version
|
|
2552
|
-
allowedResources: field.allowedResources
|
|
2553
|
-
}) : async () => [// @ts-expect-error wait for update of app-sdk version
|
|
2554
|
-
await dialogs.selectSingleResourceEntry({
|
|
2555
|
-
// @ts-expect-error wait for update of app-sdk version
|
|
2556
|
-
allowedResources: field.allowedResources
|
|
2557
|
-
})];
|
|
2558
|
-
return async () => {
|
|
2559
|
-
const res = await promptSelection();
|
|
2560
|
-
|
|
2561
|
-
if (!res) {
|
|
2562
|
-
return;
|
|
2563
|
-
}
|
|
2564
|
-
|
|
2565
|
-
onLinkedExisting(res);
|
|
2566
|
-
}; // @ts-expect-error wait for update of app-sdk version
|
|
2567
|
-
}, [dialogs, field.allowedResources, multiple, onLinkedExisting]);
|
|
2568
|
-
return {
|
|
2569
|
-
onLinkExisting,
|
|
2570
|
-
onLinkedExisting,
|
|
2571
|
-
// hardcoded values to match interface for standard reference field actions
|
|
2572
|
-
entityType: 'Entry',
|
|
2573
|
-
contentTypes: [],
|
|
2574
|
-
canCreateEntity: false,
|
|
2575
|
-
canLinkMultiple: multiple,
|
|
2576
|
-
canLinkEntity: true,
|
|
2577
|
-
isDisabled: false,
|
|
2578
|
-
isEmpty: false,
|
|
2579
|
-
isFull: false,
|
|
2580
|
-
// eslint-disable-next-line -- hardcoded values to match interface for standard reference field actions
|
|
2581
|
-
onCreate: async () => {},
|
|
2582
|
-
// eslint-disable-next-line -- hardcoded values to match interface for standard reference field actions
|
|
2583
|
-
onCreated: () => {}
|
|
2584
|
-
};
|
|
2585
|
-
}
|
|
2586
|
-
|
|
2587
|
-
function ResourceEditor(props) {
|
|
2588
|
-
const {
|
|
2589
|
-
setValue,
|
|
2590
|
-
items,
|
|
2591
|
-
apiUrl
|
|
2592
|
-
} = props;
|
|
2593
|
-
const onSortStart = useCallback((_, event) => event.preventDefault(), []);
|
|
2594
|
-
const onSortEnd = useCallback(({
|
|
2595
|
-
oldIndex,
|
|
2596
|
-
newIndex
|
|
2597
|
-
}) => {
|
|
2598
|
-
const newItems = arrayMove(items, oldIndex, newIndex);
|
|
2599
|
-
setValue(newItems);
|
|
2600
|
-
}, [items, setValue]);
|
|
2601
|
-
const onMove = useCallback((oldIndex, newIndex) => {
|
|
2602
|
-
const newItems = arrayMove(items, oldIndex, newIndex);
|
|
2603
|
-
setValue(newItems);
|
|
2604
|
-
}, [items, setValue]);
|
|
2605
|
-
const onRemoteItemAtIndex = useCallback(index => {
|
|
2606
|
-
setValue(items.filter((_v, i) => i !== index));
|
|
2607
|
-
}, [items, setValue]);
|
|
2608
|
-
const {
|
|
2609
|
-
dialogs,
|
|
2610
|
-
field
|
|
2611
|
-
} = props.sdk;
|
|
2612
|
-
const linkActionsProps = useResourceLinkActions({
|
|
2613
|
-
dialogs,
|
|
2614
|
-
field,
|
|
2615
|
-
apiUrl
|
|
2616
|
-
});
|
|
2617
|
-
return createElement(Fragment, null, props.children({ ...props,
|
|
2618
|
-
onSortStart,
|
|
2619
|
-
onSortEnd,
|
|
2620
|
-
onMove,
|
|
2621
|
-
onRemoteItemAtIndex
|
|
2622
|
-
}), createElement(CombinedLinkEntityActions, { ...linkActionsProps,
|
|
2623
|
-
renderCustomActions: props.renderCustomActions
|
|
2624
|
-
}));
|
|
2625
|
-
} // provides memoized callbacks bound to a given item
|
|
2626
|
-
|
|
2627
|
-
|
|
2628
|
-
function WithPerItemCallbacks({
|
|
2629
|
-
listLength,
|
|
2630
|
-
index,
|
|
2631
|
-
onMove,
|
|
2632
|
-
onRemoteItemAtIndex,
|
|
2633
|
-
children
|
|
2634
|
-
}) {
|
|
2635
|
-
const handleMoveTop = useMemo(() => index > 0 ? () => onMove(index, 0) : undefined, [index, onMove]);
|
|
2636
|
-
const handleMoveBottom = useMemo(() => index < listLength - 1 ? () => onMove(index, listLength - 1) : undefined, [index, onMove, listLength]);
|
|
2637
|
-
const handleRemove = useCallback(() => onRemoteItemAtIndex(index), [index, onRemoteItemAtIndex]);
|
|
2638
|
-
return createElement(Fragment, null, children({
|
|
2639
|
-
onMoveBottom: handleMoveBottom,
|
|
2640
|
-
onMoveTop: handleMoveTop,
|
|
2641
|
-
onRemove: handleRemove
|
|
2642
|
-
}));
|
|
2643
|
-
}
|
|
2644
|
-
|
|
2645
|
-
const EMPTY_ARRAY = [];
|
|
2646
|
-
function MultipleResourceReferenceEditor(props) {
|
|
2647
|
-
return createElement(EntityProvider, {
|
|
2648
|
-
sdk: props.sdk
|
|
2649
|
-
}, createElement(FieldConnector, {
|
|
2650
|
-
throttle: 0,
|
|
2651
|
-
field: props.sdk.field,
|
|
2652
|
-
isInitiallyDisabled: props.isInitiallyDisabled,
|
|
2653
|
-
isEqualValues: deepEqual
|
|
2654
|
-
}, ({
|
|
2655
|
-
value,
|
|
2656
|
-
disabled,
|
|
2657
|
-
setValue,
|
|
2658
|
-
externalReset
|
|
2659
|
-
}) => {
|
|
2660
|
-
return createElement(ResourceEditor, { ...props,
|
|
2661
|
-
items: value || EMPTY_ARRAY,
|
|
2662
|
-
isDisabled: disabled,
|
|
2663
|
-
setValue: setValue,
|
|
2664
|
-
renderCustomActions: props.renderCustomActions,
|
|
2665
|
-
key: `${externalReset}-list`
|
|
2666
|
-
}, editorProps => createElement(SortableLinkList, { ...editorProps
|
|
2667
|
-
}, ({
|
|
2668
|
-
item,
|
|
2669
|
-
isDisabled,
|
|
2670
|
-
DragHandle,
|
|
2671
|
-
index
|
|
2672
|
-
}) => createElement(WithPerItemCallbacks, {
|
|
2673
|
-
index: index,
|
|
2674
|
-
onMove: editorProps.onMove,
|
|
2675
|
-
onRemoteItemAtIndex: editorProps.onRemoteItemAtIndex,
|
|
2676
|
-
listLength: (value == null ? void 0 : value.length) || 0
|
|
2677
|
-
}, ({
|
|
2678
|
-
onMoveBottom,
|
|
2679
|
-
onMoveTop,
|
|
2680
|
-
onRemove
|
|
2681
|
-
}) => createElement(ResourceCard, {
|
|
2682
|
-
index: index,
|
|
2683
|
-
resourceLink: item,
|
|
2684
|
-
isDisabled: isDisabled,
|
|
2685
|
-
renderDragHandle: DragHandle,
|
|
2686
|
-
onMoveTop: onMoveTop,
|
|
2687
|
-
onMoveBottom: onMoveBottom,
|
|
2688
|
-
onRemove: onRemove,
|
|
2689
|
-
getEntryRouteHref: props.getEntryRouteHref
|
|
2690
|
-
}))));
|
|
2691
|
-
}));
|
|
2692
|
-
}
|
|
2693
|
-
|
|
2694
|
-
function SingleResourceReferenceEditor(props) {
|
|
2695
|
-
const {
|
|
2696
|
-
dialogs,
|
|
2697
|
-
field
|
|
2698
|
-
} = props.sdk;
|
|
2699
|
-
const linkActionsProps = useResourceLinkActions({
|
|
2700
|
-
dialogs,
|
|
2701
|
-
field,
|
|
2702
|
-
apiUrl: props.apiUrl
|
|
2703
|
-
});
|
|
2704
|
-
return createElement(EntityProvider, {
|
|
2705
|
-
sdk: props.sdk
|
|
2706
|
-
}, createElement(FieldConnector, {
|
|
2707
|
-
throttle: 0,
|
|
2708
|
-
field: props.sdk.field,
|
|
2709
|
-
isInitiallyDisabled: props.isInitiallyDisabled,
|
|
2710
|
-
isEqualValues: deepEqual
|
|
2711
|
-
}, ({
|
|
2712
|
-
value,
|
|
2713
|
-
disabled
|
|
2714
|
-
}) => {
|
|
2715
|
-
return value ? createElement(ResourceCard, {
|
|
2716
|
-
onRemove: () => props.sdk.field.removeValue(),
|
|
2717
|
-
resourceLink: value,
|
|
2718
|
-
isDisabled: disabled,
|
|
2719
|
-
getEntryRouteHref: props.getEntryRouteHref
|
|
2720
|
-
}) : createElement(CombinedLinkEntityActions, { ...linkActionsProps,
|
|
2721
|
-
renderCustomActions: props.renderCustomActions
|
|
2722
|
-
});
|
|
2723
|
-
}));
|
|
2724
|
-
}
|
|
2725
|
-
|
|
2726
|
-
export { AssetThumbnail, CombinedLinkActions, CreateEntryLinkButton, CreateEntryMenuTrigger, EntityProvider, MissingEntityCard, MultipleEntryReferenceEditor, MultipleMediaEditor, MultipleResourceReferenceEditor, ScheduledIconWithTooltip, SingleEntryReferenceEditor, SingleMediaEditor, SingleResourceReferenceEditor, SortableLinkList, WrappedAssetCard, WrappedEntryCard, getScheduleTooltipContent, useEntity, useEntityLoader, useResource };
|
|
2727
|
-
//# sourceMappingURL=field-editor-reference.esm.js.map
|