@strapi/content-releases 0.0.0-next.6d59515520a3850456f256fb0e4c54b75054ddf4 → 0.0.0-next.aa7c7ec6724534e157d8a23fe85ee8318dabbf37

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.
@@ -3,7 +3,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
3
  const jsxRuntime = require("react/jsx-runtime");
4
4
  const helperPlugin = require("@strapi/helper-plugin");
5
5
  const reactRouterDom = require("react-router-dom");
6
- const index = require("./index-KJa1Rb5F.js");
6
+ const index = require("./index-nGaPcY9m.js");
7
7
  const React = require("react");
8
8
  const strapiAdmin = require("@strapi/admin/strapi-admin");
9
9
  const designSystem = require("@strapi/design-system");
@@ -40,7 +40,9 @@ const React__namespace = /* @__PURE__ */ _interopNamespace(React);
40
40
  const styled__default = /* @__PURE__ */ _interopDefault(styled);
41
41
  const yup__namespace = /* @__PURE__ */ _interopNamespace(yup);
42
42
  const RELEASE_SCHEMA = yup__namespace.object().shape({
43
- name: yup__namespace.string().trim().required()
43
+ name: yup__namespace.string().trim().required(),
44
+ // scheduledAt is a date, but we always receive strings from the client
45
+ scheduledAt: yup__namespace.string().nullable()
44
46
  }).required().noUnknown();
45
47
  const ReleaseModal = ({
46
48
  handleClose,
@@ -114,10 +116,7 @@ const ReleaseInfoWrapper = styled__default.default(designSystem.Flex)`
114
116
  border-bottom-left-radius: ${({ theme }) => theme.borderRadius};
115
117
  border-top: 1px solid ${({ theme }) => theme.colors.neutral150};
116
118
  `;
117
- const StyledFlex = styled__default.default(designSystem.Flex)`
118
- align-self: stretch;
119
- cursor: ${({ disabled }) => disabled ? "not-allowed" : "pointer"};
120
-
119
+ const StyledMenuItem = styled__default.default(v2.Menu.Item)`
121
120
  svg path {
122
121
  fill: ${({ theme, disabled }) => disabled && theme.colors.neutral500};
123
122
  }
@@ -126,15 +125,15 @@ const StyledFlex = styled__default.default(designSystem.Flex)`
126
125
  }
127
126
  `;
128
127
  const PencilIcon = styled__default.default(icons.Pencil)`
129
- width: ${({ theme }) => theme.spaces[4]};
130
- height: ${({ theme }) => theme.spaces[4]};
128
+ width: ${({ theme }) => theme.spaces[3]};
129
+ height: ${({ theme }) => theme.spaces[3]};
131
130
  path {
132
131
  fill: ${({ theme }) => theme.colors.neutral600};
133
132
  }
134
133
  `;
135
134
  const TrashIcon = styled__default.default(icons.Trash)`
136
- width: ${({ theme }) => theme.spaces[4]};
137
- height: ${({ theme }) => theme.spaces[4]};
135
+ width: ${({ theme }) => theme.spaces[3]};
136
+ height: ${({ theme }) => theme.spaces[3]};
138
137
  path {
139
138
  fill: ${({ theme }) => theme.colors.danger600};
140
139
  }
@@ -142,24 +141,6 @@ const TrashIcon = styled__default.default(icons.Trash)`
142
141
  const TypographyMaxWidth = styled__default.default(designSystem.Typography)`
143
142
  max-width: 300px;
144
143
  `;
145
- const PopoverButton = ({ onClick, disabled, children }) => {
146
- return /* @__PURE__ */ jsxRuntime.jsx(
147
- StyledFlex,
148
- {
149
- paddingTop: 2,
150
- paddingBottom: 2,
151
- paddingLeft: 4,
152
- paddingRight: 4,
153
- alignItems: "center",
154
- gap: 2,
155
- as: "button",
156
- hasRadius: true,
157
- onClick,
158
- disabled,
159
- children
160
- }
161
- );
162
- };
163
144
  const EntryValidationText = ({ action, schema, components, entry }) => {
164
145
  const { formatMessage } = reactIntl.useIntl();
165
146
  const { validate } = strapiAdmin.unstable_useDocument();
@@ -210,8 +191,6 @@ const ReleaseDetailsLayout = ({
210
191
  }) => {
211
192
  const { formatMessage } = reactIntl.useIntl();
212
193
  const { releaseId } = reactRouterDom.useParams();
213
- const [isPopoverVisible, setIsPopoverVisible] = React__namespace.useState(false);
214
- const moreButtonRef = React__namespace.useRef(null);
215
194
  const {
216
195
  data,
217
196
  isLoading: isLoadingDetails,
@@ -225,14 +204,8 @@ const ReleaseDetailsLayout = ({
225
204
  allowedActions: { canUpdate, canDelete }
226
205
  } = helperPlugin.useRBAC(index.PERMISSIONS);
227
206
  const dispatch = index.useTypedDispatch();
207
+ const { trackUsage } = helperPlugin.useTracking();
228
208
  const release = data?.data;
229
- const handleTogglePopover = () => {
230
- setIsPopoverVisible((prev) => !prev);
231
- };
232
- const openReleaseModal = () => {
233
- toggleEditReleaseModal();
234
- handleTogglePopover();
235
- };
236
209
  const handlePublishRelease = async () => {
237
210
  const response = await publishRelease({ id: releaseId });
238
211
  if ("data" in response) {
@@ -243,6 +216,12 @@ const ReleaseDetailsLayout = ({
243
216
  defaultMessage: "Release was published successfully."
244
217
  })
245
218
  });
219
+ const { totalEntries: totalEntries2, totalPublishedEntries, totalUnpublishedEntries } = response.data.meta;
220
+ trackUsage("didPublishRelease", {
221
+ totalEntries: totalEntries2,
222
+ totalPublishedEntries,
223
+ totalUnpublishedEntries
224
+ });
246
225
  } else if (index.isAxiosError(response.error)) {
247
226
  toggleNotification({
248
227
  type: "warning",
@@ -255,13 +234,21 @@ const ReleaseDetailsLayout = ({
255
234
  });
256
235
  }
257
236
  };
258
- const openWarningConfirmDialog = () => {
259
- toggleWarningSubmit();
260
- handleTogglePopover();
261
- };
262
237
  const handleRefresh = () => {
263
238
  dispatch(index.releaseApi.util.invalidateTags([{ type: "ReleaseAction", id: "LIST" }]));
264
239
  };
240
+ const getCreatedByUser = () => {
241
+ if (!release?.createdBy) {
242
+ return null;
243
+ }
244
+ if (release.createdBy.username) {
245
+ return release.createdBy.username;
246
+ }
247
+ if (release.createdBy.firstname) {
248
+ return `${release.createdBy.firstname} ${release.createdBy.lastname || ""}`.trim();
249
+ }
250
+ return release.createdBy.email;
251
+ };
265
252
  if (isLoadingDetails) {
266
253
  return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Main, { "aria-busy": isLoadingDetails, children: /* @__PURE__ */ jsxRuntime.jsx(helperPlugin.LoadingIndicatorPage, {}) });
267
254
  }
@@ -283,7 +270,7 @@ const ReleaseDetailsLayout = ({
283
270
  );
284
271
  }
285
272
  const totalEntries = release.actions.meta.count || 0;
286
- const createdBy = release.createdBy.lastname ? `${release.createdBy.firstname} ${release.createdBy.lastname}` : `${release.createdBy.firstname}`;
273
+ const hasCreatedByUser = Boolean(getCreatedByUser());
287
274
  return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Main, { "aria-busy": isLoadingDetails, children: [
288
275
  /* @__PURE__ */ jsxRuntime.jsx(
289
276
  designSystem.HeaderLayout,
@@ -301,72 +288,98 @@ const ReleaseDetailsLayout = ({
301
288
  defaultMessage: "Back"
302
289
  }) }),
303
290
  primaryAction: !release.releasedAt && /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 2, children: [
304
- /* @__PURE__ */ jsxRuntime.jsx(
305
- designSystem.IconButton,
306
- {
307
- label: formatMessage({
308
- id: "content-releases.header.actions.open-release-actions",
309
- defaultMessage: "Release actions"
310
- }),
311
- ref: moreButtonRef,
312
- onClick: handleTogglePopover,
313
- children: /* @__PURE__ */ jsxRuntime.jsx(icons.More, {})
314
- }
315
- ),
316
- isPopoverVisible && /* @__PURE__ */ jsxRuntime.jsxs(
317
- designSystem.Popover,
318
- {
319
- source: moreButtonRef,
320
- placement: "bottom-end",
321
- onDismiss: handleTogglePopover,
322
- spacing: 4,
323
- minWidth: "242px",
324
- children: [
325
- /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { alignItems: "center", justifyContent: "center", direction: "column", padding: 1, children: [
326
- /* @__PURE__ */ jsxRuntime.jsxs(PopoverButton, { disabled: !canUpdate, onClick: openReleaseModal, children: [
327
- /* @__PURE__ */ jsxRuntime.jsx(PencilIcon, {}),
328
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { ellipsis: true, children: formatMessage({
329
- id: "content-releases.header.actions.edit",
330
- defaultMessage: "Edit"
331
- }) })
332
- ] }),
333
- /* @__PURE__ */ jsxRuntime.jsxs(PopoverButton, { disabled: !canDelete, onClick: openWarningConfirmDialog, children: [
334
- /* @__PURE__ */ jsxRuntime.jsx(TrashIcon, {}),
335
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { ellipsis: true, textColor: "danger600", children: formatMessage({
336
- id: "content-releases.header.actions.delete",
337
- defaultMessage: "Delete"
338
- }) })
339
- ] })
340
- ] }),
341
- /* @__PURE__ */ jsxRuntime.jsxs(
342
- ReleaseInfoWrapper,
343
- {
344
- direction: "column",
345
- justifyContent: "center",
346
- alignItems: "flex-start",
347
- gap: 1,
348
- padding: 5,
349
- children: [
350
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", fontWeight: "bold", children: formatMessage({
351
- id: "content-releases.header.actions.created",
352
- defaultMessage: "Created"
353
- }) }),
354
- /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Typography, { variant: "pi", color: "neutral300", children: [
355
- /* @__PURE__ */ jsxRuntime.jsx(helperPlugin.RelativeTime, { timestamp: new Date(release.createdAt) }),
356
- formatMessage(
357
- {
358
- id: "content-releases.header.actions.created.description",
359
- defaultMessage: " by {createdBy}"
360
- },
361
- { createdBy }
362
- )
363
- ] })
364
- ]
365
- }
366
- )
367
- ]
368
- }
369
- ),
291
+ /* @__PURE__ */ jsxRuntime.jsxs(v2.Menu.Root, { children: [
292
+ /* @__PURE__ */ jsxRuntime.jsx(
293
+ v2.Menu.Trigger,
294
+ {
295
+ as: designSystem.IconButton,
296
+ paddingLeft: 2,
297
+ paddingRight: 2,
298
+ "aria-label": formatMessage({
299
+ id: "content-releases.header.actions.open-release-actions",
300
+ defaultMessage: "Release edit and delete menu"
301
+ }),
302
+ icon: /* @__PURE__ */ jsxRuntime.jsx(icons.More, {}),
303
+ variant: "tertiary"
304
+ }
305
+ ),
306
+ /* @__PURE__ */ jsxRuntime.jsxs(v2.Menu.Content, { top: 1, popoverPlacement: "bottom-end", children: [
307
+ /* @__PURE__ */ jsxRuntime.jsxs(
308
+ designSystem.Flex,
309
+ {
310
+ alignItems: "center",
311
+ justifyContent: "center",
312
+ direction: "column",
313
+ padding: 1,
314
+ width: "100%",
315
+ children: [
316
+ /* @__PURE__ */ jsxRuntime.jsx(StyledMenuItem, { disabled: !canUpdate, onSelect: toggleEditReleaseModal, children: /* @__PURE__ */ jsxRuntime.jsxs(
317
+ designSystem.Flex,
318
+ {
319
+ paddingTop: 2,
320
+ paddingBottom: 2,
321
+ alignItems: "center",
322
+ gap: 2,
323
+ hasRadius: true,
324
+ width: "100%",
325
+ children: [
326
+ /* @__PURE__ */ jsxRuntime.jsx(PencilIcon, {}),
327
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { ellipsis: true, children: formatMessage({
328
+ id: "content-releases.header.actions.edit",
329
+ defaultMessage: "Edit"
330
+ }) })
331
+ ]
332
+ }
333
+ ) }),
334
+ /* @__PURE__ */ jsxRuntime.jsx(StyledMenuItem, { disabled: !canDelete, onSelect: toggleWarningSubmit, children: /* @__PURE__ */ jsxRuntime.jsxs(
335
+ designSystem.Flex,
336
+ {
337
+ paddingTop: 2,
338
+ paddingBottom: 2,
339
+ alignItems: "center",
340
+ gap: 2,
341
+ hasRadius: true,
342
+ width: "100%",
343
+ children: [
344
+ /* @__PURE__ */ jsxRuntime.jsx(TrashIcon, {}),
345
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { ellipsis: true, textColor: "danger600", children: formatMessage({
346
+ id: "content-releases.header.actions.delete",
347
+ defaultMessage: "Delete"
348
+ }) })
349
+ ]
350
+ }
351
+ ) })
352
+ ]
353
+ }
354
+ ),
355
+ /* @__PURE__ */ jsxRuntime.jsxs(
356
+ ReleaseInfoWrapper,
357
+ {
358
+ direction: "column",
359
+ justifyContent: "center",
360
+ alignItems: "flex-start",
361
+ gap: 1,
362
+ padding: 5,
363
+ children: [
364
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", fontWeight: "bold", children: formatMessage({
365
+ id: "content-releases.header.actions.created",
366
+ defaultMessage: "Created"
367
+ }) }),
368
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Typography, { variant: "pi", color: "neutral300", children: [
369
+ /* @__PURE__ */ jsxRuntime.jsx(helperPlugin.RelativeTime, { timestamp: new Date(release.createdAt) }),
370
+ formatMessage(
371
+ {
372
+ id: "content-releases.header.actions.created.description",
373
+ defaultMessage: "{hasCreatedByUser, select, true { by {createdBy}} other { by deleted user}}"
374
+ },
375
+ { createdBy: getCreatedByUser(), hasCreatedByUser }
376
+ )
377
+ ] })
378
+ ]
379
+ }
380
+ )
381
+ ] })
382
+ ] }),
370
383
  /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { size: "S", variant: "tertiary", onClick: handleRefresh, children: formatMessage({
371
384
  id: "content-releases.header.actions.refresh",
372
385
  defaultMessage: "Refresh"
@@ -422,6 +435,9 @@ const ReleaseDetailsBody = () => {
422
435
  isError: isReleaseError,
423
436
  error: releaseError
424
437
  } = index.useGetReleaseQuery({ id: releaseId });
438
+ const {
439
+ allowedActions: { canUpdate }
440
+ } = helperPlugin.useRBAC(index.PERMISSIONS);
425
441
  const release = releaseData?.data;
426
442
  const selectedGroupBy = query?.groupBy || "contentType";
427
443
  const {
@@ -435,7 +451,7 @@ const ReleaseDetailsBody = () => {
435
451
  releaseId
436
452
  });
437
453
  const [updateReleaseAction] = index.useUpdateReleaseActionMutation();
438
- const handleChangeType = async (e, actionId) => {
454
+ const handleChangeType = async (e, actionId, actionPath) => {
439
455
  const response = await updateReleaseAction({
440
456
  params: {
441
457
  releaseId,
@@ -443,7 +459,11 @@ const ReleaseDetailsBody = () => {
443
459
  },
444
460
  body: {
445
461
  type: e.target.value
446
- }
462
+ },
463
+ query,
464
+ // We are passing the query params to make optimistic updates
465
+ actionPath
466
+ // We are passing the action path to found the position in the cache of the action for optimistic updates
447
467
  });
448
468
  if ("error" in response) {
449
469
  if (index.isAxiosError(response.error)) {
@@ -524,7 +544,7 @@ const ReleaseDetailsBody = () => {
524
544
  designSystem.SingleSelect,
525
545
  {
526
546
  "aria-label": formatMessage({
527
- id: "content-releases.pages.ReleaseDetails.groupBy.label",
547
+ id: "content-releases.pages.ReleaseDetails.groupBy.aria-label",
528
548
  defaultMessage: "Group by"
529
549
  }),
530
550
  customizeContent: (value) => formatMessage(
@@ -542,7 +562,7 @@ const ReleaseDetailsBody = () => {
542
562
  }
543
563
  ) }),
544
564
  Object.keys(releaseActions).map((key) => /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 4, direction: "column", alignItems: "stretch", children: [
545
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Badge, { children: key }) }),
565
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { role: "separator", "aria-label": key, children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Badge, { children: key }) }),
546
566
  /* @__PURE__ */ jsxRuntime.jsx(
547
567
  helperPlugin.Table.Root,
548
568
  {
@@ -612,56 +632,59 @@ const ReleaseDetailsBody = () => {
612
632
  )
613
633
  ] }),
614
634
  /* @__PURE__ */ jsxRuntime.jsx(helperPlugin.Table.LoadingBody, {}),
615
- /* @__PURE__ */ jsxRuntime.jsx(helperPlugin.Table.Body, { children: releaseActions[key].map(({ id, contentType, locale, type, entry }) => /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Tr, { children: [
616
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Td, { width: "25%", maxWidth: "200px", children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { ellipsis: true, children: `${contentType.mainFieldValue || entry.id}` }) }),
617
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Td, { width: "10%", children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { children: `${locale?.name ? locale.name : "-"}` }) }),
618
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Td, { width: "10%", children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { children: contentType.displayName || "" }) }),
619
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Td, { width: "20%", children: release.releasedAt ? /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { children: formatMessage(
620
- {
621
- id: "content-releases.page.ReleaseDetails.table.action-published",
622
- defaultMessage: "This entry was <b>{isPublish, select, true {published} other {unpublished}}</b>."
623
- },
624
- {
625
- isPublish: type === "publish",
626
- b: (children) => /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { fontWeight: "bold", children })
627
- }
628
- ) }) : /* @__PURE__ */ jsxRuntime.jsx(
629
- index.ReleaseActionOptions,
630
- {
631
- selected: type,
632
- handleChange: (e) => handleChangeType(e, id),
633
- name: `release-action-${id}-type`
634
- }
635
- ) }),
636
- !release.releasedAt && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
637
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Td, { width: "20%", minWidth: "200px", children: /* @__PURE__ */ jsxRuntime.jsx(
638
- EntryValidationText,
635
+ /* @__PURE__ */ jsxRuntime.jsx(helperPlugin.Table.Body, { children: releaseActions[key].map(
636
+ ({ id, contentType, locale, type, entry }, actionIndex) => /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Tr, { children: [
637
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Td, { width: "25%", maxWidth: "200px", children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { ellipsis: true, children: `${contentType.mainFieldValue || entry.id}` }) }),
638
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Td, { width: "10%", children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { children: `${locale?.name ? locale.name : "-"}` }) }),
639
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Td, { width: "10%", children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { children: contentType.displayName || "" }) }),
640
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Td, { width: "20%", children: release.releasedAt ? /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { children: formatMessage(
641
+ {
642
+ id: "content-releases.page.ReleaseDetails.table.action-published",
643
+ defaultMessage: "This entry was <b>{isPublish, select, true {published} other {unpublished}}</b>."
644
+ },
639
645
  {
640
- action: type,
641
- schema: contentTypes?.[contentType.uid],
642
- components,
643
- entry
646
+ isPublish: type === "publish",
647
+ b: (children) => /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { fontWeight: "bold", children })
648
+ }
649
+ ) }) : /* @__PURE__ */ jsxRuntime.jsx(
650
+ index.ReleaseActionOptions,
651
+ {
652
+ selected: type,
653
+ handleChange: (e) => handleChangeType(e, id, [key, actionIndex]),
654
+ name: `release-action-${id}-type`,
655
+ disabled: !canUpdate
644
656
  }
645
657
  ) }),
646
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Td, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { justifyContent: "flex-end", children: /* @__PURE__ */ jsxRuntime.jsxs(index.ReleaseActionMenu.Root, { children: [
647
- /* @__PURE__ */ jsxRuntime.jsx(
648
- index.ReleaseActionMenu.ReleaseActionEntryLinkItem,
649
- {
650
- contentTypeUid: contentType.uid,
651
- entryId: entry.id,
652
- locale: locale?.code
653
- }
654
- ),
655
- /* @__PURE__ */ jsxRuntime.jsx(
656
- index.ReleaseActionMenu.DeleteReleaseActionItem,
658
+ !release.releasedAt && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
659
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Td, { width: "20%", minWidth: "200px", children: /* @__PURE__ */ jsxRuntime.jsx(
660
+ EntryValidationText,
657
661
  {
658
- releaseId: release.id,
659
- actionId: id
662
+ action: type,
663
+ schema: contentTypes?.[contentType.uid],
664
+ components,
665
+ entry
660
666
  }
661
- )
662
- ] }) }) })
663
- ] })
664
- ] }, id)) })
667
+ ) }),
668
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Td, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { justifyContent: "flex-end", children: /* @__PURE__ */ jsxRuntime.jsxs(index.ReleaseActionMenu.Root, { children: [
669
+ /* @__PURE__ */ jsxRuntime.jsx(
670
+ index.ReleaseActionMenu.ReleaseActionEntryLinkItem,
671
+ {
672
+ contentTypeUid: contentType.uid,
673
+ entryId: entry.id,
674
+ locale: locale?.code
675
+ }
676
+ ),
677
+ /* @__PURE__ */ jsxRuntime.jsx(
678
+ index.ReleaseActionMenu.DeleteReleaseActionItem,
679
+ {
680
+ releaseId: release.id,
681
+ actionId: id
682
+ }
683
+ )
684
+ ] }) }) })
685
+ ] })
686
+ ] }, id)
687
+ ) })
665
688
  ] })
666
689
  }
667
690
  )
@@ -786,37 +809,6 @@ const ReleaseDetailsPage = () => {
786
809
  }
787
810
  );
788
811
  };
789
- const ReleasesLayout = ({
790
- isLoading,
791
- totalReleases,
792
- onClickAddRelease,
793
- children
794
- }) => {
795
- const { formatMessage } = reactIntl.useIntl();
796
- return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Main, { "aria-busy": isLoading, children: [
797
- /* @__PURE__ */ jsxRuntime.jsx(
798
- designSystem.HeaderLayout,
799
- {
800
- title: formatMessage({
801
- id: "content-releases.pages.Releases.title",
802
- defaultMessage: "Releases"
803
- }),
804
- subtitle: !isLoading && formatMessage(
805
- {
806
- id: "content-releases.pages.Releases.header-subtitle",
807
- defaultMessage: "{number, plural, =0 {No releases} one {# release} other {# releases}}"
808
- },
809
- { number: totalReleases }
810
- ),
811
- primaryAction: /* @__PURE__ */ jsxRuntime.jsx(helperPlugin.CheckPermissions, { permissions: index.PERMISSIONS.create, children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { startIcon: /* @__PURE__ */ jsxRuntime.jsx(icons.Plus, {}), onClick: onClickAddRelease, children: formatMessage({
812
- id: "content-releases.header.actions.add-release",
813
- defaultMessage: "New release"
814
- }) }) })
815
- }
816
- ),
817
- children
818
- ] });
819
- };
820
812
  const LinkCard = styled__default.default(v2.Link)`
821
813
  display: block;
822
814
  `;
@@ -868,6 +860,14 @@ const ReleasesGrid = ({ sectionTitle, releases = [], isError = false }) => {
868
860
  }
869
861
  ) }) }, id)) });
870
862
  };
863
+ const StyledAlert = styled__default.default(designSystem.Alert)`
864
+ button {
865
+ display: none;
866
+ }
867
+ p + div {
868
+ margin-left: auto;
869
+ }
870
+ `;
871
871
  const INITIAL_FORM_VALUES = {
872
872
  name: ""
873
873
  };
@@ -882,6 +882,9 @@ const ReleasesPage = () => {
882
882
  const [{ query }, setQuery] = helperPlugin.useQueryParams();
883
883
  const response = index.useGetReleasesQuery(query);
884
884
  const [createRelease, { isLoading: isSubmittingForm }] = index.useCreateReleaseMutation();
885
+ const { getFeature } = strapiAdmin.useLicenseLimits();
886
+ const { maximumReleases = 3 } = getFeature("cms-content-releases");
887
+ const { trackUsage } = helperPlugin.useTracking();
885
888
  const { isLoading, isSuccess, isError } = response;
886
889
  const activeTab = response?.currentData?.meta?.activeTab || "pending";
887
890
  const activeTabIndex = ["pending", "done"].indexOf(activeTab);
@@ -910,9 +913,10 @@ const ReleasesPage = () => {
910
913
  setReleaseModalShown((prev) => !prev);
911
914
  };
912
915
  if (isLoading) {
913
- return /* @__PURE__ */ jsxRuntime.jsx(ReleasesLayout, { onClickAddRelease: toggleAddReleaseModal, isLoading: true, children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.ContentLayout, { children: /* @__PURE__ */ jsxRuntime.jsx(helperPlugin.LoadingIndicatorPage, {}) }) });
916
+ return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Main, { "aria-busy": isLoading, children: /* @__PURE__ */ jsxRuntime.jsx(helperPlugin.LoadingIndicatorPage, {}) });
914
917
  }
915
918
  const totalReleases = isSuccess && response.currentData?.meta?.pagination?.total || 0;
919
+ const hasReachedMaximumPendingReleases = totalReleases >= maximumReleases;
916
920
  const handleTabChange = (index2) => {
917
921
  setQuery({
918
922
  ...query,
@@ -937,6 +941,7 @@ const ReleasesPage = () => {
937
941
  defaultMessage: "Release created."
938
942
  })
939
943
  });
944
+ trackUsage("didCreateRelease");
940
945
  push(`/plugins/content-releases/${response2.data.data.id}`);
941
946
  } else if (index.isAxiosError(response2.error)) {
942
947
  toggleNotification({
@@ -950,8 +955,60 @@ const ReleasesPage = () => {
950
955
  });
951
956
  }
952
957
  };
953
- return /* @__PURE__ */ jsxRuntime.jsxs(ReleasesLayout, { onClickAddRelease: toggleAddReleaseModal, totalReleases, children: [
958
+ return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Main, { "aria-busy": isLoading, children: [
959
+ /* @__PURE__ */ jsxRuntime.jsx(
960
+ designSystem.HeaderLayout,
961
+ {
962
+ title: formatMessage({
963
+ id: "content-releases.pages.Releases.title",
964
+ defaultMessage: "Releases"
965
+ }),
966
+ subtitle: formatMessage(
967
+ {
968
+ id: "content-releases.pages.Releases.header-subtitle",
969
+ defaultMessage: "{number, plural, =0 {No releases} one {# release} other {# releases}}"
970
+ },
971
+ { number: totalReleases }
972
+ ),
973
+ primaryAction: /* @__PURE__ */ jsxRuntime.jsx(helperPlugin.CheckPermissions, { permissions: index.PERMISSIONS.create, children: /* @__PURE__ */ jsxRuntime.jsx(
974
+ designSystem.Button,
975
+ {
976
+ startIcon: /* @__PURE__ */ jsxRuntime.jsx(icons.Plus, {}),
977
+ onClick: toggleAddReleaseModal,
978
+ disabled: hasReachedMaximumPendingReleases,
979
+ children: formatMessage({
980
+ id: "content-releases.header.actions.add-release",
981
+ defaultMessage: "New release"
982
+ })
983
+ }
984
+ ) })
985
+ }
986
+ ),
954
987
  /* @__PURE__ */ jsxRuntime.jsx(designSystem.ContentLayout, { children: /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
988
+ activeTab === "pending" && hasReachedMaximumPendingReleases && /* @__PURE__ */ jsxRuntime.jsx(
989
+ StyledAlert,
990
+ {
991
+ marginBottom: 6,
992
+ action: /* @__PURE__ */ jsxRuntime.jsx(v2.Link, { href: "https://strapi.io/pricing-cloud", isExternal: true, children: formatMessage({
993
+ id: "content-releases.pages.Releases.max-limit-reached.action",
994
+ defaultMessage: "Explore plans"
995
+ }) }),
996
+ title: formatMessage(
997
+ {
998
+ id: "content-releases.pages.Releases.max-limit-reached.title",
999
+ defaultMessage: "You have reached the {number} pending {number, plural, one {release} other {releases}} limit."
1000
+ },
1001
+ { number: maximumReleases }
1002
+ ),
1003
+ onClose: () => {
1004
+ },
1005
+ closeLabel: "",
1006
+ children: formatMessage({
1007
+ id: "content-releases.pages.Releases.max-limit-reached.message",
1008
+ defaultMessage: "Upgrade to manage an unlimited number of releases."
1009
+ })
1010
+ }
1011
+ ),
955
1012
  /* @__PURE__ */ jsxRuntime.jsxs(
956
1013
  designSystem.TabGroup,
957
1014
  {
@@ -1034,4 +1091,4 @@ const App = () => {
1034
1091
  ] }) });
1035
1092
  };
1036
1093
  exports.App = App;
1037
- //# sourceMappingURL=App-_20W9dYa.js.map
1094
+ //# sourceMappingURL=App-pspKUC-W.js.map