@contentful/field-editor-reference 5.30.14 → 5.31.1
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/assets/WrappedAssetCard/FetchingWrappedAssetCard.js +4 -0
- package/dist/cjs/assets/WrappedAssetCard/WrappedAssetCard.js +5 -5
- package/dist/cjs/assets/WrappedAssetCard/WrappedAssetLink.js +5 -2
- package/dist/cjs/components/CreateEntryLinkButton/CreateEntryMenuTrigger.js +11 -5
- package/dist/cjs/components/CreateEntryLinkButton/CreateEntryMenuTrigger.spec.js +41 -0
- package/dist/cjs/components/EntityStatusBadge/EntityStatusBadge.js +12 -2
- package/dist/cjs/entries/WrappedEntryCard/FetchingWrappedEntryCard.js +4 -0
- package/dist/cjs/entries/WrappedEntryCard/WrappedEntryCard.js +6 -5
- package/dist/esm/assets/WrappedAssetCard/FetchingWrappedAssetCard.js +4 -0
- package/dist/esm/assets/WrappedAssetCard/WrappedAssetCard.js +6 -6
- package/dist/esm/assets/WrappedAssetCard/WrappedAssetLink.js +5 -2
- package/dist/esm/components/CreateEntryLinkButton/CreateEntryMenuTrigger.js +12 -6
- package/dist/esm/components/CreateEntryLinkButton/CreateEntryMenuTrigger.spec.js +41 -0
- package/dist/esm/components/EntityStatusBadge/EntityStatusBadge.js +12 -2
- package/dist/esm/entries/WrappedEntryCard/FetchingWrappedEntryCard.js +4 -0
- package/dist/esm/entries/WrappedEntryCard/WrappedEntryCard.js +7 -6
- package/dist/types/assets/WrappedAssetCard/WrappedAssetCard.d.ts +4 -0
- package/dist/types/assets/WrappedAssetCard/WrappedAssetLink.d.ts +4 -1
- package/dist/types/common/customCardTypes.d.ts +4 -0
- package/dist/types/components/EntityStatusBadge/EntityStatusBadge.d.ts +8 -2
- package/dist/types/entries/WrappedEntryCard/WrappedEntryCard.d.ts +4 -0
- package/package.json +2 -2
|
@@ -10,6 +10,7 @@ Object.defineProperty(exports, "FetchingWrappedAssetCard", {
|
|
|
10
10
|
});
|
|
11
11
|
const _react = _interop_require_wildcard(require("react"));
|
|
12
12
|
const _f36components = require("@contentful/f36-components");
|
|
13
|
+
const _fieldeditorshared = require("@contentful/field-editor-shared");
|
|
13
14
|
const _EntityStore = require("../../common/EntityStore");
|
|
14
15
|
const _components = require("../../components");
|
|
15
16
|
const _WrappedAssetCard = require("./WrappedAssetCard");
|
|
@@ -62,6 +63,7 @@ function FetchingWrappedAssetCard(props) {
|
|
|
62
63
|
getEntityScheduledActions,
|
|
63
64
|
props.assetId
|
|
64
65
|
]);
|
|
66
|
+
const localesStatusMap = (0, _fieldeditorshared.useAsyncLocalePublishStatus)(asset, props.sdk.parameters.instance.privateLocales);
|
|
65
67
|
_react.useEffect(()=>{
|
|
66
68
|
if (asset) {
|
|
67
69
|
props.onAction && props.onAction({
|
|
@@ -124,6 +126,8 @@ function FetchingWrappedAssetCard(props) {
|
|
|
124
126
|
onEdit,
|
|
125
127
|
onRemove,
|
|
126
128
|
useLocalizedEntityStatus: props.sdk.parameters.instance.useLocalizedEntityStatus,
|
|
129
|
+
localesStatusMap,
|
|
130
|
+
activeLocales: props.sdk.parameters.instance.activeLocales,
|
|
127
131
|
isLocalized: !!('localized' in props.sdk.field && props.sdk.field.localized)
|
|
128
132
|
};
|
|
129
133
|
if (props.viewType === 'link') {
|
|
@@ -114,12 +114,12 @@ const WrappedAssetCard = (props)=>{
|
|
|
114
114
|
badge: _react.createElement(_components.EntityStatusBadge, {
|
|
115
115
|
getEntityScheduledActions: props.getEntityScheduledActions,
|
|
116
116
|
entityType: "Asset",
|
|
117
|
-
|
|
118
|
-
|
|
117
|
+
status: status,
|
|
118
|
+
useLocalizedEntityStatus: props.useLocalizedEntityStatus,
|
|
119
|
+
entity: props.asset,
|
|
120
|
+
localesStatusMap: props.localesStatusMap,
|
|
121
|
+
activeLocales: props.activeLocales
|
|
119
122
|
}),
|
|
120
|
-
icon: !props.isLocalized && props.useLocalizedEntityStatus ? _react.createElement(_f36components.Badge, {
|
|
121
|
-
variant: "secondary"
|
|
122
|
-
}, "Default") : null,
|
|
123
123
|
src: entityFile && entityFile.url ? size === 'small' ? `${entityFile.url}?w=150&h=150&fit=thumb` : `${entityFile.url}?h=300` : '',
|
|
124
124
|
onClick: isClickable ? (e)=>{
|
|
125
125
|
e.preventDefault();
|
|
@@ -80,8 +80,11 @@ const WrappedAssetLink = (props)=>{
|
|
|
80
80
|
badge: _react.createElement(_components.EntityStatusBadge, {
|
|
81
81
|
getEntityScheduledActions: props.getEntityScheduledActions,
|
|
82
82
|
entityType: "Asset",
|
|
83
|
-
|
|
84
|
-
|
|
83
|
+
status: status,
|
|
84
|
+
useLocalizedEntityStatus: props.useLocalizedEntityStatus,
|
|
85
|
+
entity: props.asset,
|
|
86
|
+
localesStatusMap: props.localesStatusMap,
|
|
87
|
+
activeLocales: props.activeLocales
|
|
85
88
|
}),
|
|
86
89
|
thumbnailElement: entityFile && (0, _fieldeditorshared.isValidImage)(entityFile) ? _react.createElement(_components.AssetThumbnail, {
|
|
87
90
|
file: entityFile
|
|
@@ -102,6 +102,12 @@ const CreateEntryMenuTrigger = ({ contentTypes, suggestedContentTypeId, contentT
|
|
|
102
102
|
const textField = (0, _react.useRef)(null);
|
|
103
103
|
const menuListRef = (0, _react.useRef)(null);
|
|
104
104
|
const [dropdownWidth, setDropdownWidth] = (0, _react.useState)();
|
|
105
|
+
const filteredContentTypes = (0, _react.useMemo)(()=>contentTypes.filter((contentType)=>{
|
|
106
|
+
const annotations = (0, _get.default)(contentType, 'metadata.annotations.ContentType', []);
|
|
107
|
+
return !annotations.some((annotation)=>(0, _get.default)(annotation, 'sys.id') === 'Contentful:ExperienceType');
|
|
108
|
+
}), [
|
|
109
|
+
contentTypes
|
|
110
|
+
]);
|
|
105
111
|
const hasDropdown = contentTypes.length > 1 || !!customDropdownItems;
|
|
106
112
|
const closeMenu = ()=>setOpen(false);
|
|
107
113
|
(0, _react.useEffect)(()=>{
|
|
@@ -148,10 +154,10 @@ const CreateEntryMenuTrigger = ({ contentTypes, suggestedContentTypeId, contentT
|
|
|
148
154
|
const renderSearchResultsCount = (resultsLength)=>resultsLength ? _react.default.createElement(_f36components.Menu.SectionTitle, {
|
|
149
155
|
testId: "add-entru-menu-search-results"
|
|
150
156
|
}, resultsLength, " result", resultsLength > 1 ? 's' : '') : null;
|
|
151
|
-
const isSearchable =
|
|
157
|
+
const isSearchable = filteredContentTypes.length > MAX_ITEMS_WITHOUT_SEARCH;
|
|
152
158
|
const maxDropdownHeight = suggestedContentTypeId ? 300 : 250;
|
|
153
|
-
const suggestedContentType =
|
|
154
|
-
const
|
|
159
|
+
const suggestedContentType = filteredContentTypes.find((ct)=>ct.sys.id === suggestedContentTypeId);
|
|
160
|
+
const searchFilteredContentTypes = filteredContentTypes.filter((ct)=>!searchInput || (0, _get.default)(ct, 'name', 'Untitled').toLowerCase().includes(searchInput.toLowerCase()));
|
|
155
161
|
return _react.default.createElement("span", {
|
|
156
162
|
className: styles.wrapper,
|
|
157
163
|
ref: wrapper,
|
|
@@ -185,10 +191,10 @@ const CreateEntryMenuTrigger = ({ contentTypes, suggestedContentTypeId, contentT
|
|
|
185
191
|
onChange: (e)=>setSearchInput(e.target.value)
|
|
186
192
|
}), _react.default.createElement(_f36icons.SearchIcon, {
|
|
187
193
|
className: styles.searchIcon
|
|
188
|
-
})), _react.default.createElement(_f36components.Menu.Divider, null)), searchInput && renderSearchResultsCount(
|
|
194
|
+
})), _react.default.createElement(_f36components.Menu.Divider, null)), searchInput && renderSearchResultsCount(searchFilteredContentTypes.length), suggestedContentType && !searchInput && _react.default.createElement(_react.default.Fragment, null, _react.default.createElement(_f36components.Menu.SectionTitle, null, "Suggested Content Type"), _react.default.createElement(_f36components.Menu.Item, {
|
|
189
195
|
testId: "suggested",
|
|
190
196
|
onClick: ()=>handleSelect(suggestedContentType)
|
|
191
|
-
}, (0, _get.default)(suggestedContentType, 'name')), _react.default.createElement(_f36components.Menu.Divider, null)), !searchInput && _react.default.createElement(_f36components.Menu.SectionTitle, null, contentTypesLabel),
|
|
197
|
+
}, (0, _get.default)(suggestedContentType, 'name')), _react.default.createElement(_f36components.Menu.Divider, null)), !searchInput && _react.default.createElement(_f36components.Menu.SectionTitle, null, contentTypesLabel), searchFilteredContentTypes.length ? searchFilteredContentTypes.map((contentType, i)=>_react.default.createElement(_f36components.Menu.Item, {
|
|
192
198
|
testId: "contentType",
|
|
193
199
|
key: `${(0, _get.default)(contentType, 'name')}-${i}`,
|
|
194
200
|
onClick: ()=>handleSelect(contentType)
|
|
@@ -76,6 +76,25 @@ const CONTENT_TYPE_3 = {
|
|
|
76
76
|
id: 'ID_3'
|
|
77
77
|
}
|
|
78
78
|
};
|
|
79
|
+
const EXPERIENCE_TYPE = {
|
|
80
|
+
name: 'experience-type',
|
|
81
|
+
sys: {
|
|
82
|
+
id: 'ID_4'
|
|
83
|
+
},
|
|
84
|
+
metadata: {
|
|
85
|
+
annotations: {
|
|
86
|
+
ContentType: [
|
|
87
|
+
{
|
|
88
|
+
sys: {
|
|
89
|
+
id: 'Contentful:ExperienceType',
|
|
90
|
+
type: 'Link',
|
|
91
|
+
linkType: 'Annotation'
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
]
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
};
|
|
79
98
|
describe('CreateEntryMenuTrigger general', ()=>{
|
|
80
99
|
const props = {
|
|
81
100
|
contentTypes: [
|
|
@@ -189,4 +208,26 @@ describe('CreateEntryMenuTrigger general', ()=>{
|
|
|
189
208
|
expect(suggestedContentType).toBeDefined();
|
|
190
209
|
expect(suggestedContentType.textContent).toBe(props.contentTypes[0].name);
|
|
191
210
|
});
|
|
211
|
+
it('filters out content types with Contentful:ExperienceType annotation', ()=>{
|
|
212
|
+
const contentTypesWithExperience = [
|
|
213
|
+
CONTENT_TYPE_1,
|
|
214
|
+
CONTENT_TYPE_2,
|
|
215
|
+
CONTENT_TYPE_3,
|
|
216
|
+
EXPERIENCE_TYPE
|
|
217
|
+
];
|
|
218
|
+
const { getByTestId, getAllByTestId } = (0, _react1.render)(_react.createElement(_CreateEntryMenuTrigger.CreateEntryMenuTrigger, {
|
|
219
|
+
...props,
|
|
220
|
+
contentTypes: contentTypesWithExperience
|
|
221
|
+
}, stub));
|
|
222
|
+
(0, _react1.act)(()=>{
|
|
223
|
+
_react1.fireEvent.click(getByTestId('menu-trigger'));
|
|
224
|
+
});
|
|
225
|
+
const contentTypeItems = getAllByTestId('contentType');
|
|
226
|
+
expect(contentTypeItems).toHaveLength(3);
|
|
227
|
+
expect(contentTypeItems[0].textContent).toBe('name-1');
|
|
228
|
+
expect(contentTypeItems[1].textContent).toBe('name-2');
|
|
229
|
+
expect(contentTypeItems[2].textContent).toBe('name-3');
|
|
230
|
+
const experienceTypeItem = contentTypeItems.find((item)=>item.textContent === 'experience-type');
|
|
231
|
+
expect(experienceTypeItem).toBeUndefined();
|
|
232
|
+
});
|
|
192
233
|
});
|
|
@@ -10,6 +10,7 @@ Object.defineProperty(exports, "EntityStatusBadge", {
|
|
|
10
10
|
});
|
|
11
11
|
const _react = _interop_require_default(require("react"));
|
|
12
12
|
const _f36components = require("@contentful/f36-components");
|
|
13
|
+
const _fieldeditorshared = require("@contentful/field-editor-shared");
|
|
13
14
|
const _ScheduledIconWithTooltip = require("../ScheduledIconWithTooltip/ScheduledIconWithTooltip");
|
|
14
15
|
const _ScheduleTooltip = require("../ScheduledIconWithTooltip/ScheduleTooltip");
|
|
15
16
|
function _interop_require_default(obj) {
|
|
@@ -17,12 +18,21 @@ function _interop_require_default(obj) {
|
|
|
17
18
|
default: obj
|
|
18
19
|
};
|
|
19
20
|
}
|
|
20
|
-
function EntityStatusBadge({
|
|
21
|
+
function EntityStatusBadge({ entityType, getEntityScheduledActions, status, useLocalizedEntityStatus, localesStatusMap, activeLocales, entity, ...props }) {
|
|
21
22
|
const { isError, isLoading, jobs } = (0, _ScheduledIconWithTooltip.useScheduledActions)({
|
|
22
|
-
entityId,
|
|
23
|
+
entityId: entity.sys.id,
|
|
23
24
|
entityType,
|
|
24
25
|
getEntityScheduledActions
|
|
25
26
|
});
|
|
27
|
+
if (useLocalizedEntityStatus && activeLocales && localesStatusMap) {
|
|
28
|
+
return _react.default.createElement(_fieldeditorshared.LocalePublishingPopover, {
|
|
29
|
+
entity: entity,
|
|
30
|
+
jobs: jobs,
|
|
31
|
+
isScheduled: jobs.length !== 0,
|
|
32
|
+
localesStatusMap: localesStatusMap,
|
|
33
|
+
activeLocales: activeLocales
|
|
34
|
+
});
|
|
35
|
+
}
|
|
26
36
|
if (isError || isLoading || jobs.length === 0) {
|
|
27
37
|
return _react.default.createElement(_f36components.EntityStatusBadge, {
|
|
28
38
|
...props,
|
|
@@ -10,6 +10,7 @@ Object.defineProperty(exports, "FetchingWrappedEntryCard", {
|
|
|
10
10
|
});
|
|
11
11
|
const _react = _interop_require_wildcard(require("react"));
|
|
12
12
|
const _f36components = require("@contentful/f36-components");
|
|
13
|
+
const _fieldeditorshared = require("@contentful/field-editor-shared");
|
|
13
14
|
const _get = _interop_require_default(require("lodash/get"));
|
|
14
15
|
const _EntityStore = require("../../common/EntityStore");
|
|
15
16
|
const _components = require("../../components");
|
|
@@ -86,6 +87,7 @@ function FetchingWrappedEntryCard(props) {
|
|
|
86
87
|
getEntityScheduledActions,
|
|
87
88
|
props.entryId
|
|
88
89
|
]);
|
|
90
|
+
const localesStatusMap = (0, _fieldeditorshared.useAsyncLocalePublishStatus)(entry, props.sdk.parameters.instance.privateLocales);
|
|
89
91
|
const size = props.viewType === 'link' ? 'small' : 'default';
|
|
90
92
|
const { getEntity } = (0, _EntityStore.useEntityLoader)();
|
|
91
93
|
const getAsset = (assetId)=>getEntity('Asset', assetId);
|
|
@@ -161,6 +163,8 @@ function FetchingWrappedEntryCard(props) {
|
|
|
161
163
|
onMoveBottom: props.onMoveBottom,
|
|
162
164
|
isBeingDragged: props.isBeingDragged,
|
|
163
165
|
useLocalizedEntityStatus: props.sdk.parameters.instance.useLocalizedEntityStatus,
|
|
166
|
+
localesStatusMap,
|
|
167
|
+
activeLocales: props.sdk.parameters.instance.activeLocales,
|
|
164
168
|
isLocalized: !!('localized' in props.sdk.field && props.sdk.field.localized)
|
|
165
169
|
};
|
|
166
170
|
const { hasCardEditActions, hasCardMoveActions, hasCardRemoveActions } = props;
|
|
@@ -123,16 +123,17 @@ function WrappedEntryCard(props) {
|
|
|
123
123
|
isSelected: props.isSelected,
|
|
124
124
|
badge: _react.createElement(_components.EntityStatusBadge, {
|
|
125
125
|
status: status,
|
|
126
|
-
entityId: props.entry.sys.id,
|
|
127
126
|
entityType: "Entry",
|
|
128
|
-
getEntityScheduledActions: props.getEntityScheduledActions
|
|
127
|
+
getEntityScheduledActions: props.getEntityScheduledActions,
|
|
128
|
+
useLocalizedEntityStatus: props.useLocalizedEntityStatus,
|
|
129
|
+
entity: props.entry,
|
|
130
|
+
localesStatusMap: props.localesStatusMap,
|
|
131
|
+
activeLocales: props.activeLocales
|
|
129
132
|
}),
|
|
130
133
|
icon: props.spaceName ? _react.createElement(_SpaceName.SpaceName, {
|
|
131
134
|
spaceName: props.spaceName,
|
|
132
135
|
environmentName: props.entry.sys.environment.sys.id
|
|
133
|
-
}) :
|
|
134
|
-
variant: "secondary"
|
|
135
|
-
}, "Default") : null,
|
|
136
|
+
}) : null,
|
|
136
137
|
thumbnailElement: file && (0, _fieldeditorshared.isValidImage)(file) ? _react.createElement(_components.AssetThumbnail, {
|
|
137
138
|
file: file
|
|
138
139
|
}) : undefined,
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
2
|
import { AssetCard, EntryCard } from '@contentful/f36-components';
|
|
3
|
+
import { useAsyncLocalePublishStatus } from '@contentful/field-editor-shared';
|
|
3
4
|
import { useEntity, useEntityLoader } from '../../common/EntityStore';
|
|
4
5
|
import { MissingAssetCard } from '../../components';
|
|
5
6
|
import { WrappedAssetCard } from './WrappedAssetCard';
|
|
@@ -11,6 +12,7 @@ export function FetchingWrappedAssetCard(props) {
|
|
|
11
12
|
getEntityScheduledActions,
|
|
12
13
|
props.assetId
|
|
13
14
|
]);
|
|
15
|
+
const localesStatusMap = useAsyncLocalePublishStatus(asset, props.sdk.parameters.instance.privateLocales);
|
|
14
16
|
React.useEffect(()=>{
|
|
15
17
|
if (asset) {
|
|
16
18
|
props.onAction && props.onAction({
|
|
@@ -73,6 +75,8 @@ export function FetchingWrappedAssetCard(props) {
|
|
|
73
75
|
onEdit,
|
|
74
76
|
onRemove,
|
|
75
77
|
useLocalizedEntityStatus: props.sdk.parameters.instance.useLocalizedEntityStatus,
|
|
78
|
+
localesStatusMap,
|
|
79
|
+
activeLocales: props.sdk.parameters.instance.activeLocales,
|
|
76
80
|
isLocalized: !!('localized' in props.sdk.field && props.sdk.field.localized)
|
|
77
81
|
};
|
|
78
82
|
if (props.viewType === 'link') {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
|
-
import { AssetCard
|
|
2
|
+
import { AssetCard } from '@contentful/f36-components';
|
|
3
3
|
import { entityHelpers } from '@contentful/field-editor-shared';
|
|
4
4
|
import mimetype from '@contentful/mimetype';
|
|
5
5
|
import { EntityStatusBadge, MissingAssetCard } from '../../components';
|
|
@@ -58,12 +58,12 @@ export const WrappedAssetCard = (props)=>{
|
|
|
58
58
|
badge: React.createElement(EntityStatusBadge, {
|
|
59
59
|
getEntityScheduledActions: props.getEntityScheduledActions,
|
|
60
60
|
entityType: "Asset",
|
|
61
|
-
|
|
62
|
-
|
|
61
|
+
status: status,
|
|
62
|
+
useLocalizedEntityStatus: props.useLocalizedEntityStatus,
|
|
63
|
+
entity: props.asset,
|
|
64
|
+
localesStatusMap: props.localesStatusMap,
|
|
65
|
+
activeLocales: props.activeLocales
|
|
63
66
|
}),
|
|
64
|
-
icon: !props.isLocalized && props.useLocalizedEntityStatus ? React.createElement(Badge, {
|
|
65
|
-
variant: "secondary"
|
|
66
|
-
}, "Default") : null,
|
|
67
67
|
src: entityFile && entityFile.url ? size === 'small' ? `${entityFile.url}?w=150&h=150&fit=thumb` : `${entityFile.url}?h=300` : '',
|
|
68
68
|
onClick: isClickable ? (e)=>{
|
|
69
69
|
e.preventDefault();
|
|
@@ -29,8 +29,11 @@ export const WrappedAssetLink = (props)=>{
|
|
|
29
29
|
badge: React.createElement(EntityStatusBadge, {
|
|
30
30
|
getEntityScheduledActions: props.getEntityScheduledActions,
|
|
31
31
|
entityType: "Asset",
|
|
32
|
-
|
|
33
|
-
|
|
32
|
+
status: status,
|
|
33
|
+
useLocalizedEntityStatus: props.useLocalizedEntityStatus,
|
|
34
|
+
entity: props.asset,
|
|
35
|
+
localesStatusMap: props.localesStatusMap,
|
|
36
|
+
activeLocales: props.activeLocales
|
|
34
37
|
}),
|
|
35
38
|
thumbnailElement: entityFile && isValidImage(entityFile) ? React.createElement(AssetThumbnail, {
|
|
36
39
|
file: entityFile
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React, { useState, useRef, useEffect } from 'react';
|
|
1
|
+
import React, { useState, useRef, useEffect, useMemo } from 'react';
|
|
2
2
|
import { TextInput, Menu } from '@contentful/f36-components';
|
|
3
3
|
import { SearchIcon } from '@contentful/f36-icons';
|
|
4
4
|
import tokens from '@contentful/f36-tokens';
|
|
@@ -46,6 +46,12 @@ export const CreateEntryMenuTrigger = ({ contentTypes, suggestedContentTypeId, c
|
|
|
46
46
|
const textField = useRef(null);
|
|
47
47
|
const menuListRef = useRef(null);
|
|
48
48
|
const [dropdownWidth, setDropdownWidth] = useState();
|
|
49
|
+
const filteredContentTypes = useMemo(()=>contentTypes.filter((contentType)=>{
|
|
50
|
+
const annotations = get(contentType, 'metadata.annotations.ContentType', []);
|
|
51
|
+
return !annotations.some((annotation)=>get(annotation, 'sys.id') === 'Contentful:ExperienceType');
|
|
52
|
+
}), [
|
|
53
|
+
contentTypes
|
|
54
|
+
]);
|
|
49
55
|
const hasDropdown = contentTypes.length > 1 || !!customDropdownItems;
|
|
50
56
|
const closeMenu = ()=>setOpen(false);
|
|
51
57
|
useEffect(()=>{
|
|
@@ -92,10 +98,10 @@ export const CreateEntryMenuTrigger = ({ contentTypes, suggestedContentTypeId, c
|
|
|
92
98
|
const renderSearchResultsCount = (resultsLength)=>resultsLength ? React.createElement(Menu.SectionTitle, {
|
|
93
99
|
testId: "add-entru-menu-search-results"
|
|
94
100
|
}, resultsLength, " result", resultsLength > 1 ? 's' : '') : null;
|
|
95
|
-
const isSearchable =
|
|
101
|
+
const isSearchable = filteredContentTypes.length > MAX_ITEMS_WITHOUT_SEARCH;
|
|
96
102
|
const maxDropdownHeight = suggestedContentTypeId ? 300 : 250;
|
|
97
|
-
const suggestedContentType =
|
|
98
|
-
const
|
|
103
|
+
const suggestedContentType = filteredContentTypes.find((ct)=>ct.sys.id === suggestedContentTypeId);
|
|
104
|
+
const searchFilteredContentTypes = filteredContentTypes.filter((ct)=>!searchInput || get(ct, 'name', 'Untitled').toLowerCase().includes(searchInput.toLowerCase()));
|
|
99
105
|
return React.createElement("span", {
|
|
100
106
|
className: styles.wrapper,
|
|
101
107
|
ref: wrapper,
|
|
@@ -129,10 +135,10 @@ export const CreateEntryMenuTrigger = ({ contentTypes, suggestedContentTypeId, c
|
|
|
129
135
|
onChange: (e)=>setSearchInput(e.target.value)
|
|
130
136
|
}), React.createElement(SearchIcon, {
|
|
131
137
|
className: styles.searchIcon
|
|
132
|
-
})), React.createElement(Menu.Divider, null)), searchInput && renderSearchResultsCount(
|
|
138
|
+
})), React.createElement(Menu.Divider, null)), searchInput && renderSearchResultsCount(searchFilteredContentTypes.length), suggestedContentType && !searchInput && React.createElement(React.Fragment, null, React.createElement(Menu.SectionTitle, null, "Suggested Content Type"), React.createElement(Menu.Item, {
|
|
133
139
|
testId: "suggested",
|
|
134
140
|
onClick: ()=>handleSelect(suggestedContentType)
|
|
135
|
-
}, get(suggestedContentType, 'name')), React.createElement(Menu.Divider, null)), !searchInput && React.createElement(Menu.SectionTitle, null, contentTypesLabel),
|
|
141
|
+
}, get(suggestedContentType, 'name')), React.createElement(Menu.Divider, null)), !searchInput && React.createElement(Menu.SectionTitle, null, contentTypesLabel), searchFilteredContentTypes.length ? searchFilteredContentTypes.map((contentType, i)=>React.createElement(Menu.Item, {
|
|
136
142
|
testId: "contentType",
|
|
137
143
|
key: `${get(contentType, 'name')}-${i}`,
|
|
138
144
|
onClick: ()=>handleSelect(contentType)
|
|
@@ -26,6 +26,25 @@ const CONTENT_TYPE_3 = {
|
|
|
26
26
|
id: 'ID_3'
|
|
27
27
|
}
|
|
28
28
|
};
|
|
29
|
+
const EXPERIENCE_TYPE = {
|
|
30
|
+
name: 'experience-type',
|
|
31
|
+
sys: {
|
|
32
|
+
id: 'ID_4'
|
|
33
|
+
},
|
|
34
|
+
metadata: {
|
|
35
|
+
annotations: {
|
|
36
|
+
ContentType: [
|
|
37
|
+
{
|
|
38
|
+
sys: {
|
|
39
|
+
id: 'Contentful:ExperienceType',
|
|
40
|
+
type: 'Link',
|
|
41
|
+
linkType: 'Annotation'
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
]
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
};
|
|
29
48
|
describe('CreateEntryMenuTrigger general', ()=>{
|
|
30
49
|
const props = {
|
|
31
50
|
contentTypes: [
|
|
@@ -139,4 +158,26 @@ describe('CreateEntryMenuTrigger general', ()=>{
|
|
|
139
158
|
expect(suggestedContentType).toBeDefined();
|
|
140
159
|
expect(suggestedContentType.textContent).toBe(props.contentTypes[0].name);
|
|
141
160
|
});
|
|
161
|
+
it('filters out content types with Contentful:ExperienceType annotation', ()=>{
|
|
162
|
+
const contentTypesWithExperience = [
|
|
163
|
+
CONTENT_TYPE_1,
|
|
164
|
+
CONTENT_TYPE_2,
|
|
165
|
+
CONTENT_TYPE_3,
|
|
166
|
+
EXPERIENCE_TYPE
|
|
167
|
+
];
|
|
168
|
+
const { getByTestId, getAllByTestId } = render(React.createElement(CreateEntryMenuTrigger, {
|
|
169
|
+
...props,
|
|
170
|
+
contentTypes: contentTypesWithExperience
|
|
171
|
+
}, stub));
|
|
172
|
+
act(()=>{
|
|
173
|
+
fireEvent.click(getByTestId('menu-trigger'));
|
|
174
|
+
});
|
|
175
|
+
const contentTypeItems = getAllByTestId('contentType');
|
|
176
|
+
expect(contentTypeItems).toHaveLength(3);
|
|
177
|
+
expect(contentTypeItems[0].textContent).toBe('name-1');
|
|
178
|
+
expect(contentTypeItems[1].textContent).toBe('name-2');
|
|
179
|
+
expect(contentTypeItems[2].textContent).toBe('name-3');
|
|
180
|
+
const experienceTypeItem = contentTypeItems.find((item)=>item.textContent === 'experience-type');
|
|
181
|
+
expect(experienceTypeItem).toBeUndefined();
|
|
182
|
+
});
|
|
142
183
|
});
|
|
@@ -1,13 +1,23 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { EntityStatusBadge as StatusBadge } from '@contentful/f36-components';
|
|
3
|
+
import { LocalePublishingPopover } from '@contentful/field-editor-shared';
|
|
3
4
|
import { useScheduledActions } from '../ScheduledIconWithTooltip/ScheduledIconWithTooltip';
|
|
4
5
|
import { ScheduleTooltip } from '../ScheduledIconWithTooltip/ScheduleTooltip';
|
|
5
|
-
export function EntityStatusBadge({
|
|
6
|
+
export function EntityStatusBadge({ entityType, getEntityScheduledActions, status, useLocalizedEntityStatus, localesStatusMap, activeLocales, entity, ...props }) {
|
|
6
7
|
const { isError, isLoading, jobs } = useScheduledActions({
|
|
7
|
-
entityId,
|
|
8
|
+
entityId: entity.sys.id,
|
|
8
9
|
entityType,
|
|
9
10
|
getEntityScheduledActions
|
|
10
11
|
});
|
|
12
|
+
if (useLocalizedEntityStatus && activeLocales && localesStatusMap) {
|
|
13
|
+
return React.createElement(LocalePublishingPopover, {
|
|
14
|
+
entity: entity,
|
|
15
|
+
jobs: jobs,
|
|
16
|
+
isScheduled: jobs.length !== 0,
|
|
17
|
+
localesStatusMap: localesStatusMap,
|
|
18
|
+
activeLocales: activeLocales
|
|
19
|
+
});
|
|
20
|
+
}
|
|
11
21
|
if (isError || isLoading || jobs.length === 0) {
|
|
12
22
|
return React.createElement(StatusBadge, {
|
|
13
23
|
...props,
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
2
|
import { EntryCard } from '@contentful/f36-components';
|
|
3
|
+
import { useAsyncLocalePublishStatus } from '@contentful/field-editor-shared';
|
|
3
4
|
import get from 'lodash/get';
|
|
4
5
|
import { useEntity, useEntityLoader } from '../../common/EntityStore';
|
|
5
6
|
import { MissingEntityCard } from '../../components';
|
|
@@ -30,6 +31,7 @@ export function FetchingWrappedEntryCard(props) {
|
|
|
30
31
|
getEntityScheduledActions,
|
|
31
32
|
props.entryId
|
|
32
33
|
]);
|
|
34
|
+
const localesStatusMap = useAsyncLocalePublishStatus(entry, props.sdk.parameters.instance.privateLocales);
|
|
33
35
|
const size = props.viewType === 'link' ? 'small' : 'default';
|
|
34
36
|
const { getEntity } = useEntityLoader();
|
|
35
37
|
const getAsset = (assetId)=>getEntity('Asset', assetId);
|
|
@@ -105,6 +107,8 @@ export function FetchingWrappedEntryCard(props) {
|
|
|
105
107
|
onMoveBottom: props.onMoveBottom,
|
|
106
108
|
isBeingDragged: props.isBeingDragged,
|
|
107
109
|
useLocalizedEntityStatus: props.sdk.parameters.instance.useLocalizedEntityStatus,
|
|
110
|
+
localesStatusMap,
|
|
111
|
+
activeLocales: props.sdk.parameters.instance.activeLocales,
|
|
108
112
|
isLocalized: !!('localized' in props.sdk.field && props.sdk.field.localized)
|
|
109
113
|
};
|
|
110
114
|
const { hasCardEditActions, hasCardMoveActions, hasCardRemoveActions } = props;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
|
-
import { EntryCard, MenuItem, MenuDivider
|
|
2
|
+
import { EntryCard, MenuItem, MenuDivider } from '@contentful/f36-components';
|
|
3
3
|
import { entityHelpers, isValidImage } from '@contentful/field-editor-shared';
|
|
4
4
|
import { AssetThumbnail, MissingEntityCard, EntityStatusBadge } from '../../components';
|
|
5
5
|
import { SpaceName } from '../../components/SpaceName/SpaceName';
|
|
@@ -72,16 +72,17 @@ export function WrappedEntryCard(props) {
|
|
|
72
72
|
isSelected: props.isSelected,
|
|
73
73
|
badge: React.createElement(EntityStatusBadge, {
|
|
74
74
|
status: status,
|
|
75
|
-
entityId: props.entry.sys.id,
|
|
76
75
|
entityType: "Entry",
|
|
77
|
-
getEntityScheduledActions: props.getEntityScheduledActions
|
|
76
|
+
getEntityScheduledActions: props.getEntityScheduledActions,
|
|
77
|
+
useLocalizedEntityStatus: props.useLocalizedEntityStatus,
|
|
78
|
+
entity: props.entry,
|
|
79
|
+
localesStatusMap: props.localesStatusMap,
|
|
80
|
+
activeLocales: props.activeLocales
|
|
78
81
|
}),
|
|
79
82
|
icon: props.spaceName ? React.createElement(SpaceName, {
|
|
80
83
|
spaceName: props.spaceName,
|
|
81
84
|
environmentName: props.entry.sys.environment.sys.id
|
|
82
|
-
}) :
|
|
83
|
-
variant: "secondary"
|
|
84
|
-
}, "Default") : null,
|
|
85
|
+
}) : null,
|
|
85
86
|
thumbnailElement: file && isValidImage(file) ? React.createElement(AssetThumbnail, {
|
|
86
87
|
file: file
|
|
87
88
|
}) : undefined,
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
2
|
import { SpaceAPI } from '@contentful/app-sdk';
|
|
3
|
+
import { LocalePublishStatusMap } from '@contentful/field-editor-shared';
|
|
4
|
+
import { LocaleProps } from 'contentful-management';
|
|
3
5
|
import { Asset, RenderDragFn } from '../../types';
|
|
4
6
|
export interface WrappedAssetCardProps {
|
|
5
7
|
getEntityScheduledActions: SpaceAPI['getEntityScheduledActions'];
|
|
@@ -17,6 +19,8 @@ export interface WrappedAssetCardProps {
|
|
|
17
19
|
isClickable: boolean;
|
|
18
20
|
useLocalizedEntityStatus?: boolean;
|
|
19
21
|
isLocalized?: boolean;
|
|
22
|
+
localesStatusMap?: LocalePublishStatusMap;
|
|
23
|
+
activeLocales?: LocaleProps[];
|
|
20
24
|
}
|
|
21
25
|
export declare const WrappedAssetCard: {
|
|
22
26
|
(props: WrappedAssetCardProps): React.JSX.Element;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
|
-
import { SpaceAPI } from '@contentful/field-editor-shared';
|
|
2
|
+
import { LocalePublishStatusMap, SpaceAPI } from '@contentful/field-editor-shared';
|
|
3
|
+
import { LocaleProps } from 'contentful-management';
|
|
3
4
|
import { Asset, RenderDragFn } from '../../types';
|
|
4
5
|
export interface WrappedAssetLinkProps {
|
|
5
6
|
getEntityScheduledActions: SpaceAPI['getEntityScheduledActions'];
|
|
@@ -13,5 +14,7 @@ export interface WrappedAssetLinkProps {
|
|
|
13
14
|
onRemove: () => void;
|
|
14
15
|
renderDragHandle?: RenderDragFn;
|
|
15
16
|
useLocalizedEntityStatus?: boolean;
|
|
17
|
+
localesStatusMap?: LocalePublishStatusMap;
|
|
18
|
+
activeLocales?: LocaleProps[];
|
|
16
19
|
}
|
|
17
20
|
export declare const WrappedAssetLink: (props: WrappedAssetLinkProps) => React.JSX.Element;
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
|
+
import { LocalePublishStatusMap } from '@contentful/field-editor-shared';
|
|
3
|
+
import { LocaleProps } from 'contentful-management';
|
|
2
4
|
import { Asset, ContentType, Entry, RenderDragFn } from '../types';
|
|
3
5
|
import { CustomActionProps } from './ReferenceEditor';
|
|
4
6
|
export type MissingEntityCardProps = {
|
|
@@ -28,4 +30,6 @@ export type CustomEntityCardProps = {
|
|
|
28
30
|
isBeingDragged?: boolean;
|
|
29
31
|
isLocalized?: boolean;
|
|
30
32
|
useLocalizedEntityStatus?: boolean;
|
|
33
|
+
localesStatusMap?: LocalePublishStatusMap;
|
|
34
|
+
activeLocales?: LocaleProps[];
|
|
31
35
|
};
|
|
@@ -1,8 +1,14 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { type EntityStatus } from '@contentful/f36-components';
|
|
3
|
+
import { LocalePublishStatusMap } from '@contentful/field-editor-shared';
|
|
4
|
+
import { EntryProps, LocaleProps, AssetProps } from 'contentful-management';
|
|
3
5
|
import { type UseScheduledActionsProps } from '../ScheduledIconWithTooltip/ScheduledIconWithTooltip';
|
|
4
|
-
type EntityStatusBadgeProps = UseScheduledActionsProps & {
|
|
6
|
+
type EntityStatusBadgeProps = Omit<UseScheduledActionsProps, 'entityId'> & {
|
|
5
7
|
status: EntityStatus;
|
|
8
|
+
entity: EntryProps | AssetProps;
|
|
9
|
+
useLocalizedEntityStatus?: boolean;
|
|
10
|
+
localesStatusMap?: LocalePublishStatusMap;
|
|
11
|
+
activeLocales?: LocaleProps[];
|
|
6
12
|
};
|
|
7
|
-
export declare function EntityStatusBadge({
|
|
13
|
+
export declare function EntityStatusBadge({ entityType, getEntityScheduledActions, status, useLocalizedEntityStatus, localesStatusMap, activeLocales, entity, ...props }: EntityStatusBadgeProps): React.JSX.Element;
|
|
8
14
|
export {};
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
2
|
import { SpaceAPI } from '@contentful/app-sdk';
|
|
3
|
+
import { LocalePublishStatusMap } from '@contentful/field-editor-shared';
|
|
4
|
+
import { LocaleProps } from 'contentful-management';
|
|
3
5
|
import { ContentType, Entry, RenderDragFn } from '../../types';
|
|
4
6
|
export interface WrappedEntryCardProps {
|
|
5
7
|
getEntityScheduledActions: SpaceAPI['getEntityScheduledActions'];
|
|
@@ -25,6 +27,8 @@ export interface WrappedEntryCardProps {
|
|
|
25
27
|
hasCardRemoveActions?: boolean;
|
|
26
28
|
isLocalized?: boolean;
|
|
27
29
|
useLocalizedEntityStatus?: boolean;
|
|
30
|
+
localesStatusMap?: LocalePublishStatusMap;
|
|
31
|
+
activeLocales?: LocaleProps[];
|
|
28
32
|
}
|
|
29
33
|
export declare function WrappedEntryCard(props: WrappedEntryCardProps): React.JSX.Element;
|
|
30
34
|
export declare namespace WrappedEntryCard {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@contentful/field-editor-reference",
|
|
3
|
-
"version": "5.
|
|
3
|
+
"version": "5.31.1",
|
|
4
4
|
"main": "dist/cjs/index.js",
|
|
5
5
|
"module": "dist/esm/index.js",
|
|
6
6
|
"types": "dist/types/index.d.ts",
|
|
@@ -64,5 +64,5 @@
|
|
|
64
64
|
"publishConfig": {
|
|
65
65
|
"registry": "https://npm.pkg.github.com/"
|
|
66
66
|
},
|
|
67
|
-
"gitHead": "
|
|
67
|
+
"gitHead": "05beff8083e711ec10c00a95e49ce0ea6135db08"
|
|
68
68
|
}
|