@strapi/content-releases 5.0.0-beta.9 → 5.0.0-rc.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (100) hide show
  1. package/LICENSE +17 -1
  2. package/dist/_chunks/{App-DUmziQ17.js → App-CatMj4_9.js} +216 -257
  3. package/dist/_chunks/App-CatMj4_9.js.map +1 -0
  4. package/dist/_chunks/{App-D_6Y9N2F.mjs → App-CdTs45Xr.mjs} +215 -255
  5. package/dist/_chunks/App-CdTs45Xr.mjs.map +1 -0
  6. package/dist/_chunks/ReleasesSettingsPage-C2L6_E3J.mjs +178 -0
  7. package/dist/_chunks/ReleasesSettingsPage-C2L6_E3J.mjs.map +1 -0
  8. package/dist/_chunks/ReleasesSettingsPage-hHmY2fiE.js +178 -0
  9. package/dist/_chunks/ReleasesSettingsPage-hHmY2fiE.js.map +1 -0
  10. package/dist/_chunks/{en-DtFJ5ViE.js → en-1_1re1mc.js} +7 -2
  11. package/dist/_chunks/en-1_1re1mc.js.map +1 -0
  12. package/dist/_chunks/{en-B9Ur3VsE.mjs → en-C3sq5KNP.mjs} +7 -2
  13. package/dist/_chunks/en-C3sq5KNP.mjs.map +1 -0
  14. package/dist/_chunks/{index-BomF0-yY.mjs → index-CJpYVXMt.mjs} +525 -444
  15. package/dist/_chunks/index-CJpYVXMt.mjs.map +1 -0
  16. package/dist/_chunks/{index-C5Hc767q.js → index-DYXEZrUA.js} +518 -437
  17. package/dist/_chunks/index-DYXEZrUA.js.map +1 -0
  18. package/dist/_chunks/validation-schemas-C7P2rhPu.mjs +29 -0
  19. package/dist/_chunks/validation-schemas-C7P2rhPu.mjs.map +1 -0
  20. package/dist/_chunks/validation-schemas-bib1fBc7.js +47 -0
  21. package/dist/_chunks/validation-schemas-bib1fBc7.js.map +1 -0
  22. package/dist/admin/index.js +1 -1
  23. package/dist/admin/index.mjs +2 -2
  24. package/dist/admin/src/components/ReleaseActionMenu.d.ts +2 -2
  25. package/dist/admin/src/components/{CMReleasesContainer.d.ts → ReleaseActionModal.d.ts} +3 -1
  26. package/dist/admin/src/components/ReleaseModal.d.ts +2 -1
  27. package/dist/admin/src/components/ReleasesPanel.d.ts +3 -0
  28. package/dist/admin/src/constants.d.ts +18 -0
  29. package/dist/admin/src/modules/hooks.d.ts +7 -0
  30. package/dist/admin/src/pages/ReleasesSettingsPage.d.ts +1 -0
  31. package/dist/admin/src/services/release.d.ts +37 -32
  32. package/dist/admin/src/utils/time.d.ts +9 -0
  33. package/dist/server/index.js +784 -600
  34. package/dist/server/index.js.map +1 -1
  35. package/dist/server/index.mjs +785 -601
  36. package/dist/server/index.mjs.map +1 -1
  37. package/dist/server/src/bootstrap.d.ts.map +1 -1
  38. package/dist/server/src/constants.d.ts +11 -2
  39. package/dist/server/src/constants.d.ts.map +1 -1
  40. package/dist/server/src/content-types/index.d.ts +3 -5
  41. package/dist/server/src/content-types/index.d.ts.map +1 -1
  42. package/dist/server/src/content-types/release-action/index.d.ts +3 -5
  43. package/dist/server/src/content-types/release-action/index.d.ts.map +1 -1
  44. package/dist/server/src/content-types/release-action/schema.d.ts +3 -5
  45. package/dist/server/src/content-types/release-action/schema.d.ts.map +1 -1
  46. package/dist/server/src/controllers/index.d.ts +6 -3
  47. package/dist/server/src/controllers/index.d.ts.map +1 -1
  48. package/dist/server/src/controllers/release-action.d.ts +0 -1
  49. package/dist/server/src/controllers/release-action.d.ts.map +1 -1
  50. package/dist/server/src/controllers/release.d.ts +7 -2
  51. package/dist/server/src/controllers/release.d.ts.map +1 -1
  52. package/dist/server/src/controllers/settings.d.ts +11 -0
  53. package/dist/server/src/controllers/settings.d.ts.map +1 -0
  54. package/dist/server/src/controllers/validation/release-action.d.ts +7 -1
  55. package/dist/server/src/controllers/validation/release-action.d.ts.map +1 -1
  56. package/dist/server/src/controllers/validation/release.d.ts +1 -0
  57. package/dist/server/src/controllers/validation/release.d.ts.map +1 -1
  58. package/dist/server/src/controllers/validation/settings.d.ts +2 -0
  59. package/dist/server/src/controllers/validation/settings.d.ts.map +1 -0
  60. package/dist/server/src/index.d.ts +66 -51
  61. package/dist/server/src/index.d.ts.map +1 -1
  62. package/dist/server/src/middlewares/documents.d.ts +6 -0
  63. package/dist/server/src/middlewares/documents.d.ts.map +1 -0
  64. package/dist/server/src/migrations/database/5.0.0-document-id-in-actions.d.ts +9 -0
  65. package/dist/server/src/migrations/database/5.0.0-document-id-in-actions.d.ts.map +1 -0
  66. package/dist/server/src/migrations/index.d.ts.map +1 -1
  67. package/dist/server/src/register.d.ts.map +1 -1
  68. package/dist/server/src/routes/index.d.ts +16 -0
  69. package/dist/server/src/routes/index.d.ts.map +1 -1
  70. package/dist/server/src/routes/release-action.d.ts.map +1 -1
  71. package/dist/server/src/routes/release.d.ts.map +1 -1
  72. package/dist/server/src/routes/settings.d.ts +18 -0
  73. package/dist/server/src/routes/settings.d.ts.map +1 -0
  74. package/dist/server/src/services/index.d.ts +38 -38
  75. package/dist/server/src/services/index.d.ts.map +1 -1
  76. package/dist/server/src/services/release-action.d.ts +36 -0
  77. package/dist/server/src/services/release-action.d.ts.map +1 -0
  78. package/dist/server/src/services/release.d.ts +6 -41
  79. package/dist/server/src/services/release.d.ts.map +1 -1
  80. package/dist/server/src/services/settings.d.ts +13 -0
  81. package/dist/server/src/services/settings.d.ts.map +1 -0
  82. package/dist/server/src/services/validation.d.ts +1 -1
  83. package/dist/server/src/services/validation.d.ts.map +1 -1
  84. package/dist/server/src/utils/index.d.ts +29 -8
  85. package/dist/server/src/utils/index.d.ts.map +1 -1
  86. package/dist/shared/contracts/release-actions.d.ts +6 -5
  87. package/dist/shared/contracts/release-actions.d.ts.map +1 -1
  88. package/dist/shared/contracts/releases.d.ts +6 -5
  89. package/dist/shared/contracts/releases.d.ts.map +1 -1
  90. package/dist/shared/contracts/settings.d.ts +39 -0
  91. package/dist/shared/contracts/settings.d.ts.map +1 -0
  92. package/dist/shared/validation-schemas.d.ts +1 -0
  93. package/dist/shared/validation-schemas.d.ts.map +1 -1
  94. package/package.json +10 -9
  95. package/dist/_chunks/App-DUmziQ17.js.map +0 -1
  96. package/dist/_chunks/App-D_6Y9N2F.mjs.map +0 -1
  97. package/dist/_chunks/en-B9Ur3VsE.mjs.map +0 -1
  98. package/dist/_chunks/en-DtFJ5ViE.js.map +0 -1
  99. package/dist/_chunks/index-BomF0-yY.mjs.map +0 -1
  100. package/dist/_chunks/index-C5Hc767q.js.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"App-CdTs45Xr.mjs","sources":["../../admin/src/components/RelativeTime.tsx","../../admin/src/components/ReleaseModal.tsx","../../admin/src/store/hooks.ts","../../admin/src/utils/api.ts","../../admin/src/pages/ReleasesPage.tsx","../../admin/src/pages/ReleaseDetailsPage.tsx","../../admin/src/pages/App.tsx"],"sourcesContent":["import * as React from 'react';\n\nimport { Duration, intervalToDuration, isPast } from 'date-fns';\nimport { useIntl } from 'react-intl';\n\nconst intervals: Array<keyof Duration> = ['years', 'months', 'days', 'hours', 'minutes', 'seconds'];\n\ninterface CustomInterval {\n unit: keyof Duration;\n text: string;\n threshold: number;\n}\n\ninterface RelativeTimeProps extends React.ComponentPropsWithoutRef<'time'> {\n timestamp: Date;\n customIntervals?: CustomInterval[];\n}\n\n/**\n * Displays the relative time between a given timestamp and the current time.\n * You can display a custom message for given time intervals by passing an array of custom intervals.\n *\n * @example\n * ```jsx\n * <caption>Display \"last hour\" if the timestamp is less than an hour ago</caption>\n * <RelativeTime\n * timestamp={new Date('2021-01-01')}\n * customIntervals={[\n * { unit: 'hours', threshold: 1, text: 'last hour' },\n * ]}\n * ```\n */\nconst RelativeTime = React.forwardRef<HTMLTimeElement, RelativeTimeProps>(\n ({ timestamp, customIntervals = [], ...restProps }, forwardedRef) => {\n const { formatRelativeTime, formatDate, formatTime } = useIntl();\n\n /**\n * TODO: make this auto-update, like a clock.\n */\n const interval = intervalToDuration({\n start: timestamp,\n end: Date.now(),\n // see https://github.com/date-fns/date-fns/issues/2891 – No idea why it's all partial it returns it every time.\n }) as Required<Duration>;\n\n const unit = intervals.find((intervalUnit) => {\n return interval[intervalUnit] > 0 && Object.keys(interval).includes(intervalUnit);\n })!;\n\n const relativeTime = isPast(timestamp) ? -interval[unit] : interval[unit];\n\n // Display custom text if interval is less than the threshold\n const customInterval = customIntervals.find(\n (custom) => interval[custom.unit] < custom.threshold\n );\n\n const displayText = customInterval\n ? customInterval.text\n : formatRelativeTime(relativeTime, unit, { numeric: 'auto' });\n\n return (\n <time\n ref={forwardedRef}\n dateTime={timestamp.toISOString()}\n role=\"time\"\n title={`${formatDate(timestamp)} ${formatTime(timestamp)}`}\n {...restProps}\n >\n {displayText}\n </time>\n );\n }\n);\n\nexport { RelativeTime };\nexport type { CustomInterval, RelativeTimeProps };\n","import * as React from 'react';\n\nimport {\n Button,\n Modal,\n TextInput,\n Typography,\n Checkbox,\n Flex,\n Box,\n DatePicker,\n TimePicker,\n Combobox,\n ComboboxOption,\n Field,\n} from '@strapi/design-system';\nimport { formatISO } from 'date-fns';\nimport { utcToZonedTime, zonedTimeToUtc } from 'date-fns-tz';\nimport { Formik, Form, useFormikContext } from 'formik';\nimport { useIntl } from 'react-intl';\nimport { useLocation } from 'react-router-dom';\n\nimport { RELEASE_SCHEMA } from '../../../shared/validation-schemas';\nimport { pluginId } from '../pluginId';\nimport { getTimezones } from '../utils/time';\n\nexport interface FormValues {\n name: string;\n date?: string;\n time: string;\n timezone: string | null;\n isScheduled?: boolean;\n scheduledAt: Date | null;\n}\n\ninterface ReleaseModalProps {\n handleClose: () => void;\n handleSubmit: (values: FormValues) => void;\n isLoading?: boolean;\n initialValues: FormValues;\n open?: boolean;\n}\n\nexport const ReleaseModal = ({\n handleClose,\n open,\n handleSubmit,\n initialValues,\n isLoading = false,\n}: ReleaseModalProps) => {\n const { formatMessage } = useIntl();\n const { pathname } = useLocation();\n const isCreatingRelease = pathname === `/plugins/${pluginId}`;\n // Set default first timezone from the list if no system timezone detected\n const { timezoneList, systemTimezone = { value: 'UTC+00:00-Africa/Abidjan ' } } = getTimezones(\n initialValues.scheduledAt ? new Date(initialValues.scheduledAt) : new Date()\n );\n\n /**\n * Generate scheduled time using selected date, time and timezone\n */\n const getScheduledTimestamp = (values: FormValues) => {\n const { date, time, timezone } = values;\n if (!date || !time || !timezone) return null;\n const timezoneWithoutOffset = timezone.split('&')[1];\n return zonedTimeToUtc(`${date} ${time}`, timezoneWithoutOffset);\n };\n\n /**\n * Get timezone with offset to show the selected value in the dropdown\n */\n const getTimezoneWithOffset = () => {\n const currentTimezone = timezoneList.find(\n (timezone) => timezone.value.split('&')[1] === initialValues.timezone\n );\n return currentTimezone?.value || systemTimezone.value;\n };\n\n return (\n <Modal.Root open={open} onOpenChange={handleClose}>\n <Modal.Content>\n <Modal.Header>\n <Modal.Title>\n {formatMessage(\n {\n id: 'content-releases.modal.title',\n defaultMessage:\n '{isCreatingRelease, select, true {New release} other {Edit release}}',\n },\n { isCreatingRelease: isCreatingRelease }\n )}\n </Modal.Title>\n </Modal.Header>\n <Formik\n onSubmit={(values) => {\n handleSubmit({\n ...values,\n timezone: values.timezone ? values.timezone.split('&')[1] : null,\n scheduledAt: values.isScheduled ? getScheduledTimestamp(values) : null,\n });\n }}\n initialValues={{\n ...initialValues,\n timezone: initialValues.timezone ? getTimezoneWithOffset() : systemTimezone.value,\n }}\n validationSchema={RELEASE_SCHEMA}\n validateOnChange={false}\n >\n {({ values, errors, handleChange, setFieldValue }) => {\n return (\n <Form>\n <Modal.Body>\n <Flex direction=\"column\" alignItems=\"stretch\" gap={6}>\n <Field.Root name=\"name\" error={errors.name} required>\n <Field.Label>\n {formatMessage({\n id: 'content-releases.modal.form.input.label.release-name',\n defaultMessage: 'Name',\n })}\n </Field.Label>\n <TextInput value={values.name} onChange={handleChange} />\n <Field.Error />\n </Field.Root>\n <Box width=\"max-content\">\n <Checkbox\n name=\"isScheduled\"\n checked={values.isScheduled}\n onCheckedChange={(checked) => {\n setFieldValue('isScheduled', checked);\n if (!checked) {\n // Clear scheduling info from a release on unchecking schedule release, which reset scheduling info in DB\n setFieldValue('date', null);\n setFieldValue('time', '');\n setFieldValue('timezone', null);\n } else {\n // On ticking back schedule release date, time and timezone should be restored to the initial state\n setFieldValue('date', initialValues.date);\n setFieldValue('time', initialValues.time);\n setFieldValue(\n 'timezone',\n initialValues.timezone ?? systemTimezone?.value\n );\n }\n }}\n >\n <Typography\n textColor={values.isScheduled ? 'primary600' : 'neutral800'}\n fontWeight={values.isScheduled ? 'semiBold' : 'regular'}\n >\n {formatMessage({\n id: 'modal.form.input.label.schedule-release',\n defaultMessage: 'Schedule release',\n })}\n </Typography>\n </Checkbox>\n </Box>\n {values.isScheduled && (\n <>\n <Flex gap={4} alignItems=\"start\">\n <Box width=\"100%\">\n <Field.Root name=\"date\" error={errors.date} required>\n <Field.Label>\n {formatMessage({\n id: 'content-releases.modal.form.input.label.date',\n defaultMessage: 'Date',\n })}\n </Field.Label>\n <DatePicker\n onChange={(date) => {\n const isoFormatDate = date\n ? formatISO(date, { representation: 'date' })\n : null;\n setFieldValue('date', isoFormatDate);\n }}\n clearLabel={formatMessage({\n id: 'content-releases.modal.form.input.clearLabel',\n defaultMessage: 'Clear',\n })}\n onClear={() => {\n setFieldValue('date', null);\n }}\n value={values.date ? new Date(values.date) : new Date()}\n minDate={utcToZonedTime(new Date(), values.timezone.split('&')[1])}\n />\n <Field.Error />\n </Field.Root>\n </Box>\n <Box width=\"100%\">\n <Field.Root name=\"time\" error={errors.time} required>\n <Field.Label>\n {formatMessage({\n id: 'content-releases.modal.form.input.label.time',\n defaultMessage: 'Time',\n })}\n </Field.Label>\n <TimePicker\n onChange={(time) => {\n setFieldValue('time', time);\n }}\n clearLabel={formatMessage({\n id: 'content-releases.modal.form.input.clearLabel',\n defaultMessage: 'Clear',\n })}\n onClear={() => {\n setFieldValue('time', '');\n }}\n value={values.time || undefined}\n />\n <Field.Error />\n </Field.Root>\n </Box>\n </Flex>\n <TimezoneComponent timezoneOptions={timezoneList} />\n </>\n )}\n </Flex>\n </Modal.Body>\n <Modal.Footer>\n <Modal.Close>\n <Button variant=\"tertiary\" name=\"cancel\">\n {formatMessage({ id: 'cancel', defaultMessage: 'Cancel' })}\n </Button>\n </Modal.Close>\n <Button name=\"submit\" loading={isLoading} type=\"submit\">\n {formatMessage(\n {\n id: 'content-releases.modal.form.button.submit',\n defaultMessage: '{isCreatingRelease, select, true {Continue} other {Save}}',\n },\n { isCreatingRelease: isCreatingRelease }\n )}\n </Button>\n </Modal.Footer>\n </Form>\n );\n }}\n </Formik>\n </Modal.Content>\n </Modal.Root>\n );\n};\n\n/**\n * Generates the list of timezones and user's current timezone(system timezone)\n */\ninterface ITimezoneOption {\n offset: string;\n value: string;\n}\n\nconst TimezoneComponent = ({ timezoneOptions }: { timezoneOptions: ITimezoneOption[] }) => {\n const { values, errors, setFieldValue } = useFormikContext<FormValues>();\n const { formatMessage } = useIntl();\n const [timezoneList, setTimezoneList] = React.useState<ITimezoneOption[]>(timezoneOptions);\n\n React.useEffect(() => {\n if (values.date) {\n // Update the timezone offset which varies with DST based on the date selected\n const { timezoneList } = getTimezones(new Date(values.date));\n setTimezoneList(timezoneList);\n\n const updatedTimezone =\n values.timezone &&\n timezoneList.find((tz) => tz.value.split('&')[1] === values.timezone!.split('&')[1]);\n if (updatedTimezone) {\n setFieldValue('timezone', updatedTimezone!.value);\n }\n }\n }, [setFieldValue, values.date, values.timezone]);\n\n return (\n <Field.Root name=\"timezone\" error={errors.timezone} required>\n <Field.Label>\n {formatMessage({\n id: 'content-releases.modal.form.input.label.timezone',\n defaultMessage: 'Timezone',\n })}\n </Field.Label>\n <Combobox\n autocomplete={{ type: 'list', filter: 'contains' }}\n value={values.timezone || undefined}\n textValue={values.timezone ? values.timezone.replace(/&/, ' ') : undefined} // textValue is required to show the updated DST timezone\n onChange={(timezone) => {\n setFieldValue('timezone', timezone);\n }}\n onTextValueChange={(timezone) => {\n setFieldValue('timezone', timezone);\n }}\n onClear={() => {\n setFieldValue('timezone', '');\n }}\n >\n {timezoneList.map((timezone) => (\n <ComboboxOption key={timezone.value} value={timezone.value}>\n {timezone.value.replace(/&/, ' ')}\n </ComboboxOption>\n ))}\n </Combobox>\n <Field.Error />\n </Field.Root>\n );\n};\n","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 { SerializedError } from '@reduxjs/toolkit';\nimport { ApiError } from '@strapi/admin/strapi-admin';\n\ntype BaseQueryError = ApiError | SerializedError;\n\nconst isBaseQueryError = (error?: BaseQueryError): error is BaseQueryError => {\n return typeof error !== 'undefined' && error.name !== undefined;\n};\n\nexport { isBaseQueryError };\nexport type { BaseQueryError };\n","import * as React from 'react';\n\nimport {\n Page,\n Pagination,\n useTracking,\n useAPIErrorHandler,\n useNotification,\n useQueryParams,\n useRBAC,\n isFetchError,\n Layouts,\n} from '@strapi/admin/strapi-admin';\nimport { useLicenseLimits } from '@strapi/admin/strapi-admin/ee';\nimport {\n Alert,\n Badge,\n Box,\n Button,\n Divider,\n EmptyStateLayout,\n Flex,\n Grid,\n Main,\n Tabs,\n Typography,\n Link,\n} from '@strapi/design-system';\nimport { Plus } from '@strapi/icons';\nimport { EmptyDocuments } from '@strapi/icons/symbols';\nimport { useIntl } from 'react-intl';\nimport { useNavigate, useLocation, NavLink } from 'react-router-dom';\nimport { styled } from 'styled-components';\n\nimport { GetReleases, type Release } from '../../../shared/contracts/releases';\nimport { RelativeTime as BaseRelativeTime } from '../components/RelativeTime';\nimport { ReleaseModal, FormValues } from '../components/ReleaseModal';\nimport { PERMISSIONS } from '../constants';\nimport {\n useGetReleasesQuery,\n GetReleasesQueryParams,\n useCreateReleaseMutation,\n} from '../services/release';\n\n/* -------------------------------------------------------------------------------------------------\n * ReleasesGrid\n * -----------------------------------------------------------------------------------------------*/\ninterface ReleasesGridProps {\n sectionTitle: 'pending' | 'done';\n releases?: GetReleases.Response['data'];\n isError?: boolean;\n}\n\nconst LinkCard = styled(Link)`\n display: block;\n`;\n\nconst RelativeTime = styled(BaseRelativeTime)`\n display: inline-block;\n &::first-letter {\n text-transform: uppercase;\n }\n`;\n\nconst getBadgeProps = (status: Release['status']) => {\n let color;\n switch (status) {\n case 'ready':\n color = 'success';\n break;\n case 'blocked':\n color = 'warning';\n break;\n case 'failed':\n color = 'danger';\n break;\n case 'done':\n color = 'primary';\n break;\n case 'empty':\n default:\n color = 'neutral';\n }\n\n return {\n textColor: `${color}600`,\n backgroundColor: `${color}100`,\n borderColor: `${color}200`,\n };\n};\n\nconst ReleasesGrid = ({ sectionTitle, releases = [], isError = false }: ReleasesGridProps) => {\n const { formatMessage } = useIntl();\n\n if (isError) {\n return <Page.Error />;\n }\n\n if (releases?.length === 0) {\n return (\n <EmptyStateLayout\n content={formatMessage(\n {\n id: 'content-releases.page.Releases.tab.emptyEntries',\n defaultMessage: 'No releases',\n },\n {\n target: sectionTitle,\n }\n )}\n icon={<EmptyDocuments width=\"16rem\" />}\n />\n );\n }\n\n return (\n <Grid.Root gap={4}>\n {releases.map(({ id, name, scheduledAt, status }) => (\n <Grid.Item col={3} s={6} xs={12} key={id}>\n <LinkCard tag={NavLink} to={`${id}`} isExternal={false}>\n <Flex\n direction=\"column\"\n justifyContent=\"space-between\"\n padding={4}\n hasRadius\n background=\"neutral0\"\n shadow=\"tableShadow\"\n height=\"100%\"\n width=\"100%\"\n alignItems=\"start\"\n gap={4}\n >\n <Flex direction=\"column\" alignItems=\"start\" gap={1}>\n <Typography textColor=\"neutral800\" tag=\"h3\" variant=\"delta\" fontWeight=\"bold\">\n {name}\n </Typography>\n <Typography variant=\"pi\" textColor=\"neutral600\">\n {scheduledAt ? (\n <RelativeTime timestamp={new Date(scheduledAt)} />\n ) : (\n formatMessage({\n id: 'content-releases.pages.Releases.not-scheduled',\n defaultMessage: 'Not scheduled',\n })\n )}\n </Typography>\n </Flex>\n <Badge {...getBadgeProps(status)}>{status}</Badge>\n </Flex>\n </LinkCard>\n </Grid.Item>\n ))}\n </Grid.Root>\n );\n};\n\n/* -------------------------------------------------------------------------------------------------\n * ReleasesPage\n * -----------------------------------------------------------------------------------------------*/\n\nconst StyledAlert = styled(Alert)`\n button {\n display: none;\n }\n p + div {\n margin-left: auto;\n }\n`;\n\nconst INITIAL_FORM_VALUES = {\n name: '',\n date: undefined,\n time: '',\n isScheduled: true,\n scheduledAt: null,\n timezone: null,\n} satisfies FormValues;\n\nconst ReleasesPage = () => {\n const location = useLocation();\n const [releaseModalShown, setReleaseModalShown] = React.useState(false);\n const { toggleNotification } = useNotification();\n const { formatMessage } = useIntl();\n const navigate = useNavigate();\n const { formatAPIError } = useAPIErrorHandler();\n const [{ query }, setQuery] = useQueryParams<GetReleasesQueryParams>();\n const response = useGetReleasesQuery(query);\n const [createRelease, { isLoading: isSubmittingForm }] = useCreateReleaseMutation();\n const { getFeature } = useLicenseLimits();\n const { maximumReleases = 3 } = getFeature('cms-content-releases') as {\n maximumReleases: number;\n };\n const { trackUsage } = useTracking();\n const {\n allowedActions: { canCreate },\n } = useRBAC(PERMISSIONS);\n\n const { isLoading, isSuccess, isError } = response;\n const activeTab = response?.currentData?.meta?.activeTab || 'pending';\n\n // Check if we have some errors and show a notification to the user to explain the error\n React.useEffect(() => {\n if (location?.state?.errors) {\n toggleNotification({\n type: 'danger',\n title: formatMessage({\n id: 'content-releases.pages.Releases.notification.error.title',\n defaultMessage: 'Your request could not be processed.',\n }),\n message: formatMessage({\n id: 'content-releases.pages.Releases.notification.error.message',\n defaultMessage: 'Please try again or open another release.',\n }),\n });\n navigate('', { replace: true, state: null });\n }\n }, [formatMessage, location?.state?.errors, navigate, toggleNotification]);\n\n const toggleAddReleaseModal = () => {\n setReleaseModalShown((prev) => !prev);\n };\n\n if (isLoading) {\n return <Page.Loading />;\n }\n\n const totalPendingReleases = (isSuccess && response.currentData?.meta?.pendingReleasesCount) || 0;\n const hasReachedMaximumPendingReleases = totalPendingReleases >= maximumReleases;\n\n const handleTabChange = (tabValue: string) => {\n setQuery({\n ...query,\n page: 1,\n pageSize: response?.currentData?.meta?.pagination?.pageSize || 16,\n filters: {\n releasedAt: {\n $notNull: tabValue !== 'pending',\n },\n },\n });\n };\n\n const handleAddRelease = async ({ name, scheduledAt, timezone }: FormValues) => {\n const response = await createRelease({\n name,\n scheduledAt,\n timezone,\n });\n if ('data' in response) {\n // When the response returns an object with 'data', handle success\n toggleNotification({\n type: 'success',\n message: formatMessage({\n id: 'content-releases.modal.release-created-notification-success',\n defaultMessage: 'Release created.',\n }),\n });\n\n trackUsage('didCreateRelease');\n navigate(response.data.data.id.toString());\n } else if (isFetchError(response.error)) {\n // When the response returns an object with 'error', handle fetch error\n toggleNotification({\n type: 'danger',\n message: formatAPIError(response.error),\n });\n } else {\n // Otherwise, the response returns an object with 'error', handle a generic error\n toggleNotification({\n type: 'danger',\n message: formatMessage({ id: 'notification.error', defaultMessage: 'An error occurred' }),\n });\n }\n };\n\n return (\n <Main aria-busy={isLoading}>\n <Layouts.Header\n title={formatMessage({\n id: 'content-releases.pages.Releases.title',\n defaultMessage: 'Releases',\n })}\n subtitle={formatMessage({\n id: 'content-releases.pages.Releases.header-subtitle',\n defaultMessage: 'Create and manage content updates',\n })}\n primaryAction={\n canCreate ? (\n <Button\n startIcon={<Plus />}\n onClick={toggleAddReleaseModal}\n disabled={hasReachedMaximumPendingReleases}\n >\n {formatMessage({\n id: 'content-releases.header.actions.add-release',\n defaultMessage: 'New release',\n })}\n </Button>\n ) : null\n }\n />\n <Layouts.Content>\n <>\n {hasReachedMaximumPendingReleases && (\n <StyledAlert\n marginBottom={6}\n action={\n <Link href=\"https://strapi.io/pricing-cloud\" isExternal>\n {formatMessage({\n id: 'content-releases.pages.Releases.max-limit-reached.action',\n defaultMessage: 'Explore plans',\n })}\n </Link>\n }\n title={formatMessage(\n {\n id: 'content-releases.pages.Releases.max-limit-reached.title',\n defaultMessage:\n 'You have reached the {number} pending {number, plural, one {release} other {releases}} limit.',\n },\n { number: maximumReleases }\n )}\n onClose={() => {}}\n closeLabel=\"\"\n >\n {formatMessage({\n id: 'content-releases.pages.Releases.max-limit-reached.message',\n defaultMessage: 'Upgrade to manage an unlimited number of releases.',\n })}\n </StyledAlert>\n )}\n <Tabs.Root variant=\"simple\" onValueChange={handleTabChange} value={activeTab}>\n <Box paddingBottom={8}>\n <Tabs.List\n aria-label={formatMessage({\n id: 'content-releases.pages.Releases.tab-group.label',\n defaultMessage: 'Releases list',\n })}\n >\n <Tabs.Trigger value=\"pending\">\n {formatMessage(\n {\n id: 'content-releases.pages.Releases.tab.pending',\n defaultMessage: 'Pending ({count})',\n },\n {\n count: totalPendingReleases,\n }\n )}\n </Tabs.Trigger>\n <Tabs.Trigger value=\"done\">\n {formatMessage({\n id: 'content-releases.pages.Releases.tab.done',\n defaultMessage: 'Done',\n })}\n </Tabs.Trigger>\n </Tabs.List>\n <Divider />\n </Box>\n {/* Pending releases */}\n <Tabs.Content value=\"pending\">\n <ReleasesGrid\n sectionTitle=\"pending\"\n releases={response?.currentData?.data}\n isError={isError}\n />\n </Tabs.Content>\n {/* Done releases */}\n <Tabs.Content value=\"done\">\n <ReleasesGrid\n sectionTitle=\"done\"\n releases={response?.currentData?.data}\n isError={isError}\n />\n </Tabs.Content>\n </Tabs.Root>\n <Pagination.Root\n {...response?.currentData?.meta?.pagination}\n defaultPageSize={response?.currentData?.meta?.pagination?.pageSize}\n >\n <Pagination.PageSize options={['8', '16', '32', '64']} />\n <Pagination.Links />\n </Pagination.Root>\n </>\n </Layouts.Content>\n <ReleaseModal\n open={releaseModalShown}\n handleClose={toggleAddReleaseModal}\n handleSubmit={handleAddRelease}\n isLoading={isSubmittingForm}\n initialValues={INITIAL_FORM_VALUES}\n />\n </Main>\n );\n};\n\nexport { ReleasesPage, getBadgeProps };\n","import * as React from 'react';\n\nimport {\n Page,\n Pagination,\n Table,\n BackButton,\n ConfirmDialog,\n useTracking,\n useAPIErrorHandler,\n useNotification,\n useQueryParams,\n useRBAC,\n isFetchError,\n useStrapiApp,\n Layouts,\n} from '@strapi/admin/strapi-admin';\nimport { unstable_useDocument } from '@strapi/content-manager/strapi-admin';\nimport {\n Button,\n Flex,\n Main,\n Tr,\n Td,\n Typography,\n Badge,\n SingleSelect,\n SingleSelectOption,\n Tooltip,\n EmptyStateLayout,\n LinkButton,\n Dialog,\n SimpleMenu,\n MenuItem,\n} from '@strapi/design-system';\nimport {\n CheckCircle,\n More,\n Pencil,\n Trash,\n CrossCircle,\n ArrowsCounterClockwise,\n} from '@strapi/icons';\nimport { EmptyDocuments } from '@strapi/icons/symbols';\nimport format from 'date-fns/format';\nimport { utcToZonedTime } from 'date-fns-tz';\nimport { useIntl } from 'react-intl';\nimport { useParams, useNavigate, Link as ReactRouterLink, Navigate } from 'react-router-dom';\nimport { styled } from 'styled-components';\n\nimport { RelativeTime } from '../components/RelativeTime';\nimport { ReleaseActionMenu } from '../components/ReleaseActionMenu';\nimport { ReleaseActionOptions } from '../components/ReleaseActionOptions';\nimport { ReleaseModal, FormValues } from '../components/ReleaseModal';\nimport { PERMISSIONS } from '../constants';\nimport {\n GetReleaseActionsQueryParams,\n useGetReleaseActionsQuery,\n useGetReleaseQuery,\n useUpdateReleaseMutation,\n useUpdateReleaseActionMutation,\n usePublishReleaseMutation,\n useDeleteReleaseMutation,\n releaseApi,\n} from '../services/release';\nimport { useTypedDispatch } from '../store/hooks';\nimport { isBaseQueryError } from '../utils/api';\nimport { getTimezoneOffset } from '../utils/time';\n\nimport { getBadgeProps } from './ReleasesPage';\n\nimport type {\n ReleaseAction,\n ReleaseActionGroupBy,\n ReleaseActionEntry,\n} from '../../../shared/contracts/release-actions';\nimport type { Struct, Internal } from '@strapi/types';\n\n/* -------------------------------------------------------------------------------------------------\n * ReleaseDetailsLayout\n * -----------------------------------------------------------------------------------------------*/\nconst ReleaseInfoWrapper = styled(Flex)`\n align-self: stretch;\n border-bottom-right-radius: ${({ theme }) => theme.borderRadius};\n border-bottom-left-radius: ${({ theme }) => theme.borderRadius};\n border-top: 1px solid ${({ theme }) => theme.colors.neutral150};\n`;\n\nconst StyledMenuItem = styled(MenuItem)<{\n disabled?: boolean;\n $variant?: 'neutral' | 'danger';\n}>`\n svg path {\n fill: ${({ theme, disabled }) => disabled && theme.colors.neutral500};\n }\n span {\n color: ${({ theme, disabled }) => disabled && theme.colors.neutral500};\n }\n\n &:hover {\n background: ${({ theme, $variant = 'neutral' }) => theme.colors[`${$variant}100`]};\n }\n`;\n\nconst PencilIcon = styled(Pencil)`\n width: ${({ theme }) => theme.spaces[3]};\n height: ${({ theme }) => theme.spaces[3]};\n path {\n fill: ${({ theme }) => theme.colors.neutral600};\n }\n`;\n\nconst TrashIcon = styled(Trash)`\n width: ${({ theme }) => theme.spaces[3]};\n height: ${({ theme }) => theme.spaces[3]};\n path {\n fill: ${({ theme }) => theme.colors.danger600};\n }\n`;\n\nconst TypographyMaxWidth = styled(Typography)`\n max-width: 300px;\n`;\n\ninterface EntryValidationTextProps {\n action: ReleaseAction['type'];\n schema?: Struct.ContentTypeSchema;\n components: { [key: Internal.UID.Component]: Struct.ComponentSchema };\n entry: ReleaseActionEntry;\n status: ReleaseAction['status'];\n}\n\nconst EntryValidationText = ({ action, schema, entry, status }: EntryValidationTextProps) => {\n const { formatMessage } = useIntl();\n\n const { validate, isLoading } = unstable_useDocument(\n {\n collectionType: schema?.kind ?? '',\n model: schema?.uid ?? '',\n },\n {\n // useDocument makes a request to get more data about the entry, but we only want to have the validation function so we skip the request\n skip: true,\n }\n );\n\n if (isLoading) {\n return null;\n }\n\n const errors = validate(entry) ?? {};\n\n if (action === 'publish') {\n if (Object.keys(errors).length > 0) {\n const validationErrorsMessages = Object.entries(errors)\n .map(([key, value]) =>\n formatMessage(\n // @ts-expect-error – TODO: fix this will better checks\n { id: `${value.id}.withField`, defaultMessage: value.defaultMessage },\n { field: key }\n )\n )\n .join(' ');\n\n return (\n <Flex gap={2}>\n <CrossCircle fill=\"danger600\" />\n <Tooltip description={validationErrorsMessages}>\n <TypographyMaxWidth\n textColor=\"danger600\"\n variant=\"omega\"\n fontWeight=\"semiBold\"\n ellipsis\n >\n {validationErrorsMessages}\n </TypographyMaxWidth>\n </Tooltip>\n </Flex>\n );\n }\n\n if (status === 'draft') {\n return (\n <Flex gap={2}>\n <CheckCircle fill=\"success600\" />\n <Typography>\n {formatMessage({\n id: 'content-releases.pages.ReleaseDetails.entry-validation.ready-to-publish',\n defaultMessage: 'Ready to publish',\n })}\n </Typography>\n </Flex>\n );\n }\n\n if (status === 'modified') {\n return (\n <Flex gap={2}>\n <ArrowsCounterClockwise fill=\"alternative600\" />\n <Typography>\n {formatMessage({\n id: 'content-releases.pages.ReleaseDetails.entry-validation.modified',\n defaultMessage: 'Ready to publish changes',\n })}\n </Typography>\n </Flex>\n );\n }\n\n if (status === 'published') {\n return (\n <Flex gap={2}>\n <CheckCircle fill=\"success600\" />\n <Typography>\n {formatMessage({\n id: 'content-releases.pages.ReleaseDetails.entry-validation.already-published',\n defaultMessage: 'Already published',\n })}\n </Typography>\n </Flex>\n );\n }\n }\n\n return (\n <Flex gap={2}>\n <CheckCircle fill=\"success600\" />\n {!entry.publishedAt ? (\n <Typography textColor=\"success600\" fontWeight=\"bold\">\n {formatMessage({\n id: 'content-releases.pages.ReleaseDetails.entry-validation.already-unpublished',\n defaultMessage: 'Already unpublished',\n })}\n </Typography>\n ) : (\n <Typography>\n {formatMessage({\n id: 'content-releases.pages.ReleaseDetails.entry-validation.ready-to-unpublish',\n defaultMessage: 'Ready to unpublish',\n })}\n </Typography>\n )}\n </Flex>\n );\n};\ninterface ReleaseDetailsLayoutProps {\n toggleEditReleaseModal: () => void;\n toggleWarningSubmit: () => void;\n children: React.ReactNode;\n}\n\nconst ReleaseDetailsLayout = ({\n toggleEditReleaseModal,\n toggleWarningSubmit,\n children,\n}: ReleaseDetailsLayoutProps) => {\n const { formatMessage, formatDate, formatTime } = useIntl();\n const { releaseId } = useParams<{ releaseId: string }>();\n const {\n data,\n isLoading: isLoadingDetails,\n error,\n } = useGetReleaseQuery(\n { id: releaseId! },\n {\n skip: !releaseId,\n }\n );\n const [publishRelease, { isLoading: isPublishing }] = usePublishReleaseMutation();\n const { toggleNotification } = useNotification();\n const { formatAPIError } = useAPIErrorHandler();\n const { allowedActions } = useRBAC(PERMISSIONS);\n const { canUpdate, canDelete, canPublish } = allowedActions;\n const dispatch = useTypedDispatch();\n const { trackUsage } = useTracking();\n\n const release = data?.data;\n\n const handlePublishRelease = (id: string) => async () => {\n const response = await publishRelease({ id });\n\n if ('data' in response) {\n // When the response returns an object with 'data', handle success\n toggleNotification({\n type: 'success',\n message: formatMessage({\n id: 'content-releases.pages.ReleaseDetails.publish-notification-success',\n defaultMessage: 'Release was published successfully.',\n }),\n });\n\n const { totalEntries, totalPublishedEntries, totalUnpublishedEntries } = response.data.meta;\n\n trackUsage('didPublishRelease', {\n totalEntries,\n totalPublishedEntries,\n totalUnpublishedEntries,\n });\n } else if (isFetchError(response.error)) {\n // When the response returns an object with 'error', handle fetch error\n toggleNotification({\n type: 'danger',\n message: formatAPIError(response.error),\n });\n } else {\n // Otherwise, the response returns an object with 'error', handle a generic error\n toggleNotification({\n type: 'danger',\n message: formatMessage({ id: 'notification.error', defaultMessage: 'An error occurred' }),\n });\n }\n };\n\n const handleRefresh = () => {\n dispatch(\n releaseApi.util.invalidateTags([\n { type: 'ReleaseAction', id: 'LIST' },\n { type: 'Release', id: releaseId },\n ])\n );\n };\n\n const getCreatedByUser = () => {\n if (!release?.createdBy) {\n return null;\n }\n\n // Favor the username\n if (release.createdBy.username) {\n return release.createdBy.username;\n }\n\n // Firstname may not exist if created with SSO\n if (release.createdBy.firstname) {\n return `${release.createdBy.firstname} ${release.createdBy.lastname || ''}`.trim();\n }\n\n // All users must have at least an email\n return release.createdBy.email;\n };\n\n if (isLoadingDetails) {\n return <Page.Loading />;\n }\n\n if ((isBaseQueryError(error) && 'code' in error) || !release) {\n return (\n <Navigate\n to=\"..\"\n state={{\n errors: [\n {\n // @ts-expect-error – TODO: fix this weird error flow\n code: error?.code,\n },\n ],\n }}\n />\n );\n }\n\n const totalEntries = release.actions.meta.count || 0;\n const hasCreatedByUser = Boolean(getCreatedByUser());\n\n const isScheduled = release.scheduledAt && release.timezone;\n const numberOfEntriesText = formatMessage(\n {\n id: 'content-releases.pages.Details.header-subtitle',\n defaultMessage: '{number, plural, =0 {No entries} one {# entry} other {# entries}}',\n },\n { number: totalEntries }\n );\n const scheduledText = isScheduled\n ? formatMessage(\n {\n id: 'content-releases.pages.ReleaseDetails.header-subtitle.scheduled',\n defaultMessage: 'Scheduled for {date} at {time} ({offset})',\n },\n {\n date: formatDate(new Date(release.scheduledAt!), {\n weekday: 'long',\n day: 'numeric',\n month: 'long',\n year: 'numeric',\n timeZone: release.timezone!,\n }),\n time: formatTime(new Date(release.scheduledAt!), {\n timeZone: release.timezone!,\n hourCycle: 'h23',\n }),\n offset: getTimezoneOffset(release.timezone!, new Date(release.scheduledAt!)),\n }\n )\n : '';\n\n return (\n <Main aria-busy={isLoadingDetails}>\n <Layouts.Header\n title={release.name}\n subtitle={\n <Flex gap={2} lineHeight={6}>\n <Typography textColor=\"neutral600\" variant=\"epsilon\">\n {numberOfEntriesText + (isScheduled ? ` - ${scheduledText}` : '')}\n </Typography>\n <Badge {...getBadgeProps(release.status)}>{release.status}</Badge>\n </Flex>\n }\n navigationAction={<BackButton />}\n primaryAction={\n !release.releasedAt && (\n <Flex gap={2}>\n <SimpleMenu\n label={<More />}\n variant=\"tertiary\"\n endIcon={null}\n paddingLeft={2}\n paddingRight={2}\n aria-label={formatMessage({\n id: 'content-releases.header.actions.open-release-actions',\n defaultMessage: 'Release edit and delete menu',\n })}\n popoverPlacement=\"bottom-end\"\n >\n <StyledMenuItem disabled={!canUpdate} onSelect={toggleEditReleaseModal}>\n <Flex alignItems=\"center\" gap={2} hasRadius width=\"100%\">\n <PencilIcon />\n <Typography ellipsis>\n {formatMessage({\n id: 'content-releases.header.actions.edit',\n defaultMessage: 'Edit',\n })}\n </Typography>\n </Flex>\n </StyledMenuItem>\n <StyledMenuItem\n disabled={!canDelete}\n onSelect={toggleWarningSubmit}\n $variant=\"danger\"\n >\n <Flex alignItems=\"center\" gap={2} hasRadius width=\"100%\">\n <TrashIcon />\n <Typography ellipsis textColor=\"danger600\">\n {formatMessage({\n id: 'content-releases.header.actions.delete',\n defaultMessage: 'Delete',\n })}\n </Typography>\n </Flex>\n </StyledMenuItem>\n <ReleaseInfoWrapper\n direction=\"column\"\n justifyContent=\"center\"\n alignItems=\"flex-start\"\n gap={1}\n padding={5}\n >\n <Typography variant=\"pi\" fontWeight=\"bold\">\n {formatMessage({\n id: 'content-releases.header.actions.created',\n defaultMessage: 'Created',\n })}\n </Typography>\n <Typography variant=\"pi\" color=\"neutral300\">\n <RelativeTime timestamp={new Date(release.createdAt)} />\n {formatMessage(\n {\n id: 'content-releases.header.actions.created.description',\n defaultMessage:\n '{hasCreatedByUser, select, true { by {createdBy}} other { by deleted user}}',\n },\n { createdBy: getCreatedByUser(), hasCreatedByUser }\n )}\n </Typography>\n </ReleaseInfoWrapper>\n </SimpleMenu>\n <Button size=\"S\" variant=\"tertiary\" onClick={handleRefresh}>\n {formatMessage({\n id: 'content-releases.header.actions.refresh',\n defaultMessage: 'Refresh',\n })}\n </Button>\n {canPublish ? (\n <Button\n size=\"S\"\n variant=\"default\"\n onClick={handlePublishRelease(release.id.toString())}\n loading={isPublishing}\n disabled={release.actions.meta.count === 0}\n >\n {formatMessage({\n id: 'content-releases.header.actions.publish',\n defaultMessage: 'Publish',\n })}\n </Button>\n ) : null}\n </Flex>\n )\n }\n />\n {children}\n </Main>\n );\n};\n\n/* -------------------------------------------------------------------------------------------------\n * ReleaseDetailsBody\n * -----------------------------------------------------------------------------------------------*/\nconst GROUP_BY_OPTIONS = ['contentType', 'locale', 'action'] as const;\nconst GROUP_BY_OPTIONS_NO_LOCALE = ['contentType', 'action'] as const;\nconst getGroupByOptionLabel = (value: (typeof GROUP_BY_OPTIONS)[number]) => {\n if (value === 'locale') {\n return {\n id: 'content-releases.pages.ReleaseDetails.groupBy.option.locales',\n defaultMessage: 'Locales',\n };\n }\n\n if (value === 'action') {\n return {\n id: 'content-releases.pages.ReleaseDetails.groupBy.option.actions',\n defaultMessage: 'Actions',\n };\n }\n\n return {\n id: 'content-releases.pages.ReleaseDetails.groupBy.option.content-type',\n defaultMessage: 'Content-Types',\n };\n};\n\ninterface ReleaseDetailsBodyProps {\n releaseId: string;\n}\n\nconst ReleaseDetailsBody = ({ releaseId }: ReleaseDetailsBodyProps) => {\n const { formatMessage } = useIntl();\n const [{ query }, setQuery] = useQueryParams<GetReleaseActionsQueryParams>();\n const { toggleNotification } = useNotification();\n const { formatAPIError } = useAPIErrorHandler();\n const {\n data: releaseData,\n isLoading: isReleaseLoading,\n error: releaseError,\n } = useGetReleaseQuery({ id: releaseId });\n const {\n allowedActions: { canUpdate },\n } = useRBAC(PERMISSIONS);\n const runHookWaterfall = useStrapiApp('ReleaseDetailsPage', (state) => state.runHookWaterfall);\n\n // TODO: Migrated displayedHeader to v5\n const { displayedHeaders, hasI18nEnabled }: { displayedHeaders: any; hasI18nEnabled: boolean } =\n runHookWaterfall('ContentReleases/pages/ReleaseDetails/add-locale-in-releases', {\n displayedHeaders: [\n {\n label: {\n id: 'content-releases.page.ReleaseDetails.table.header.label.name',\n defaultMessage: 'name',\n },\n name: 'name',\n },\n ],\n hasI18nEnabled: false,\n });\n\n const release = releaseData?.data;\n const selectedGroupBy = query?.groupBy || 'contentType';\n\n const {\n isLoading,\n isFetching,\n isError,\n data,\n error: releaseActionsError,\n } = useGetReleaseActionsQuery({\n ...query,\n releaseId,\n });\n\n const [updateReleaseAction] = useUpdateReleaseActionMutation();\n\n const handleChangeType = async (\n e: React.ChangeEvent<HTMLInputElement>,\n actionId: ReleaseAction['id'],\n actionPath: [string, number]\n ) => {\n const response = await updateReleaseAction({\n params: {\n releaseId,\n actionId,\n },\n body: {\n type: e.target.value as ReleaseAction['type'],\n },\n query, // We are passing the query params to make optimistic updates\n actionPath, // We are passing the action path to found the position in the cache of the action for optimistic updates\n });\n\n if ('error' in response) {\n if (isFetchError(response.error)) {\n // When the response returns an object with 'error', handle fetch error\n toggleNotification({\n type: 'danger',\n message: formatAPIError(response.error),\n });\n } else {\n // Otherwise, the response returns an object with 'error', handle a generic error\n toggleNotification({\n type: 'danger',\n message: formatMessage({ id: 'notification.error', defaultMessage: 'An error occurred' }),\n });\n }\n }\n };\n\n if (isLoading || isReleaseLoading) {\n return <Page.Loading />;\n }\n\n const releaseActions = data?.data;\n const releaseMeta = data?.meta;\n const contentTypes = releaseMeta?.contentTypes || {};\n const components = releaseMeta?.components || {};\n\n if (isBaseQueryError(releaseError) || !release) {\n const errorsArray = [];\n if (releaseError && 'code' in releaseError) {\n errorsArray.push({\n code: releaseError.code,\n });\n }\n if (releaseActionsError && 'code' in releaseActionsError) {\n errorsArray.push({\n code: releaseActionsError.code,\n });\n }\n return (\n <Navigate\n to=\"..\"\n state={{\n errors: errorsArray,\n }}\n />\n );\n }\n\n if (isError || !releaseActions) {\n return <Page.Error />;\n }\n\n if (Object.keys(releaseActions).length === 0) {\n return (\n <Layouts.Content>\n <EmptyStateLayout\n action={\n <LinkButton\n tag={ReactRouterLink}\n to={{\n pathname: '/content-manager',\n }}\n style={{ textDecoration: 'none' }}\n variant=\"secondary\"\n >\n {formatMessage({\n id: 'content-releases.page.Details.button.openContentManager',\n defaultMessage: 'Open the Content Manager',\n })}\n </LinkButton>\n }\n icon={<EmptyDocuments width=\"16rem\" />}\n content={formatMessage({\n id: 'content-releases.pages.Details.tab.emptyEntries',\n defaultMessage:\n 'This release is empty. Open the Content Manager, select an entry and add it to the release.',\n })}\n />\n </Layouts.Content>\n );\n }\n\n const groupByLabel = formatMessage({\n id: 'content-releases.pages.ReleaseDetails.groupBy.aria-label',\n defaultMessage: 'Group by',\n });\n const headers = [\n ...displayedHeaders,\n {\n label: {\n id: 'content-releases.page.ReleaseDetails.table.header.label.content-type',\n defaultMessage: 'content-type',\n },\n name: 'content-type',\n },\n {\n label: {\n id: 'content-releases.page.ReleaseDetails.table.header.label.action',\n defaultMessage: 'action',\n },\n name: 'action',\n },\n ...(!release.releasedAt\n ? [\n {\n label: {\n id: 'content-releases.page.ReleaseDetails.table.header.label.status',\n defaultMessage: 'status',\n },\n name: 'status',\n },\n ]\n : []),\n ];\n\n const options = hasI18nEnabled ? GROUP_BY_OPTIONS : GROUP_BY_OPTIONS_NO_LOCALE;\n\n return (\n <Layouts.Content>\n <Flex gap={8} direction=\"column\" alignItems=\"stretch\">\n <Flex>\n <SingleSelect\n placeholder={groupByLabel}\n aria-label={groupByLabel}\n customizeContent={(value) =>\n formatMessage(\n {\n id: `content-releases.pages.ReleaseDetails.groupBy.label`,\n defaultMessage: `Group by {groupBy}`,\n },\n {\n groupBy: value,\n }\n )\n }\n value={formatMessage(getGroupByOptionLabel(selectedGroupBy))}\n onChange={(value) => setQuery({ groupBy: value as ReleaseActionGroupBy })}\n >\n {options.map((option) => (\n <SingleSelectOption key={option} value={option}>\n {formatMessage(getGroupByOptionLabel(option))}\n </SingleSelectOption>\n ))}\n </SingleSelect>\n </Flex>\n {Object.keys(releaseActions).map((key) => (\n <Flex key={`releases-group-${key}`} gap={4} direction=\"column\" alignItems=\"stretch\">\n <Flex role=\"separator\" aria-label={key}>\n <Badge>{key}</Badge>\n </Flex>\n <Table.Root\n rows={releaseActions[key].map((item) => ({\n ...item,\n id: Number(item.entry.id),\n }))}\n headers={headers}\n isLoading={isLoading || isFetching}\n >\n <Table.Content>\n <Table.Head>\n {headers.map(({ label, name }) => (\n <Table.HeaderCell key={name} label={formatMessage(label)} name={name} />\n ))}\n </Table.Head>\n <Table.Loading />\n <Table.Body>\n {releaseActions[key].map(\n ({ id, contentType, locale, type, entry, status }, actionIndex) => (\n <Tr key={id}>\n <Td width=\"25%\" maxWidth=\"200px\">\n <Typography ellipsis>{`${\n contentType.mainFieldValue || entry.id\n }`}</Typography>\n </Td>\n {hasI18nEnabled && (\n <Td width=\"10%\">\n <Typography>{`${locale?.name ? locale.name : '-'}`}</Typography>\n </Td>\n )}\n\n <Td width=\"10%\">\n <Typography>{contentType.displayName || ''}</Typography>\n </Td>\n <Td width=\"20%\">\n {release.releasedAt ? (\n <Typography>\n {formatMessage(\n {\n id: 'content-releases.page.ReleaseDetails.table.action-published',\n defaultMessage:\n 'This entry was <b>{isPublish, select, true {published} other {unpublished}}</b>.',\n },\n {\n isPublish: type === 'publish',\n b: (children: React.ReactNode) => (\n <Typography fontWeight=\"bold\">{children}</Typography>\n ),\n }\n )}\n </Typography>\n ) : (\n <ReleaseActionOptions\n selected={type}\n handleChange={(e) => handleChangeType(e, id, [key, actionIndex])}\n name={`release-action-${id}-type`}\n disabled={!canUpdate}\n />\n )}\n </Td>\n {!release.releasedAt && (\n <>\n <Td width=\"20%\" minWidth=\"200px\">\n <EntryValidationText\n action={type}\n schema={contentTypes?.[contentType.uid]}\n components={components}\n entry={entry}\n status={status}\n />\n </Td>\n <Td>\n <Flex justifyContent=\"flex-end\">\n <ReleaseActionMenu.Root>\n <ReleaseActionMenu.ReleaseActionEntryLinkItem\n contentTypeUid={contentType.uid}\n documentId={entry.documentId}\n locale={locale?.code}\n />\n <ReleaseActionMenu.DeleteReleaseActionItem\n releaseId={release.id}\n actionId={id}\n />\n </ReleaseActionMenu.Root>\n </Flex>\n </Td>\n </>\n )}\n </Tr>\n )\n )}\n </Table.Body>\n </Table.Content>\n </Table.Root>\n </Flex>\n ))}\n <Pagination.Root\n {...releaseMeta?.pagination}\n defaultPageSize={releaseMeta?.pagination?.pageSize}\n >\n <Pagination.PageSize />\n <Pagination.Links />\n </Pagination.Root>\n </Flex>\n </Layouts.Content>\n );\n};\n\n/* -------------------------------------------------------------------------------------------------\n * ReleaseDetailsPage\n * -----------------------------------------------------------------------------------------------*/\nconst ReleaseDetailsPage = () => {\n const { formatMessage } = useIntl();\n const { releaseId } = useParams<{ releaseId: string }>();\n const { toggleNotification } = useNotification();\n const { formatAPIError } = useAPIErrorHandler();\n const navigate = useNavigate();\n const [releaseModalShown, setReleaseModalShown] = React.useState(false);\n const [showWarningSubmit, setWarningSubmit] = React.useState(false);\n\n const {\n isLoading: isLoadingDetails,\n data,\n isSuccess: isSuccessDetails,\n } = useGetReleaseQuery(\n { id: releaseId! },\n {\n skip: !releaseId,\n }\n );\n const [updateRelease, { isLoading: isSubmittingForm }] = useUpdateReleaseMutation();\n const [deleteRelease] = useDeleteReleaseMutation();\n\n const toggleEditReleaseModal = () => {\n setReleaseModalShown((prev) => !prev);\n };\n\n const toggleWarningSubmit = () => setWarningSubmit((prevState) => !prevState);\n\n if (isLoadingDetails) {\n return (\n <ReleaseDetailsLayout\n toggleEditReleaseModal={toggleEditReleaseModal}\n toggleWarningSubmit={toggleWarningSubmit}\n >\n <Page.Loading />\n </ReleaseDetailsLayout>\n );\n }\n\n if (!releaseId) {\n return <Navigate to=\"..\" />;\n }\n\n const releaseData = (isSuccessDetails && data?.data) || null;\n\n const title = releaseData?.name || '';\n const timezone = releaseData?.timezone ?? null;\n const scheduledAt =\n releaseData?.scheduledAt && timezone ? utcToZonedTime(releaseData.scheduledAt, timezone) : null;\n // Just get the date and time to display without considering updated timezone time\n const date = scheduledAt ? format(scheduledAt, 'yyyy-MM-dd') : undefined;\n const time = scheduledAt ? format(scheduledAt, 'HH:mm') : '';\n\n const handleEditRelease = async (values: FormValues) => {\n const response = await updateRelease({\n id: releaseId,\n name: values.name,\n scheduledAt: values.scheduledAt,\n timezone: values.timezone,\n });\n\n if ('data' in response) {\n // When the response returns an object with 'data', handle success\n toggleNotification({\n type: 'success',\n message: formatMessage({\n id: 'content-releases.modal.release-updated-notification-success',\n defaultMessage: 'Release updated.',\n }),\n });\n toggleEditReleaseModal();\n } else if (isFetchError(response.error)) {\n // When the response returns an object with 'error', handle fetch error\n toggleNotification({\n type: 'danger',\n message: formatAPIError(response.error),\n });\n } else {\n // Otherwise, the response returns an object with 'error', handle a generic error\n toggleNotification({\n type: 'danger',\n message: formatMessage({ id: 'notification.error', defaultMessage: 'An error occurred' }),\n });\n }\n };\n\n const handleDeleteRelease = async () => {\n const response = await deleteRelease({\n id: releaseId,\n });\n\n if ('data' in response) {\n navigate('..');\n } else if (isFetchError(response.error)) {\n // When the response returns an object with 'error', handle fetch error\n toggleNotification({\n type: 'danger',\n message: formatAPIError(response.error),\n });\n } else {\n // Otherwise, the response returns an object with 'error', handle a generic error\n toggleNotification({\n type: 'danger',\n message: formatMessage({ id: 'notification.error', defaultMessage: 'An error occurred' }),\n });\n }\n };\n\n return (\n <ReleaseDetailsLayout\n toggleEditReleaseModal={toggleEditReleaseModal}\n toggleWarningSubmit={toggleWarningSubmit}\n >\n <ReleaseDetailsBody releaseId={releaseId} />\n <ReleaseModal\n open={releaseModalShown}\n handleClose={toggleEditReleaseModal}\n handleSubmit={handleEditRelease}\n isLoading={isLoadingDetails || isSubmittingForm}\n initialValues={{\n name: title || '',\n scheduledAt,\n date,\n time,\n isScheduled: Boolean(scheduledAt),\n timezone,\n }}\n />\n <Dialog.Root open={showWarningSubmit} onOpenChange={toggleWarningSubmit}>\n <ConfirmDialog onConfirm={handleDeleteRelease}>\n {formatMessage({\n id: 'content-releases.dialog.confirmation-message',\n defaultMessage: 'Are you sure you want to delete this release?',\n })}\n </ConfirmDialog>\n </Dialog.Root>\n </ReleaseDetailsLayout>\n );\n};\n\nexport { ReleaseDetailsPage };\n","import { Page } from '@strapi/admin/strapi-admin';\nimport { Route, Routes } from 'react-router-dom';\n\nimport { PERMISSIONS } from '../constants';\n\nimport { ReleaseDetailsPage } from './ReleaseDetailsPage';\nimport { ReleasesPage } from './ReleasesPage';\n\nexport const App = () => {\n return (\n <Page.Protect permissions={PERMISSIONS.main}>\n <Routes>\n <Route index element={<ReleasesPage />} />\n <Route path={':releaseId'} element={<ReleaseDetailsPage />} />\n </Routes>\n </Page.Protect>\n );\n};\n"],"names":["RelativeTime","timezoneList","BaseRelativeTime","response","totalEntries","ReactRouterLink"],"mappings":"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"}
@@ -0,0 +1,178 @@
1
+ import { jsx, jsxs, Fragment } from "react/jsx-runtime";
2
+ import { Page, useAPIErrorHandler, useNotification, useRBAC, Layouts, Form, useField, isFetchError } from "@strapi/admin/strapi-admin";
3
+ import { Button, Flex, Typography, Grid, Field, Combobox, ComboboxOption } from "@strapi/design-system";
4
+ import { Check } from "@strapi/icons";
5
+ import { useIntl } from "react-intl";
6
+ import { S as SETTINGS_SCHEMA } from "./validation-schemas-C7P2rhPu.mjs";
7
+ import { useSelector } from "react-redux";
8
+ import { k as useGetReleaseSettingsQuery, l as useUpdateReleaseSettingsMutation, g as getTimezones } from "./index-CJpYVXMt.mjs";
9
+ const useTypedSelector = useSelector;
10
+ const ReleasesSettingsPage = () => {
11
+ const { formatMessage } = useIntl();
12
+ const { formatAPIError } = useAPIErrorHandler();
13
+ const { toggleNotification } = useNotification();
14
+ const { data, isLoading: isLoadingSettings } = useGetReleaseSettingsQuery();
15
+ const [updateReleaseSettings, { isLoading: isSubmittingForm }] = useUpdateReleaseSettingsMutation();
16
+ const permissions = useTypedSelector(
17
+ (state) => state.admin_app.permissions["settings"]?.["releases"]
18
+ );
19
+ const {
20
+ allowedActions: { canUpdate }
21
+ } = useRBAC(permissions);
22
+ const { timezoneList } = getTimezones(/* @__PURE__ */ new Date());
23
+ const handleSubmit = async (body) => {
24
+ const { defaultTimezone } = body;
25
+ const isBodyTimezoneValid = timezoneList.some((timezone) => timezone.value === defaultTimezone);
26
+ const newBody = !defaultTimezone || !isBodyTimezoneValid ? { defaultTimezone: null } : { ...body };
27
+ try {
28
+ const response = await updateReleaseSettings(newBody);
29
+ if ("data" in response) {
30
+ toggleNotification({
31
+ type: "success",
32
+ message: formatMessage({
33
+ id: "content-releases.pages.Settings.releases.setting.default-timezone-notification-success",
34
+ defaultMessage: "Default timezone updated."
35
+ })
36
+ });
37
+ } else if (isFetchError(response.error)) {
38
+ toggleNotification({
39
+ type: "danger",
40
+ message: formatAPIError(response.error)
41
+ });
42
+ } else {
43
+ toggleNotification({
44
+ type: "danger",
45
+ message: formatMessage({ id: "notification.error", defaultMessage: "An error occurred" })
46
+ });
47
+ }
48
+ } catch (error) {
49
+ toggleNotification({
50
+ type: "danger",
51
+ message: formatMessage({ id: "notification.error", defaultMessage: "An error occurred" })
52
+ });
53
+ }
54
+ };
55
+ if (isLoadingSettings) {
56
+ return /* @__PURE__ */ jsx(Page.Loading, {});
57
+ }
58
+ return /* @__PURE__ */ jsxs(Layouts.Root, { children: [
59
+ /* @__PURE__ */ jsx(Page.Title, { children: formatMessage(
60
+ { id: "Settings.PageTitle", defaultMessage: "Settings - {name}" },
61
+ {
62
+ name: "Releases"
63
+ }
64
+ ) }),
65
+ /* @__PURE__ */ jsx(Page.Main, { "aria-busy": isLoadingSettings, tabIndex: -1, children: /* @__PURE__ */ jsx(
66
+ Form,
67
+ {
68
+ method: "PUT",
69
+ initialValues: {
70
+ defaultTimezone: data?.data.defaultTimezone
71
+ },
72
+ onSubmit: handleSubmit,
73
+ validationSchema: SETTINGS_SCHEMA,
74
+ children: ({ modified, isSubmitting }) => {
75
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
76
+ /* @__PURE__ */ jsx(
77
+ Layouts.Header,
78
+ {
79
+ primaryAction: canUpdate ? /* @__PURE__ */ jsx(
80
+ Button,
81
+ {
82
+ disabled: !modified || isSubmittingForm,
83
+ loading: isSubmitting,
84
+ startIcon: /* @__PURE__ */ jsx(Check, {}),
85
+ type: "submit",
86
+ children: formatMessage({
87
+ id: "global.save",
88
+ defaultMessage: "Save"
89
+ })
90
+ }
91
+ ) : null,
92
+ title: formatMessage({
93
+ id: "content-releases.pages.Settings.releases.title",
94
+ defaultMessage: "Releases"
95
+ }),
96
+ subtitle: formatMessage({
97
+ id: "content-releases.pages.Settings.releases.description",
98
+ defaultMessage: "Create and manage content updates"
99
+ })
100
+ }
101
+ ),
102
+ /* @__PURE__ */ jsx(Layouts.Content, { children: /* @__PURE__ */ jsxs(
103
+ Flex,
104
+ {
105
+ direction: "column",
106
+ background: "neutral0",
107
+ alignItems: "stretch",
108
+ padding: 6,
109
+ gap: 6,
110
+ shadow: "filterShadow",
111
+ hasRadius: true,
112
+ children: [
113
+ /* @__PURE__ */ jsx(Typography, { variant: "delta", tag: "h2", children: formatMessage({
114
+ id: "content-releases.pages.Settings.releases.preferences.title",
115
+ defaultMessage: "Preferences"
116
+ }) }),
117
+ /* @__PURE__ */ jsx(Grid.Root, { children: /* @__PURE__ */ jsx(Grid.Item, { col: 6, s: 12, children: /* @__PURE__ */ jsx(TimezoneDropdown, {}) }) })
118
+ ]
119
+ }
120
+ ) })
121
+ ] });
122
+ }
123
+ }
124
+ ) })
125
+ ] });
126
+ };
127
+ const TimezoneDropdown = () => {
128
+ const permissions = useTypedSelector(
129
+ (state) => state.admin_app.permissions["settings"]?.["releases"]
130
+ );
131
+ const {
132
+ allowedActions: { canUpdate }
133
+ } = useRBAC(permissions);
134
+ const { formatMessage } = useIntl();
135
+ const { timezoneList } = getTimezones(/* @__PURE__ */ new Date());
136
+ const field = useField("defaultTimezone");
137
+ return /* @__PURE__ */ jsxs(
138
+ Field.Root,
139
+ {
140
+ name: "defaultTimezone",
141
+ hint: formatMessage({
142
+ id: "content-releases.pages.Settings.releases.timezone.hint",
143
+ defaultMessage: "The timezone of every release can still be changed individually. "
144
+ }),
145
+ error: field.error,
146
+ children: [
147
+ /* @__PURE__ */ jsx(Field.Label, { children: formatMessage({
148
+ id: "content-releases.pages.Settings.releases.timezone.label",
149
+ defaultMessage: "Default timezone"
150
+ }) }),
151
+ /* @__PURE__ */ jsx(
152
+ Combobox,
153
+ {
154
+ autocomplete: { type: "list", filter: "contains" },
155
+ onChange: (value) => field.onChange("defaultTimezone", value),
156
+ onTextValueChange: (value) => field.onChange("defaultTimezone", value),
157
+ onClear: () => field.onChange("defaultTimezone", ""),
158
+ value: field.value,
159
+ disabled: !canUpdate,
160
+ children: timezoneList.map((timezone) => /* @__PURE__ */ jsx(ComboboxOption, { value: timezone.value, children: timezone.value.replace(/&/, " ") }, timezone.value))
161
+ }
162
+ ),
163
+ /* @__PURE__ */ jsx(Field.Hint, {}),
164
+ /* @__PURE__ */ jsx(Field.Error, {})
165
+ ]
166
+ }
167
+ );
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
+ };
175
+ export {
176
+ ProtectedReleasesSettingsPage
177
+ };
178
+ //# sourceMappingURL=ReleasesSettingsPage-C2L6_E3J.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ReleasesSettingsPage-C2L6_E3J.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 { SETTINGS_SCHEMA } from '../../../shared/validation-schemas';\nimport { useTypedSelector } from '../modules/hooks';\nimport { useGetReleaseSettingsQuery, useUpdateReleaseSettingsMutation } from '../services/release';\nimport { getTimezones } from '../utils/time';\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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"}
@@ -0,0 +1,178 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
+ const jsxRuntime = require("react/jsx-runtime");
4
+ const strapiAdmin = require("@strapi/admin/strapi-admin");
5
+ const designSystem = require("@strapi/design-system");
6
+ const icons = require("@strapi/icons");
7
+ const reactIntl = require("react-intl");
8
+ const validationSchemas = require("./validation-schemas-bib1fBc7.js");
9
+ const reactRedux = require("react-redux");
10
+ const index = require("./index-DYXEZrUA.js");
11
+ const useTypedSelector = reactRedux.useSelector;
12
+ const ReleasesSettingsPage = () => {
13
+ const { formatMessage } = reactIntl.useIntl();
14
+ const { formatAPIError } = strapiAdmin.useAPIErrorHandler();
15
+ const { toggleNotification } = strapiAdmin.useNotification();
16
+ const { data, isLoading: isLoadingSettings } = index.useGetReleaseSettingsQuery();
17
+ const [updateReleaseSettings, { isLoading: isSubmittingForm }] = index.useUpdateReleaseSettingsMutation();
18
+ const permissions = useTypedSelector(
19
+ (state) => state.admin_app.permissions["settings"]?.["releases"]
20
+ );
21
+ const {
22
+ allowedActions: { canUpdate }
23
+ } = strapiAdmin.useRBAC(permissions);
24
+ const { timezoneList } = index.getTimezones(/* @__PURE__ */ new Date());
25
+ const handleSubmit = async (body) => {
26
+ const { defaultTimezone } = body;
27
+ const isBodyTimezoneValid = timezoneList.some((timezone) => timezone.value === defaultTimezone);
28
+ const newBody = !defaultTimezone || !isBodyTimezoneValid ? { defaultTimezone: null } : { ...body };
29
+ try {
30
+ const response = await updateReleaseSettings(newBody);
31
+ if ("data" in response) {
32
+ toggleNotification({
33
+ type: "success",
34
+ message: formatMessage({
35
+ id: "content-releases.pages.Settings.releases.setting.default-timezone-notification-success",
36
+ defaultMessage: "Default timezone updated."
37
+ })
38
+ });
39
+ } else if (strapiAdmin.isFetchError(response.error)) {
40
+ toggleNotification({
41
+ type: "danger",
42
+ message: formatAPIError(response.error)
43
+ });
44
+ } else {
45
+ toggleNotification({
46
+ type: "danger",
47
+ message: formatMessage({ id: "notification.error", defaultMessage: "An error occurred" })
48
+ });
49
+ }
50
+ } catch (error) {
51
+ toggleNotification({
52
+ type: "danger",
53
+ message: formatMessage({ id: "notification.error", defaultMessage: "An error occurred" })
54
+ });
55
+ }
56
+ };
57
+ if (isLoadingSettings) {
58
+ return /* @__PURE__ */ jsxRuntime.jsx(strapiAdmin.Page.Loading, {});
59
+ }
60
+ return /* @__PURE__ */ jsxRuntime.jsxs(strapiAdmin.Layouts.Root, { children: [
61
+ /* @__PURE__ */ jsxRuntime.jsx(strapiAdmin.Page.Title, { children: formatMessage(
62
+ { id: "Settings.PageTitle", defaultMessage: "Settings - {name}" },
63
+ {
64
+ name: "Releases"
65
+ }
66
+ ) }),
67
+ /* @__PURE__ */ jsxRuntime.jsx(strapiAdmin.Page.Main, { "aria-busy": isLoadingSettings, tabIndex: -1, children: /* @__PURE__ */ jsxRuntime.jsx(
68
+ strapiAdmin.Form,
69
+ {
70
+ method: "PUT",
71
+ initialValues: {
72
+ defaultTimezone: data?.data.defaultTimezone
73
+ },
74
+ onSubmit: handleSubmit,
75
+ validationSchema: validationSchemas.SETTINGS_SCHEMA,
76
+ children: ({ modified, isSubmitting }) => {
77
+ return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
78
+ /* @__PURE__ */ jsxRuntime.jsx(
79
+ strapiAdmin.Layouts.Header,
80
+ {
81
+ primaryAction: canUpdate ? /* @__PURE__ */ jsxRuntime.jsx(
82
+ designSystem.Button,
83
+ {
84
+ disabled: !modified || isSubmittingForm,
85
+ loading: isSubmitting,
86
+ startIcon: /* @__PURE__ */ jsxRuntime.jsx(icons.Check, {}),
87
+ type: "submit",
88
+ children: formatMessage({
89
+ id: "global.save",
90
+ defaultMessage: "Save"
91
+ })
92
+ }
93
+ ) : null,
94
+ title: formatMessage({
95
+ id: "content-releases.pages.Settings.releases.title",
96
+ defaultMessage: "Releases"
97
+ }),
98
+ subtitle: formatMessage({
99
+ id: "content-releases.pages.Settings.releases.description",
100
+ defaultMessage: "Create and manage content updates"
101
+ })
102
+ }
103
+ ),
104
+ /* @__PURE__ */ jsxRuntime.jsx(strapiAdmin.Layouts.Content, { children: /* @__PURE__ */ jsxRuntime.jsxs(
105
+ designSystem.Flex,
106
+ {
107
+ direction: "column",
108
+ background: "neutral0",
109
+ alignItems: "stretch",
110
+ padding: 6,
111
+ gap: 6,
112
+ shadow: "filterShadow",
113
+ hasRadius: true,
114
+ children: [
115
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "delta", tag: "h2", children: formatMessage({
116
+ id: "content-releases.pages.Settings.releases.preferences.title",
117
+ defaultMessage: "Preferences"
118
+ }) }),
119
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Grid.Root, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Grid.Item, { col: 6, s: 12, children: /* @__PURE__ */ jsxRuntime.jsx(TimezoneDropdown, {}) }) })
120
+ ]
121
+ }
122
+ ) })
123
+ ] });
124
+ }
125
+ }
126
+ ) })
127
+ ] });
128
+ };
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);
136
+ const { formatMessage } = reactIntl.useIntl();
137
+ const { timezoneList } = index.getTimezones(/* @__PURE__ */ new Date());
138
+ const field = strapiAdmin.useField("defaultTimezone");
139
+ return /* @__PURE__ */ jsxRuntime.jsxs(
140
+ designSystem.Field.Root,
141
+ {
142
+ name: "defaultTimezone",
143
+ hint: formatMessage({
144
+ id: "content-releases.pages.Settings.releases.timezone.hint",
145
+ defaultMessage: "The timezone of every release can still be changed individually. "
146
+ }),
147
+ error: field.error,
148
+ children: [
149
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Field.Label, { children: formatMessage({
150
+ id: "content-releases.pages.Settings.releases.timezone.label",
151
+ defaultMessage: "Default timezone"
152
+ }) }),
153
+ /* @__PURE__ */ jsxRuntime.jsx(
154
+ designSystem.Combobox,
155
+ {
156
+ autocomplete: { type: "list", filter: "contains" },
157
+ onChange: (value) => field.onChange("defaultTimezone", value),
158
+ onTextValueChange: (value) => field.onChange("defaultTimezone", value),
159
+ onClear: () => field.onChange("defaultTimezone", ""),
160
+ value: field.value,
161
+ disabled: !canUpdate,
162
+ children: timezoneList.map((timezone) => /* @__PURE__ */ jsxRuntime.jsx(designSystem.ComboboxOption, { value: timezone.value, children: timezone.value.replace(/&/, " ") }, timezone.value))
163
+ }
164
+ ),
165
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Field.Hint, {}),
166
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Field.Error, {})
167
+ ]
168
+ }
169
+ );
170
+ };
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-hHmY2fiE.js.map