@strapi/content-releases 5.0.0-alpha.5 → 5.0.0-alpha.8

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 (43) hide show
  1. package/dist/_chunks/{App-FuRaphre.js → App-1LckaIGY.js} +14 -7
  2. package/dist/_chunks/App-1LckaIGY.js.map +1 -0
  3. package/dist/_chunks/{App-IkyOz9wq.mjs → App-X01LBg5V.mjs} +14 -7
  4. package/dist/_chunks/App-X01LBg5V.mjs.map +1 -0
  5. package/dist/_chunks/{index-qP3rNiDS.mjs → index-OD9AlD-6.mjs} +6 -5
  6. package/dist/_chunks/index-OD9AlD-6.mjs.map +1 -0
  7. package/dist/_chunks/{index-Sb3Nal8H.js → index-cYWov2wa.js} +6 -5
  8. package/dist/_chunks/index-cYWov2wa.js.map +1 -0
  9. package/dist/admin/index.js +1 -1
  10. package/dist/admin/index.mjs +1 -1
  11. package/dist/admin/src/services/release.d.ts +12 -12
  12. package/dist/server/index.js +8 -20
  13. package/dist/server/index.js.map +1 -1
  14. package/dist/server/index.mjs +9 -21
  15. package/dist/server/index.mjs.map +1 -1
  16. package/dist/server/src/bootstrap.d.ts +2 -2
  17. package/dist/server/src/bootstrap.d.ts.map +1 -1
  18. package/dist/server/src/controllers/validation/release-action.d.ts +7 -2
  19. package/dist/server/src/controllers/validation/release-action.d.ts.map +1 -1
  20. package/dist/server/src/destroy.d.ts +2 -2
  21. package/dist/server/src/destroy.d.ts.map +1 -1
  22. package/dist/server/src/index.d.ts +1411 -1411
  23. package/dist/server/src/migrations/index.d.ts.map +1 -1
  24. package/dist/server/src/register.d.ts +2 -2
  25. package/dist/server/src/register.d.ts.map +1 -1
  26. package/dist/server/src/services/index.d.ts +1407 -1407
  27. package/dist/server/src/services/release.d.ts +7 -7
  28. package/dist/server/src/services/release.d.ts.map +1 -1
  29. package/dist/server/src/services/scheduling.d.ts +6 -6
  30. package/dist/server/src/services/scheduling.d.ts.map +1 -1
  31. package/dist/server/src/services/validation.d.ts +2 -2
  32. package/dist/server/src/services/validation.d.ts.map +1 -1
  33. package/dist/server/src/utils/index.d.ts +8 -8
  34. package/dist/server/src/utils/index.d.ts.map +1 -1
  35. package/dist/shared/contracts/release-actions.d.ts +9 -9
  36. package/dist/shared/contracts/release-actions.d.ts.map +1 -1
  37. package/dist/shared/types.d.ts +2 -2
  38. package/dist/shared/types.d.ts.map +1 -1
  39. package/package.json +8 -8
  40. package/dist/_chunks/App-FuRaphre.js.map +0 -1
  41. package/dist/_chunks/App-IkyOz9wq.mjs.map +0 -1
  42. package/dist/_chunks/index-Sb3Nal8H.js.map +0 -1
  43. package/dist/_chunks/index-qP3rNiDS.mjs.map +0 -1
@@ -3,7 +3,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
3
  const jsxRuntime = require("react/jsx-runtime");
4
4
  const strapiAdmin = require("@strapi/admin/strapi-admin");
5
5
  const reactRouterDom = require("react-router-dom");
6
- const index = require("./index-Sb3Nal8H.js");
6
+ const index = require("./index-cYWov2wa.js");
7
7
  const React = require("react");
8
8
  const designSystem = require("@strapi/design-system");
9
9
  const v2 = require("@strapi/design-system/v2");
@@ -754,7 +754,12 @@ const ReleaseDetailsLayout = ({
754
754
  }
755
755
  };
756
756
  const handleRefresh = () => {
757
- dispatch(index.releaseApi.util.invalidateTags([{ type: "ReleaseAction", id: "LIST" }]));
757
+ dispatch(
758
+ index.releaseApi.util.invalidateTags([
759
+ { type: "ReleaseAction", id: "LIST" },
760
+ { type: "Release", id: releaseId }
761
+ ])
762
+ );
758
763
  };
759
764
  const getCreatedByUser = () => {
760
765
  if (!release?.createdBy) {
@@ -1062,6 +1067,10 @@ const ReleaseDetailsBody = ({ releaseId }) => {
1062
1067
  }
1063
1068
  ) });
1064
1069
  }
1070
+ const groupByLabel = formatMessage({
1071
+ id: "content-releases.pages.ReleaseDetails.groupBy.aria-label",
1072
+ defaultMessage: "Group by"
1073
+ });
1065
1074
  const headers = [
1066
1075
  {
1067
1076
  label: formatMessage({
@@ -1105,10 +1114,8 @@ const ReleaseDetailsBody = ({ releaseId }) => {
1105
1114
  /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { children: /* @__PURE__ */ jsxRuntime.jsx(
1106
1115
  designSystem.SingleSelect,
1107
1116
  {
1108
- "aria-label": formatMessage({
1109
- id: "content-releases.pages.ReleaseDetails.groupBy.aria-label",
1110
- defaultMessage: "Group by"
1111
- }),
1117
+ placeholder: groupByLabel,
1118
+ "aria-label": groupByLabel,
1112
1119
  customizeContent: (value) => formatMessage(
1113
1120
  {
1114
1121
  id: `content-releases.pages.ReleaseDetails.groupBy.label`,
@@ -1342,4 +1349,4 @@ const App = () => {
1342
1349
  ] }) });
1343
1350
  };
1344
1351
  exports.App = App;
1345
- //# sourceMappingURL=App-FuRaphre.js.map
1352
+ //# sourceMappingURL=App-1LckaIGY.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"App-1LckaIGY.js","sources":["../../admin/src/components/RelativeTime.tsx","../../shared/validation-schemas.ts","../../admin/src/components/ReleaseModal.tsx","../../admin/src/store/hooks.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 yup from 'yup';\n\nexport const RELEASE_SCHEMA = yup\n .object()\n .shape({\n name: yup.string().trim().required(),\n scheduledAt: yup.string().nullable(),\n isScheduled: yup.boolean().optional(),\n time: yup.string().when('isScheduled', {\n is: true,\n then: yup.string().trim().required(),\n otherwise: yup.string().nullable(),\n }),\n timezone: yup.string().when('isScheduled', {\n is: true,\n then: yup.string().required().nullable(),\n otherwise: yup.string().nullable(),\n }),\n date: yup.string().when('isScheduled', {\n is: true,\n then: yup.string().required().nullable(),\n otherwise: yup.string().nullable(),\n }),\n })\n .required()\n .noUnknown();\n","import * as React from 'react';\n\nimport {\n Button,\n ModalBody,\n ModalFooter,\n ModalLayout,\n ModalHeader,\n TextInput,\n Typography,\n Checkbox,\n Flex,\n Box,\n DatePicker,\n TimePicker,\n Combobox,\n ComboboxOption,\n} from '@strapi/design-system';\nimport { formatISO, parse } 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 { getTimezoneOffset } from '../utils/time';\n\nexport interface FormValues {\n name: string;\n date: Date | null;\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}\n\nexport const ReleaseModal = ({\n handleClose,\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 formattedDate = parse(time, 'HH:mm', new Date(date));\n const timezoneWithoutOffset = timezone.split('&')[1];\n return zonedTimeToUtc(formattedDate, 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 <ModalLayout onClose={handleClose} labelledBy=\"title\">\n <ModalHeader>\n <Typography id=\"title\" fontWeight=\"bold\" textColor=\"neutral800\">\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 </Typography>\n </ModalHeader>\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 <Form>\n <ModalBody>\n <Flex direction=\"column\" alignItems=\"stretch\" gap={6}>\n <TextInput\n label={formatMessage({\n id: 'content-releases.modal.form.input.label.release-name',\n defaultMessage: 'Name',\n })}\n name=\"name\"\n value={values.name}\n error={errors.name}\n onChange={handleChange}\n required\n />\n <Box width=\"max-content\">\n <Checkbox\n name=\"isScheduled\"\n value={values.isScheduled}\n onChange={(event) => {\n setFieldValue('isScheduled', event.target.checked);\n if (!event.target.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('timezone', initialValues.timezone ?? systemTimezone?.value);\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 <DatePicker\n label={formatMessage({\n id: 'content-releases.modal.form.input.label.date',\n defaultMessage: 'Date',\n })}\n name=\"date\"\n error={errors.date}\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 selectedDate={values.date || undefined}\n required\n minDate={utcToZonedTime(new Date(), values.timezone.split('&')[1])}\n />\n </Box>\n <Box width=\"100%\">\n <TimePicker\n label={formatMessage({\n id: 'content-releases.modal.form.input.label.time',\n defaultMessage: 'Time',\n })}\n name=\"time\"\n error={errors.time}\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 required\n />\n </Box>\n </Flex>\n <TimezoneComponent timezoneOptions={timezoneList} />\n </>\n )}\n </Flex>\n </ModalBody>\n <ModalFooter\n startActions={\n <Button onClick={handleClose} variant=\"tertiary\" name=\"cancel\">\n {formatMessage({ id: 'cancel', defaultMessage: 'Cancel' })}\n </Button>\n }\n endActions={\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 }\n />\n </Form>\n )}\n </Formik>\n </ModalLayout>\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 getTimezones = (selectedDate: Date) => {\n const timezoneList: ITimezoneOption[] = Intl.supportedValuesOf('timeZone').map((timezone) => {\n // Timezone will be in the format GMT${OFFSET} where offset could be nothing,\n // a four digit string e.g. +05:00 or -08:00\n const utcOffset = getTimezoneOffset(timezone, selectedDate);\n\n // Offset and timezone are concatenated with '&', so to split and save the required timezone in DB\n return { offset: utcOffset, value: `${utcOffset}&${timezone}` } satisfies ITimezoneOption;\n });\n\n const systemTimezone = timezoneList.find(\n (timezone) => timezone.value.split('&')[1] === Intl.DateTimeFormat().resolvedOptions().timeZone\n );\n\n return { timezoneList, systemTimezone };\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 <Combobox\n label={formatMessage({\n id: 'content-releases.modal.form.input.label.timezone',\n defaultMessage: 'Timezone',\n })}\n autocomplete={{ type: 'list', filter: 'contains' }}\n name=\"timezone\"\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 error={errors.timezone}\n required\n >\n {timezoneList.map((timezone) => (\n <ComboboxOption key={timezone.value} value={timezone.value}>\n {timezone.value.replace(/&/, ' ')}\n </ComboboxOption>\n ))}\n </Combobox>\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 * as React from 'react';\n\n// TODO: Replace this import with the same hook exported from the @strapi/admin/strapi-admin/ee in another iteration of this solution\nimport {\n Page,\n Pagination,\n useLicenseLimits,\n useTracking,\n useAPIErrorHandler,\n useNotification,\n useQueryParams,\n useRBAC,\n} from '@strapi/admin/strapi-admin';\nimport {\n Alert,\n Badge,\n Box,\n Button,\n ContentLayout,\n Divider,\n EmptyStateLayout,\n Flex,\n Grid,\n GridItem,\n HeaderLayout,\n Main,\n Tab,\n TabGroup,\n TabPanel,\n TabPanels,\n Tabs,\n Typography,\n} from '@strapi/design-system';\nimport { Link } from '@strapi/design-system/v2';\nimport { EmptyDocuments, Plus } from '@strapi/icons';\nimport { useIntl } from 'react-intl';\nimport { useNavigate, useLocation } from 'react-router-dom';\nimport styled from 'styled-components';\n\nimport { GetReleases, type Release } from '../../../shared/contracts/releases';\nimport { RelativeTime } from '../components/RelativeTime';\nimport { ReleaseModal, FormValues } from '../components/ReleaseModal';\nimport { PERMISSIONS } from '../constants';\nimport { isAxiosError } from '../services/axios';\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 CapitalizeRelativeTime = styled(RelativeTime)`\n text-transform: capitalize;\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=\"10rem\" />}\n />\n );\n }\n\n return (\n <Grid gap={4}>\n {releases.map(({ id, name, scheduledAt, status }) => (\n <GridItem col={3} s={6} xs={12} key={id}>\n <LinkCard href={`content-releases/${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 as=\"h3\" variant=\"delta\" fontWeight=\"bold\">\n {name}\n </Typography>\n <Typography variant=\"pi\" textColor=\"neutral600\">\n {scheduledAt ? (\n <CapitalizeRelativeTime 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 </GridItem>\n ))}\n </Grid>\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: null,\n time: '',\n isScheduled: true,\n scheduledAt: null,\n timezone: null,\n} satisfies FormValues;\n\nconst ReleasesPage = () => {\n const tabRef = React.useRef<any>(null);\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 const activeTabIndex = ['pending', 'done'].indexOf(activeTab);\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 // TODO: Replace this solution with v2 of the Design System\n // Check if the active tab index changes and call the handler of the ref to update the tab group component\n React.useEffect(() => {\n if (tabRef.current) {\n tabRef.current._handlers.setSelectedTabIndex(activeTabIndex);\n }\n }, [activeTabIndex]);\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 = (index: number) => {\n setQuery({\n ...query,\n page: 1,\n pageSize: response?.currentData?.meta?.pagination?.pageSize || 16,\n filters: {\n releasedAt: {\n $notNull: index === 0 ? false : true,\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\n navigate(response.data.data.id.toString());\n } else if (isAxiosError(response.error)) {\n // When the response returns an object with 'error', handle axios 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 <HeaderLayout\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 <ContentLayout>\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 <TabGroup\n label={formatMessage({\n id: 'content-releases.pages.Releases.tab-group.label',\n defaultMessage: 'Releases list',\n })}\n variant=\"simple\"\n initialSelectedTabIndex={activeTabIndex}\n onTabChange={handleTabChange}\n ref={tabRef}\n >\n <Box paddingBottom={8}>\n <Tabs>\n <Tab>\n {formatMessage(\n {\n id: 'content-releases.pages.Releases.tab.pending',\n defaultMessage: 'Pending ({count})',\n },\n {\n count: totalPendingReleases,\n }\n )}\n </Tab>\n <Tab>\n {formatMessage({\n id: 'content-releases.pages.Releases.tab.done',\n defaultMessage: 'Done',\n })}\n </Tab>\n </Tabs>\n <Divider />\n </Box>\n <TabPanels>\n {/* Pending releases */}\n <TabPanel>\n <ReleasesGrid\n sectionTitle=\"pending\"\n releases={response?.currentData?.data}\n isError={isError}\n />\n </TabPanel>\n {/* Done releases */}\n <TabPanel>\n <ReleasesGrid\n sectionTitle=\"done\"\n releases={response?.currentData?.data}\n isError={isError}\n />\n </TabPanel>\n </TabPanels>\n </TabGroup>\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 </ContentLayout>\n {releaseModalShown && (\n <ReleaseModal\n handleClose={toggleAddReleaseModal}\n handleSubmit={handleAddRelease}\n isLoading={isSubmittingForm}\n initialValues={INITIAL_FORM_VALUES}\n />\n )}\n </Main>\n );\n};\n\nexport { ReleasesPage, getBadgeProps };\n","import * as React from 'react';\n\nimport {\n Page,\n unstable_useDocument,\n Pagination,\n Table,\n BackButton,\n ConfirmDialog,\n useTracking,\n useAPIErrorHandler,\n useNotification,\n useQueryParams,\n useRBAC,\n} from '@strapi/admin/strapi-admin';\nimport {\n Button,\n ContentLayout,\n Flex,\n HeaderLayout,\n IconButton,\n Main,\n Tr,\n Td,\n Typography,\n Badge,\n SingleSelect,\n SingleSelectOption,\n Icon,\n Tooltip,\n EmptyStateLayout,\n} from '@strapi/design-system';\nimport { LinkButton, Menu } from '@strapi/design-system/v2';\nimport { CheckCircle, More, Pencil, Trash, CrossCircle, EmptyDocuments } from '@strapi/icons';\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 { isAxiosError } from '../services/axios';\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 { 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 { Schema } 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(Menu.Item)<{\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?: Schema.ContentType;\n components: { [key: Schema.Component['uid']]: Schema.Component };\n entry: ReleaseActionEntry;\n}\n\nconst EntryValidationText = ({ action, schema, entry }: EntryValidationTextProps) => {\n const { formatMessage } = useIntl();\n const { validate } = unstable_useDocument(\n {\n collectionType: schema?.kind ?? '',\n model: schema?.uid ?? '',\n },\n {\n skip: !schema,\n }\n );\n\n const errors = validate(entry) ?? {};\n\n if (Object.keys(errors).length > 0) {\n const validationErrorsMessages = Object.entries(errors)\n .map(([key, value]) =>\n formatMessage(\n { id: `${value.id}.withField`, defaultMessage: value.defaultMessage },\n { field: key }\n )\n )\n .join(' ');\n\n return (\n <Flex gap={2}>\n <Icon color=\"danger600\" as={CrossCircle} />\n <Tooltip description={validationErrorsMessages}>\n <TypographyMaxWidth textColor=\"danger600\" variant=\"omega\" fontWeight=\"semiBold\" ellipsis>\n {validationErrorsMessages}\n </TypographyMaxWidth>\n </Tooltip>\n </Flex>\n );\n }\n\n if (action == 'publish') {\n return (\n <Flex gap={2}>\n <Icon color=\"success600\" as={CheckCircle} />\n {entry.publishedAt ? (\n <Typography textColor=\"success600\" fontWeight=\"bold\">\n {formatMessage({\n id: 'content-releases.pages.ReleaseDetails.entry-validation.already-published',\n defaultMessage: 'Already published',\n })}\n </Typography>\n ) : (\n <Typography>\n {formatMessage({\n id: 'content-releases.pages.ReleaseDetails.entry-validation.ready-to-publish',\n defaultMessage: 'Ready to publish',\n })}\n </Typography>\n )}\n </Flex>\n );\n }\n\n return (\n <Flex gap={2}>\n <Icon color=\"success600\" as={CheckCircle} />\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 isError,\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 (isAxiosError(response.error)) {\n // When the response returns an object with 'error', handle axios 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 (isError || !release) {\n return (\n <Navigate\n to=\"..\"\n state={{\n errors: [\n {\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 <HeaderLayout\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 <Menu.Root>\n {/*\n TODO Fix in the DS\n - as={IconButton} has TS error: Property 'icon' does not exist on type 'IntrinsicAttributes & TriggerProps & RefAttributes<HTMLButtonElement>'\n - The Icon doesn't actually show unless you hack it with some padding...and it's still a little strange\n */}\n <Menu.Trigger\n as={IconButton}\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 // @ts-expect-error See above\n icon={<More />}\n variant=\"tertiary\"\n />\n {/*\n TODO: Using Menu instead of SimpleMenu mainly because there is no positioning provided from the DS,\n Refactor this once fixed in the DS\n */}\n <Menu.Content top={1} popoverPlacement=\"bottom-end\">\n <Flex\n alignItems=\"center\"\n justifyContent=\"center\"\n direction=\"column\"\n padding={1}\n width=\"100%\"\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 </Flex>\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 </Menu.Content>\n </Menu.Root>\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 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 isError: isReleaseError,\n error: releaseError,\n } = useGetReleaseQuery({ id: releaseId });\n const {\n allowedActions: { canUpdate },\n } = useRBAC(PERMISSIONS);\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 (isAxiosError(response.error)) {\n // When the response returns an object with 'error', handle axios 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 (isReleaseError || !release) {\n const errorsArray = [];\n if (releaseError) {\n errorsArray.push({\n code: releaseError.code,\n });\n }\n if (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 <ContentLayout>\n <EmptyStateLayout\n action={\n <LinkButton\n as={ReactRouterLink}\n // @ts-expect-error - types are not inferred correctly through the as prop.\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=\"10rem\" />}\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 </ContentLayout>\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 {\n label: formatMessage({\n id: 'content-releases.page.ReleaseDetails.table.header.label.name',\n defaultMessage: 'name',\n }),\n name: 'name',\n },\n {\n label: formatMessage({\n id: 'content-releases.page.ReleaseDetails.table.header.label.locale',\n defaultMessage: 'locale',\n }),\n name: 'locale',\n },\n {\n label: formatMessage({\n id: 'content-releases.page.ReleaseDetails.table.header.label.content-type',\n defaultMessage: 'content-type',\n }),\n name: 'content-type',\n },\n {\n label: formatMessage({\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: formatMessage({\n id: 'content-releases.page.ReleaseDetails.table.header.label.status',\n defaultMessage: 'status',\n }),\n name: 'status',\n },\n ]\n : []),\n ];\n\n return (\n <ContentLayout>\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 {GROUP_BY_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((header) => (\n <Table.HeaderCell key={header.name} {...header} />\n ))}\n </Table.Head>\n <Table.Loading />\n <Table.Body>\n {releaseActions[key].map(\n ({ id, contentType, locale, type, entry }, actionIndex) => (\n <Tr key={id}>\n <Td width=\"25%\" maxWidth=\"200px\">\n <Typography ellipsis>{`${\n contentType.mainFieldValue || entry.id\n }`}</Typography>\n </Td>\n <Td width=\"10%\">\n <Typography>{`${locale?.name ? locale.name : '-'}`}</Typography>\n </Td>\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 />\n </Td>\n <Td>\n <Flex justifyContent=\"flex-end\">\n <ReleaseActionMenu.Root>\n <ReleaseActionMenu.ReleaseActionEntryLinkItem\n contentTypeUid={contentType.uid}\n entryId={entry.id}\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 </ContentLayout>\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 ? new Date(format(scheduledAt, 'yyyy-MM-dd')) : null;\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 } else if (isAxiosError(response.error)) {\n // When the response returns an object with 'error', handle axios 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 toggleEditReleaseModal();\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 (isAxiosError(response.error)) {\n // When the response returns an object with 'error', handle axios 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 {releaseModalShown && (\n <ReleaseModal\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 )}\n <ConfirmDialog\n isOpen={showWarningSubmit}\n onClose={toggleWarningSubmit}\n onConfirm={handleDeleteRelease}\n >\n {formatMessage({\n id: 'content-releases.dialog.confirmation-message',\n defaultMessage: 'Are you sure you want to delete this release?',\n })}\n </ConfirmDialog>\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":["React","useIntl","intervalToDuration","isPast","jsx","yup","useLocation","pluginId","parse","zonedTimeToUtc","jsxs","ModalLayout","ModalHeader","Typography","Formik","Form","ModalBody","Flex","TextInput","Box","Checkbox","Fragment","DatePicker","formatISO","utcToZonedTime","TimePicker","ModalFooter","Button","getTimezoneOffset","useFormikContext","timezoneList","Combobox","ComboboxOption","useDispatch","styled","Link","Page","EmptyStateLayout","EmptyDocuments","Grid","GridItem","Badge","Alert","useNotification","useNavigate","useAPIErrorHandler","useQueryParams","useGetReleasesQuery","useCreateReleaseMutation","useLicenseLimits","useTracking","useRBAC","PERMISSIONS","index","response","isAxiosError","Main","HeaderLayout","Plus","ContentLayout","TabGroup","Tabs","Tab","Divider","TabPanels","TabPanel","Pagination","Menu","Pencil","Trash","unstable_useDocument","Icon","CrossCircle","Tooltip","CheckCircle","useParams","useGetReleaseQuery","usePublishReleaseMutation","totalEntries","releaseApi","Navigate","BackButton","IconButton","More","useGetReleaseActionsQuery","useUpdateReleaseActionMutation","LinkButton","ReactRouterLink","SingleSelect","SingleSelectOption","Table","Tr","Td","ReleaseActionOptions","ReleaseActionMenu","useUpdateReleaseMutation","useDeleteReleaseMutation","format","ConfirmDialog","Routes","Route"],"mappings":"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"}
@@ -1,7 +1,7 @@
1
1
  import { jsx, jsxs, Fragment } from "react/jsx-runtime";
2
2
  import { useNotification, useAPIErrorHandler, useQueryParams, useLicenseLimits, useTracking, useRBAC, Page, Pagination, ConfirmDialog, BackButton, Table, unstable_useDocument } from "@strapi/admin/strapi-admin";
3
3
  import { useLocation, useNavigate, useParams, Navigate, Link as Link$1, Routes, Route } from "react-router-dom";
4
- import { g as getTimezoneOffset, p as pluginId, u as useGetReleasesQuery, a as useCreateReleaseMutation, P as PERMISSIONS, i as isAxiosError, b as useGetReleaseQuery, c as useUpdateReleaseMutation, d as useDeleteReleaseMutation, e as usePublishReleaseMutation, f as useGetReleaseActionsQuery, h as useUpdateReleaseActionMutation, R as ReleaseActionOptions, j as ReleaseActionMenu, r as releaseApi } from "./index-qP3rNiDS.mjs";
4
+ import { g as getTimezoneOffset, p as pluginId, u as useGetReleasesQuery, a as useCreateReleaseMutation, P as PERMISSIONS, i as isAxiosError, b as useGetReleaseQuery, c as useUpdateReleaseMutation, d as useDeleteReleaseMutation, e as usePublishReleaseMutation, f as useGetReleaseActionsQuery, h as useUpdateReleaseActionMutation, R as ReleaseActionOptions, j as ReleaseActionMenu, r as releaseApi } from "./index-OD9AlD-6.mjs";
5
5
  import * as React from "react";
6
6
  import { ModalLayout, ModalHeader, Typography, ModalBody, Flex, TextInput, Box, Checkbox, DatePicker, TimePicker, ModalFooter, Button, Combobox, ComboboxOption, Alert, Main, HeaderLayout, ContentLayout, TabGroup, Tabs, Tab, Divider, TabPanels, TabPanel, EmptyStateLayout, Grid, GridItem, Badge, IconButton, SingleSelect, SingleSelectOption, Tr, Td, Icon, Tooltip } from "@strapi/design-system";
7
7
  import { Link, Menu, LinkButton } from "@strapi/design-system/v2";
@@ -729,7 +729,12 @@ const ReleaseDetailsLayout = ({
729
729
  }
730
730
  };
731
731
  const handleRefresh = () => {
732
- dispatch(releaseApi.util.invalidateTags([{ type: "ReleaseAction", id: "LIST" }]));
732
+ dispatch(
733
+ releaseApi.util.invalidateTags([
734
+ { type: "ReleaseAction", id: "LIST" },
735
+ { type: "Release", id: releaseId }
736
+ ])
737
+ );
733
738
  };
734
739
  const getCreatedByUser = () => {
735
740
  if (!release?.createdBy) {
@@ -1037,6 +1042,10 @@ const ReleaseDetailsBody = ({ releaseId }) => {
1037
1042
  }
1038
1043
  ) });
1039
1044
  }
1045
+ const groupByLabel = formatMessage({
1046
+ id: "content-releases.pages.ReleaseDetails.groupBy.aria-label",
1047
+ defaultMessage: "Group by"
1048
+ });
1040
1049
  const headers = [
1041
1050
  {
1042
1051
  label: formatMessage({
@@ -1080,10 +1089,8 @@ const ReleaseDetailsBody = ({ releaseId }) => {
1080
1089
  /* @__PURE__ */ jsx(Flex, { children: /* @__PURE__ */ jsx(
1081
1090
  SingleSelect,
1082
1091
  {
1083
- "aria-label": formatMessage({
1084
- id: "content-releases.pages.ReleaseDetails.groupBy.aria-label",
1085
- defaultMessage: "Group by"
1086
- }),
1092
+ placeholder: groupByLabel,
1093
+ "aria-label": groupByLabel,
1087
1094
  customizeContent: (value) => formatMessage(
1088
1095
  {
1089
1096
  id: `content-releases.pages.ReleaseDetails.groupBy.label`,
@@ -1319,4 +1326,4 @@ const App = () => {
1319
1326
  export {
1320
1327
  App
1321
1328
  };
1322
- //# sourceMappingURL=App-IkyOz9wq.mjs.map
1329
+ //# sourceMappingURL=App-X01LBg5V.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"App-X01LBg5V.mjs","sources":["../../admin/src/components/RelativeTime.tsx","../../shared/validation-schemas.ts","../../admin/src/components/ReleaseModal.tsx","../../admin/src/store/hooks.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 yup from 'yup';\n\nexport const RELEASE_SCHEMA = yup\n .object()\n .shape({\n name: yup.string().trim().required(),\n scheduledAt: yup.string().nullable(),\n isScheduled: yup.boolean().optional(),\n time: yup.string().when('isScheduled', {\n is: true,\n then: yup.string().trim().required(),\n otherwise: yup.string().nullable(),\n }),\n timezone: yup.string().when('isScheduled', {\n is: true,\n then: yup.string().required().nullable(),\n otherwise: yup.string().nullable(),\n }),\n date: yup.string().when('isScheduled', {\n is: true,\n then: yup.string().required().nullable(),\n otherwise: yup.string().nullable(),\n }),\n })\n .required()\n .noUnknown();\n","import * as React from 'react';\n\nimport {\n Button,\n ModalBody,\n ModalFooter,\n ModalLayout,\n ModalHeader,\n TextInput,\n Typography,\n Checkbox,\n Flex,\n Box,\n DatePicker,\n TimePicker,\n Combobox,\n ComboboxOption,\n} from '@strapi/design-system';\nimport { formatISO, parse } 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 { getTimezoneOffset } from '../utils/time';\n\nexport interface FormValues {\n name: string;\n date: Date | null;\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}\n\nexport const ReleaseModal = ({\n handleClose,\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 formattedDate = parse(time, 'HH:mm', new Date(date));\n const timezoneWithoutOffset = timezone.split('&')[1];\n return zonedTimeToUtc(formattedDate, 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 <ModalLayout onClose={handleClose} labelledBy=\"title\">\n <ModalHeader>\n <Typography id=\"title\" fontWeight=\"bold\" textColor=\"neutral800\">\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 </Typography>\n </ModalHeader>\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 <Form>\n <ModalBody>\n <Flex direction=\"column\" alignItems=\"stretch\" gap={6}>\n <TextInput\n label={formatMessage({\n id: 'content-releases.modal.form.input.label.release-name',\n defaultMessage: 'Name',\n })}\n name=\"name\"\n value={values.name}\n error={errors.name}\n onChange={handleChange}\n required\n />\n <Box width=\"max-content\">\n <Checkbox\n name=\"isScheduled\"\n value={values.isScheduled}\n onChange={(event) => {\n setFieldValue('isScheduled', event.target.checked);\n if (!event.target.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('timezone', initialValues.timezone ?? systemTimezone?.value);\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 <DatePicker\n label={formatMessage({\n id: 'content-releases.modal.form.input.label.date',\n defaultMessage: 'Date',\n })}\n name=\"date\"\n error={errors.date}\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 selectedDate={values.date || undefined}\n required\n minDate={utcToZonedTime(new Date(), values.timezone.split('&')[1])}\n />\n </Box>\n <Box width=\"100%\">\n <TimePicker\n label={formatMessage({\n id: 'content-releases.modal.form.input.label.time',\n defaultMessage: 'Time',\n })}\n name=\"time\"\n error={errors.time}\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 required\n />\n </Box>\n </Flex>\n <TimezoneComponent timezoneOptions={timezoneList} />\n </>\n )}\n </Flex>\n </ModalBody>\n <ModalFooter\n startActions={\n <Button onClick={handleClose} variant=\"tertiary\" name=\"cancel\">\n {formatMessage({ id: 'cancel', defaultMessage: 'Cancel' })}\n </Button>\n }\n endActions={\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 }\n />\n </Form>\n )}\n </Formik>\n </ModalLayout>\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 getTimezones = (selectedDate: Date) => {\n const timezoneList: ITimezoneOption[] = Intl.supportedValuesOf('timeZone').map((timezone) => {\n // Timezone will be in the format GMT${OFFSET} where offset could be nothing,\n // a four digit string e.g. +05:00 or -08:00\n const utcOffset = getTimezoneOffset(timezone, selectedDate);\n\n // Offset and timezone are concatenated with '&', so to split and save the required timezone in DB\n return { offset: utcOffset, value: `${utcOffset}&${timezone}` } satisfies ITimezoneOption;\n });\n\n const systemTimezone = timezoneList.find(\n (timezone) => timezone.value.split('&')[1] === Intl.DateTimeFormat().resolvedOptions().timeZone\n );\n\n return { timezoneList, systemTimezone };\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 <Combobox\n label={formatMessage({\n id: 'content-releases.modal.form.input.label.timezone',\n defaultMessage: 'Timezone',\n })}\n autocomplete={{ type: 'list', filter: 'contains' }}\n name=\"timezone\"\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 error={errors.timezone}\n required\n >\n {timezoneList.map((timezone) => (\n <ComboboxOption key={timezone.value} value={timezone.value}>\n {timezone.value.replace(/&/, ' ')}\n </ComboboxOption>\n ))}\n </Combobox>\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 * as React from 'react';\n\n// TODO: Replace this import with the same hook exported from the @strapi/admin/strapi-admin/ee in another iteration of this solution\nimport {\n Page,\n Pagination,\n useLicenseLimits,\n useTracking,\n useAPIErrorHandler,\n useNotification,\n useQueryParams,\n useRBAC,\n} from '@strapi/admin/strapi-admin';\nimport {\n Alert,\n Badge,\n Box,\n Button,\n ContentLayout,\n Divider,\n EmptyStateLayout,\n Flex,\n Grid,\n GridItem,\n HeaderLayout,\n Main,\n Tab,\n TabGroup,\n TabPanel,\n TabPanels,\n Tabs,\n Typography,\n} from '@strapi/design-system';\nimport { Link } from '@strapi/design-system/v2';\nimport { EmptyDocuments, Plus } from '@strapi/icons';\nimport { useIntl } from 'react-intl';\nimport { useNavigate, useLocation } from 'react-router-dom';\nimport styled from 'styled-components';\n\nimport { GetReleases, type Release } from '../../../shared/contracts/releases';\nimport { RelativeTime } from '../components/RelativeTime';\nimport { ReleaseModal, FormValues } from '../components/ReleaseModal';\nimport { PERMISSIONS } from '../constants';\nimport { isAxiosError } from '../services/axios';\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 CapitalizeRelativeTime = styled(RelativeTime)`\n text-transform: capitalize;\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=\"10rem\" />}\n />\n );\n }\n\n return (\n <Grid gap={4}>\n {releases.map(({ id, name, scheduledAt, status }) => (\n <GridItem col={3} s={6} xs={12} key={id}>\n <LinkCard href={`content-releases/${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 as=\"h3\" variant=\"delta\" fontWeight=\"bold\">\n {name}\n </Typography>\n <Typography variant=\"pi\" textColor=\"neutral600\">\n {scheduledAt ? (\n <CapitalizeRelativeTime 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 </GridItem>\n ))}\n </Grid>\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: null,\n time: '',\n isScheduled: true,\n scheduledAt: null,\n timezone: null,\n} satisfies FormValues;\n\nconst ReleasesPage = () => {\n const tabRef = React.useRef<any>(null);\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 const activeTabIndex = ['pending', 'done'].indexOf(activeTab);\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 // TODO: Replace this solution with v2 of the Design System\n // Check if the active tab index changes and call the handler of the ref to update the tab group component\n React.useEffect(() => {\n if (tabRef.current) {\n tabRef.current._handlers.setSelectedTabIndex(activeTabIndex);\n }\n }, [activeTabIndex]);\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 = (index: number) => {\n setQuery({\n ...query,\n page: 1,\n pageSize: response?.currentData?.meta?.pagination?.pageSize || 16,\n filters: {\n releasedAt: {\n $notNull: index === 0 ? false : true,\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\n navigate(response.data.data.id.toString());\n } else if (isAxiosError(response.error)) {\n // When the response returns an object with 'error', handle axios 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 <HeaderLayout\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 <ContentLayout>\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 <TabGroup\n label={formatMessage({\n id: 'content-releases.pages.Releases.tab-group.label',\n defaultMessage: 'Releases list',\n })}\n variant=\"simple\"\n initialSelectedTabIndex={activeTabIndex}\n onTabChange={handleTabChange}\n ref={tabRef}\n >\n <Box paddingBottom={8}>\n <Tabs>\n <Tab>\n {formatMessage(\n {\n id: 'content-releases.pages.Releases.tab.pending',\n defaultMessage: 'Pending ({count})',\n },\n {\n count: totalPendingReleases,\n }\n )}\n </Tab>\n <Tab>\n {formatMessage({\n id: 'content-releases.pages.Releases.tab.done',\n defaultMessage: 'Done',\n })}\n </Tab>\n </Tabs>\n <Divider />\n </Box>\n <TabPanels>\n {/* Pending releases */}\n <TabPanel>\n <ReleasesGrid\n sectionTitle=\"pending\"\n releases={response?.currentData?.data}\n isError={isError}\n />\n </TabPanel>\n {/* Done releases */}\n <TabPanel>\n <ReleasesGrid\n sectionTitle=\"done\"\n releases={response?.currentData?.data}\n isError={isError}\n />\n </TabPanel>\n </TabPanels>\n </TabGroup>\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 </ContentLayout>\n {releaseModalShown && (\n <ReleaseModal\n handleClose={toggleAddReleaseModal}\n handleSubmit={handleAddRelease}\n isLoading={isSubmittingForm}\n initialValues={INITIAL_FORM_VALUES}\n />\n )}\n </Main>\n );\n};\n\nexport { ReleasesPage, getBadgeProps };\n","import * as React from 'react';\n\nimport {\n Page,\n unstable_useDocument,\n Pagination,\n Table,\n BackButton,\n ConfirmDialog,\n useTracking,\n useAPIErrorHandler,\n useNotification,\n useQueryParams,\n useRBAC,\n} from '@strapi/admin/strapi-admin';\nimport {\n Button,\n ContentLayout,\n Flex,\n HeaderLayout,\n IconButton,\n Main,\n Tr,\n Td,\n Typography,\n Badge,\n SingleSelect,\n SingleSelectOption,\n Icon,\n Tooltip,\n EmptyStateLayout,\n} from '@strapi/design-system';\nimport { LinkButton, Menu } from '@strapi/design-system/v2';\nimport { CheckCircle, More, Pencil, Trash, CrossCircle, EmptyDocuments } from '@strapi/icons';\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 { isAxiosError } from '../services/axios';\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 { 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 { Schema } 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(Menu.Item)<{\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?: Schema.ContentType;\n components: { [key: Schema.Component['uid']]: Schema.Component };\n entry: ReleaseActionEntry;\n}\n\nconst EntryValidationText = ({ action, schema, entry }: EntryValidationTextProps) => {\n const { formatMessage } = useIntl();\n const { validate } = unstable_useDocument(\n {\n collectionType: schema?.kind ?? '',\n model: schema?.uid ?? '',\n },\n {\n skip: !schema,\n }\n );\n\n const errors = validate(entry) ?? {};\n\n if (Object.keys(errors).length > 0) {\n const validationErrorsMessages = Object.entries(errors)\n .map(([key, value]) =>\n formatMessage(\n { id: `${value.id}.withField`, defaultMessage: value.defaultMessage },\n { field: key }\n )\n )\n .join(' ');\n\n return (\n <Flex gap={2}>\n <Icon color=\"danger600\" as={CrossCircle} />\n <Tooltip description={validationErrorsMessages}>\n <TypographyMaxWidth textColor=\"danger600\" variant=\"omega\" fontWeight=\"semiBold\" ellipsis>\n {validationErrorsMessages}\n </TypographyMaxWidth>\n </Tooltip>\n </Flex>\n );\n }\n\n if (action == 'publish') {\n return (\n <Flex gap={2}>\n <Icon color=\"success600\" as={CheckCircle} />\n {entry.publishedAt ? (\n <Typography textColor=\"success600\" fontWeight=\"bold\">\n {formatMessage({\n id: 'content-releases.pages.ReleaseDetails.entry-validation.already-published',\n defaultMessage: 'Already published',\n })}\n </Typography>\n ) : (\n <Typography>\n {formatMessage({\n id: 'content-releases.pages.ReleaseDetails.entry-validation.ready-to-publish',\n defaultMessage: 'Ready to publish',\n })}\n </Typography>\n )}\n </Flex>\n );\n }\n\n return (\n <Flex gap={2}>\n <Icon color=\"success600\" as={CheckCircle} />\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 isError,\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 (isAxiosError(response.error)) {\n // When the response returns an object with 'error', handle axios 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 (isError || !release) {\n return (\n <Navigate\n to=\"..\"\n state={{\n errors: [\n {\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 <HeaderLayout\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 <Menu.Root>\n {/*\n TODO Fix in the DS\n - as={IconButton} has TS error: Property 'icon' does not exist on type 'IntrinsicAttributes & TriggerProps & RefAttributes<HTMLButtonElement>'\n - The Icon doesn't actually show unless you hack it with some padding...and it's still a little strange\n */}\n <Menu.Trigger\n as={IconButton}\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 // @ts-expect-error See above\n icon={<More />}\n variant=\"tertiary\"\n />\n {/*\n TODO: Using Menu instead of SimpleMenu mainly because there is no positioning provided from the DS,\n Refactor this once fixed in the DS\n */}\n <Menu.Content top={1} popoverPlacement=\"bottom-end\">\n <Flex\n alignItems=\"center\"\n justifyContent=\"center\"\n direction=\"column\"\n padding={1}\n width=\"100%\"\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 </Flex>\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 </Menu.Content>\n </Menu.Root>\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 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 isError: isReleaseError,\n error: releaseError,\n } = useGetReleaseQuery({ id: releaseId });\n const {\n allowedActions: { canUpdate },\n } = useRBAC(PERMISSIONS);\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 (isAxiosError(response.error)) {\n // When the response returns an object with 'error', handle axios 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 (isReleaseError || !release) {\n const errorsArray = [];\n if (releaseError) {\n errorsArray.push({\n code: releaseError.code,\n });\n }\n if (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 <ContentLayout>\n <EmptyStateLayout\n action={\n <LinkButton\n as={ReactRouterLink}\n // @ts-expect-error - types are not inferred correctly through the as prop.\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=\"10rem\" />}\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 </ContentLayout>\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 {\n label: formatMessage({\n id: 'content-releases.page.ReleaseDetails.table.header.label.name',\n defaultMessage: 'name',\n }),\n name: 'name',\n },\n {\n label: formatMessage({\n id: 'content-releases.page.ReleaseDetails.table.header.label.locale',\n defaultMessage: 'locale',\n }),\n name: 'locale',\n },\n {\n label: formatMessage({\n id: 'content-releases.page.ReleaseDetails.table.header.label.content-type',\n defaultMessage: 'content-type',\n }),\n name: 'content-type',\n },\n {\n label: formatMessage({\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: formatMessage({\n id: 'content-releases.page.ReleaseDetails.table.header.label.status',\n defaultMessage: 'status',\n }),\n name: 'status',\n },\n ]\n : []),\n ];\n\n return (\n <ContentLayout>\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 {GROUP_BY_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((header) => (\n <Table.HeaderCell key={header.name} {...header} />\n ))}\n </Table.Head>\n <Table.Loading />\n <Table.Body>\n {releaseActions[key].map(\n ({ id, contentType, locale, type, entry }, actionIndex) => (\n <Tr key={id}>\n <Td width=\"25%\" maxWidth=\"200px\">\n <Typography ellipsis>{`${\n contentType.mainFieldValue || entry.id\n }`}</Typography>\n </Td>\n <Td width=\"10%\">\n <Typography>{`${locale?.name ? locale.name : '-'}`}</Typography>\n </Td>\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 />\n </Td>\n <Td>\n <Flex justifyContent=\"flex-end\">\n <ReleaseActionMenu.Root>\n <ReleaseActionMenu.ReleaseActionEntryLinkItem\n contentTypeUid={contentType.uid}\n entryId={entry.id}\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 </ContentLayout>\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 ? new Date(format(scheduledAt, 'yyyy-MM-dd')) : null;\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 } else if (isAxiosError(response.error)) {\n // When the response returns an object with 'error', handle axios 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 toggleEditReleaseModal();\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 (isAxiosError(response.error)) {\n // When the response returns an object with 'error', handle axios 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 {releaseModalShown && (\n <ReleaseModal\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 )}\n <ConfirmDialog\n isOpen={showWarningSubmit}\n onClose={toggleWarningSubmit}\n onConfirm={handleDeleteRelease}\n >\n {formatMessage({\n id: 'content-releases.dialog.confirmation-message',\n defaultMessage: 'Are you sure you want to delete this release?',\n })}\n </ConfirmDialog>\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":["timezoneList","response","totalEntries","ReactRouterLink"],"mappings":"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"}