@contentful/field-editor-shared 2.12.2 → 2.13.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.
Files changed (33) hide show
  1. package/dist/cjs/ReleaseEntityStatusBadge/ReleaseEntityStatusPopover.js +5 -14
  2. package/dist/cjs/ReleaseEntityStatusBadge/constants.js +7 -0
  3. package/dist/cjs/hooks/useLocalePublishStatus.js +7 -22
  4. package/dist/cjs/hooks/useReleaseStatus.js +137 -0
  5. package/dist/cjs/hooks/{useActiveReleaseLocalesStatuses.spec.js → useReleaseStatus.spec.js} +91 -99
  6. package/dist/cjs/index.js +1 -2
  7. package/dist/cjs/utils/sanitizeLocales.js +20 -0
  8. package/dist/esm/ReleaseEntityStatusBadge/ReleaseEntityStatusPopover.js +6 -15
  9. package/dist/esm/ReleaseEntityStatusBadge/constants.js +7 -0
  10. package/dist/esm/hooks/useLocalePublishStatus.js +7 -22
  11. package/dist/esm/hooks/useReleaseStatus.js +127 -0
  12. package/dist/esm/hooks/{useActiveReleaseLocalesStatuses.spec.js → useReleaseStatus.spec.js} +91 -99
  13. package/dist/esm/index.js +1 -2
  14. package/dist/esm/utils/sanitizeLocales.js +10 -0
  15. package/dist/types/ReleaseEntityStatusBadge/ReleaseEntityStatusLocalesList.d.ts +2 -2
  16. package/dist/types/ReleaseEntityStatusBadge/ReleaseEntityStatusPopover.d.ts +3 -3
  17. package/dist/types/ReleaseEntityStatusBadge/constants.d.ts +7 -0
  18. package/dist/types/hooks/useLocalePublishStatus.d.ts +4 -2
  19. package/dist/types/hooks/useReleaseStatus.d.ts +14 -0
  20. package/dist/types/index.d.ts +1 -2
  21. package/dist/types/types.d.ts +3 -3
  22. package/dist/types/utils/sanitizeLocales.d.ts +4 -0
  23. package/package.json +4 -4
  24. package/dist/cjs/hooks/useActiveReleaseLocalesStatuses.js +0 -112
  25. package/dist/cjs/utils/getPreviousReleaseEntity.js +0 -32
  26. package/dist/cjs/utils/parseReleaseParameters.js +0 -42
  27. package/dist/esm/hooks/useActiveReleaseLocalesStatuses.js +0 -102
  28. package/dist/esm/utils/getPreviousReleaseEntity.js +0 -22
  29. package/dist/esm/utils/parseReleaseParameters.js +0 -32
  30. package/dist/types/hooks/useActiveReleaseLocalesStatuses.d.ts +0 -14
  31. package/dist/types/utils/getPreviousReleaseEntity.d.ts +0 -12
  32. package/dist/types/utils/parseReleaseParameters.d.ts +0 -11
  33. /package/dist/types/hooks/{useActiveReleaseLocalesStatuses.spec.d.ts → useReleaseStatus.spec.d.ts} +0 -0
@@ -1,5 +1,5 @@
1
1
  import React, { useCallback, useRef, useState } from 'react';
2
- import { Badge, Flex, Popover, Skeleton } from '@contentful/f36-components';
2
+ import { Badge, Flex, Popover } from '@contentful/f36-components';
3
3
  import { CaretDownIcon } from '@contentful/f36-icons';
4
4
  import tokens from '@contentful/f36-tokens';
5
5
  import { cx, css } from 'emotion';
@@ -136,7 +136,7 @@ const determineBadgeStatus = (localesStatusMap, activeLocales)=>{
136
136
  };
137
137
  }
138
138
  };
139
- export function ReleaseEntityStatusPopover({ releaseLocalesStatusMap, activeLocales, isLoading = false }) {
139
+ export function ReleaseEntityStatusPopover({ releaseStatusMap, activeLocales }) {
140
140
  const [isOpen, setIsOpen] = useState(false);
141
141
  const timeoutRef = useRef();
142
142
  const onMouseEnter = useCallback(()=>{
@@ -151,20 +151,11 @@ export function ReleaseEntityStatusPopover({ releaseLocalesStatusMap, activeLoca
151
151
  setIsOpen(false);
152
152
  }, 300);
153
153
  }, []);
154
- const status = determineBadgeStatus(releaseLocalesStatusMap, activeLocales);
154
+ const status = determineBadgeStatus(releaseStatusMap, activeLocales);
155
155
  const ariaLabel = status.secondary ? 'Multiple statuses' : status.primary;
156
156
  const wrapperClass = generateDynamicStyles(status);
157
- if (isLoading) {
158
- return /*#__PURE__*/ React.createElement(Skeleton.Container, {
159
- className: styles.skeletonBadge
160
- }, /*#__PURE__*/ React.createElement(Skeleton.Image, {
161
- testId: `Release-entity-locale-status-badge-skeleton`,
162
- width: "65px",
163
- height: "20px"
164
- }));
165
- }
166
157
  return /*#__PURE__*/ React.createElement(Popover, {
167
- isOpen: releaseLocalesStatusMap && isOpen,
158
+ isOpen: releaseStatusMap && isOpen,
168
159
  onClose: ()=>setIsOpen(false),
169
160
  autoFocus: false,
170
161
  placement: "bottom-end"
@@ -208,8 +199,8 @@ export function ReleaseEntityStatusPopover({ releaseLocalesStatusMap, activeLoca
208
199
  className: styles.popoverContent,
209
200
  onMouseEnter: onMouseEnter,
210
201
  onMouseLeave: onMouseLeave
211
- }, !!releaseLocalesStatusMap && /*#__PURE__*/ React.createElement(React.Fragment, null, /*#__PURE__*/ React.createElement(ReleaseEntityStatusLocalesList, {
212
- statusMap: releaseLocalesStatusMap,
202
+ }, !!releaseStatusMap && /*#__PURE__*/ React.createElement(React.Fragment, null, /*#__PURE__*/ React.createElement(ReleaseEntityStatusLocalesList, {
203
+ statusMap: releaseStatusMap,
213
204
  activeLocales: activeLocales
214
205
  }))));
215
206
  }
@@ -7,6 +7,13 @@ export const RELEASE_BADGES = {
7
7
  hover: tokens.green400,
8
8
  icon: tokens.green400
9
9
  },
10
+ published: {
11
+ label: 'Published',
12
+ variant: 'positive',
13
+ default: tokens.green300,
14
+ hover: tokens.green400,
15
+ icon: tokens.green400
16
+ },
10
17
  becomesDraft: {
11
18
  label: 'Becomes draft',
12
19
  variant: 'warning',
@@ -1,6 +1,7 @@
1
1
  import { useMemo } from 'react';
2
2
  import * as entityHelpers from '../utils/entityHelpers';
3
- function getLocalePublishStatusMap(entity, localesApi) {
3
+ import { sanitizeLocales } from '../utils/sanitizeLocales';
4
+ function getLocalePublishStatusMap(entity, locales) {
4
5
  const entityStatus = entityHelpers.getEntityStatus(entity.sys);
5
6
  if ([
6
7
  'archived',
@@ -8,15 +9,11 @@ function getLocalePublishStatusMap(entity, localesApi) {
8
9
  ].includes(entityStatus)) {
9
10
  return;
10
11
  }
11
- const statusMap = new Map(localesApi.available.map((localeCode)=>[
12
- localeCode,
12
+ const statusMap = new Map(locales.map((locale)=>[
13
+ locale.code,
13
14
  {
14
- status: entityHelpers.getEntityStatus(entity.sys, localeCode),
15
- locale: {
16
- code: localeCode,
17
- default: localeCode === localesApi.default,
18
- name: localesApi.names[localeCode]
19
- }
15
+ status: entityHelpers.getEntityStatus(entity.sys, locale.code),
16
+ locale
20
17
  }
21
18
  ]));
22
19
  return statusMap;
@@ -24,19 +21,7 @@ function getLocalePublishStatusMap(entity, localesApi) {
24
21
  export function useLocalePublishStatus(entity, locales) {
25
22
  return useMemo(()=>{
26
23
  if (entity && locales) {
27
- const localesApi = Array.isArray(locales) ? locales.reduce((api, locale)=>{
28
- api.available.push(locale.code);
29
- api.names[locale.code] = locale.name;
30
- if (locale.default) {
31
- api.default = locale.code;
32
- }
33
- return api;
34
- }, {
35
- available: [],
36
- names: {},
37
- default: ''
38
- }) : locales;
39
- return getLocalePublishStatusMap(entity, localesApi);
24
+ return getLocalePublishStatusMap(entity, locales ? sanitizeLocales(locales) : []);
40
25
  }
41
26
  return undefined;
42
27
  }, [
@@ -0,0 +1,127 @@
1
+ import { useMemo } from 'react';
2
+ import { getEntityStatus } from '../utils/entityHelpers';
3
+ import { sanitizeLocales } from '../utils/sanitizeLocales';
4
+ function createReleaseLocaleStatus(locale, status) {
5
+ switch(status){
6
+ case 'published':
7
+ return {
8
+ variant: 'positive',
9
+ status,
10
+ label: 'Published',
11
+ locale
12
+ };
13
+ case 'willPublish':
14
+ return {
15
+ variant: 'positive',
16
+ status: 'willPublish',
17
+ label: 'Will publish',
18
+ locale
19
+ };
20
+ case 'becomesDraft':
21
+ return {
22
+ variant: 'warning',
23
+ status: 'becomesDraft',
24
+ label: 'Becomes draft',
25
+ locale
26
+ };
27
+ case 'remainsDraft':
28
+ return {
29
+ variant: 'warning',
30
+ status: 'remainsDraft',
31
+ label: 'Remains draft',
32
+ locale
33
+ };
34
+ case 'notInRelease':
35
+ return {
36
+ variant: 'secondary',
37
+ status: 'notInRelease',
38
+ label: 'Not in release',
39
+ locale
40
+ };
41
+ default:
42
+ throw new Error(`Unknown release entity status: ${status}`);
43
+ }
44
+ }
45
+ function getReleaseItemLocaleStatus(releaseItem, locale, previousEntityOnTimeline) {
46
+ if ('action' in releaseItem) {
47
+ if (releaseItem.action === 'publish') {
48
+ return 'willPublish';
49
+ }
50
+ if (releaseItem.action === 'unpublish') {
51
+ const status = previousEntityOnTimeline ? getEntityStatus(previousEntityOnTimeline.sys) : 'draft';
52
+ return [
53
+ 'published',
54
+ 'changed'
55
+ ].includes(status) ? 'becomesDraft' : 'remainsDraft';
56
+ }
57
+ }
58
+ const addedLocales = releaseItem.add?.fields['*'] || [];
59
+ const removedLocales = releaseItem.remove?.fields['*'] || [];
60
+ if (addedLocales.includes(locale.code)) {
61
+ return 'willPublish';
62
+ }
63
+ if (removedLocales.includes(locale.code)) {
64
+ const status = previousEntityOnTimeline ? getEntityStatus(previousEntityOnTimeline.sys, locale.code) : 'draft';
65
+ return [
66
+ 'published',
67
+ 'changed'
68
+ ].includes(status) ? 'becomesDraft' : 'remainsDraft';
69
+ }
70
+ return 'remainsDraft';
71
+ }
72
+ export function useReleaseStatus({ entity, release, locales, previousEntityOnTimeline }) {
73
+ const sanitizedLocales = useMemo(()=>sanitizeLocales(locales), [
74
+ locales
75
+ ]);
76
+ const releaseStatusMap = useMemo(()=>{
77
+ if (!entity?.sys || !release || !('schemaVersion' in release.sys) || release.sys.schemaVersion !== 'Release.v2') {
78
+ return new Map();
79
+ }
80
+ const releaseItem = release.entities.items.find((e)=>e.entity.sys.linkType === entity.sys.type && e.entity.sys.id === entity.sys.id);
81
+ if (!releaseItem) {
82
+ return new Map(sanitizedLocales.map((locale)=>{
83
+ if ([
84
+ 'published',
85
+ 'changed'
86
+ ].includes(getEntityStatus(entity.sys, locale.code))) {
87
+ return [
88
+ locale.code,
89
+ createReleaseLocaleStatus(locale, 'published')
90
+ ];
91
+ }
92
+ return [
93
+ locale.code,
94
+ createReleaseLocaleStatus(locale, 'notInRelease')
95
+ ];
96
+ }));
97
+ }
98
+ return new Map(sanitizedLocales.map((locale)=>[
99
+ locale.code,
100
+ createReleaseLocaleStatus(locale, getReleaseItemLocaleStatus(releaseItem, locale, previousEntityOnTimeline))
101
+ ]));
102
+ }, [
103
+ entity?.sys,
104
+ previousEntityOnTimeline,
105
+ release,
106
+ sanitizedLocales
107
+ ]);
108
+ const releaseAction = useMemo(()=>{
109
+ if (releaseStatusMap.size === 0) {
110
+ return undefined;
111
+ }
112
+ const releaseArray = Array.from(releaseStatusMap.values());
113
+ if (releaseArray.find(({ status })=>status === 'willPublish')) {
114
+ return 'publish';
115
+ }
116
+ if (releaseArray.find(({ status })=>status === 'becomesDraft')) {
117
+ return 'unpublish';
118
+ }
119
+ return 'not-in-release';
120
+ }, [
121
+ releaseStatusMap
122
+ ]);
123
+ return {
124
+ releaseStatusMap,
125
+ releaseAction
126
+ };
127
+ }
@@ -1,6 +1,5 @@
1
1
  import { renderHook } from '@testing-library/react';
2
- import { getPreviousReleaseEntity } from '../utils/getPreviousReleaseEntity';
3
- import { useActiveReleaseLocalesStatuses } from './useActiveReleaseLocalesStatuses';
2
+ import { useReleaseStatus } from './useReleaseStatus';
4
3
  const buildEntry = (status, id = 'entry-1')=>({
5
4
  sys: {
6
5
  id,
@@ -9,7 +8,9 @@ const buildEntry = (status, id = 'entry-1')=>({
9
8
  '*': {
10
9
  'en-US': status
11
10
  }
12
- }
11
+ },
12
+ version: 3,
13
+ publishedVersion: status === 'published' ? 2 : undefined
13
14
  }
14
15
  });
15
16
  const buildAsset = (status, id = 'asset-1')=>({
@@ -20,7 +21,9 @@ const buildAsset = (status, id = 'asset-1')=>({
20
21
  '*': {
21
22
  'en-US': status
22
23
  }
23
- }
24
+ },
25
+ version: 3,
26
+ publishedVersion: status === 'published' ? 2 : undefined
24
27
  }
25
28
  });
26
29
  const createEntryBasedReleaseEntity = ({ entityId = 'entry-1', action = 'publish', entityType = 'Entry' })=>({
@@ -83,51 +86,38 @@ const createLocaleBasedRelease = ({ entityId, verb, entityType = 'Entry' } = {})
83
86
  ]
84
87
  }
85
88
  });
86
- jest.mock('../utils/getPreviousReleaseEntity', ()=>({
87
- getPreviousReleaseEntity: jest.fn()
88
- }));
89
89
  const ENTITY_TYPES = [
90
90
  'Entry',
91
91
  'Asset'
92
92
  ];
93
- describe('useActiveReleaseLocalesStatuses', ()=>{
93
+ describe('useReleaseStatus', ()=>{
94
94
  beforeEach(()=>{
95
95
  jest.clearAllMocks();
96
96
  });
97
97
  ENTITY_TYPES.forEach((entityType)=>{
98
98
  const entityId = entityType === 'Entry' ? 'entry-1' : 'asset-1';
99
99
  const baseParams = {
100
- entityId,
101
- entityType,
102
100
  locales: [
103
101
  {
104
102
  code: 'en-US'
105
103
  }
106
- ],
107
- isActiveReleaseLoading: false,
108
- releaseVersionMap: new Map(),
109
- releases: {
110
- items: []
111
- }
104
+ ]
112
105
  };
106
+ function buildEntity(status) {
107
+ return entityType === 'Entry' ? buildEntry(status) : buildAsset(status);
108
+ }
113
109
  describe(`${entityType} with entry based publishing`, ()=>{
114
110
  it('returns Will publish status when active release has publish action', ()=>{
115
- getPreviousReleaseEntity.mockReturnValue({
116
- previousReleaseEntity: createEntryBasedReleaseEntity({
117
- entityId,
118
- action: 'unpublish',
119
- entityType
120
- })
121
- });
122
- const { result } = renderHook(()=>useActiveReleaseLocalesStatuses({
111
+ const { result } = renderHook(()=>useReleaseStatus({
123
112
  ...baseParams,
124
- activeRelease: createEntryBasedRelease({
113
+ previousEntityOnTimeline: buildEntity('draft'),
114
+ release: createEntryBasedRelease({
125
115
  entityId,
126
116
  entityType
127
117
  }),
128
- currentEntityDraft: entityType === 'Entry' ? buildEntry('draft') : buildAsset('draft')
118
+ entity: buildEntity('published')
129
119
  }));
130
- expect(result.current.releaseLocalesStatusMap.get('en-US')).toEqual({
120
+ expect(result.current.releaseStatusMap.get('en-US')).toEqual({
131
121
  variant: 'positive',
132
122
  status: 'willPublish',
133
123
  label: 'Will publish',
@@ -137,23 +127,17 @@ describe('useActiveReleaseLocalesStatuses', ()=>{
137
127
  });
138
128
  });
139
129
  it('returns Becomes draft status when previous version has published locales and active version has unpublish action', ()=>{
140
- getPreviousReleaseEntity.mockReturnValue({
141
- previousReleaseEntity: createEntryBasedReleaseEntity({
142
- entityId,
143
- action: 'publish',
144
- entityType
145
- })
146
- });
147
- const { result } = renderHook(()=>useActiveReleaseLocalesStatuses({
130
+ const { result } = renderHook(()=>useReleaseStatus({
148
131
  ...baseParams,
149
- activeRelease: createEntryBasedRelease({
132
+ previousEntityOnTimeline: buildEntity('published'),
133
+ release: createEntryBasedRelease({
150
134
  action: 'unpublish',
151
135
  entityId,
152
136
  entityType
153
137
  }),
154
- currentEntityDraft: entityType === 'Entry' ? buildEntry('published') : buildAsset('published')
138
+ entity: buildEntity('draft')
155
139
  }));
156
- expect(result.current.releaseLocalesStatusMap.get('en-US')).toEqual({
140
+ expect(result.current.releaseStatusMap.get('en-US')).toEqual({
157
141
  variant: 'warning',
158
142
  status: 'becomesDraft',
159
143
  label: 'Becomes draft',
@@ -163,24 +147,18 @@ describe('useActiveReleaseLocalesStatuses', ()=>{
163
147
  });
164
148
  });
165
149
  it('returns Remains draft status when previous version has draft locales and active version has unpublish action', ()=>{
166
- getPreviousReleaseEntity.mockReturnValue({
167
- previousReleaseEntity: createEntryBasedReleaseEntity({
168
- action: 'unpublish',
169
- entityType,
170
- entityId
171
- })
172
- });
173
- const { result } = renderHook(()=>useActiveReleaseLocalesStatuses({
150
+ const { result } = renderHook(()=>useReleaseStatus({
174
151
  ...baseParams,
175
- activeRelease: createEntryBasedRelease({
152
+ previousEntityOnTimeline: buildEntity('draft'),
153
+ release: createEntryBasedRelease({
176
154
  action: 'unpublish',
177
155
  entityId,
178
156
  entityType
179
157
  }),
180
- currentEntityDraft: entityType === 'Entry' ? buildEntry('draft') : buildAsset('draft')
158
+ entity: buildEntity('draft')
181
159
  }));
182
- expect(result.current.releaseLocalesStatusMap.get('en-US')).toEqual({
183
- variant: 'secondary',
160
+ expect(result.current.releaseStatusMap.get('en-US')).toEqual({
161
+ variant: 'warning',
184
162
  status: 'remainsDraft',
185
163
  label: 'Remains draft',
186
164
  locale: {
@@ -189,19 +167,16 @@ describe('useActiveReleaseLocalesStatuses', ()=>{
189
167
  });
190
168
  });
191
169
  it('returns Not in release status when entity is not in the release', ()=>{
192
- getPreviousReleaseEntity.mockReturnValue({
193
- previousReleaseEntity: undefined
194
- });
195
- const { result } = renderHook(()=>useActiveReleaseLocalesStatuses({
170
+ const { result } = renderHook(()=>useReleaseStatus({
196
171
  ...baseParams,
197
- activeRelease: createEntryBasedRelease({
172
+ release: createEntryBasedRelease({
198
173
  entityId: entityType === 'Entry' ? 'entry-2' : 'asset-2',
199
174
  action: 'publish',
200
175
  entityType
201
176
  }),
202
- currentEntityDraft: entityType === 'Entry' ? buildEntry('draft') : buildAsset('draft')
177
+ entity: buildEntity('draft')
203
178
  }));
204
- expect(result.current.releaseLocalesStatusMap.get('en-US')).toEqual({
179
+ expect(result.current.releaseStatusMap.get('en-US')).toEqual({
205
180
  variant: 'secondary',
206
181
  status: 'notInRelease',
207
182
  label: 'Not in release',
@@ -210,25 +185,38 @@ describe('useActiveReleaseLocalesStatuses', ()=>{
210
185
  }
211
186
  });
212
187
  });
188
+ it('returns published when not in release but already published', ()=>{
189
+ const { result } = renderHook(()=>useReleaseStatus({
190
+ ...baseParams,
191
+ release: createEntryBasedRelease({
192
+ entityId: entityType === 'Entry' ? 'entry-2' : 'asset-2',
193
+ action: 'publish',
194
+ entityType
195
+ }),
196
+ entity: buildEntity('published')
197
+ }));
198
+ expect(result.current.releaseStatusMap.get('en-US')).toEqual({
199
+ variant: 'positive',
200
+ status: 'published',
201
+ label: 'Published',
202
+ locale: {
203
+ code: 'en-US'
204
+ }
205
+ });
206
+ });
213
207
  });
214
208
  describe(`${entityType} with locale based publishing`, ()=>{
215
209
  it('returns Will publish status when active release has publish action', ()=>{
216
- getPreviousReleaseEntity.mockReturnValue({
217
- previousReleaseEntity: createLocaleBasedReleaseEntity({
218
- entityId,
219
- verb: 'remove',
220
- entityType
221
- })
222
- });
223
- const { result } = renderHook(()=>useActiveReleaseLocalesStatuses({
210
+ const { result } = renderHook(()=>useReleaseStatus({
224
211
  ...baseParams,
225
- activeRelease: createLocaleBasedRelease({
212
+ previousEntityOnTimeline: buildEntity('draft'),
213
+ release: createLocaleBasedRelease({
226
214
  entityId,
227
215
  entityType
228
216
  }),
229
- currentEntityDraft: entityType === 'Entry' ? buildEntry('draft') : buildAsset('draft')
217
+ entity: buildEntity('published')
230
218
  }));
231
- expect(result.current.releaseLocalesStatusMap.get('en-US')).toEqual({
219
+ expect(result.current.releaseStatusMap.get('en-US')).toEqual({
232
220
  variant: 'positive',
233
221
  status: 'willPublish',
234
222
  label: 'Will publish',
@@ -238,23 +226,17 @@ describe('useActiveReleaseLocalesStatuses', ()=>{
238
226
  });
239
227
  });
240
228
  it('returns Becomes draft status when previous version has published locales and active version has unpublish action', ()=>{
241
- getPreviousReleaseEntity.mockReturnValue({
242
- previousReleaseEntity: createLocaleBasedReleaseEntity({
243
- entityId: 'entry-1',
244
- verb: 'add',
245
- entityType
246
- })
247
- });
248
- const { result } = renderHook(()=>useActiveReleaseLocalesStatuses({
229
+ const { result } = renderHook(()=>useReleaseStatus({
249
230
  ...baseParams,
250
- activeRelease: createLocaleBasedRelease({
231
+ previousEntityOnTimeline: buildEntity('published'),
232
+ release: createLocaleBasedRelease({
251
233
  verb: 'remove',
252
234
  entityId,
253
235
  entityType
254
236
  }),
255
- currentEntityDraft: entityType === 'Entry' ? buildEntry('published') : buildAsset('published')
237
+ entity: buildEntity('draft')
256
238
  }));
257
- expect(result.current.releaseLocalesStatusMap.get('en-US')).toEqual({
239
+ expect(result.current.releaseStatusMap.get('en-US')).toEqual({
258
240
  variant: 'warning',
259
241
  status: 'becomesDraft',
260
242
  label: 'Becomes draft',
@@ -264,24 +246,18 @@ describe('useActiveReleaseLocalesStatuses', ()=>{
264
246
  });
265
247
  });
266
248
  it('returns Remains draft status when previous version has draft locales and active version has unpublish action', ()=>{
267
- getPreviousReleaseEntity.mockReturnValue({
268
- previousReleaseEntity: createLocaleBasedReleaseEntity({
269
- verb: 'remove',
270
- entityId,
271
- entityType
272
- })
273
- });
274
- const { result } = renderHook(()=>useActiveReleaseLocalesStatuses({
249
+ const { result } = renderHook(()=>useReleaseStatus({
275
250
  ...baseParams,
276
- activeRelease: createLocaleBasedRelease({
251
+ previousEntityOnTimeline: buildEntity('draft'),
252
+ release: createLocaleBasedRelease({
277
253
  verb: 'remove',
278
254
  entityId,
279
255
  entityType
280
256
  }),
281
- currentEntityDraft: entityType === 'Entry' ? buildEntry('draft') : buildAsset('draft')
257
+ entity: buildEntity('draft')
282
258
  }));
283
- expect(result.current.releaseLocalesStatusMap.get('en-US')).toEqual({
284
- variant: 'secondary',
259
+ expect(result.current.releaseStatusMap.get('en-US')).toEqual({
260
+ variant: 'warning',
285
261
  status: 'remainsDraft',
286
262
  label: 'Remains draft',
287
263
  locale: {
@@ -289,20 +265,17 @@ describe('useActiveReleaseLocalesStatuses', ()=>{
289
265
  }
290
266
  });
291
267
  });
292
- it('returns Not in release status when entry is not in the release', ()=>{
293
- getPreviousReleaseEntity.mockReturnValue({
294
- previousReleaseEntity: undefined
295
- });
296
- const { result } = renderHook(()=>useActiveReleaseLocalesStatuses({
268
+ it('returns Not in release status when entry is in draft state and not in the release', ()=>{
269
+ const { result } = renderHook(()=>useReleaseStatus({
297
270
  ...baseParams,
298
- activeRelease: createLocaleBasedRelease({
271
+ release: createLocaleBasedRelease({
299
272
  entityId: entityType === 'Entry' ? 'entry-2' : 'asset-2',
300
273
  entityType,
301
274
  verb: 'add'
302
275
  }),
303
- currentEntityDraft: entityType === 'Entry' ? buildEntry('draft') : buildAsset('draft')
276
+ entity: buildEntity('draft')
304
277
  }));
305
- expect(result.current.releaseLocalesStatusMap.get('en-US')).toEqual({
278
+ expect(result.current.releaseStatusMap.get('en-US')).toEqual({
306
279
  variant: 'secondary',
307
280
  status: 'notInRelease',
308
281
  label: 'Not in release',
@@ -311,6 +284,25 @@ describe('useActiveReleaseLocalesStatuses', ()=>{
311
284
  }
312
285
  });
313
286
  });
287
+ it('returns published status when entry is in published state and not in the release', ()=>{
288
+ const { result } = renderHook(()=>useReleaseStatus({
289
+ ...baseParams,
290
+ release: createLocaleBasedRelease({
291
+ entityId: entityType === 'Entry' ? 'entry-2' : 'asset-2',
292
+ entityType,
293
+ verb: 'add'
294
+ }),
295
+ entity: buildEntity('published')
296
+ }));
297
+ expect(result.current.releaseStatusMap.get('en-US')).toEqual({
298
+ variant: 'positive',
299
+ status: 'published',
300
+ label: 'Published',
301
+ locale: {
302
+ code: 'en-US'
303
+ }
304
+ });
305
+ });
314
306
  });
315
307
  });
316
308
  });
package/dist/esm/index.js CHANGED
@@ -13,10 +13,9 @@ export { isValidImage } from './utils/isValidImage';
13
13
  export { shortenStorageUnit, toLocaleString } from './utils/shortenStorageUnit';
14
14
  export * from './types';
15
15
  export * from './hooks/useActiveLocales';
16
- export * from './hooks/useActiveReleaseLocalesStatuses';
16
+ export * from './hooks/useReleaseStatus';
17
17
  export * from './hooks/useLocalePublishStatus';
18
18
  export * from './LocalePublishingEntityStatusBadge';
19
19
  export * from './ReleaseEntityStatusBadge';
20
20
  export * from './utils/determineReleaseAction';
21
21
  export * from './utils/getEntityReleaseStatus';
22
- export * from './utils/parseReleaseParameters';
@@ -0,0 +1,10 @@
1
+ export function sanitizeLocales(locales) {
2
+ if (Array.isArray(locales)) {
3
+ return locales;
4
+ }
5
+ return locales.available.map((code)=>({
6
+ code,
7
+ default: code === locales.default,
8
+ name: locales.names[code]
9
+ }));
10
+ }
@@ -1,8 +1,8 @@
1
1
  import React from 'react';
2
2
  import type { LocaleProps } from 'contentful-management';
3
- import { ReleaseLocalesStatusMap } from '../types';
3
+ import { ReleaseStatusMap } from '../types';
4
4
  type ReleaseEntityStatusLocalesListProps = {
5
- statusMap: ReleaseLocalesStatusMap;
5
+ statusMap: ReleaseStatusMap;
6
6
  activeLocales?: Pick<LocaleProps, 'code'>[];
7
7
  };
8
8
  export declare function ReleaseEntityStatusLocalesList({ statusMap, activeLocales, }: ReleaseEntityStatusLocalesListProps): React.JSX.Element;
@@ -1,10 +1,10 @@
1
1
  import React from 'react';
2
2
  import type { LocaleProps } from 'contentful-management';
3
- import type { ReleaseLocalesStatusMap } from '../types';
3
+ import type { ReleaseStatusMap } from '../types';
4
4
  type ReleaseLocalePublishingPopoverProps = {
5
- releaseLocalesStatusMap: ReleaseLocalesStatusMap;
5
+ releaseStatusMap: ReleaseStatusMap;
6
6
  activeLocales: Pick<LocaleProps, 'code'>[];
7
7
  isLoading?: boolean;
8
8
  };
9
- export declare function ReleaseEntityStatusPopover({ releaseLocalesStatusMap, activeLocales, isLoading, }: ReleaseLocalePublishingPopoverProps): React.JSX.Element;
9
+ export declare function ReleaseEntityStatusPopover({ releaseStatusMap, activeLocales, }: ReleaseLocalePublishingPopoverProps): React.JSX.Element;
10
10
  export {};
@@ -6,6 +6,13 @@ export declare const RELEASE_BADGES: {
6
6
  readonly hover: string;
7
7
  readonly icon: string;
8
8
  };
9
+ readonly published: {
10
+ readonly label: "Published";
11
+ readonly variant: "positive";
12
+ readonly default: string;
13
+ readonly hover: string;
14
+ readonly icon: string;
15
+ };
9
16
  readonly becomesDraft: {
10
17
  readonly label: "Becomes draft";
11
18
  readonly variant: "warning";
@@ -1,8 +1,10 @@
1
1
  import type { LocalesAPI } from '@contentful/app-sdk';
2
2
  import type { AssetProps, EntryProps, LocaleProps } from 'contentful-management/types';
3
+ import { type SanitizedLocale } from '../utils/sanitizeLocales';
4
+ export type PublishStatus = 'draft' | 'published' | 'changed';
3
5
  export type LocalePublishStatus = {
4
- status: 'draft' | 'published' | 'changed';
5
- locale: Pick<LocaleProps, 'code' | 'default' | 'name'>;
6
+ status: PublishStatus;
7
+ locale: SanitizedLocale;
6
8
  };
7
9
  export type LocalePublishStatusMap = Map<string, LocalePublishStatus>;
8
10
  /**