@strapi/content-releases 0.0.0-experimental.bd712ad3930045f4a5d2144c119e0b7856e97fc4 → 0.0.0-experimental.c5235059f5636c4549ea2118c75c43b92e2615c8

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 (67) hide show
  1. package/dist/_chunks/{App-zzUitryC.js → App-D2cVDqQK.js} +141 -94
  2. package/dist/_chunks/App-D2cVDqQK.js.map +1 -0
  3. package/dist/_chunks/{App-6gbM0io-.mjs → App-DbD5Ks8-.mjs} +144 -97
  4. package/dist/_chunks/App-DbD5Ks8-.mjs.map +1 -0
  5. package/dist/_chunks/{SettingsPage-CuSH193e.mjs → ReleasesSettingsPage-BDinCYKz.mjs} +34 -13
  6. package/dist/_chunks/ReleasesSettingsPage-BDinCYKz.mjs.map +1 -0
  7. package/dist/_chunks/{SettingsPage-CTOl3Qtw.js → ReleasesSettingsPage-CE_KqB_s.js} +34 -13
  8. package/dist/_chunks/ReleasesSettingsPage-CE_KqB_s.js.map +1 -0
  9. package/dist/_chunks/{en-1_1re1mc.js → en-CmYoEnA7.js} +3 -1
  10. package/dist/_chunks/en-CmYoEnA7.js.map +1 -0
  11. package/dist/_chunks/{en-C3sq5KNP.mjs → en-D0yVZFqf.mjs} +3 -1
  12. package/dist/_chunks/en-D0yVZFqf.mjs.map +1 -0
  13. package/dist/_chunks/{index-CuchqQ4_.mjs → index-Bgq1X1sL.mjs} +259 -24
  14. package/dist/_chunks/index-Bgq1X1sL.mjs.map +1 -0
  15. package/dist/_chunks/{index-BxRiXenX.js → index-mECKW99O.js} +245 -10
  16. package/dist/_chunks/index-mECKW99O.js.map +1 -0
  17. package/dist/_chunks/schemas-63pFihNF.mjs +44 -0
  18. package/dist/_chunks/schemas-63pFihNF.mjs.map +1 -0
  19. package/dist/_chunks/{validation-schemas-bib1fBc7.js → schemas-z5zp-_Gd.js} +21 -6
  20. package/dist/_chunks/schemas-z5zp-_Gd.js.map +1 -0
  21. package/dist/admin/index.js +1 -1
  22. package/dist/admin/index.mjs +1 -1
  23. package/dist/admin/src/components/ReleaseListCell.d.ts +28 -0
  24. package/dist/admin/src/constants.d.ts +18 -0
  25. package/dist/admin/src/modules/hooks.d.ts +7 -0
  26. package/dist/admin/src/pages/ReleasesSettingsPage.d.ts +1 -0
  27. package/dist/admin/src/services/release.d.ts +6 -4
  28. package/dist/admin/src/validation/schemas.d.ts +6 -0
  29. package/dist/server/index.js +83 -94
  30. package/dist/server/index.js.map +1 -1
  31. package/dist/server/index.mjs +83 -94
  32. package/dist/server/index.mjs.map +1 -1
  33. package/dist/server/src/controllers/index.d.ts +2 -0
  34. package/dist/server/src/controllers/index.d.ts.map +1 -1
  35. package/dist/server/src/controllers/release-action.d.ts +1 -0
  36. package/dist/server/src/controllers/release-action.d.ts.map +1 -1
  37. package/dist/server/src/controllers/release.d.ts +1 -0
  38. package/dist/server/src/controllers/release.d.ts.map +1 -1
  39. package/dist/server/src/controllers/validation/release.d.ts +1 -0
  40. package/dist/server/src/controllers/validation/release.d.ts.map +1 -1
  41. package/dist/server/src/controllers/validation/settings.d.ts +1 -0
  42. package/dist/server/src/controllers/validation/settings.d.ts.map +1 -1
  43. package/dist/server/src/index.d.ts +2 -0
  44. package/dist/server/src/index.d.ts.map +1 -1
  45. package/dist/server/src/routes/release-action.d.ts.map +1 -1
  46. package/dist/server/src/routes/release.d.ts.map +1 -1
  47. package/dist/shared/contracts/release-actions.d.ts +3 -5
  48. package/dist/shared/contracts/release-actions.d.ts.map +1 -1
  49. package/dist/shared/contracts/releases.d.ts +3 -2
  50. package/dist/shared/contracts/releases.d.ts.map +1 -1
  51. package/dist/shared/contracts/settings.d.ts +1 -1
  52. package/dist/shared/contracts/settings.d.ts.map +1 -1
  53. package/package.json +8 -8
  54. package/dist/_chunks/App-6gbM0io-.mjs.map +0 -1
  55. package/dist/_chunks/App-zzUitryC.js.map +0 -1
  56. package/dist/_chunks/SettingsPage-CTOl3Qtw.js.map +0 -1
  57. package/dist/_chunks/SettingsPage-CuSH193e.mjs.map +0 -1
  58. package/dist/_chunks/en-1_1re1mc.js.map +0 -1
  59. package/dist/_chunks/en-C3sq5KNP.mjs.map +0 -1
  60. package/dist/_chunks/index-BxRiXenX.js.map +0 -1
  61. package/dist/_chunks/index-CuchqQ4_.mjs.map +0 -1
  62. package/dist/_chunks/validation-schemas-C7P2rhPu.mjs +0 -29
  63. package/dist/_chunks/validation-schemas-C7P2rhPu.mjs.map +0 -1
  64. package/dist/_chunks/validation-schemas-bib1fBc7.js.map +0 -1
  65. package/dist/admin/src/pages/SettingsPage.d.ts +0 -1
  66. package/dist/shared/validation-schemas.d.ts +0 -3
  67. package/dist/shared/validation-schemas.d.ts.map +0 -1
@@ -1,16 +1,24 @@
1
1
  import { jsx, jsxs, Fragment } from "react/jsx-runtime";
2
- import { useNotification, useAPIErrorHandler, Page, Layouts, Form, useField, isFetchError } from "@strapi/admin/strapi-admin";
2
+ import { Page, useAPIErrorHandler, useNotification, useRBAC, Layouts, Form, useField, isFetchError } from "@strapi/admin/strapi-admin";
3
3
  import { Button, Flex, Typography, Grid, Field, Combobox, ComboboxOption } from "@strapi/design-system";
4
4
  import { Check } from "@strapi/icons";
5
5
  import { useIntl } from "react-intl";
6
- import { S as SETTINGS_SCHEMA } from "./validation-schemas-C7P2rhPu.mjs";
7
- import { k as useGetReleaseSettingsQuery, l as useUpdateReleaseSettingsMutation, g as getTimezones } from "./index-CuchqQ4_.mjs";
8
- const SettingsPage = () => {
6
+ import { useSelector } from "react-redux";
7
+ import { a as useGetReleaseSettingsQuery, l as useUpdateReleaseSettingsMutation, g as getTimezones } from "./index-Bgq1X1sL.mjs";
8
+ import { S as SETTINGS_SCHEMA } from "./schemas-63pFihNF.mjs";
9
+ const useTypedSelector = useSelector;
10
+ const ReleasesSettingsPage = () => {
9
11
  const { formatMessage } = useIntl();
12
+ const { formatAPIError } = useAPIErrorHandler();
13
+ const { toggleNotification } = useNotification();
10
14
  const { data, isLoading: isLoadingSettings } = useGetReleaseSettingsQuery();
11
15
  const [updateReleaseSettings, { isLoading: isSubmittingForm }] = useUpdateReleaseSettingsMutation();
12
- const { toggleNotification } = useNotification();
13
- const { formatAPIError } = useAPIErrorHandler();
16
+ const permissions = useTypedSelector(
17
+ (state) => state.admin_app.permissions["settings"]?.["releases"]
18
+ );
19
+ const {
20
+ allowedActions: { canUpdate }
21
+ } = useRBAC(permissions);
14
22
  const { timezoneList } = getTimezones(/* @__PURE__ */ new Date());
15
23
  const handleSubmit = async (body) => {
16
24
  const { defaultTimezone } = body;
@@ -58,8 +66,8 @@ const SettingsPage = () => {
58
66
  Form,
59
67
  {
60
68
  method: "PUT",
61
- initialValues: data?.data.defaultTimezone ? data.data : {
62
- defaultTimezone: null
69
+ initialValues: {
70
+ defaultTimezone: data?.data.defaultTimezone
63
71
  },
64
72
  onSubmit: handleSubmit,
65
73
  validationSchema: SETTINGS_SCHEMA,
@@ -68,7 +76,7 @@ const SettingsPage = () => {
68
76
  /* @__PURE__ */ jsx(
69
77
  Layouts.Header,
70
78
  {
71
- primaryAction: /* @__PURE__ */ jsx(
79
+ primaryAction: canUpdate ? /* @__PURE__ */ jsx(
72
80
  Button,
73
81
  {
74
82
  disabled: !modified || isSubmittingForm,
@@ -80,7 +88,7 @@ const SettingsPage = () => {
80
88
  defaultMessage: "Save"
81
89
  })
82
90
  }
83
- ),
91
+ ) : null,
84
92
  title: formatMessage({
85
93
  id: "content-releases.pages.Settings.releases.title",
86
94
  defaultMessage: "Releases"
@@ -117,6 +125,12 @@ const SettingsPage = () => {
117
125
  ] });
118
126
  };
119
127
  const TimezoneDropdown = () => {
128
+ const permissions = useTypedSelector(
129
+ (state) => state.admin_app.permissions["settings"]?.["releases"]
130
+ );
131
+ const {
132
+ allowedActions: { canUpdate }
133
+ } = useRBAC(permissions);
120
134
  const { formatMessage } = useIntl();
121
135
  const { timezoneList } = getTimezones(/* @__PURE__ */ new Date());
122
136
  const field = useField("defaultTimezone");
@@ -141,7 +155,8 @@ const TimezoneDropdown = () => {
141
155
  onChange: (value) => field.onChange("defaultTimezone", value),
142
156
  onTextValueChange: (value) => field.onChange("defaultTimezone", value),
143
157
  onClear: () => field.onChange("defaultTimezone", ""),
144
- value: field.value ?? "",
158
+ value: field.value,
159
+ disabled: !canUpdate,
145
160
  children: timezoneList.map((timezone) => /* @__PURE__ */ jsx(ComboboxOption, { value: timezone.value, children: timezone.value.replace(/&/, " ") }, timezone.value))
146
161
  }
147
162
  ),
@@ -151,7 +166,13 @@ const TimezoneDropdown = () => {
151
166
  }
152
167
  );
153
168
  };
169
+ const ProtectedReleasesSettingsPage = () => {
170
+ const permissions = useTypedSelector(
171
+ (state) => state.admin_app.permissions["settings"]?.["releases"]?.read
172
+ );
173
+ return /* @__PURE__ */ jsx(Page.Protect, { permissions, children: /* @__PURE__ */ jsx(ReleasesSettingsPage, {}) });
174
+ };
154
175
  export {
155
- SettingsPage
176
+ ProtectedReleasesSettingsPage
156
177
  };
157
- //# sourceMappingURL=SettingsPage-CuSH193e.mjs.map
178
+ //# sourceMappingURL=ReleasesSettingsPage-BDinCYKz.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ReleasesSettingsPage-BDinCYKz.mjs","sources":["../../admin/src/modules/hooks.ts","../../admin/src/pages/ReleasesSettingsPage.tsx"],"sourcesContent":["import { Dispatch } from '@reduxjs/toolkit';\nimport { TypedUseSelectorHook, useDispatch, useSelector } from 'react-redux';\n\nimport type { Store } from '@strapi/admin/strapi-admin';\n\ntype RootState = ReturnType<Store['getState']>;\n\nconst useTypedDispatch: () => Dispatch = useDispatch;\nconst useTypedSelector: TypedUseSelectorHook<RootState> = useSelector;\n\nexport { useTypedSelector, useTypedDispatch };\n","import {\n Form,\n Layouts,\n Page,\n useAPIErrorHandler,\n isFetchError,\n useNotification,\n useField,\n useRBAC,\n} from '@strapi/admin/strapi-admin';\nimport {\n Button,\n Combobox,\n ComboboxOption,\n Field,\n Flex,\n Grid,\n Typography,\n} from '@strapi/design-system';\nimport { Check } from '@strapi/icons';\nimport { useIntl } from 'react-intl';\n\nimport { useTypedSelector } from '../modules/hooks';\nimport { useGetReleaseSettingsQuery, useUpdateReleaseSettingsMutation } from '../services/release';\nimport { getTimezones } from '../utils/time';\nimport { SETTINGS_SCHEMA } from '../validation/schemas';\n\nimport type { UpdateSettings } from '../../../shared/contracts/settings';\n\nconst ReleasesSettingsPage = () => {\n const { formatMessage } = useIntl();\n const { formatAPIError } = useAPIErrorHandler();\n const { toggleNotification } = useNotification();\n const { data, isLoading: isLoadingSettings } = useGetReleaseSettingsQuery();\n const [updateReleaseSettings, { isLoading: isSubmittingForm }] =\n useUpdateReleaseSettingsMutation();\n const permissions = useTypedSelector(\n (state) => state.admin_app.permissions['settings']?.['releases']\n );\n const {\n allowedActions: { canUpdate },\n } = useRBAC(permissions);\n\n const { timezoneList } = getTimezones(new Date());\n\n const handleSubmit = async (body: UpdateSettings.Request['body']) => {\n const { defaultTimezone } = body;\n const isBodyTimezoneValid = timezoneList.some((timezone) => timezone.value === defaultTimezone);\n const newBody =\n !defaultTimezone || !isBodyTimezoneValid ? { defaultTimezone: null } : { ...body };\n try {\n const response = await updateReleaseSettings(newBody);\n\n if ('data' in response) {\n toggleNotification({\n type: 'success',\n message: formatMessage({\n id: 'content-releases.pages.Settings.releases.setting.default-timezone-notification-success',\n defaultMessage: 'Default timezone updated.',\n }),\n });\n } else if (isFetchError(response.error)) {\n toggleNotification({\n type: 'danger',\n message: formatAPIError(response.error),\n });\n } else {\n toggleNotification({\n type: 'danger',\n message: formatMessage({ id: 'notification.error', defaultMessage: 'An error occurred' }),\n });\n }\n } catch (error) {\n toggleNotification({\n type: 'danger',\n message: formatMessage({ id: 'notification.error', defaultMessage: 'An error occurred' }),\n });\n }\n };\n\n if (isLoadingSettings) {\n return <Page.Loading />;\n }\n\n return (\n <Layouts.Root>\n <Page.Title>\n {formatMessage(\n { id: 'Settings.PageTitle', defaultMessage: 'Settings - {name}' },\n {\n name: 'Releases',\n }\n )}\n </Page.Title>\n <Page.Main aria-busy={isLoadingSettings} tabIndex={-1}>\n <Form\n method=\"PUT\"\n initialValues={{\n defaultTimezone: data?.data.defaultTimezone,\n }}\n onSubmit={handleSubmit}\n validationSchema={SETTINGS_SCHEMA}\n >\n {({ modified, isSubmitting }: { modified: boolean; isSubmitting: boolean }) => {\n return (\n <>\n <Layouts.Header\n primaryAction={\n canUpdate ? (\n <Button\n disabled={!modified || isSubmittingForm}\n loading={isSubmitting}\n startIcon={<Check />}\n type=\"submit\"\n >\n {formatMessage({\n id: 'global.save',\n defaultMessage: 'Save',\n })}\n </Button>\n ) : null\n }\n title={formatMessage({\n id: 'content-releases.pages.Settings.releases.title',\n defaultMessage: 'Releases',\n })}\n subtitle={formatMessage({\n id: 'content-releases.pages.Settings.releases.description',\n defaultMessage: 'Create and manage content updates',\n })}\n />\n <Layouts.Content>\n <Flex\n direction=\"column\"\n background=\"neutral0\"\n alignItems=\"stretch\"\n padding={6}\n gap={6}\n shadow=\"filterShadow\"\n hasRadius\n >\n <Typography variant=\"delta\" tag=\"h2\">\n {formatMessage({\n id: 'content-releases.pages.Settings.releases.preferences.title',\n defaultMessage: 'Preferences',\n })}\n </Typography>\n <Grid.Root>\n <Grid.Item col={6} s={12}>\n <TimezoneDropdown />\n </Grid.Item>\n </Grid.Root>\n </Flex>\n </Layouts.Content>\n </>\n );\n }}\n </Form>\n </Page.Main>\n </Layouts.Root>\n );\n};\n\nconst TimezoneDropdown = () => {\n const permissions = useTypedSelector(\n (state) => state.admin_app.permissions['settings']?.['releases']\n );\n const {\n allowedActions: { canUpdate },\n } = useRBAC(permissions);\n const { formatMessage } = useIntl();\n const { timezoneList } = getTimezones(new Date());\n const field = useField('defaultTimezone');\n return (\n <Field.Root\n name=\"defaultTimezone\"\n hint={formatMessage({\n id: 'content-releases.pages.Settings.releases.timezone.hint',\n defaultMessage: 'The timezone of every release can still be changed individually. ',\n })}\n error={field.error}\n >\n <Field.Label>\n {formatMessage({\n id: 'content-releases.pages.Settings.releases.timezone.label',\n defaultMessage: 'Default timezone',\n })}\n </Field.Label>\n <Combobox\n autocomplete={{ type: 'list', filter: 'contains' }}\n onChange={(value) => field.onChange('defaultTimezone', value)}\n onTextValueChange={(value) => field.onChange('defaultTimezone', value)}\n onClear={() => field.onChange('defaultTimezone', '')}\n value={field.value}\n disabled={!canUpdate}\n >\n {timezoneList.map((timezone) => (\n <ComboboxOption key={timezone.value} value={timezone.value}>\n {timezone.value.replace(/&/, ' ')}\n </ComboboxOption>\n ))}\n </Combobox>\n <Field.Hint />\n <Field.Error />\n </Field.Root>\n );\n};\n\n/* -------------------------------------------------------------------------------------------------\n * ProtectedSettingsPage\n * -----------------------------------------------------------------------------------------------*/\n\nexport const ProtectedReleasesSettingsPage = () => {\n const permissions = useTypedSelector(\n (state) => state.admin_app.permissions['settings']?.['releases']?.read\n );\n\n return (\n <Page.Protect permissions={permissions}>\n <ReleasesSettingsPage />\n </Page.Protect>\n );\n};\n"],"names":[],"mappings":"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"}
@@ -5,14 +5,22 @@ const strapiAdmin = require("@strapi/admin/strapi-admin");
5
5
  const designSystem = require("@strapi/design-system");
6
6
  const icons = require("@strapi/icons");
7
7
  const reactIntl = require("react-intl");
8
- const validationSchemas = require("./validation-schemas-bib1fBc7.js");
9
- const index = require("./index-BxRiXenX.js");
10
- const SettingsPage = () => {
8
+ const reactRedux = require("react-redux");
9
+ const index = require("./index-mECKW99O.js");
10
+ const schemas = require("./schemas-z5zp-_Gd.js");
11
+ const useTypedSelector = reactRedux.useSelector;
12
+ const ReleasesSettingsPage = () => {
11
13
  const { formatMessage } = reactIntl.useIntl();
14
+ const { formatAPIError } = strapiAdmin.useAPIErrorHandler();
15
+ const { toggleNotification } = strapiAdmin.useNotification();
12
16
  const { data, isLoading: isLoadingSettings } = index.useGetReleaseSettingsQuery();
13
17
  const [updateReleaseSettings, { isLoading: isSubmittingForm }] = index.useUpdateReleaseSettingsMutation();
14
- const { toggleNotification } = strapiAdmin.useNotification();
15
- const { formatAPIError } = strapiAdmin.useAPIErrorHandler();
18
+ const permissions = useTypedSelector(
19
+ (state) => state.admin_app.permissions["settings"]?.["releases"]
20
+ );
21
+ const {
22
+ allowedActions: { canUpdate }
23
+ } = strapiAdmin.useRBAC(permissions);
16
24
  const { timezoneList } = index.getTimezones(/* @__PURE__ */ new Date());
17
25
  const handleSubmit = async (body) => {
18
26
  const { defaultTimezone } = body;
@@ -60,17 +68,17 @@ const SettingsPage = () => {
60
68
  strapiAdmin.Form,
61
69
  {
62
70
  method: "PUT",
63
- initialValues: data?.data.defaultTimezone ? data.data : {
64
- defaultTimezone: null
71
+ initialValues: {
72
+ defaultTimezone: data?.data.defaultTimezone
65
73
  },
66
74
  onSubmit: handleSubmit,
67
- validationSchema: validationSchemas.SETTINGS_SCHEMA,
75
+ validationSchema: schemas.SETTINGS_SCHEMA,
68
76
  children: ({ modified, isSubmitting }) => {
69
77
  return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
70
78
  /* @__PURE__ */ jsxRuntime.jsx(
71
79
  strapiAdmin.Layouts.Header,
72
80
  {
73
- primaryAction: /* @__PURE__ */ jsxRuntime.jsx(
81
+ primaryAction: canUpdate ? /* @__PURE__ */ jsxRuntime.jsx(
74
82
  designSystem.Button,
75
83
  {
76
84
  disabled: !modified || isSubmittingForm,
@@ -82,7 +90,7 @@ const SettingsPage = () => {
82
90
  defaultMessage: "Save"
83
91
  })
84
92
  }
85
- ),
93
+ ) : null,
86
94
  title: formatMessage({
87
95
  id: "content-releases.pages.Settings.releases.title",
88
96
  defaultMessage: "Releases"
@@ -119,6 +127,12 @@ const SettingsPage = () => {
119
127
  ] });
120
128
  };
121
129
  const TimezoneDropdown = () => {
130
+ const permissions = useTypedSelector(
131
+ (state) => state.admin_app.permissions["settings"]?.["releases"]
132
+ );
133
+ const {
134
+ allowedActions: { canUpdate }
135
+ } = strapiAdmin.useRBAC(permissions);
122
136
  const { formatMessage } = reactIntl.useIntl();
123
137
  const { timezoneList } = index.getTimezones(/* @__PURE__ */ new Date());
124
138
  const field = strapiAdmin.useField("defaultTimezone");
@@ -143,7 +157,8 @@ const TimezoneDropdown = () => {
143
157
  onChange: (value) => field.onChange("defaultTimezone", value),
144
158
  onTextValueChange: (value) => field.onChange("defaultTimezone", value),
145
159
  onClear: () => field.onChange("defaultTimezone", ""),
146
- value: field.value ?? "",
160
+ value: field.value,
161
+ disabled: !canUpdate,
147
162
  children: timezoneList.map((timezone) => /* @__PURE__ */ jsxRuntime.jsx(designSystem.ComboboxOption, { value: timezone.value, children: timezone.value.replace(/&/, " ") }, timezone.value))
148
163
  }
149
164
  ),
@@ -153,5 +168,11 @@ const TimezoneDropdown = () => {
153
168
  }
154
169
  );
155
170
  };
156
- exports.SettingsPage = SettingsPage;
157
- //# sourceMappingURL=SettingsPage-CTOl3Qtw.js.map
171
+ const ProtectedReleasesSettingsPage = () => {
172
+ const permissions = useTypedSelector(
173
+ (state) => state.admin_app.permissions["settings"]?.["releases"]?.read
174
+ );
175
+ return /* @__PURE__ */ jsxRuntime.jsx(strapiAdmin.Page.Protect, { permissions, children: /* @__PURE__ */ jsxRuntime.jsx(ReleasesSettingsPage, {}) });
176
+ };
177
+ exports.ProtectedReleasesSettingsPage = ProtectedReleasesSettingsPage;
178
+ //# sourceMappingURL=ReleasesSettingsPage-CE_KqB_s.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ReleasesSettingsPage-CE_KqB_s.js","sources":["../../admin/src/modules/hooks.ts","../../admin/src/pages/ReleasesSettingsPage.tsx"],"sourcesContent":["import { Dispatch } from '@reduxjs/toolkit';\nimport { TypedUseSelectorHook, useDispatch, useSelector } from 'react-redux';\n\nimport type { Store } from '@strapi/admin/strapi-admin';\n\ntype RootState = ReturnType<Store['getState']>;\n\nconst useTypedDispatch: () => Dispatch = useDispatch;\nconst useTypedSelector: TypedUseSelectorHook<RootState> = useSelector;\n\nexport { useTypedSelector, useTypedDispatch };\n","import {\n Form,\n Layouts,\n Page,\n useAPIErrorHandler,\n isFetchError,\n useNotification,\n useField,\n useRBAC,\n} from '@strapi/admin/strapi-admin';\nimport {\n Button,\n Combobox,\n ComboboxOption,\n Field,\n Flex,\n Grid,\n Typography,\n} from '@strapi/design-system';\nimport { Check } from '@strapi/icons';\nimport { useIntl } from 'react-intl';\n\nimport { useTypedSelector } from '../modules/hooks';\nimport { useGetReleaseSettingsQuery, useUpdateReleaseSettingsMutation } from '../services/release';\nimport { getTimezones } from '../utils/time';\nimport { SETTINGS_SCHEMA } from '../validation/schemas';\n\nimport type { UpdateSettings } from '../../../shared/contracts/settings';\n\nconst ReleasesSettingsPage = () => {\n const { formatMessage } = useIntl();\n const { formatAPIError } = useAPIErrorHandler();\n const { toggleNotification } = useNotification();\n const { data, isLoading: isLoadingSettings } = useGetReleaseSettingsQuery();\n const [updateReleaseSettings, { isLoading: isSubmittingForm }] =\n useUpdateReleaseSettingsMutation();\n const permissions = useTypedSelector(\n (state) => state.admin_app.permissions['settings']?.['releases']\n );\n const {\n allowedActions: { canUpdate },\n } = useRBAC(permissions);\n\n const { timezoneList } = getTimezones(new Date());\n\n const handleSubmit = async (body: UpdateSettings.Request['body']) => {\n const { defaultTimezone } = body;\n const isBodyTimezoneValid = timezoneList.some((timezone) => timezone.value === defaultTimezone);\n const newBody =\n !defaultTimezone || !isBodyTimezoneValid ? { defaultTimezone: null } : { ...body };\n try {\n const response = await updateReleaseSettings(newBody);\n\n if ('data' in response) {\n toggleNotification({\n type: 'success',\n message: formatMessage({\n id: 'content-releases.pages.Settings.releases.setting.default-timezone-notification-success',\n defaultMessage: 'Default timezone updated.',\n }),\n });\n } else if (isFetchError(response.error)) {\n toggleNotification({\n type: 'danger',\n message: formatAPIError(response.error),\n });\n } else {\n toggleNotification({\n type: 'danger',\n message: formatMessage({ id: 'notification.error', defaultMessage: 'An error occurred' }),\n });\n }\n } catch (error) {\n toggleNotification({\n type: 'danger',\n message: formatMessage({ id: 'notification.error', defaultMessage: 'An error occurred' }),\n });\n }\n };\n\n if (isLoadingSettings) {\n return <Page.Loading />;\n }\n\n return (\n <Layouts.Root>\n <Page.Title>\n {formatMessage(\n { id: 'Settings.PageTitle', defaultMessage: 'Settings - {name}' },\n {\n name: 'Releases',\n }\n )}\n </Page.Title>\n <Page.Main aria-busy={isLoadingSettings} tabIndex={-1}>\n <Form\n method=\"PUT\"\n initialValues={{\n defaultTimezone: data?.data.defaultTimezone,\n }}\n onSubmit={handleSubmit}\n validationSchema={SETTINGS_SCHEMA}\n >\n {({ modified, isSubmitting }: { modified: boolean; isSubmitting: boolean }) => {\n return (\n <>\n <Layouts.Header\n primaryAction={\n canUpdate ? (\n <Button\n disabled={!modified || isSubmittingForm}\n loading={isSubmitting}\n startIcon={<Check />}\n type=\"submit\"\n >\n {formatMessage({\n id: 'global.save',\n defaultMessage: 'Save',\n })}\n </Button>\n ) : null\n }\n title={formatMessage({\n id: 'content-releases.pages.Settings.releases.title',\n defaultMessage: 'Releases',\n })}\n subtitle={formatMessage({\n id: 'content-releases.pages.Settings.releases.description',\n defaultMessage: 'Create and manage content updates',\n })}\n />\n <Layouts.Content>\n <Flex\n direction=\"column\"\n background=\"neutral0\"\n alignItems=\"stretch\"\n padding={6}\n gap={6}\n shadow=\"filterShadow\"\n hasRadius\n >\n <Typography variant=\"delta\" tag=\"h2\">\n {formatMessage({\n id: 'content-releases.pages.Settings.releases.preferences.title',\n defaultMessage: 'Preferences',\n })}\n </Typography>\n <Grid.Root>\n <Grid.Item col={6} s={12}>\n <TimezoneDropdown />\n </Grid.Item>\n </Grid.Root>\n </Flex>\n </Layouts.Content>\n </>\n );\n }}\n </Form>\n </Page.Main>\n </Layouts.Root>\n );\n};\n\nconst TimezoneDropdown = () => {\n const permissions = useTypedSelector(\n (state) => state.admin_app.permissions['settings']?.['releases']\n );\n const {\n allowedActions: { canUpdate },\n } = useRBAC(permissions);\n const { formatMessage } = useIntl();\n const { timezoneList } = getTimezones(new Date());\n const field = useField('defaultTimezone');\n return (\n <Field.Root\n name=\"defaultTimezone\"\n hint={formatMessage({\n id: 'content-releases.pages.Settings.releases.timezone.hint',\n defaultMessage: 'The timezone of every release can still be changed individually. ',\n })}\n error={field.error}\n >\n <Field.Label>\n {formatMessage({\n id: 'content-releases.pages.Settings.releases.timezone.label',\n defaultMessage: 'Default timezone',\n })}\n </Field.Label>\n <Combobox\n autocomplete={{ type: 'list', filter: 'contains' }}\n onChange={(value) => field.onChange('defaultTimezone', value)}\n onTextValueChange={(value) => field.onChange('defaultTimezone', value)}\n onClear={() => field.onChange('defaultTimezone', '')}\n value={field.value}\n disabled={!canUpdate}\n >\n {timezoneList.map((timezone) => (\n <ComboboxOption key={timezone.value} value={timezone.value}>\n {timezone.value.replace(/&/, ' ')}\n </ComboboxOption>\n ))}\n </Combobox>\n <Field.Hint />\n <Field.Error />\n </Field.Root>\n );\n};\n\n/* -------------------------------------------------------------------------------------------------\n * ProtectedSettingsPage\n * -----------------------------------------------------------------------------------------------*/\n\nexport const ProtectedReleasesSettingsPage = () => {\n const permissions = useTypedSelector(\n (state) => state.admin_app.permissions['settings']?.['releases']?.read\n );\n\n return (\n <Page.Protect permissions={permissions}>\n <ReleasesSettingsPage />\n </Page.Protect>\n );\n};\n"],"names":["useSelector","useIntl","useAPIErrorHandler","useNotification","useGetReleaseSettingsQuery","useUpdateReleaseSettingsMutation","useRBAC","getTimezones","isFetchError","jsx","Page","jsxs","Layouts","Form","SETTINGS_SCHEMA","Fragment","Button","Check","Flex","Typography","Grid","useField","Field","Combobox","ComboboxOption"],"mappings":"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"}
@@ -17,6 +17,7 @@ const en = {
17
17
  "content-releases.content-manager-edit-view.edit-entry": "Edit entry",
18
18
  "content-manager-edit-view.remove-from-release.notification.success": "Entry removed from release",
19
19
  "content-manager-edit-view.release-action-menu": "Release action options",
20
+ "content-manager.list-view.releases.header": "To be released in",
20
21
  "content-manager-list-view.add-to-release": "Add to release",
21
22
  "content-manager-list-view.add-to-release.cancel-button": "Cancel",
22
23
  "content-manager-list-view.add-to-release.continue-button": "Continue",
@@ -53,6 +54,7 @@ const en = {
53
54
  "modal.form.input.label.timezone": "Timezone",
54
55
  "modal.form.input.clearLabel": "Clear",
55
56
  "modal.form.button.submit": "{isCreatingRelease, select, true {Continue} other {Save}}",
57
+ "modal.form.time.has-passed": "Selected time has already passed.",
56
58
  "pages.Details.header-subtitle": "{number, plural, =0 {No entries} one {# entry} other {# entries}}",
57
59
  "pages.Releases.tab-group.label": "Releases list",
58
60
  "pages.Releases.tab.pending": "Pending ({count})",
@@ -88,4 +90,4 @@ const en = {
88
90
  "pages.Settings.releases.setting.default-timezone-notification-success": "Default timezone updated."
89
91
  };
90
92
  exports.default = en;
91
- //# sourceMappingURL=en-1_1re1mc.js.map
93
+ //# sourceMappingURL=en-CmYoEnA7.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"en-CmYoEnA7.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
@@ -15,6 +15,7 @@ const en = {
15
15
  "content-releases.content-manager-edit-view.edit-entry": "Edit entry",
16
16
  "content-manager-edit-view.remove-from-release.notification.success": "Entry removed from release",
17
17
  "content-manager-edit-view.release-action-menu": "Release action options",
18
+ "content-manager.list-view.releases.header": "To be released in",
18
19
  "content-manager-list-view.add-to-release": "Add to release",
19
20
  "content-manager-list-view.add-to-release.cancel-button": "Cancel",
20
21
  "content-manager-list-view.add-to-release.continue-button": "Continue",
@@ -51,6 +52,7 @@ const en = {
51
52
  "modal.form.input.label.timezone": "Timezone",
52
53
  "modal.form.input.clearLabel": "Clear",
53
54
  "modal.form.button.submit": "{isCreatingRelease, select, true {Continue} other {Save}}",
55
+ "modal.form.time.has-passed": "Selected time has already passed.",
54
56
  "pages.Details.header-subtitle": "{number, plural, =0 {No entries} one {# entry} other {# entries}}",
55
57
  "pages.Releases.tab-group.label": "Releases list",
56
58
  "pages.Releases.tab.pending": "Pending ({count})",
@@ -88,4 +90,4 @@ const en = {
88
90
  export {
89
91
  en as default
90
92
  };
91
- //# sourceMappingURL=en-C3sq5KNP.mjs.map
93
+ //# sourceMappingURL=en-D0yVZFqf.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"en-D0yVZFqf.mjs","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
@@ -1,11 +1,11 @@
1
- import { Cursor, Cross, Pencil, More, PaperPlane } from "@strapi/icons";
2
- import { jsxs, jsx, Fragment } from "react/jsx-runtime";
3
- import { adminApi, useRBAC, useNotification, useAPIErrorHandler, useQueryParams, isFetchError, useAuth } from "@strapi/admin/strapi-admin";
1
+ import { PaperPlane, CaretDown, Cross, Pencil, More } from "@strapi/icons";
2
+ import { jsxs, jsx } from "react/jsx-runtime";
3
+ import { adminApi, useRBAC, useNotification, useAPIErrorHandler, useQueryParams, isFetchError, useTable, useAuth } from "@strapi/admin/strapi-admin";
4
+ import { Field, Flex, VisuallyHidden, Modal, Button, EmptyStateLayout, LinkButton, Box, SingleSelect, SingleSelectOption, Popover, Typography, Link as Link$1, Menu, AccessibleIcon } from "@strapi/design-system";
5
+ import { useFormik, Formik, Form } from "formik";
6
+ import { useIntl } from "react-intl";
4
7
  import { unstable_useDocumentLayout } from "@strapi/content-manager/strapi-admin";
5
- import { Field, Flex, VisuallyHidden, Button, Box, SingleSelect, SingleSelectOption, EmptyStateLayout, LinkButton, Menu, Typography, AccessibleIcon } from "@strapi/design-system";
6
8
  import { EmptyDocuments } from "@strapi/icons/symbols";
7
- import { useFormik } from "formik";
8
- import { useIntl } from "react-intl";
9
9
  import { Link, NavLink } from "react-router-dom";
10
10
  import * as yup from "yup";
11
11
  import { styled } from "styled-components";
@@ -654,7 +654,7 @@ const ReleaseActionModalForm = ({
654
654
  id: "content-releases.content-manager-edit-view.add-to-release",
655
655
  defaultMessage: "Add to release"
656
656
  }),
657
- icon: /* @__PURE__ */ jsx(Cursor, {}),
657
+ icon: /* @__PURE__ */ jsx(PaperPlane, {}),
658
658
  position: ["panel", "table-row"],
659
659
  dialog: {
660
660
  type: "modal",
@@ -671,7 +671,7 @@ const ReleaseActionModalForm = ({
671
671
  values: formik.values
672
672
  }
673
673
  ),
674
- footer: ({ onClose }) => /* @__PURE__ */ jsxs(Fragment, { children: [
674
+ footer: ({ onClose }) => /* @__PURE__ */ jsxs(Modal.Footer, { children: [
675
675
  /* @__PURE__ */ jsx(Button, { onClick: onClose, variant: "tertiary", name: "cancel", children: formatMessage({
676
676
  id: "content-releases.content-manager-edit-view.add-to-release.cancel-button",
677
677
  defaultMessage: "Cancel"
@@ -693,6 +693,233 @@ const ReleaseActionModalForm = ({
693
693
  }
694
694
  };
695
695
  };
696
+ const getContentPermissions = (subject) => {
697
+ const permissions = {
698
+ publish: [
699
+ {
700
+ action: "plugin::content-manager.explorer.publish",
701
+ subject,
702
+ id: "",
703
+ actionParameters: {},
704
+ properties: {},
705
+ conditions: []
706
+ }
707
+ ]
708
+ };
709
+ return permissions;
710
+ };
711
+ const ReleaseAction = ({ documents, model }) => {
712
+ const { formatMessage } = useIntl();
713
+ const { toggleNotification } = useNotification();
714
+ const { formatAPIError } = useAPIErrorHandler();
715
+ const [{ query }] = useQueryParams();
716
+ const contentPermissions = getContentPermissions(model);
717
+ const {
718
+ allowedActions: { canPublish }
719
+ } = useRBAC(contentPermissions);
720
+ const {
721
+ allowedActions: { canCreate }
722
+ } = useRBAC(PERMISSIONS);
723
+ const response = useGetReleasesQuery();
724
+ const releases = response.data?.data;
725
+ const [createManyReleaseActions, { isLoading }] = useCreateManyReleaseActionsMutation();
726
+ const documentIds = documents.map((doc) => doc.documentId);
727
+ const handleSubmit = async (values) => {
728
+ const locale = query.plugins?.i18n?.locale;
729
+ const releaseActionEntries = documentIds.map(
730
+ (entryDocumentId) => ({
731
+ type: values.type,
732
+ contentType: model,
733
+ entryDocumentId,
734
+ locale
735
+ })
736
+ );
737
+ const response2 = await createManyReleaseActions({
738
+ body: releaseActionEntries,
739
+ params: { releaseId: values.releaseId }
740
+ });
741
+ if ("data" in response2) {
742
+ const notificationMessage = formatMessage(
743
+ {
744
+ id: "content-releases.content-manager-list-view.add-to-release.notification.success.message",
745
+ defaultMessage: "{entriesAlreadyInRelease} out of {totalEntries} entries were already in the release."
746
+ },
747
+ {
748
+ entriesAlreadyInRelease: response2.data.meta.entriesAlreadyInRelease,
749
+ totalEntries: response2.data.meta.totalEntries
750
+ }
751
+ );
752
+ const notification = {
753
+ type: "success",
754
+ title: formatMessage(
755
+ {
756
+ id: "content-releases.content-manager-list-view.add-to-release.notification.success.title",
757
+ defaultMessage: "Successfully added to release."
758
+ },
759
+ {
760
+ entriesAlreadyInRelease: response2.data.meta.entriesAlreadyInRelease,
761
+ totalEntries: response2.data.meta.totalEntries
762
+ }
763
+ ),
764
+ message: response2.data.meta.entriesAlreadyInRelease ? notificationMessage : ""
765
+ };
766
+ toggleNotification(notification);
767
+ return true;
768
+ }
769
+ if ("error" in response2) {
770
+ if (isFetchError(response2.error)) {
771
+ toggleNotification({
772
+ type: "warning",
773
+ message: formatAPIError(response2.error)
774
+ });
775
+ } else {
776
+ toggleNotification({
777
+ type: "warning",
778
+ message: formatMessage({ id: "notification.error", defaultMessage: "An error occurred" })
779
+ });
780
+ }
781
+ }
782
+ };
783
+ if (!canCreate || !canPublish)
784
+ return null;
785
+ return {
786
+ actionType: "release",
787
+ variant: "tertiary",
788
+ label: formatMessage({
789
+ id: "content-manager-list-view.add-to-release",
790
+ defaultMessage: "Add to Release"
791
+ }),
792
+ dialog: {
793
+ type: "modal",
794
+ title: formatMessage({
795
+ id: "content-manager-list-view.add-to-release",
796
+ defaultMessage: "Add to Release"
797
+ }),
798
+ content: ({ onClose }) => {
799
+ return /* @__PURE__ */ jsx(
800
+ Formik,
801
+ {
802
+ onSubmit: async (values) => {
803
+ const data = await handleSubmit(values);
804
+ if (data) {
805
+ return onClose();
806
+ }
807
+ },
808
+ validationSchema: RELEASE_ACTION_FORM_SCHEMA,
809
+ initialValues: INITIAL_VALUES,
810
+ children: ({ values, setFieldValue }) => /* @__PURE__ */ jsxs(Form, { children: [
811
+ releases?.length === 0 ? /* @__PURE__ */ jsx(NoReleases, {}) : /* @__PURE__ */ jsx(Modal.Body, { children: /* @__PURE__ */ jsxs(Flex, { direction: "column", alignItems: "stretch", gap: 2, children: [
812
+ /* @__PURE__ */ jsx(Box, { paddingBottom: 6, children: /* @__PURE__ */ jsxs(Field.Root, { required: true, children: [
813
+ /* @__PURE__ */ jsx(Field.Label, { children: formatMessage({
814
+ id: "content-releases.content-manager-list-view.add-to-release.select-label",
815
+ defaultMessage: "Select a release"
816
+ }) }),
817
+ /* @__PURE__ */ jsx(
818
+ SingleSelect,
819
+ {
820
+ placeholder: formatMessage({
821
+ id: "content-releases.content-manager-list-view.add-to-release.select-placeholder",
822
+ defaultMessage: "Select"
823
+ }),
824
+ onChange: (value) => setFieldValue("releaseId", value),
825
+ value: values.releaseId,
826
+ children: releases?.map((release) => /* @__PURE__ */ jsx(SingleSelectOption, { value: release.id, children: release.name }, release.id))
827
+ }
828
+ )
829
+ ] }) }),
830
+ /* @__PURE__ */ jsx(Field.Label, { children: formatMessage({
831
+ id: "content-releases.content-manager-list-view.add-to-release.action-type-label",
832
+ defaultMessage: "What do you want to do with these entries?"
833
+ }) }),
834
+ /* @__PURE__ */ jsx(
835
+ ReleaseActionOptions,
836
+ {
837
+ selected: values.type,
838
+ handleChange: (e) => setFieldValue("type", e.target.value),
839
+ name: "type"
840
+ }
841
+ )
842
+ ] }) }),
843
+ /* @__PURE__ */ jsxs(Modal.Footer, { children: [
844
+ /* @__PURE__ */ jsx(Button, { onClick: onClose, variant: "tertiary", name: "cancel", children: formatMessage({
845
+ id: "content-releases.content-manager-list-view.add-to-release.cancel-button",
846
+ defaultMessage: "Cancel"
847
+ }) }),
848
+ /* @__PURE__ */ jsx(Button, { type: "submit", disabled: !values.releaseId, loading: isLoading, children: formatMessage({
849
+ id: "content-releases.content-manager-list-view.add-to-release.continue-button",
850
+ defaultMessage: "Continue"
851
+ }) })
852
+ ] })
853
+ ] })
854
+ }
855
+ );
856
+ }
857
+ }
858
+ };
859
+ };
860
+ const StyledButton = styled(Button)`
861
+ span {
862
+ font-weight: 400;
863
+ }
864
+ `;
865
+ const useReleasesList = (contentTypeUid, documentId) => {
866
+ const listViewData = useTable("ListView", (state) => state.rows);
867
+ const documentIds = listViewData.map((entry) => entry.documentId);
868
+ const [{ query }] = useQueryParams();
869
+ const locale = query?.plugins?.i18n?.locale || void 0;
870
+ const response = useGetMappedEntriesInReleasesQuery(
871
+ { contentTypeUid, documentIds, locale },
872
+ { skip: !documentIds || !contentTypeUid || documentIds.length === 0 }
873
+ );
874
+ const mappedEntriesInReleases = response.data || {};
875
+ return mappedEntriesInReleases?.[documentId] || [];
876
+ };
877
+ const addColumnToTableHook = ({ displayedHeaders, layout }) => {
878
+ const { options } = layout;
879
+ if (!options?.draftAndPublish) {
880
+ return { displayedHeaders, layout };
881
+ }
882
+ return {
883
+ displayedHeaders: [
884
+ ...displayedHeaders,
885
+ {
886
+ searchable: false,
887
+ sortable: false,
888
+ name: "releases",
889
+ label: {
890
+ id: "content-releases.content-manager.list-view.releases.header",
891
+ defaultMessage: "To be released in"
892
+ },
893
+ cellFormatter: (props, _, { model }) => /* @__PURE__ */ jsx(ReleaseListCell, { ...props, model })
894
+ }
895
+ ],
896
+ layout
897
+ };
898
+ };
899
+ const ReleaseListCell = ({ documentId, model }) => {
900
+ const releases = useReleasesList(model, documentId);
901
+ const { formatMessage } = useIntl();
902
+ return /* @__PURE__ */ jsxs(Popover.Root, { children: [
903
+ /* @__PURE__ */ jsx(Popover.Trigger, { children: /* @__PURE__ */ jsx(
904
+ StyledButton,
905
+ {
906
+ variant: "ghost",
907
+ onClick: (e) => e.stopPropagation(),
908
+ endIcon: /* @__PURE__ */ jsx(CaretDown, {}),
909
+ children: /* @__PURE__ */ jsx(Typography, { style: { maxWidth: "252px", cursor: "pointer" }, textColor: "neutral800", children: releases.length > 0 ? formatMessage(
910
+ {
911
+ id: "content-releases.content-manager.list-view.releases-number",
912
+ defaultMessage: "{number} {number, plural, one {release} other {releases}}"
913
+ },
914
+ {
915
+ number: releases.length
916
+ }
917
+ ) : "-" })
918
+ }
919
+ ) }),
920
+ /* @__PURE__ */ jsx(Popover.Content, { children: /* @__PURE__ */ jsx("ul", { children: releases.map(({ id, name }) => /* @__PURE__ */ jsx(Box, { padding: 3, tag: "li", children: /* @__PURE__ */ jsx(Link$1, { href: `/admin/plugins/content-releases/${id}`, isExternal: false, children: name }) }, id)) }) })
921
+ ] });
922
+ };
696
923
  const getTimezoneOffset = (timezone, date) => {
697
924
  try {
698
925
  const offsetPart = new Intl.DateTimeFormat("en", {
@@ -859,7 +1086,7 @@ const Root = ({ children }) => {
859
1086
  return (
860
1087
  // A user can access the dropdown if they have permissions to delete a release-action OR update a release
861
1088
  allowedActions.canDeleteAction || allowedActions.canUpdate ? /* @__PURE__ */ jsxs(Menu.Root, { children: [
862
- /* @__PURE__ */ jsx(Menu.Trigger, { variant: "tertiary", endIcon: null, paddingLeft: 2, paddingRight: 2, children: /* @__PURE__ */ jsx(
1089
+ /* @__PURE__ */ jsx(Menu.Trigger, { variant: "tertiary", endIcon: null, paddingLeft: "7px", paddingRight: "7px", children: /* @__PURE__ */ jsx(
863
1090
  AccessibleIcon,
864
1091
  {
865
1092
  label: formatMessage({
@@ -1012,7 +1239,7 @@ const admin = {
1012
1239
  id: `${pluginId}.plugin.name`,
1013
1240
  defaultMessage: "Releases"
1014
1241
  },
1015
- Component: () => import("./App-6gbM0io-.mjs").then((mod) => ({ default: mod.App })),
1242
+ Component: () => import("./App-DbD5Ks8-.mjs").then((mod) => ({ default: mod.App })),
1016
1243
  permissions: PERMISSIONS.main,
1017
1244
  position: 2
1018
1245
  });
@@ -1036,10 +1263,18 @@ const admin = {
1036
1263
  },
1037
1264
  permissions: [],
1038
1265
  async Component() {
1039
- const { SettingsPage } = await import("./SettingsPage-CuSH193e.mjs");
1040
- return { default: SettingsPage };
1266
+ const { ProtectedReleasesSettingsPage } = await import("./ReleasesSettingsPage-BDinCYKz.mjs");
1267
+ return { default: ProtectedReleasesSettingsPage };
1041
1268
  }
1042
1269
  });
1270
+ if ("addBulkAction" in contentManagerPluginApis && typeof contentManagerPluginApis.addBulkAction === "function") {
1271
+ contentManagerPluginApis.addBulkAction((actions) => {
1272
+ const deleteActionIndex = actions.findIndex((action) => action.type === "delete");
1273
+ actions.splice(deleteActionIndex, 0, ReleaseAction);
1274
+ return actions;
1275
+ });
1276
+ }
1277
+ app.registerHook("Admin/CM/pages/ListView/inject-column-in-table", addColumnToTableHook);
1043
1278
  } else if (!window.strapi.features.isEnabled("cms-content-releases") && window.strapi?.flags?.promoteEE) {
1044
1279
  app.addSettingsLink("global", {
1045
1280
  id: pluginId,
@@ -1060,7 +1295,7 @@ const admin = {
1060
1295
  async registerTrads({ locales }) {
1061
1296
  const importedTrads = await Promise.all(
1062
1297
  locales.map((locale) => {
1063
- return __variableDynamicImportRuntimeHelper(/* @__PURE__ */ Object.assign({ "./translations/en.json": () => import("./en-C3sq5KNP.mjs") }), `./translations/${locale}.json`).then(({ default: data }) => {
1298
+ return __variableDynamicImportRuntimeHelper(/* @__PURE__ */ Object.assign({ "./translations/en.json": () => import("./en-D0yVZFqf.mjs") }), `./translations/${locale}.json`).then(({ default: data }) => {
1064
1299
  return {
1065
1300
  data: prefixPluginTranslations(data, "content-releases"),
1066
1301
  locale
@@ -1079,21 +1314,21 @@ const admin = {
1079
1314
  export {
1080
1315
  PERMISSIONS as P,
1081
1316
  ReleaseActionOptions as R,
1082
- useCreateReleaseMutation as a,
1083
- useGetReleaseQuery as b,
1084
- useUpdateReleaseMutation as c,
1085
- useDeleteReleaseMutation as d,
1086
- usePublishReleaseMutation as e,
1087
- getTimezoneOffset as f,
1317
+ useGetReleaseSettingsQuery as a,
1318
+ useCreateReleaseMutation as b,
1319
+ useGetReleaseQuery as c,
1320
+ useUpdateReleaseMutation as d,
1321
+ useDeleteReleaseMutation as e,
1322
+ usePublishReleaseMutation as f,
1088
1323
  getTimezones as g,
1089
- useGetReleaseActionsQuery as h,
1090
- useUpdateReleaseActionMutation as i,
1091
- ReleaseActionMenu as j,
1092
- useGetReleaseSettingsQuery as k,
1324
+ getTimezoneOffset as h,
1325
+ useGetReleaseActionsQuery as i,
1326
+ useUpdateReleaseActionMutation as j,
1327
+ ReleaseActionMenu as k,
1093
1328
  useUpdateReleaseSettingsMutation as l,
1094
1329
  admin as m,
1095
1330
  pluginId as p,
1096
1331
  releaseApi as r,
1097
1332
  useGetReleasesQuery as u
1098
1333
  };
1099
- //# sourceMappingURL=index-CuchqQ4_.mjs.map
1334
+ //# sourceMappingURL=index-Bgq1X1sL.mjs.map