@strapi/content-releases 0.0.0-experimental.d954d57341a6623992a0d211daaec8e245c3517d → 0.0.0-experimental.d9f9f725e07a329ca272ecedef7bd85fa74dd661

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 (111) hide show
  1. package/LICENSE +17 -1
  2. package/dist/_chunks/{App-CqbuK4M6.js → App-dLXY5ei3.js} +439 -431
  3. package/dist/_chunks/App-dLXY5ei3.js.map +1 -0
  4. package/dist/_chunks/{App-Do-Rnv0A.mjs → App-jrh58sXY.mjs} +416 -409
  5. package/dist/_chunks/App-jrh58sXY.mjs.map +1 -0
  6. package/dist/_chunks/{PurchaseContentReleases-_MxP6-Dt.mjs → PurchaseContentReleases-3tRbmbY3.mjs} +7 -8
  7. package/dist/_chunks/PurchaseContentReleases-3tRbmbY3.mjs.map +1 -0
  8. package/dist/_chunks/{PurchaseContentReleases-Be3acS2L.js → PurchaseContentReleases-bpIYXOfu.js} +6 -7
  9. package/dist/_chunks/PurchaseContentReleases-bpIYXOfu.js.map +1 -0
  10. package/dist/_chunks/{en-DtFJ5ViE.js → en-HrREghh3.js} +1 -1
  11. package/dist/_chunks/en-HrREghh3.js.map +1 -0
  12. package/dist/_chunks/{en-B9Ur3VsE.mjs → en-ltT1TlKQ.mjs} +1 -1
  13. package/dist/_chunks/en-ltT1TlKQ.mjs.map +1 -0
  14. package/dist/_chunks/{index-Tedsw4GC.js → index-CVO0Rqdm.js} +504 -197
  15. package/dist/_chunks/index-CVO0Rqdm.js.map +1 -0
  16. package/dist/_chunks/{index-D_pgdqQL.mjs → index-PiOGBETy.mjs} +503 -198
  17. package/dist/_chunks/index-PiOGBETy.mjs.map +1 -0
  18. package/dist/admin/index.js +15 -1
  19. package/dist/admin/index.js.map +1 -1
  20. package/dist/admin/index.mjs +16 -2
  21. package/dist/admin/index.mjs.map +1 -1
  22. package/dist/server/index.js +86 -83
  23. package/dist/server/index.js.map +1 -1
  24. package/dist/server/index.mjs +86 -84
  25. package/dist/server/index.mjs.map +1 -1
  26. package/package.json +36 -29
  27. package/dist/_chunks/App-CqbuK4M6.js.map +0 -1
  28. package/dist/_chunks/App-Do-Rnv0A.mjs.map +0 -1
  29. package/dist/_chunks/PurchaseContentReleases-Be3acS2L.js.map +0 -1
  30. package/dist/_chunks/PurchaseContentReleases-_MxP6-Dt.mjs.map +0 -1
  31. package/dist/_chunks/en-B9Ur3VsE.mjs.map +0 -1
  32. package/dist/_chunks/en-DtFJ5ViE.js.map +0 -1
  33. package/dist/_chunks/index-D_pgdqQL.mjs.map +0 -1
  34. package/dist/_chunks/index-Tedsw4GC.js.map +0 -1
  35. package/dist/admin/src/components/CMReleasesContainer.d.ts +0 -22
  36. package/dist/admin/src/components/RelativeTime.d.ts +0 -28
  37. package/dist/admin/src/components/ReleaseAction.d.ts +0 -3
  38. package/dist/admin/src/components/ReleaseActionMenu.d.ts +0 -26
  39. package/dist/admin/src/components/ReleaseActionOptions.d.ts +0 -9
  40. package/dist/admin/src/components/ReleaseListCell.d.ts +0 -0
  41. package/dist/admin/src/components/ReleaseModal.d.ts +0 -17
  42. package/dist/admin/src/constants.d.ts +0 -58
  43. package/dist/admin/src/index.d.ts +0 -3
  44. package/dist/admin/src/pages/App.d.ts +0 -1
  45. package/dist/admin/src/pages/PurchaseContentReleases.d.ts +0 -2
  46. package/dist/admin/src/pages/ReleaseDetailsPage.d.ts +0 -2
  47. package/dist/admin/src/pages/ReleasesPage.d.ts +0 -8
  48. package/dist/admin/src/pages/tests/mockReleaseDetailsPageData.d.ts +0 -181
  49. package/dist/admin/src/pages/tests/mockReleasesPageData.d.ts +0 -39
  50. package/dist/admin/src/pluginId.d.ts +0 -1
  51. package/dist/admin/src/services/release.d.ts +0 -105
  52. package/dist/admin/src/store/hooks.d.ts +0 -7
  53. package/dist/admin/src/utils/api.d.ts +0 -6
  54. package/dist/admin/src/utils/prefixPluginTranslations.d.ts +0 -3
  55. package/dist/admin/src/utils/time.d.ts +0 -1
  56. package/dist/server/src/bootstrap.d.ts +0 -5
  57. package/dist/server/src/bootstrap.d.ts.map +0 -1
  58. package/dist/server/src/constants.d.ts +0 -12
  59. package/dist/server/src/constants.d.ts.map +0 -1
  60. package/dist/server/src/content-types/index.d.ts +0 -99
  61. package/dist/server/src/content-types/index.d.ts.map +0 -1
  62. package/dist/server/src/content-types/release/index.d.ts +0 -48
  63. package/dist/server/src/content-types/release/index.d.ts.map +0 -1
  64. package/dist/server/src/content-types/release/schema.d.ts +0 -47
  65. package/dist/server/src/content-types/release/schema.d.ts.map +0 -1
  66. package/dist/server/src/content-types/release-action/index.d.ts +0 -50
  67. package/dist/server/src/content-types/release-action/index.d.ts.map +0 -1
  68. package/dist/server/src/content-types/release-action/schema.d.ts +0 -49
  69. package/dist/server/src/content-types/release-action/schema.d.ts.map +0 -1
  70. package/dist/server/src/controllers/index.d.ts +0 -20
  71. package/dist/server/src/controllers/index.d.ts.map +0 -1
  72. package/dist/server/src/controllers/release-action.d.ts +0 -10
  73. package/dist/server/src/controllers/release-action.d.ts.map +0 -1
  74. package/dist/server/src/controllers/release.d.ts +0 -12
  75. package/dist/server/src/controllers/release.d.ts.map +0 -1
  76. package/dist/server/src/controllers/validation/release-action.d.ts +0 -8
  77. package/dist/server/src/controllers/validation/release-action.d.ts.map +0 -1
  78. package/dist/server/src/controllers/validation/release.d.ts +0 -2
  79. package/dist/server/src/controllers/validation/release.d.ts.map +0 -1
  80. package/dist/server/src/destroy.d.ts +0 -5
  81. package/dist/server/src/destroy.d.ts.map +0 -1
  82. package/dist/server/src/index.d.ts +0 -2096
  83. package/dist/server/src/index.d.ts.map +0 -1
  84. package/dist/server/src/migrations/index.d.ts +0 -13
  85. package/dist/server/src/migrations/index.d.ts.map +0 -1
  86. package/dist/server/src/register.d.ts +0 -5
  87. package/dist/server/src/register.d.ts.map +0 -1
  88. package/dist/server/src/routes/index.d.ts +0 -35
  89. package/dist/server/src/routes/index.d.ts.map +0 -1
  90. package/dist/server/src/routes/release-action.d.ts +0 -18
  91. package/dist/server/src/routes/release-action.d.ts.map +0 -1
  92. package/dist/server/src/routes/release.d.ts +0 -18
  93. package/dist/server/src/routes/release.d.ts.map +0 -1
  94. package/dist/server/src/services/index.d.ts +0 -1826
  95. package/dist/server/src/services/index.d.ts.map +0 -1
  96. package/dist/server/src/services/release.d.ts +0 -66
  97. package/dist/server/src/services/release.d.ts.map +0 -1
  98. package/dist/server/src/services/scheduling.d.ts +0 -18
  99. package/dist/server/src/services/scheduling.d.ts.map +0 -1
  100. package/dist/server/src/services/validation.d.ts +0 -18
  101. package/dist/server/src/services/validation.d.ts.map +0 -1
  102. package/dist/server/src/utils/index.d.ts +0 -14
  103. package/dist/server/src/utils/index.d.ts.map +0 -1
  104. package/dist/shared/contracts/release-actions.d.ts +0 -131
  105. package/dist/shared/contracts/release-actions.d.ts.map +0 -1
  106. package/dist/shared/contracts/releases.d.ts +0 -182
  107. package/dist/shared/contracts/releases.d.ts.map +0 -1
  108. package/dist/shared/types.d.ts +0 -24
  109. package/dist/shared/types.d.ts.map +0 -1
  110. package/dist/shared/validation-schemas.d.ts +0 -2
  111. package/dist/shared/validation-schemas.d.ts.map +0 -1
@@ -1,17 +1,20 @@
1
1
  "use strict";
2
+ const helperPlugin = require("@strapi/helper-plugin");
2
3
  const icons = require("@strapi/icons");
3
4
  const jsxRuntime = require("react/jsx-runtime");
4
5
  const React = require("react");
5
6
  const query = require("@reduxjs/toolkit/query");
6
- const strapiAdmin = require("@strapi/admin/strapi-admin");
7
- const strapiAdmin$1 = require("@strapi/content-manager/strapi-admin");
8
7
  const designSystem = require("@strapi/design-system");
9
- const symbols = require("@strapi/icons/symbols");
8
+ const v2 = require("@strapi/design-system/v2");
9
+ const axios = require("axios");
10
10
  const formik = require("formik");
11
11
  const reactIntl = require("react-intl");
12
12
  const reactRouterDom = require("react-router-dom");
13
13
  const yup = require("yup");
14
- const styledComponents = require("styled-components");
14
+ const react = require("@reduxjs/toolkit/query/react");
15
+ const styled = require("styled-components");
16
+ const reactRedux = require("react-redux");
17
+ const _interopDefault = (e) => e && e.__esModule ? e : { default: e };
15
18
  function _interopNamespace(e) {
16
19
  if (e && e.__esModule)
17
20
  return e;
@@ -32,6 +35,7 @@ function _interopNamespace(e) {
32
35
  }
33
36
  const React__namespace = /* @__PURE__ */ _interopNamespace(React);
34
37
  const yup__namespace = /* @__PURE__ */ _interopNamespace(yup);
38
+ const styled__default = /* @__PURE__ */ _interopDefault(styled);
35
39
  const __variableDynamicImportRuntimeHelper = (glob, path) => {
36
40
  const v = glob[path];
37
41
  if (v) {
@@ -113,9 +117,49 @@ const PERMISSIONS = {
113
117
  }
114
118
  ]
115
119
  };
116
- const releaseApi = strapiAdmin.adminApi.enhanceEndpoints({
117
- addTagTypes: ["Release", "ReleaseAction", "EntriesInRelease"]
118
- }).injectEndpoints({
120
+ const pluginId = "content-releases";
121
+ const axiosBaseQuery = async ({
122
+ url,
123
+ method,
124
+ data,
125
+ config
126
+ }) => {
127
+ try {
128
+ const { get, post, del, put } = helperPlugin.getFetchClient();
129
+ if (method === "POST") {
130
+ const result2 = await post(url, data, config);
131
+ return { data: result2.data };
132
+ }
133
+ if (method === "DELETE") {
134
+ const result2 = await del(url, config);
135
+ return { data: result2.data };
136
+ }
137
+ if (method === "PUT") {
138
+ const result2 = await put(url, data, config);
139
+ return { data: result2.data };
140
+ }
141
+ const result = await get(url, config);
142
+ return { data: result.data };
143
+ } catch (error) {
144
+ const err = error;
145
+ return {
146
+ error: {
147
+ status: err.response?.status,
148
+ code: err.code,
149
+ response: {
150
+ data: err.response?.data
151
+ }
152
+ }
153
+ };
154
+ }
155
+ };
156
+ const isAxiosError = (err) => {
157
+ return typeof err === "object" && err !== null && "response" in err && typeof err.response === "object" && err.response !== null && "data" in err.response;
158
+ };
159
+ const releaseApi = react.createApi({
160
+ reducerPath: pluginId,
161
+ baseQuery: axiosBaseQuery,
162
+ tagTypes: ["Release", "ReleaseAction", "EntriesInRelease"],
119
163
  endpoints: (build) => {
120
164
  return {
121
165
  getReleasesForEntry: build.query({
@@ -259,17 +303,13 @@ const releaseApi = strapiAdmin.adminApi.enhanceEndpoints({
259
303
  ...query2
260
304
  };
261
305
  const patchResult = dispatch(
262
- releaseApi.util.updateQueryData(
263
- "getReleaseActions",
264
- paramsWithoutActionId,
265
- (draft) => {
266
- const [key, index] = actionPath;
267
- const action = draft.data[key][index];
268
- if (action) {
269
- action.type = body.type;
270
- }
306
+ releaseApi.util.updateQueryData("getReleaseActions", paramsWithoutActionId, (draft) => {
307
+ const [key, index] = actionPath;
308
+ const action = draft.data[key][index];
309
+ if (action) {
310
+ action.type = body.type;
271
311
  }
272
- )
312
+ })
273
313
  );
274
314
  try {
275
315
  await queryFulfilled;
@@ -359,12 +399,16 @@ const getTimezoneOffset = (timezone, date) => {
359
399
  return "";
360
400
  }
361
401
  };
362
- const StyledMenuItem = styledComponents.styled(designSystem.Menu.Item)`
402
+ const useTypedDispatch = reactRedux.useDispatch;
403
+ const useTypedSelector = reactRedux.useSelector;
404
+ const StyledMenuItem = styled__default.default(v2.Menu.Item)`
363
405
  &:hover {
364
- background: ${({ theme, $variant = "neutral" }) => theme.colors[`${$variant}100`]};
406
+ background: ${({ theme, variant = "neutral" }) => theme.colors[`${variant}100`]};
365
407
 
366
408
  svg {
367
- fill: ${({ theme, $variant = "neutral" }) => theme.colors[`${$variant}600`]};
409
+ path {
410
+ fill: ${({ theme, variant = "neutral" }) => theme.colors[`${variant}600`]};
411
+ }
368
412
  }
369
413
 
370
414
  a {
@@ -373,7 +417,9 @@ const StyledMenuItem = styledComponents.styled(designSystem.Menu.Item)`
373
417
  }
374
418
 
375
419
  svg {
376
- fill: ${({ theme, $variant = "neutral" }) => theme.colors[`${$variant}600`]};
420
+ path {
421
+ fill: ${({ theme, variant = "neutral" }) => theme.colors[`${variant}600`]};
422
+ }
377
423
  }
378
424
 
379
425
  a {
@@ -385,14 +431,15 @@ const StyledMenuItem = styledComponents.styled(designSystem.Menu.Item)`
385
431
  width: 100%;
386
432
  }
387
433
  `;
434
+ const StyledIconButton = styled__default.default(designSystem.IconButton)`
435
+ /* Setting this style inline with borderColor will not apply the style */
436
+ border: ${({ theme }) => `1px solid ${theme.colors.neutral200}`};
437
+ `;
388
438
  const DeleteReleaseActionItem = ({ releaseId, actionId }) => {
389
439
  const { formatMessage } = reactIntl.useIntl();
390
- const { toggleNotification } = strapiAdmin.useNotification();
391
- const { formatAPIError } = strapiAdmin.useAPIErrorHandler();
440
+ const toggleNotification = helperPlugin.useNotification();
441
+ const { formatAPIError } = helperPlugin.useAPIErrorHandler();
392
442
  const [deleteReleaseAction] = useDeleteReleaseActionMutation();
393
- const {
394
- allowedActions: { canDeleteAction }
395
- } = strapiAdmin.useRBAC(PERMISSIONS);
396
443
  const handleDeleteAction = async () => {
397
444
  const response = await deleteReleaseAction({
398
445
  params: { releaseId, actionId }
@@ -408,29 +455,26 @@ const DeleteReleaseActionItem = ({ releaseId, actionId }) => {
408
455
  return;
409
456
  }
410
457
  if ("error" in response) {
411
- if (strapiAdmin.isFetchError(response.error)) {
458
+ if (axios.isAxiosError(response.error)) {
412
459
  toggleNotification({
413
- type: "danger",
460
+ type: "warning",
414
461
  message: formatAPIError(response.error)
415
462
  });
416
463
  } else {
417
464
  toggleNotification({
418
- type: "danger",
465
+ type: "warning",
419
466
  message: formatMessage({ id: "notification.error", defaultMessage: "An error occurred" })
420
467
  });
421
468
  }
422
469
  }
423
470
  };
424
- if (!canDeleteAction) {
425
- return null;
426
- }
427
- return /* @__PURE__ */ jsxRuntime.jsx(StyledMenuItem, { $variant: "danger", onSelect: handleDeleteAction, children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 2, children: [
428
- /* @__PURE__ */ jsxRuntime.jsx(icons.Cross, { width: "1.6rem", height: "1.6rem" }),
471
+ return /* @__PURE__ */ jsxRuntime.jsx(helperPlugin.CheckPermissions, { permissions: PERMISSIONS.deleteAction, children: /* @__PURE__ */ jsxRuntime.jsx(StyledMenuItem, { variant: "danger", onSelect: handleDeleteAction, children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 2, children: [
472
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Icon, { as: icons.Cross, width: 3, height: 3 }),
429
473
  /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { textColor: "danger600", variant: "omega", children: formatMessage({
430
474
  id: "content-releases.content-manager-edit-view.remove-from-release",
431
475
  defaultMessage: "Remove from release"
432
476
  }) })
433
- ] }) });
477
+ ] }) }) });
434
478
  };
435
479
  const ReleaseActionEntryLinkItem = ({
436
480
  contentTypeUid,
@@ -438,79 +482,77 @@ const ReleaseActionEntryLinkItem = ({
438
482
  locale
439
483
  }) => {
440
484
  const { formatMessage } = reactIntl.useIntl();
441
- const userPermissions = strapiAdmin.useAuth("ReleaseActionEntryLinkItem", (state) => state.permissions);
442
- const canUpdateEntryForLocale = React__namespace.useMemo(() => {
443
- const updatePermissions = userPermissions.find(
444
- (permission) => permission.subject === contentTypeUid && permission.action === "plugin::content-manager.explorer.update"
445
- );
446
- if (!updatePermissions) {
447
- return false;
448
- }
449
- return Boolean(!locale || updatePermissions.properties?.locales?.includes(locale));
450
- }, [contentTypeUid, locale, userPermissions]);
451
- const {
452
- allowedActions: { canUpdate: canUpdateContentType }
453
- } = strapiAdmin.useRBAC({
454
- updateContentType: [
455
- {
456
- action: "plugin::content-manager.explorer.update",
457
- subject: contentTypeUid
458
- }
459
- ]
460
- });
461
- if (!canUpdateContentType || !canUpdateEntryForLocale) {
462
- return null;
463
- }
485
+ const collectionTypePermissions = useTypedSelector(
486
+ (state) => state.rbacProvider.collectionTypesRelatedPermissions
487
+ );
488
+ const updatePermissions = contentTypeUid ? collectionTypePermissions[contentTypeUid]?.["plugin::content-manager.explorer.update"] : [];
489
+ const canUpdateEntryForLocale = Boolean(
490
+ !locale || updatePermissions?.find(
491
+ (permission) => permission.properties?.locales?.includes(locale)
492
+ )
493
+ );
464
494
  return /* @__PURE__ */ jsxRuntime.jsx(
465
- StyledMenuItem,
495
+ helperPlugin.CheckPermissions,
466
496
  {
467
- tag: reactRouterDom.Link,
468
- isLink: true,
469
- to: {
470
- pathname: `/content-manager/collection-types/${contentTypeUid}/${entryId}`,
471
- search: locale && `?plugins[i18n][locale]=${locale}`
472
- },
473
- children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 2, children: [
474
- /* @__PURE__ */ jsxRuntime.jsx(icons.Pencil, { width: "1.6rem", height: "1.6rem" }),
475
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "omega", children: formatMessage({
476
- id: "content-releases.content-manager-edit-view.edit-entry",
477
- defaultMessage: "Edit entry"
478
- }) })
479
- ] })
497
+ permissions: [
498
+ {
499
+ action: "plugin::content-manager.explorer.update",
500
+ subject: contentTypeUid
501
+ }
502
+ ],
503
+ children: canUpdateEntryForLocale && /* @__PURE__ */ jsxRuntime.jsx(StyledMenuItem, { children: /* @__PURE__ */ jsxRuntime.jsx(
504
+ v2.Link,
505
+ {
506
+ as: reactRouterDom.NavLink,
507
+ to: {
508
+ pathname: `/content-manager/collection-types/${contentTypeUid}/${entryId}`,
509
+ search: locale && `?plugins[i18n][locale]=${locale}`
510
+ },
511
+ startIcon: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Icon, { as: icons.Pencil, width: 3, height: 3 }),
512
+ children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "omega", children: formatMessage({
513
+ id: "content-releases.content-manager-edit-view.edit-entry",
514
+ defaultMessage: "Edit entry"
515
+ }) })
516
+ }
517
+ ) })
480
518
  }
481
519
  );
482
520
  };
483
521
  const EditReleaseItem = ({ releaseId }) => {
484
522
  const { formatMessage } = reactIntl.useIntl();
485
- return (
486
- /* @ts-expect-error inference isn't working in DS */
487
- /* @__PURE__ */ jsxRuntime.jsx(StyledMenuItem, { tag: reactRouterDom.Link, isLink: true, to: `/plugins/content-releases/${releaseId}`, children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 2, children: [
488
- /* @__PURE__ */ jsxRuntime.jsx(icons.Pencil, { width: "1.6rem", height: "1.6rem" }),
489
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "omega", children: formatMessage({
523
+ return /* @__PURE__ */ jsxRuntime.jsx(StyledMenuItem, { children: /* @__PURE__ */ jsxRuntime.jsx(
524
+ v2.Link,
525
+ {
526
+ href: `/admin/plugins/content-releases/${releaseId}`,
527
+ startIcon: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Icon, { as: icons.Pencil, width: 3, height: 3 }),
528
+ isExternal: false,
529
+ children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "omega", children: formatMessage({
490
530
  id: "content-releases.content-manager-edit-view.edit-release",
491
531
  defaultMessage: "Edit release"
492
532
  }) })
493
- ] }) })
494
- );
533
+ }
534
+ ) });
495
535
  };
496
- const Root = ({ children }) => {
536
+ const Root = ({ children, hasTriggerBorder = false }) => {
497
537
  const { formatMessage } = reactIntl.useIntl();
498
- const { allowedActions } = strapiAdmin.useRBAC(PERMISSIONS);
499
538
  return (
500
539
  // A user can access the dropdown if they have permissions to delete a release-action OR update a release
501
- allowedActions.canDeleteAction || allowedActions.canUpdate ? /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Menu.Root, { children: [
502
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Menu.Trigger, { paddingLeft: 2, paddingRight: 2, children: /* @__PURE__ */ jsxRuntime.jsx(
503
- designSystem.AccessibleIcon,
540
+ /* @__PURE__ */ jsxRuntime.jsx(helperPlugin.CheckPermissions, { permissions: [...PERMISSIONS.deleteAction, ...PERMISSIONS.update], children: /* @__PURE__ */ jsxRuntime.jsxs(v2.Menu.Root, { children: [
541
+ /* @__PURE__ */ jsxRuntime.jsx(
542
+ v2.Menu.Trigger,
504
543
  {
505
- label: formatMessage({
544
+ as: hasTriggerBorder ? StyledIconButton : designSystem.IconButton,
545
+ paddingLeft: 2,
546
+ paddingRight: 2,
547
+ "aria-label": formatMessage({
506
548
  id: "content-releases.content-manager-edit-view.release-action-menu",
507
549
  defaultMessage: "Release action options"
508
550
  }),
509
- children: /* @__PURE__ */ jsxRuntime.jsx(icons.More, {})
551
+ icon: /* @__PURE__ */ jsxRuntime.jsx(icons.More, {})
510
552
  }
511
- ) }),
512
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Menu.Content, { top: 1, popoverPlacement: "bottom-end", children })
513
- ] }) : null
553
+ ),
554
+ /* @__PURE__ */ jsxRuntime.jsx(v2.Menu.Content, { top: 1, popoverPlacement: "bottom-end", children })
555
+ ] }) })
514
556
  );
515
557
  };
516
558
  const ReleaseActionMenu = {
@@ -525,11 +567,11 @@ const getBorderLeftRadiusValue = (actionType) => {
525
567
  const getBorderRightRadiusValue = (actionType) => {
526
568
  return actionType === "publish" ? 0 : 1;
527
569
  };
528
- const FieldWrapper = styledComponents.styled(designSystem.Field.Root)`
529
- border-top-left-radius: ${({ $actionType, theme }) => theme.spaces[getBorderLeftRadiusValue($actionType)]};
530
- border-bottom-left-radius: ${({ $actionType, theme }) => theme.spaces[getBorderLeftRadiusValue($actionType)]};
531
- border-top-right-radius: ${({ $actionType, theme }) => theme.spaces[getBorderRightRadiusValue($actionType)]};
532
- border-bottom-right-radius: ${({ $actionType, theme }) => theme.spaces[getBorderRightRadiusValue($actionType)]};
570
+ const FieldWrapper = styled__default.default(designSystem.Field)`
571
+ border-top-left-radius: ${({ actionType, theme }) => theme.spaces[getBorderLeftRadiusValue(actionType)]};
572
+ border-bottom-left-radius: ${({ actionType, theme }) => theme.spaces[getBorderLeftRadiusValue(actionType)]};
573
+ border-top-right-radius: ${({ actionType, theme }) => theme.spaces[getBorderRightRadiusValue(actionType)]};
574
+ border-bottom-right-radius: ${({ actionType, theme }) => theme.spaces[getBorderRightRadiusValue(actionType)]};
533
575
 
534
576
  > label {
535
577
  color: inherit;
@@ -540,14 +582,14 @@ const FieldWrapper = styledComponents.styled(designSystem.Field.Root)`
540
582
  }
541
583
 
542
584
  &[data-checked='true'] {
543
- color: ${({ theme, $actionType }) => $actionType === "publish" ? theme.colors.primary700 : theme.colors.danger600};
544
- background-color: ${({ theme, $actionType }) => $actionType === "publish" ? theme.colors.primary100 : theme.colors.danger100};
545
- border-color: ${({ theme, $actionType }) => $actionType === "publish" ? theme.colors.primary700 : theme.colors.danger600};
585
+ color: ${({ theme, actionType }) => actionType === "publish" ? theme.colors.primary700 : theme.colors.danger600};
586
+ background-color: ${({ theme, actionType }) => actionType === "publish" ? theme.colors.primary100 : theme.colors.danger100};
587
+ border-color: ${({ theme, actionType }) => actionType === "publish" ? theme.colors.primary700 : theme.colors.danger600};
546
588
  }
547
589
 
548
590
  &[data-checked='false'] {
549
- border-left: ${({ $actionType }) => $actionType === "unpublish" && "none"};
550
- border-right: ${({ $actionType }) => $actionType === "publish" && "none"};
591
+ border-left: ${({ actionType }) => actionType === "unpublish" && "none"};
592
+ border-right: ${({ actionType }) => actionType === "publish" && "none"};
551
593
  }
552
594
 
553
595
  &[data-checked='false'][data-disabled='false']:hover {
@@ -576,7 +618,7 @@ const ActionOption = ({
576
618
  return /* @__PURE__ */ jsxRuntime.jsx(
577
619
  FieldWrapper,
578
620
  {
579
- $actionType: actionType,
621
+ actionType,
580
622
  background: "primary0",
581
623
  borderColor: "neutral200",
582
624
  color: selected === actionType ? "primary600" : "neutral600",
@@ -584,11 +626,12 @@ const ActionOption = ({
584
626
  cursor: "pointer",
585
627
  "data-checked": selected === actionType,
586
628
  "data-disabled": disabled && selected !== actionType,
587
- children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Field.Label, { children: [
629
+ children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.FieldLabel, { htmlFor: `${name}-${actionType}`, children: [
588
630
  /* @__PURE__ */ jsxRuntime.jsx(designSystem.VisuallyHidden, { children: /* @__PURE__ */ jsxRuntime.jsx(
589
- designSystem.Field.Input,
631
+ designSystem.FieldInput,
590
632
  {
591
633
  type: "radio",
634
+ id: `${name}-${actionType}`,
592
635
  name,
593
636
  checked: selected === actionType,
594
637
  onChange: handleChange,
@@ -641,20 +684,19 @@ const INITIAL_VALUES = {
641
684
  const NoReleases = () => {
642
685
  const { formatMessage } = reactIntl.useIntl();
643
686
  return /* @__PURE__ */ jsxRuntime.jsx(
644
- designSystem.EmptyStateLayout,
687
+ helperPlugin.NoContent,
645
688
  {
646
- icon: /* @__PURE__ */ jsxRuntime.jsx(symbols.EmptyDocuments, { width: "16rem" }),
647
- content: formatMessage({
689
+ content: {
648
690
  id: "content-releases.content-manager-edit-view.add-to-release.no-releases-message",
649
691
  defaultMessage: "No available releases. Open the list of releases and create a new one from there."
650
- }),
692
+ },
651
693
  action: /* @__PURE__ */ jsxRuntime.jsx(
652
- designSystem.LinkButton,
694
+ v2.LinkButton,
653
695
  {
654
696
  to: {
655
697
  pathname: "/plugins/content-releases"
656
698
  },
657
- tag: reactRouterDom.Link,
699
+ as: reactRouterDom.Link,
658
700
  variant: "secondary",
659
701
  children: formatMessage({
660
702
  id: "content-releases.content-manager-edit-view.add-to-release.redirect-button",
@@ -666,16 +708,15 @@ const NoReleases = () => {
666
708
  );
667
709
  };
668
710
  const AddActionToReleaseModal = ({
669
- open,
670
- onOpenChange,
711
+ handleClose,
671
712
  contentTypeUid,
672
713
  entryId
673
714
  }) => {
715
+ const releaseHeaderId = React__namespace.useId();
674
716
  const { formatMessage } = reactIntl.useIntl();
675
- const { toggleNotification } = strapiAdmin.useNotification();
676
- const { formatAPIError } = strapiAdmin.useAPIErrorHandler();
677
- const [{ query: query2 }] = strapiAdmin.useQueryParams();
678
- const locale = query2.plugins?.i18n?.locale;
717
+ const toggleNotification = helperPlugin.useNotification();
718
+ const { formatAPIError } = helperPlugin.useAPIErrorHandler();
719
+ const { modifiedData } = helperPlugin.useCMEditViewDataManager();
679
720
  const response = useGetReleasesForEntryQuery({
680
721
  contentTypeUid,
681
722
  entryId,
@@ -684,6 +725,7 @@ const AddActionToReleaseModal = ({
684
725
  const releases = response.data?.data;
685
726
  const [createReleaseAction, { isLoading }] = useCreateReleaseActionMutation();
686
727
  const handleSubmit = async (values) => {
728
+ const locale = modifiedData.locale;
687
729
  const releaseActionEntry = {
688
730
  contentType: contentTypeUid,
689
731
  id: entryId,
@@ -701,25 +743,25 @@ const AddActionToReleaseModal = ({
701
743
  defaultMessage: "Entry added to release"
702
744
  })
703
745
  });
704
- onOpenChange();
746
+ handleClose();
705
747
  return;
706
748
  }
707
749
  if ("error" in response2) {
708
- if (strapiAdmin.isFetchError(response2.error)) {
750
+ if (axios.isAxiosError(response2.error)) {
709
751
  toggleNotification({
710
- type: "danger",
752
+ type: "warning",
711
753
  message: formatAPIError(response2.error)
712
754
  });
713
755
  } else {
714
756
  toggleNotification({
715
- type: "danger",
757
+ type: "warning",
716
758
  message: formatMessage({ id: "notification.error", defaultMessage: "An error occurred" })
717
759
  });
718
760
  }
719
761
  }
720
762
  };
721
- return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Modal.Root, { open, onOpenChange, children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Modal.Content, { children: [
722
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Modal.Header, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Modal.Title, { fontWeight: "bold", children: formatMessage({
763
+ return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.ModalLayout, { onClose: handleClose, labelledBy: releaseHeaderId, children: [
764
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.ModalHeader, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { id: releaseHeaderId, fontWeight: "bold", textColor: "neutral800", children: formatMessage({
723
765
  id: "content-releases.content-manager-edit-view.add-to-release",
724
766
  defaultMessage: "Add to release"
725
767
  }) }) }),
@@ -731,26 +773,25 @@ const AddActionToReleaseModal = ({
731
773
  initialValues: INITIAL_VALUES,
732
774
  children: ({ values, setFieldValue }) => {
733
775
  return /* @__PURE__ */ jsxRuntime.jsxs(formik.Form, { children: [
734
- releases?.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx(NoReleases, {}) : /* @__PURE__ */ jsxRuntime.jsx(designSystem.Modal.Body, { children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", alignItems: "stretch", gap: 2, children: [
735
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { paddingBottom: 6, children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Field.Root, { required: true, children: [
736
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Field.Label, { children: formatMessage({
737
- id: "content-releases.content-manager-edit-view.add-to-release.select-label",
738
- defaultMessage: "Select a release"
739
- }) }),
740
- /* @__PURE__ */ jsxRuntime.jsx(
741
- designSystem.SingleSelect,
742
- {
743
- placeholder: formatMessage({
744
- id: "content-releases.content-manager-edit-view.add-to-release.select-placeholder",
745
- defaultMessage: "Select"
746
- }),
747
- onChange: (value) => setFieldValue("releaseId", value),
748
- value: values.releaseId,
749
- children: releases?.map((release) => /* @__PURE__ */ jsxRuntime.jsx(designSystem.SingleSelectOption, { value: release.id, children: release.name }, release.id))
750
- }
751
- )
752
- ] }) }),
753
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Field.Label, { children: formatMessage({
776
+ releases?.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx(NoReleases, {}) : /* @__PURE__ */ jsxRuntime.jsx(designSystem.ModalBody, { children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", alignItems: "stretch", gap: 2, children: [
777
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { paddingBottom: 6, children: /* @__PURE__ */ jsxRuntime.jsx(
778
+ designSystem.SingleSelect,
779
+ {
780
+ required: true,
781
+ label: formatMessage({
782
+ id: "content-releases.content-manager-edit-view.add-to-release.select-label",
783
+ defaultMessage: "Select a release"
784
+ }),
785
+ placeholder: formatMessage({
786
+ id: "content-releases.content-manager-edit-view.add-to-release.select-placeholder",
787
+ defaultMessage: "Select"
788
+ }),
789
+ onChange: (value) => setFieldValue("releaseId", value),
790
+ value: values.releaseId,
791
+ children: releases?.map((release) => /* @__PURE__ */ jsxRuntime.jsx(designSystem.SingleSelectOption, { value: release.id, children: release.name }, release.id))
792
+ }
793
+ ) }),
794
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.FieldLabel, { children: formatMessage({
754
795
  id: "content-releases.content-manager-edit-view.add-to-release.action-type-label",
755
796
  defaultMessage: "What do you want to do with this entry?"
756
797
  }) }),
@@ -763,37 +804,42 @@ const AddActionToReleaseModal = ({
763
804
  }
764
805
  )
765
806
  ] }) }),
766
- /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Modal.Footer, { children: [
767
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Modal.Close, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { variant: "tertiary", name: "cancel", children: formatMessage({
768
- id: "content-releases.content-manager-edit-view.add-to-release.cancel-button",
769
- defaultMessage: "Cancel"
770
- }) }) }),
771
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { type: "submit", disabled: !values.releaseId, loading: isLoading, children: formatMessage({
772
- id: "content-releases.content-manager-edit-view.add-to-release.continue-button",
773
- defaultMessage: "Continue"
774
- }) })
775
- ] })
807
+ /* @__PURE__ */ jsxRuntime.jsx(
808
+ designSystem.ModalFooter,
809
+ {
810
+ startActions: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { onClick: handleClose, variant: "tertiary", name: "cancel", children: formatMessage({
811
+ id: "content-releases.content-manager-edit-view.add-to-release.cancel-button",
812
+ defaultMessage: "Cancel"
813
+ }) }),
814
+ endActions: (
815
+ /**
816
+ * TODO: Ideally we would use isValid from Formik to disable the button, however currently it always returns true
817
+ * for yup.string().required(), even when the value is falsy (including empty string)
818
+ */
819
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { type: "submit", disabled: !values.releaseId, loading: isLoading, children: formatMessage({
820
+ id: "content-releases.content-manager-edit-view.add-to-release.continue-button",
821
+ defaultMessage: "Continue"
822
+ }) })
823
+ )
824
+ }
825
+ )
776
826
  ] });
777
827
  }
778
828
  }
779
829
  )
780
- ] }) });
830
+ ] });
781
831
  };
782
832
  const CMReleasesContainer = () => {
783
833
  const [isModalOpen, setIsModalOpen] = React__namespace.useState(false);
784
834
  const { formatMessage, formatDate, formatTime } = reactIntl.useIntl();
785
- const { id, slug, collectionType } = reactRouterDom.useParams();
786
- const isCreatingEntry = id === "create";
787
- const entryId = parseInt(id, 10);
788
- const { allowedActions } = strapiAdmin.useRBAC(PERMISSIONS);
789
- const { canCreateAction, canRead: canMain, canDeleteAction } = allowedActions;
790
- const { schema } = strapiAdmin$1.unstable_useDocument({
791
- collectionType,
792
- model: slug
793
- });
794
- const hasDraftAndPublish = schema?.options?.draftAndPublish;
835
+ const {
836
+ isCreatingEntry,
837
+ hasDraftAndPublish,
838
+ initialData: { id: entryId },
839
+ slug
840
+ } = helperPlugin.useCMEditViewDataManager();
795
841
  const contentTypeUid = slug;
796
- const canFetch = id != null && contentTypeUid != null;
842
+ const canFetch = entryId != null && contentTypeUid != null;
797
843
  const fetchParams = canFetch ? {
798
844
  contentTypeUid,
799
845
  entryId,
@@ -814,13 +860,10 @@ const CMReleasesContainer = () => {
814
860
  }
815
861
  return `success${shade}`;
816
862
  };
817
- if (!canMain) {
818
- return null;
819
- }
820
- return /* @__PURE__ */ jsxRuntime.jsxs(
863
+ return /* @__PURE__ */ jsxRuntime.jsx(helperPlugin.CheckPermissions, { permissions: PERMISSIONS.main, children: /* @__PURE__ */ jsxRuntime.jsxs(
821
864
  designSystem.Box,
822
865
  {
823
- tag: "aside",
866
+ as: "aside",
824
867
  "aria-label": formatMessage({
825
868
  id: "content-releases.plugin.name",
826
869
  defaultMessage: "Releases"
@@ -874,7 +917,7 @@ const CMReleasesContainer = () => {
874
917
  )
875
918
  }
876
919
  ),
877
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { padding: 4, direction: "column", gap: 2, width: "100%", alignItems: "flex-start", children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { padding: 4, direction: "column", gap: 2, width: "100%", alignItems: "flex-start", children: [
920
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { padding: 4, direction: "column", gap: 2, width: "100%", alignItems: "flex-start", children: [
878
921
  /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { fontSize: 2, fontWeight: "bold", variant: "omega", textColor: "neutral700", children: release.name }),
879
922
  release.scheduledAt && release.timezone && /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", textColor: "neutral600", children: formatMessage(
880
923
  {
@@ -898,7 +941,7 @@ const CMReleasesContainer = () => {
898
941
  )
899
942
  }
900
943
  ) }),
901
- canDeleteAction ? /* @__PURE__ */ jsxRuntime.jsxs(ReleaseActionMenu.Root, { hasTriggerBorder: true, children: [
944
+ /* @__PURE__ */ jsxRuntime.jsx(helperPlugin.CheckPermissions, { permissions: PERMISSIONS.deleteAction, children: /* @__PURE__ */ jsxRuntime.jsxs(ReleaseActionMenu.Root, { hasTriggerBorder: true, children: [
902
945
  /* @__PURE__ */ jsxRuntime.jsx(ReleaseActionMenu.EditReleaseItem, { releaseId: release.id }),
903
946
  /* @__PURE__ */ jsxRuntime.jsx(
904
947
  ReleaseActionMenu.DeleteReleaseActionItem,
@@ -907,14 +950,14 @@ const CMReleasesContainer = () => {
907
950
  actionId: release.actions[0].id
908
951
  }
909
952
  )
910
- ] }) : null
911
- ] }) })
953
+ ] }) })
954
+ ] })
912
955
  ]
913
956
  },
914
957
  release.id
915
958
  );
916
959
  }),
917
- canCreateAction ? /* @__PURE__ */ jsxRuntime.jsx(
960
+ /* @__PURE__ */ jsxRuntime.jsx(helperPlugin.CheckPermissions, { permissions: PERMISSIONS.createAction, children: /* @__PURE__ */ jsxRuntime.jsx(
918
961
  designSystem.Button,
919
962
  {
920
963
  justifyContent: "center",
@@ -929,30 +972,281 @@ const CMReleasesContainer = () => {
929
972
  defaultMessage: "Add to release"
930
973
  })
931
974
  }
932
- ) : null
975
+ ) })
933
976
  ] }),
934
- /* @__PURE__ */ jsxRuntime.jsx(
977
+ isModalOpen && /* @__PURE__ */ jsxRuntime.jsx(
935
978
  AddActionToReleaseModal,
936
979
  {
937
- open: isModalOpen,
938
- onOpenChange: toggleModal,
980
+ handleClose: toggleModal,
939
981
  contentTypeUid,
940
982
  entryId
941
983
  }
942
984
  )
943
985
  ]
944
986
  }
987
+ ) });
988
+ };
989
+ const getContentPermissions = (subject) => {
990
+ const permissions = {
991
+ publish: [
992
+ {
993
+ action: "plugin::content-manager.explorer.publish",
994
+ subject,
995
+ id: "",
996
+ actionParameters: {},
997
+ properties: {},
998
+ conditions: []
999
+ }
1000
+ ]
1001
+ };
1002
+ return permissions;
1003
+ };
1004
+ const ReleaseAction = ({ ids, model }) => {
1005
+ const { formatMessage } = reactIntl.useIntl();
1006
+ const toggleNotification = helperPlugin.useNotification();
1007
+ const { formatAPIError } = helperPlugin.useAPIErrorHandler();
1008
+ const { modifiedData } = helperPlugin.useCMEditViewDataManager();
1009
+ const contentPermissions = getContentPermissions(model);
1010
+ const {
1011
+ allowedActions: { canPublish }
1012
+ } = helperPlugin.useRBAC(contentPermissions);
1013
+ const {
1014
+ allowedActions: { canCreate }
1015
+ } = helperPlugin.useRBAC(PERMISSIONS);
1016
+ const response = useGetReleasesQuery();
1017
+ const releases = response.data?.data;
1018
+ const [createManyReleaseActions, { isLoading }] = useCreateManyReleaseActionsMutation();
1019
+ const handleSubmit = async (values) => {
1020
+ const locale = modifiedData.locale;
1021
+ const releaseActionEntries = ids.map((id) => ({
1022
+ type: values.type,
1023
+ entry: {
1024
+ contentType: model,
1025
+ id,
1026
+ locale
1027
+ }
1028
+ }));
1029
+ const response2 = await createManyReleaseActions({
1030
+ body: releaseActionEntries,
1031
+ params: { releaseId: values.releaseId }
1032
+ });
1033
+ if ("data" in response2) {
1034
+ const notificationMessage = formatMessage(
1035
+ {
1036
+ id: "content-releases.content-manager-list-view.add-to-release.notification.success.message",
1037
+ defaultMessage: "{entriesAlreadyInRelease} out of {totalEntries} entries were already in the release."
1038
+ },
1039
+ {
1040
+ entriesAlreadyInRelease: response2.data.meta.entriesAlreadyInRelease,
1041
+ totalEntries: response2.data.meta.totalEntries
1042
+ }
1043
+ );
1044
+ const notification = {
1045
+ type: "success",
1046
+ title: formatMessage(
1047
+ {
1048
+ id: "content-releases.content-manager-list-view.add-to-release.notification.success.title",
1049
+ defaultMessage: "Successfully added to release."
1050
+ },
1051
+ {
1052
+ entriesAlreadyInRelease: response2.data.meta.entriesAlreadyInRelease,
1053
+ totalEntries: response2.data.meta.totalEntries
1054
+ }
1055
+ ),
1056
+ message: response2.data.meta.entriesAlreadyInRelease ? notificationMessage : ""
1057
+ };
1058
+ toggleNotification(notification);
1059
+ return true;
1060
+ }
1061
+ if ("error" in response2) {
1062
+ if (axios.isAxiosError(response2.error)) {
1063
+ toggleNotification({
1064
+ type: "warning",
1065
+ message: formatAPIError(response2.error)
1066
+ });
1067
+ } else {
1068
+ toggleNotification({
1069
+ type: "warning",
1070
+ message: formatMessage({ id: "notification.error", defaultMessage: "An error occurred" })
1071
+ });
1072
+ }
1073
+ }
1074
+ };
1075
+ if (!canCreate || !canPublish)
1076
+ return null;
1077
+ return {
1078
+ actionType: "release",
1079
+ variant: "tertiary",
1080
+ label: formatMessage({
1081
+ id: "content-manager-list-view.add-to-release",
1082
+ defaultMessage: "Add to Release"
1083
+ }),
1084
+ dialog: {
1085
+ type: "modal",
1086
+ title: formatMessage({
1087
+ id: "content-manager-list-view.add-to-release",
1088
+ defaultMessage: "Add to Release"
1089
+ }),
1090
+ content: ({ onClose }) => {
1091
+ return /* @__PURE__ */ jsxRuntime.jsx(
1092
+ formik.Formik,
1093
+ {
1094
+ onSubmit: async (values) => {
1095
+ const data = await handleSubmit(values);
1096
+ if (data) {
1097
+ return onClose();
1098
+ }
1099
+ },
1100
+ validationSchema: RELEASE_ACTION_FORM_SCHEMA,
1101
+ initialValues: INITIAL_VALUES,
1102
+ children: ({ values, setFieldValue }) => /* @__PURE__ */ jsxRuntime.jsxs(formik.Form, { children: [
1103
+ releases?.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx(NoReleases, {}) : /* @__PURE__ */ jsxRuntime.jsx(designSystem.ModalBody, { children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", alignItems: "stretch", gap: 2, children: [
1104
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { paddingBottom: 6, children: /* @__PURE__ */ jsxRuntime.jsx(
1105
+ designSystem.SingleSelect,
1106
+ {
1107
+ required: true,
1108
+ label: formatMessage({
1109
+ id: "content-releases.content-manager-list-view.add-to-release.select-label",
1110
+ defaultMessage: "Select a release"
1111
+ }),
1112
+ placeholder: formatMessage({
1113
+ id: "content-releases.content-manager-list-view.add-to-release.select-placeholder",
1114
+ defaultMessage: "Select"
1115
+ }),
1116
+ onChange: (value) => setFieldValue("releaseId", value),
1117
+ value: values.releaseId,
1118
+ children: releases?.map((release) => /* @__PURE__ */ jsxRuntime.jsx(designSystem.SingleSelectOption, { value: release.id, children: release.name }, release.id))
1119
+ }
1120
+ ) }),
1121
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.FieldLabel, { children: formatMessage({
1122
+ id: "content-releases.content-manager-list-view.add-to-release.action-type-label",
1123
+ defaultMessage: "What do you want to do with these entries?"
1124
+ }) }),
1125
+ /* @__PURE__ */ jsxRuntime.jsx(
1126
+ ReleaseActionOptions,
1127
+ {
1128
+ selected: values.type,
1129
+ handleChange: (e) => setFieldValue("type", e.target.value),
1130
+ name: "type"
1131
+ }
1132
+ )
1133
+ ] }) }),
1134
+ /* @__PURE__ */ jsxRuntime.jsx(
1135
+ designSystem.ModalFooter,
1136
+ {
1137
+ startActions: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { onClick: onClose, variant: "tertiary", name: "cancel", children: formatMessage({
1138
+ id: "content-releases.content-manager-list-view.add-to-release.cancel-button",
1139
+ defaultMessage: "Cancel"
1140
+ }) }),
1141
+ endActions: (
1142
+ /**
1143
+ * TODO: Ideally we would use isValid from Formik to disable the button, however currently it always returns true
1144
+ * for yup.string().required(), even when the value is falsy (including empty string)
1145
+ */
1146
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { type: "submit", disabled: !values.releaseId, loading: isLoading, children: formatMessage({
1147
+ id: "content-releases.content-manager-list-view.add-to-release.continue-button",
1148
+ defaultMessage: "Continue"
1149
+ }) })
1150
+ )
1151
+ }
1152
+ )
1153
+ ] })
1154
+ }
1155
+ );
1156
+ }
1157
+ }
1158
+ };
1159
+ };
1160
+ const Button = styled__default.default.button`
1161
+ svg {
1162
+ > g,
1163
+ path {
1164
+ fill: ${({ theme }) => theme.colors.neutral500};
1165
+ }
1166
+ }
1167
+ &:hover {
1168
+ svg {
1169
+ > g,
1170
+ path {
1171
+ fill: ${({ theme }) => theme.colors.neutral600};
1172
+ }
1173
+ }
1174
+ }
1175
+ &:active {
1176
+ svg {
1177
+ > g,
1178
+ path {
1179
+ fill: ${({ theme }) => theme.colors.neutral400};
1180
+ }
1181
+ }
1182
+ }
1183
+ `;
1184
+ const ActionWrapper = styled__default.default(designSystem.Flex)`
1185
+ svg {
1186
+ height: ${4 / 16}rem;
1187
+ }
1188
+ `;
1189
+ const useReleasesList = (entryId) => {
1190
+ const { uid: contentTypeUid } = useTypedSelector(
1191
+ (state) => state["content-manager_listView"].contentType
1192
+ );
1193
+ const listViewData = useTypedSelector((state) => state["content-manager_listView"].data);
1194
+ const entriesIds = listViewData.map((entry) => entry.id);
1195
+ const response = useGetMappedEntriesInReleasesQuery(
1196
+ { contentTypeUid, entriesIds },
1197
+ { skip: !entriesIds || !contentTypeUid || entriesIds.length === 0 }
945
1198
  );
1199
+ const mappedEntriesInReleases = response.data || {};
1200
+ return mappedEntriesInReleases?.[entryId] || [];
946
1201
  };
947
- const pluginId = "content-releases";
948
- const prefixPluginTranslations = (trad, pluginId2) => {
949
- if (!pluginId2) {
950
- throw new TypeError("pluginId can't be empty");
1202
+ const addColumnToTableHook = ({ displayedHeaders, layout }) => {
1203
+ const { contentType } = layout;
1204
+ if (!contentType.options?.draftAndPublish) {
1205
+ return { displayedHeaders, layout };
951
1206
  }
952
- return Object.keys(trad).reduce((acc, current) => {
953
- acc[`${pluginId2}.${current}`] = trad[current];
954
- return acc;
955
- }, {});
1207
+ return {
1208
+ displayedHeaders: [
1209
+ ...displayedHeaders,
1210
+ {
1211
+ key: "__release_key__",
1212
+ fieldSchema: { type: "string" },
1213
+ metadatas: { label: "To be released in", searchable: true, sortable: false },
1214
+ name: "releasedAt",
1215
+ cellFormatter: (props) => /* @__PURE__ */ jsxRuntime.jsx(ReleaseListCell, { ...props })
1216
+ }
1217
+ ],
1218
+ layout
1219
+ };
1220
+ };
1221
+ const ReleaseListCell = ({ id }) => {
1222
+ const releases = useReleasesList(id);
1223
+ const [visible, setVisible] = React__namespace.useState(false);
1224
+ const buttonRef = React__namespace.useRef(null);
1225
+ const { formatMessage } = reactIntl.useIntl();
1226
+ const handleTogglePopover = () => setVisible((prev) => !prev);
1227
+ return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { onClick: (e) => e.stopPropagation(), children: /* @__PURE__ */ jsxRuntime.jsx(Button, { type: "button", onClick: handleTogglePopover, ref: buttonRef, children: /* @__PURE__ */ jsxRuntime.jsxs(ActionWrapper, { height: "2rem", width: "2rem", children: [
1228
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { style: { maxWidth: "252px", cursor: "pointer" }, textColor: "neutral800", children: releases.length > 0 ? formatMessage(
1229
+ {
1230
+ id: "content-releases.content-manager.list-view.releases-number",
1231
+ defaultMessage: "{number} {number, plural, one {release} other {releases}}"
1232
+ },
1233
+ {
1234
+ number: releases.length
1235
+ }
1236
+ ) : "-" }),
1237
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { children: [
1238
+ releases.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(helperPlugin.SortIcon, {}),
1239
+ visible && /* @__PURE__ */ jsxRuntime.jsx(
1240
+ designSystem.Popover,
1241
+ {
1242
+ onDismiss: handleTogglePopover,
1243
+ source: buttonRef,
1244
+ spacing: 16,
1245
+ children: /* @__PURE__ */ jsxRuntime.jsx("ul", { children: releases.map(({ id: id2, name }) => /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { padding: 3, as: "li", children: /* @__PURE__ */ jsxRuntime.jsx(v2.Link, { href: `/admin/plugins/content-releases/${id2}`, isExternal: false, children: name }) }, id2)) })
1246
+ }
1247
+ )
1248
+ ] })
1249
+ ] }) }) });
956
1250
  };
957
1251
  const admin = {
958
1252
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
@@ -960,20 +1254,32 @@ const admin = {
960
1254
  app.createHook("ContentReleases/pages/ReleaseDetails/add-locale-in-releases");
961
1255
  if (window.strapi.features.isEnabled("cms-content-releases")) {
962
1256
  app.addMenuLink({
963
- to: `plugins/${pluginId}`,
1257
+ to: `/plugins/${pluginId}`,
964
1258
  icon: icons.PaperPlane,
965
1259
  intlLabel: {
966
1260
  id: `${pluginId}.plugin.name`,
967
1261
  defaultMessage: "Releases"
968
1262
  },
969
- Component: () => Promise.resolve().then(() => require("./App-CqbuK4M6.js")).then((mod) => ({ default: mod.App })),
970
- permissions: PERMISSIONS.main,
971
- position: 2
1263
+ async Component() {
1264
+ const { App } = await Promise.resolve().then(() => require("./App-dLXY5ei3.js"));
1265
+ return App;
1266
+ },
1267
+ permissions: PERMISSIONS.main
972
1268
  });
973
- app.getPlugin("content-manager").injectComponent("editView", "right-links", {
1269
+ app.addMiddlewares([() => releaseApi.middleware]);
1270
+ app.addReducers({
1271
+ [releaseApi.reducerPath]: releaseApi.reducer
1272
+ });
1273
+ app.injectContentManagerComponent("editView", "right-links", {
974
1274
  name: `${pluginId}-link`,
975
1275
  Component: CMReleasesContainer
976
1276
  });
1277
+ app.plugins["content-manager"].apis.addBulkAction((actions) => {
1278
+ const deleteActionIndex = actions.findIndex((action) => action.name === "DeleteAction");
1279
+ actions.splice(deleteActionIndex, 0, ReleaseAction);
1280
+ return actions;
1281
+ });
1282
+ app.registerHook("Admin/CM/pages/ListView/inject-column-in-table", addColumnToTableHook);
977
1283
  } else if (!window.strapi.features.isEnabled("cms-content-releases") && window.strapi?.flags?.promoteEE) {
978
1284
  app.addMenuLink({
979
1285
  to: `/plugins/purchase-content-releases`,
@@ -982,22 +1288,21 @@ const admin = {
982
1288
  id: `${pluginId}.plugin.name`,
983
1289
  defaultMessage: "Releases"
984
1290
  },
985
- permissions: [],
986
1291
  async Component() {
987
- const { PurchaseContentReleases } = await Promise.resolve().then(() => require("./PurchaseContentReleases-Be3acS2L.js"));
988
- return { default: PurchaseContentReleases };
1292
+ const { PurchaseContentReleases } = await Promise.resolve().then(() => require("./PurchaseContentReleases-bpIYXOfu.js"));
1293
+ return PurchaseContentReleases;
989
1294
  },
990
- lockIcon: true,
991
- position: 2
1295
+ lockIcon: true
1296
+ // TODO: to replace with another name in v5
992
1297
  });
993
1298
  }
994
1299
  },
995
1300
  async registerTrads({ locales }) {
996
1301
  const importedTrads = await Promise.all(
997
1302
  locales.map((locale) => {
998
- return __variableDynamicImportRuntimeHelper(/* @__PURE__ */ Object.assign({ "./translations/en.json": () => Promise.resolve().then(() => require("./en-DtFJ5ViE.js")) }), `./translations/${locale}.json`).then(({ default: data }) => {
1303
+ return __variableDynamicImportRuntimeHelper(/* @__PURE__ */ Object.assign({ "./translations/en.json": () => Promise.resolve().then(() => require("./en-HrREghh3.js")) }), `./translations/${locale}.json`).then(({ default: data }) => {
999
1304
  return {
1000
- data: prefixPluginTranslations(data, "content-releases"),
1305
+ data: helperPlugin.prefixPluginTranslations(data, "content-releases"),
1001
1306
  locale
1002
1307
  };
1003
1308
  }).catch(() => {
@@ -1016,6 +1321,7 @@ exports.ReleaseActionMenu = ReleaseActionMenu;
1016
1321
  exports.ReleaseActionOptions = ReleaseActionOptions;
1017
1322
  exports.admin = admin;
1018
1323
  exports.getTimezoneOffset = getTimezoneOffset;
1324
+ exports.isAxiosError = isAxiosError;
1019
1325
  exports.pluginId = pluginId;
1020
1326
  exports.releaseApi = releaseApi;
1021
1327
  exports.useCreateReleaseMutation = useCreateReleaseMutation;
@@ -1024,6 +1330,7 @@ exports.useGetReleaseActionsQuery = useGetReleaseActionsQuery;
1024
1330
  exports.useGetReleaseQuery = useGetReleaseQuery;
1025
1331
  exports.useGetReleasesQuery = useGetReleasesQuery;
1026
1332
  exports.usePublishReleaseMutation = usePublishReleaseMutation;
1333
+ exports.useTypedDispatch = useTypedDispatch;
1027
1334
  exports.useUpdateReleaseActionMutation = useUpdateReleaseActionMutation;
1028
1335
  exports.useUpdateReleaseMutation = useUpdateReleaseMutation;
1029
- //# sourceMappingURL=index-Tedsw4GC.js.map
1336
+ //# sourceMappingURL=index-CVO0Rqdm.js.map