@strapi/content-releases 5.52.2 → 5.53.0

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 (56) hide show
  1. package/dist/admin/pages/ReleasesPage.js +0 -1
  2. package/dist/admin/pages/ReleasesPage.js.map +1 -1
  3. package/dist/admin/pages/ReleasesPage.mjs +0 -1
  4. package/dist/admin/pages/ReleasesPage.mjs.map +1 -1
  5. package/dist/server/audit-logs.js +182 -0
  6. package/dist/server/audit-logs.js.map +1 -0
  7. package/dist/server/audit-logs.mjs +175 -0
  8. package/dist/server/audit-logs.mjs.map +1 -0
  9. package/dist/server/bootstrap.js +6 -0
  10. package/dist/server/bootstrap.js.map +1 -1
  11. package/dist/server/bootstrap.mjs +6 -0
  12. package/dist/server/bootstrap.mjs.map +1 -1
  13. package/dist/server/constants.js +20 -0
  14. package/dist/server/constants.js.map +1 -1
  15. package/dist/server/constants.mjs +20 -1
  16. package/dist/server/constants.mjs.map +1 -1
  17. package/dist/server/controllers/release.js +9 -21
  18. package/dist/server/controllers/release.js.map +1 -1
  19. package/dist/server/controllers/release.mjs +9 -21
  20. package/dist/server/controllers/release.mjs.map +1 -1
  21. package/dist/server/controllers/settings.js +0 -1
  22. package/dist/server/controllers/settings.js.map +1 -1
  23. package/dist/server/controllers/settings.mjs +0 -1
  24. package/dist/server/controllers/settings.mjs.map +1 -1
  25. package/dist/server/services/release-action.js +59 -3
  26. package/dist/server/services/release-action.js.map +1 -1
  27. package/dist/server/services/release-action.mjs +60 -4
  28. package/dist/server/services/release-action.mjs.map +1 -1
  29. package/dist/server/services/release.js +110 -10
  30. package/dist/server/services/release.js.map +1 -1
  31. package/dist/server/services/release.mjs +111 -11
  32. package/dist/server/services/release.mjs.map +1 -1
  33. package/dist/server/services/scheduling.js +7 -2
  34. package/dist/server/services/scheduling.js.map +1 -1
  35. package/dist/server/services/scheduling.mjs +7 -2
  36. package/dist/server/services/scheduling.mjs.map +1 -1
  37. package/dist/server/services/settings.js +29 -1
  38. package/dist/server/services/settings.js.map +1 -1
  39. package/dist/server/services/settings.mjs +29 -1
  40. package/dist/server/services/settings.mjs.map +1 -1
  41. package/dist/server/src/audit-logs.d.ts +99 -0
  42. package/dist/server/src/audit-logs.d.ts.map +1 -0
  43. package/dist/server/src/bootstrap.d.ts.map +1 -1
  44. package/dist/server/src/constants.d.ts +20 -0
  45. package/dist/server/src/constants.d.ts.map +1 -1
  46. package/dist/server/src/controllers/release.d.ts.map +1 -1
  47. package/dist/server/src/index.d.ts +8 -1
  48. package/dist/server/src/index.d.ts.map +1 -1
  49. package/dist/server/src/services/index.d.ts +8 -1
  50. package/dist/server/src/services/index.d.ts.map +1 -1
  51. package/dist/server/src/services/release-action.d.ts.map +1 -1
  52. package/dist/server/src/services/release.d.ts +8 -1
  53. package/dist/server/src/services/release.d.ts.map +1 -1
  54. package/dist/server/src/services/scheduling.d.ts.map +1 -1
  55. package/dist/server/src/services/settings.d.ts.map +1 -1
  56. package/package.json +7 -7
@@ -216,7 +216,6 @@ const ReleasesPage = ()=>{
216
216
  const hasReachedMaximumPendingReleases = totalPendingReleases >= maximumReleases;
217
217
  const handleTabChange = (tabValue)=>{
218
218
  setQuery({
219
- ...query,
220
219
  page: 1,
221
220
  pageSize: response?.currentData?.meta?.pagination?.pageSize || 16,
222
221
  filters: {
@@ -1 +1 @@
1
- {"version":3,"file":"ReleasesPage.js","sources":["../../../admin/src/pages/ReleasesPage.tsx"],"sourcesContent":["import * as React from 'react';\n\nimport {\n Page,\n Pagination,\n useTracking,\n useAPIErrorHandler,\n useNotification,\n useQueryParams,\n useRBAC,\n isFetchError,\n Layouts,\n GradientBadge,\n} from '@strapi/admin/strapi-admin';\nimport { useLicenseLimits } from '@strapi/admin/strapi-admin/ee';\nimport {\n Alert,\n Badge,\n Box,\n Button,\n Divider,\n EmptyStateLayout,\n Flex,\n Grid,\n Main,\n Tabs,\n Typography,\n Link,\n} from '@strapi/design-system';\nimport { Plus } from '@strapi/icons';\nimport { EmptyDocuments } from '@strapi/icons/symbols';\nimport { format } from 'date-fns';\nimport { useIntl } from 'react-intl';\nimport { useNavigate, useLocation, NavLink } from 'react-router-dom';\nimport { styled } from 'styled-components';\n\nimport { GetReleases, type Release } from '../../../shared/contracts/releases';\nimport { RelativeTime as BaseRelativeTime } from '../components/RelativeTime';\nimport { ReleaseModal, FormValues } from '../components/ReleaseModal';\nimport { PERMISSIONS } from '../constants';\nimport {\n useGetReleasesQuery,\n useGetReleaseSettingsQuery,\n GetReleasesQueryParams,\n useCreateReleaseMutation,\n} from '../services/release';\n\n/* -------------------------------------------------------------------------------------------------\n * ReleasesGrid\n * -----------------------------------------------------------------------------------------------*/\ninterface ReleasesGridProps {\n sectionTitle: 'pending' | 'done';\n releases?: GetReleases.Response['data'];\n isError?: boolean;\n}\n\nconst LinkCard = styled(Link)`\n display: block;\n`;\n\nconst RelativeTime = styled(BaseRelativeTime)`\n display: inline-block;\n &::first-letter {\n text-transform: uppercase;\n }\n`;\n\nconst getBadgeProps = (status: Release['status']) => {\n let color;\n switch (status) {\n case 'ready':\n color = 'success';\n break;\n case 'blocked':\n color = 'warning';\n break;\n case 'failed':\n color = 'danger';\n break;\n case 'done':\n color = 'primary';\n break;\n case 'empty':\n default:\n color = 'neutral';\n }\n\n return {\n textColor: `${color}600`,\n backgroundColor: `${color}100`,\n borderColor: `${color}200`,\n };\n};\n\nconst ReleasesGrid = ({ sectionTitle, releases = [], isError = false }: ReleasesGridProps) => {\n const { formatMessage } = useIntl();\n\n if (isError) {\n return <Page.Error />;\n }\n\n if (releases?.length === 0) {\n return (\n <EmptyStateLayout\n content={formatMessage(\n {\n id: 'content-releases.page.Releases.tab.emptyEntries',\n defaultMessage: 'No releases',\n },\n {\n target: sectionTitle,\n }\n )}\n icon={<EmptyDocuments width=\"16rem\" />}\n />\n );\n }\n\n return (\n <Grid.Root gap={4}>\n {releases.map(({ id, name, scheduledAt, status }) => (\n <Grid.Item col={3} s={6} xs={12} key={id} direction=\"column\" alignItems=\"stretch\">\n <LinkCard tag={NavLink} to={`${id}`} isExternal={false}>\n <Flex\n direction=\"column\"\n justifyContent=\"space-between\"\n padding={4}\n hasRadius\n background=\"neutral0\"\n shadow=\"tableShadow\"\n height=\"100%\"\n width=\"100%\"\n alignItems=\"start\"\n gap={4}\n >\n <Flex direction=\"column\" alignItems=\"start\" gap={1}>\n <Typography textColor=\"neutral800\" tag=\"h3\" variant=\"delta\" fontWeight=\"bold\">\n {name}\n </Typography>\n <Typography variant=\"pi\" textColor=\"neutral600\">\n {scheduledAt ? (\n <RelativeTime timestamp={new Date(scheduledAt)} />\n ) : (\n formatMessage({\n id: 'content-releases.pages.Releases.not-scheduled',\n defaultMessage: 'Not scheduled',\n })\n )}\n </Typography>\n </Flex>\n <Badge {...getBadgeProps(status)}>{status}</Badge>\n </Flex>\n </LinkCard>\n </Grid.Item>\n ))}\n </Grid.Root>\n );\n};\n\n/* -------------------------------------------------------------------------------------------------\n * ReleasesPage\n * -----------------------------------------------------------------------------------------------*/\n\nconst StyledAlert = styled(Alert)`\n button {\n display: none;\n }\n p + div {\n margin-left: auto;\n }\n`;\n\nconst INITIAL_FORM_VALUES = {\n name: '',\n date: format(new Date(), 'yyyy-MM-dd'),\n time: '',\n isScheduled: true,\n scheduledAt: null,\n timezone: null,\n} satisfies FormValues;\n\nconst ReleasesPage = () => {\n const location = useLocation();\n const [releaseModalShown, setReleaseModalShown] = React.useState(false);\n const { toggleNotification } = useNotification();\n const { formatMessage } = useIntl();\n const navigate = useNavigate();\n const { formatAPIError } = useAPIErrorHandler();\n const [{ query }, setQuery] = useQueryParams<GetReleasesQueryParams>();\n const response = useGetReleasesQuery(query);\n const { data, isLoading: isLoadingSettings } = useGetReleaseSettingsQuery();\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: isLoadingReleases, isSuccess, isError } = response;\n const activeTab = response?.currentData?.meta?.activeTab || 'pending';\n\n // Check if we have some errors and show a notification to the user to explain the error\n React.useEffect(() => {\n if (location?.state?.errors) {\n toggleNotification({\n type: 'danger',\n title: formatMessage({\n id: 'content-releases.pages.Releases.notification.error.title',\n defaultMessage: 'Your request could not be processed.',\n }),\n message: formatMessage({\n id: 'content-releases.pages.Releases.notification.error.message',\n defaultMessage: 'Please try again or open another release.',\n }),\n });\n navigate('', { replace: true, state: null });\n }\n }, [formatMessage, location?.state?.errors, navigate, toggleNotification]);\n\n const toggleAddReleaseModal = () => {\n setReleaseModalShown((prev) => !prev);\n };\n\n if (isLoadingReleases || isLoadingSettings) {\n return <Page.Loading />;\n }\n\n const totalPendingReleases = (isSuccess && response.currentData?.meta?.pendingReleasesCount) || 0;\n const hasReachedMaximumPendingReleases = totalPendingReleases >= maximumReleases;\n\n const handleTabChange = (tabValue: string) => {\n setQuery({\n ...query,\n page: 1,\n pageSize: response?.currentData?.meta?.pagination?.pageSize || 16,\n filters: {\n releasedAt: {\n $notNull: tabValue !== 'pending',\n },\n },\n });\n };\n\n const handleAddRelease = async ({ name, scheduledAt, timezone }: FormValues) => {\n const response = await createRelease({\n name,\n scheduledAt,\n timezone,\n });\n if ('data' in response) {\n // When the response returns an object with 'data', handle success\n toggleNotification({\n type: 'success',\n message: formatMessage({\n id: 'content-releases.modal.release-created-notification-success',\n defaultMessage: 'Release created.',\n }),\n });\n\n trackUsage('didCreateRelease');\n navigate(response.data.data.id.toString());\n } else if (isFetchError(response.error)) {\n // When the response returns an object with 'error', handle fetch error\n toggleNotification({\n type: 'danger',\n message: formatAPIError(response.error),\n });\n } else {\n // Otherwise, the response returns an object with 'error', handle a generic error\n toggleNotification({\n type: 'danger',\n message: formatMessage({ id: 'notification.error', defaultMessage: 'An error occurred' }),\n });\n }\n };\n\n return (\n <Layouts.Root>\n <Main aria-busy={isLoadingReleases || isLoadingSettings}>\n <Layouts.Header\n title={formatMessage({\n id: 'content-releases.pages.Releases.title',\n defaultMessage: 'Releases',\n })}\n secondaryAction={\n <GradientBadge\n label={formatMessage({\n id: 'components.premiumFeature.title',\n defaultMessage: 'Premium feature',\n })}\n />\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 fullWidth\n >\n {formatMessage({\n id: 'content-releases.header.actions.add-release',\n defaultMessage: 'New release',\n })}\n </Button>\n ) : null\n }\n />\n <Layouts.Content>\n <>\n {hasReachedMaximumPendingReleases && (\n <StyledAlert\n marginBottom={6}\n action={\n <Link href=\"https://strapi.io/pricing-cloud\" isExternal>\n {formatMessage({\n id: 'content-releases.pages.Releases.max-limit-reached.action',\n defaultMessage: 'Explore plans',\n })}\n </Link>\n }\n title={formatMessage(\n {\n id: 'content-releases.pages.Releases.max-limit-reached.title',\n defaultMessage:\n 'You have reached the {number} pending {number, plural, one {release} other {releases}} limit.',\n },\n { number: maximumReleases }\n )}\n onClose={() => {}}\n closeLabel=\"\"\n >\n {formatMessage({\n id: 'content-releases.pages.Releases.max-limit-reached.message',\n defaultMessage: 'Upgrade to manage an unlimited number of releases.',\n })}\n </StyledAlert>\n )}\n <Tabs.Root variant=\"simple\" onValueChange={handleTabChange} value={activeTab}>\n <Box paddingBottom={8}>\n <Tabs.List\n aria-label={formatMessage({\n id: 'content-releases.pages.Releases.tab-group.label',\n defaultMessage: 'Releases list',\n })}\n >\n <Tabs.Trigger value=\"pending\">\n {formatMessage(\n {\n id: 'content-releases.pages.Releases.tab.pending',\n defaultMessage: 'Pending ({count})',\n },\n {\n count: totalPendingReleases,\n }\n )}\n </Tabs.Trigger>\n <Tabs.Trigger value=\"done\">\n {formatMessage({\n id: 'content-releases.pages.Releases.tab.done',\n defaultMessage: 'Done',\n })}\n </Tabs.Trigger>\n </Tabs.List>\n <Divider />\n </Box>\n {/* Pending releases */}\n <Tabs.Content value=\"pending\">\n <ReleasesGrid\n sectionTitle=\"pending\"\n releases={response?.currentData?.data}\n isError={isError}\n />\n </Tabs.Content>\n {/* Done releases */}\n <Tabs.Content value=\"done\">\n <ReleasesGrid\n sectionTitle=\"done\"\n releases={response?.currentData?.data}\n isError={isError}\n />\n </Tabs.Content>\n </Tabs.Root>\n <Pagination.Root\n {...response?.currentData?.meta?.pagination}\n defaultPageSize={response?.currentData?.meta?.pagination?.pageSize}\n >\n <Pagination.PageSize options={['8', '16', '32', '64']} />\n <Pagination.Links />\n </Pagination.Root>\n </>\n </Layouts.Content>\n <ReleaseModal\n open={releaseModalShown}\n handleClose={toggleAddReleaseModal}\n handleSubmit={handleAddRelease}\n isLoading={isSubmittingForm}\n initialValues={{\n ...INITIAL_FORM_VALUES,\n timezone: data?.data.defaultTimezone ? data.data.defaultTimezone.split('&')[1] : null,\n }}\n />\n </Main>\n </Layouts.Root>\n );\n};\n\nexport { ReleasesPage, getBadgeProps };\n"],"names":["LinkCard","styled","Link","RelativeTime","BaseRelativeTime","getBadgeProps","status","color","textColor","backgroundColor","borderColor","ReleasesGrid","sectionTitle","releases","isError","formatMessage","useIntl","_jsx","Page","Error","length","EmptyStateLayout","content","id","defaultMessage","target","icon","EmptyDocuments","width","Grid","Root","gap","map","name","scheduledAt","Item","col","s","xs","direction","alignItems","tag","NavLink","to","isExternal","_jsxs","Flex","justifyContent","padding","hasRadius","background","shadow","height","Typography","variant","fontWeight","timestamp","Date","Badge","StyledAlert","Alert","INITIAL_FORM_VALUES","date","format","time","isScheduled","timezone","ReleasesPage","location","useLocation","releaseModalShown","setReleaseModalShown","React","useState","toggleNotification","useNotification","navigate","useNavigate","formatAPIError","useAPIErrorHandler","query","setQuery","useQueryParams","response","useGetReleasesQuery","data","isLoading","isLoadingSettings","useGetReleaseSettingsQuery","createRelease","isSubmittingForm","useCreateReleaseMutation","getFeature","useLicenseLimits","maximumReleases","trackUsage","useTracking","allowedActions","canCreate","useRBAC","PERMISSIONS","isLoadingReleases","isSuccess","activeTab","currentData","meta","useEffect","state","errors","type","title","message","replace","toggleAddReleaseModal","prev","Loading","totalPendingReleases","pendingReleasesCount","hasReachedMaximumPendingReleases","handleTabChange","tabValue","page","pageSize","pagination","filters","releasedAt","$notNull","handleAddRelease","toString","isFetchError","error","Layouts","Main","aria-busy","Header","secondaryAction","GradientBadge","label","subtitle","primaryAction","Button","startIcon","Plus","onClick","disabled","fullWidth","Content","_Fragment","marginBottom","action","href","number","onClose","closeLabel","Tabs","onValueChange","value","Box","paddingBottom","List","aria-label","Trigger","count","Divider","Pagination","defaultPageSize","PageSize","options","Links","ReleaseModal","open","handleClose","handleSubmit","initialValues","defaultTimezone","split"],"mappings":"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"}
1
+ {"version":3,"file":"ReleasesPage.js","sources":["../../../admin/src/pages/ReleasesPage.tsx"],"sourcesContent":["import * as React from 'react';\n\nimport {\n Page,\n Pagination,\n useTracking,\n useAPIErrorHandler,\n useNotification,\n useQueryParams,\n useRBAC,\n isFetchError,\n Layouts,\n GradientBadge,\n} from '@strapi/admin/strapi-admin';\nimport { useLicenseLimits } from '@strapi/admin/strapi-admin/ee';\nimport {\n Alert,\n Badge,\n Box,\n Button,\n Divider,\n EmptyStateLayout,\n Flex,\n Grid,\n Main,\n Tabs,\n Typography,\n Link,\n} from '@strapi/design-system';\nimport { Plus } from '@strapi/icons';\nimport { EmptyDocuments } from '@strapi/icons/symbols';\nimport { format } from 'date-fns';\nimport { useIntl } from 'react-intl';\nimport { useNavigate, useLocation, NavLink } from 'react-router-dom';\nimport { styled } from 'styled-components';\n\nimport { GetReleases, type Release } from '../../../shared/contracts/releases';\nimport { RelativeTime as BaseRelativeTime } from '../components/RelativeTime';\nimport { ReleaseModal, FormValues } from '../components/ReleaseModal';\nimport { PERMISSIONS } from '../constants';\nimport {\n useGetReleasesQuery,\n useGetReleaseSettingsQuery,\n GetReleasesQueryParams,\n useCreateReleaseMutation,\n} from '../services/release';\n\n/* -------------------------------------------------------------------------------------------------\n * ReleasesGrid\n * -----------------------------------------------------------------------------------------------*/\ninterface ReleasesGridProps {\n sectionTitle: 'pending' | 'done';\n releases?: GetReleases.Response['data'];\n isError?: boolean;\n}\n\nconst LinkCard = styled(Link)`\n display: block;\n`;\n\nconst RelativeTime = styled(BaseRelativeTime)`\n display: inline-block;\n &::first-letter {\n text-transform: uppercase;\n }\n`;\n\nconst getBadgeProps = (status: Release['status']) => {\n let color;\n switch (status) {\n case 'ready':\n color = 'success';\n break;\n case 'blocked':\n color = 'warning';\n break;\n case 'failed':\n color = 'danger';\n break;\n case 'done':\n color = 'primary';\n break;\n case 'empty':\n default:\n color = 'neutral';\n }\n\n return {\n textColor: `${color}600`,\n backgroundColor: `${color}100`,\n borderColor: `${color}200`,\n };\n};\n\nconst ReleasesGrid = ({ sectionTitle, releases = [], isError = false }: ReleasesGridProps) => {\n const { formatMessage } = useIntl();\n\n if (isError) {\n return <Page.Error />;\n }\n\n if (releases?.length === 0) {\n return (\n <EmptyStateLayout\n content={formatMessage(\n {\n id: 'content-releases.page.Releases.tab.emptyEntries',\n defaultMessage: 'No releases',\n },\n {\n target: sectionTitle,\n }\n )}\n icon={<EmptyDocuments width=\"16rem\" />}\n />\n );\n }\n\n return (\n <Grid.Root gap={4}>\n {releases.map(({ id, name, scheduledAt, status }) => (\n <Grid.Item col={3} s={6} xs={12} key={id} direction=\"column\" alignItems=\"stretch\">\n <LinkCard tag={NavLink} to={`${id}`} isExternal={false}>\n <Flex\n direction=\"column\"\n justifyContent=\"space-between\"\n padding={4}\n hasRadius\n background=\"neutral0\"\n shadow=\"tableShadow\"\n height=\"100%\"\n width=\"100%\"\n alignItems=\"start\"\n gap={4}\n >\n <Flex direction=\"column\" alignItems=\"start\" gap={1}>\n <Typography textColor=\"neutral800\" tag=\"h3\" variant=\"delta\" fontWeight=\"bold\">\n {name}\n </Typography>\n <Typography variant=\"pi\" textColor=\"neutral600\">\n {scheduledAt ? (\n <RelativeTime timestamp={new Date(scheduledAt)} />\n ) : (\n formatMessage({\n id: 'content-releases.pages.Releases.not-scheduled',\n defaultMessage: 'Not scheduled',\n })\n )}\n </Typography>\n </Flex>\n <Badge {...getBadgeProps(status)}>{status}</Badge>\n </Flex>\n </LinkCard>\n </Grid.Item>\n ))}\n </Grid.Root>\n );\n};\n\n/* -------------------------------------------------------------------------------------------------\n * ReleasesPage\n * -----------------------------------------------------------------------------------------------*/\n\nconst StyledAlert = styled(Alert)`\n button {\n display: none;\n }\n p + div {\n margin-left: auto;\n }\n`;\n\nconst INITIAL_FORM_VALUES = {\n name: '',\n date: format(new Date(), 'yyyy-MM-dd'),\n time: '',\n isScheduled: true,\n scheduledAt: null,\n timezone: null,\n} satisfies FormValues;\n\nconst ReleasesPage = () => {\n const location = useLocation();\n const [releaseModalShown, setReleaseModalShown] = React.useState(false);\n const { toggleNotification } = useNotification();\n const { formatMessage } = useIntl();\n const navigate = useNavigate();\n const { formatAPIError } = useAPIErrorHandler();\n const [{ query }, setQuery] = useQueryParams<GetReleasesQueryParams>();\n const response = useGetReleasesQuery(query);\n const { data, isLoading: isLoadingSettings } = useGetReleaseSettingsQuery();\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: isLoadingReleases, isSuccess, isError } = response;\n const activeTab = response?.currentData?.meta?.activeTab || 'pending';\n\n // Check if we have some errors and show a notification to the user to explain the error\n React.useEffect(() => {\n if (location?.state?.errors) {\n toggleNotification({\n type: 'danger',\n title: formatMessage({\n id: 'content-releases.pages.Releases.notification.error.title',\n defaultMessage: 'Your request could not be processed.',\n }),\n message: formatMessage({\n id: 'content-releases.pages.Releases.notification.error.message',\n defaultMessage: 'Please try again or open another release.',\n }),\n });\n navigate('', { replace: true, state: null });\n }\n }, [formatMessage, location?.state?.errors, navigate, toggleNotification]);\n\n const toggleAddReleaseModal = () => {\n setReleaseModalShown((prev) => !prev);\n };\n\n if (isLoadingReleases || isLoadingSettings) {\n return <Page.Loading />;\n }\n\n const totalPendingReleases = (isSuccess && response.currentData?.meta?.pendingReleasesCount) || 0;\n const hasReachedMaximumPendingReleases = totalPendingReleases >= maximumReleases;\n\n const handleTabChange = (tabValue: string) => {\n setQuery({\n page: 1,\n pageSize: response?.currentData?.meta?.pagination?.pageSize || 16,\n filters: {\n releasedAt: {\n $notNull: tabValue !== 'pending',\n },\n },\n });\n };\n\n const handleAddRelease = async ({ name, scheduledAt, timezone }: FormValues) => {\n const response = await createRelease({\n name,\n scheduledAt,\n timezone,\n });\n if ('data' in response) {\n // When the response returns an object with 'data', handle success\n toggleNotification({\n type: 'success',\n message: formatMessage({\n id: 'content-releases.modal.release-created-notification-success',\n defaultMessage: 'Release created.',\n }),\n });\n\n trackUsage('didCreateRelease');\n navigate(response.data.data.id.toString());\n } else if (isFetchError(response.error)) {\n // When the response returns an object with 'error', handle fetch error\n toggleNotification({\n type: 'danger',\n message: formatAPIError(response.error),\n });\n } else {\n // Otherwise, the response returns an object with 'error', handle a generic error\n toggleNotification({\n type: 'danger',\n message: formatMessage({ id: 'notification.error', defaultMessage: 'An error occurred' }),\n });\n }\n };\n\n return (\n <Layouts.Root>\n <Main aria-busy={isLoadingReleases || isLoadingSettings}>\n <Layouts.Header\n title={formatMessage({\n id: 'content-releases.pages.Releases.title',\n defaultMessage: 'Releases',\n })}\n secondaryAction={\n <GradientBadge\n label={formatMessage({\n id: 'components.premiumFeature.title',\n defaultMessage: 'Premium feature',\n })}\n />\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 fullWidth\n >\n {formatMessage({\n id: 'content-releases.header.actions.add-release',\n defaultMessage: 'New release',\n })}\n </Button>\n ) : null\n }\n />\n <Layouts.Content>\n <>\n {hasReachedMaximumPendingReleases && (\n <StyledAlert\n marginBottom={6}\n action={\n <Link href=\"https://strapi.io/pricing-cloud\" isExternal>\n {formatMessage({\n id: 'content-releases.pages.Releases.max-limit-reached.action',\n defaultMessage: 'Explore plans',\n })}\n </Link>\n }\n title={formatMessage(\n {\n id: 'content-releases.pages.Releases.max-limit-reached.title',\n defaultMessage:\n 'You have reached the {number} pending {number, plural, one {release} other {releases}} limit.',\n },\n { number: maximumReleases }\n )}\n onClose={() => {}}\n closeLabel=\"\"\n >\n {formatMessage({\n id: 'content-releases.pages.Releases.max-limit-reached.message',\n defaultMessage: 'Upgrade to manage an unlimited number of releases.',\n })}\n </StyledAlert>\n )}\n <Tabs.Root variant=\"simple\" onValueChange={handleTabChange} value={activeTab}>\n <Box paddingBottom={8}>\n <Tabs.List\n aria-label={formatMessage({\n id: 'content-releases.pages.Releases.tab-group.label',\n defaultMessage: 'Releases list',\n })}\n >\n <Tabs.Trigger value=\"pending\">\n {formatMessage(\n {\n id: 'content-releases.pages.Releases.tab.pending',\n defaultMessage: 'Pending ({count})',\n },\n {\n count: totalPendingReleases,\n }\n )}\n </Tabs.Trigger>\n <Tabs.Trigger value=\"done\">\n {formatMessage({\n id: 'content-releases.pages.Releases.tab.done',\n defaultMessage: 'Done',\n })}\n </Tabs.Trigger>\n </Tabs.List>\n <Divider />\n </Box>\n {/* Pending releases */}\n <Tabs.Content value=\"pending\">\n <ReleasesGrid\n sectionTitle=\"pending\"\n releases={response?.currentData?.data}\n isError={isError}\n />\n </Tabs.Content>\n {/* Done releases */}\n <Tabs.Content value=\"done\">\n <ReleasesGrid\n sectionTitle=\"done\"\n releases={response?.currentData?.data}\n isError={isError}\n />\n </Tabs.Content>\n </Tabs.Root>\n <Pagination.Root\n {...response?.currentData?.meta?.pagination}\n defaultPageSize={response?.currentData?.meta?.pagination?.pageSize}\n >\n <Pagination.PageSize options={['8', '16', '32', '64']} />\n <Pagination.Links />\n </Pagination.Root>\n </>\n </Layouts.Content>\n <ReleaseModal\n open={releaseModalShown}\n handleClose={toggleAddReleaseModal}\n handleSubmit={handleAddRelease}\n isLoading={isSubmittingForm}\n initialValues={{\n ...INITIAL_FORM_VALUES,\n timezone: data?.data.defaultTimezone ? data.data.defaultTimezone.split('&')[1] : null,\n }}\n />\n </Main>\n </Layouts.Root>\n );\n};\n\nexport { ReleasesPage, getBadgeProps };\n"],"names":["LinkCard","styled","Link","RelativeTime","BaseRelativeTime","getBadgeProps","status","color","textColor","backgroundColor","borderColor","ReleasesGrid","sectionTitle","releases","isError","formatMessage","useIntl","_jsx","Page","Error","length","EmptyStateLayout","content","id","defaultMessage","target","icon","EmptyDocuments","width","Grid","Root","gap","map","name","scheduledAt","Item","col","s","xs","direction","alignItems","tag","NavLink","to","isExternal","_jsxs","Flex","justifyContent","padding","hasRadius","background","shadow","height","Typography","variant","fontWeight","timestamp","Date","Badge","StyledAlert","Alert","INITIAL_FORM_VALUES","date","format","time","isScheduled","timezone","ReleasesPage","location","useLocation","releaseModalShown","setReleaseModalShown","React","useState","toggleNotification","useNotification","navigate","useNavigate","formatAPIError","useAPIErrorHandler","query","setQuery","useQueryParams","response","useGetReleasesQuery","data","isLoading","isLoadingSettings","useGetReleaseSettingsQuery","createRelease","isSubmittingForm","useCreateReleaseMutation","getFeature","useLicenseLimits","maximumReleases","trackUsage","useTracking","allowedActions","canCreate","useRBAC","PERMISSIONS","isLoadingReleases","isSuccess","activeTab","currentData","meta","useEffect","state","errors","type","title","message","replace","toggleAddReleaseModal","prev","Loading","totalPendingReleases","pendingReleasesCount","hasReachedMaximumPendingReleases","handleTabChange","tabValue","page","pageSize","pagination","filters","releasedAt","$notNull","handleAddRelease","toString","isFetchError","error","Layouts","Main","aria-busy","Header","secondaryAction","GradientBadge","label","subtitle","primaryAction","Button","startIcon","Plus","onClick","disabled","fullWidth","Content","_Fragment","marginBottom","action","href","number","onClose","closeLabel","Tabs","onValueChange","value","Box","paddingBottom","List","aria-label","Trigger","count","Divider","Pagination","defaultPageSize","PageSize","options","Links","ReleaseModal","open","handleClose","handleSubmit","initialValues","defaultTimezone","split"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAwDA,MAAMA,QAAAA,GAAWC,uBAAAA,CAAOC,iBAAAA,CAAK;;AAE7B,CAAC;AAED,MAAMC,YAAAA,GAAeF,uBAAAA,CAAOG,2BAAAA,CAAiB;;;;;AAK7C,CAAC;AAED,MAAMC,gBAAgB,CAACC,MAAAA,GAAAA;IACrB,IAAIC,KAAAA;IACJ,OAAQD,MAAAA;QACN,KAAK,OAAA;YACHC,KAAAA,GAAQ,SAAA;AACR,YAAA;QACF,KAAK,SAAA;YACHA,KAAAA,GAAQ,SAAA;AACR,YAAA;QACF,KAAK,QAAA;YACHA,KAAAA,GAAQ,QAAA;AACR,YAAA;QACF,KAAK,MAAA;YACHA,KAAAA,GAAQ,SAAA;AACR,YAAA;QACF,KAAK,OAAA;AACL,QAAA;YACEA,KAAAA,GAAQ,SAAA;AACZ;IAEA,OAAO;QACLC,SAAAA,EAAW,CAAA,EAAGD,KAAAA,CAAM,GAAG,CAAC;QACxBE,eAAAA,EAAiB,CAAA,EAAGF,KAAAA,CAAM,GAAG,CAAC;QAC9BG,WAAAA,EAAa,CAAA,EAAGH,KAAAA,CAAM,GAAG;AAC3B,KAAA;AACF;AAEA,MAAMI,YAAAA,GAAe,CAAC,EAAEC,YAAY,EAAEC,WAAW,EAAE,EAAEC,OAAAA,GAAU,KAAK,EAAqB,GAAA;IACvF,MAAM,EAAEC,aAAa,EAAE,GAAGC,iBAAAA,EAAAA;AAE1B,IAAA,IAAIF,OAAAA,EAAS;QACX,qBAAOG,cAAA,CAACC,iBAAKC,KAAK,EAAA,EAAA,CAAA;AACpB,IAAA;IAEA,IAAIN,QAAAA,EAAUO,WAAW,CAAA,EAAG;AAC1B,QAAA,qBACEH,cAAA,CAACI,6BAAAA,EAAAA;AACCC,YAAAA,OAAAA,EAASP,aAAAA,CACP;gBACEQ,EAAAA,EAAI,iDAAA;gBACJC,cAAAA,EAAgB;aAClB,EACA;gBACEC,MAAAA,EAAQb;AACV,aAAA,CAAA;AAEFc,YAAAA,IAAAA,gBAAMT,cAAA,CAACU,sBAAAA,EAAAA;gBAAeC,KAAAA,EAAM;;;AAGlC,IAAA;IAEA,qBACEX,cAAA,CAACY,kBAAKC,IAAI,EAAA;QAACC,GAAAA,EAAK,CAAA;AACblB,QAAAA,QAAAA,EAAAA,QAAAA,CAASmB,GAAG,CAAC,CAAC,EAAET,EAAE,EAAEU,IAAI,EAAEC,WAAW,EAAE5B,MAAM,EAAE,iBAC9CW,cAAA,CAACY,kBAAKM,IAAI,EAAA;gBAACC,GAAAA,EAAK,CAAA;gBAAGC,CAAAA,EAAG,CAAA;gBAAGC,EAAAA,EAAI,EAAA;gBAAaC,SAAAA,EAAU,QAAA;gBAASC,UAAAA,EAAW,SAAA;AACtE,gBAAA,QAAA,gBAAAvB,cAAA,CAACjB,QAAAA,EAAAA;oBAASyC,GAAAA,EAAKC,sBAAAA;AAASC,oBAAAA,EAAAA,EAAI,GAAGpB,EAAAA,CAAAA,CAAI;oBAAEqB,UAAAA,EAAY,KAAA;AAC/C,oBAAA,QAAA,gBAAAC,eAAA,CAACC,iBAAAA,EAAAA;wBACCP,SAAAA,EAAU,QAAA;wBACVQ,cAAAA,EAAe,eAAA;wBACfC,OAAAA,EAAS,CAAA;wBACTC,SAAS,EAAA,IAAA;wBACTC,UAAAA,EAAW,UAAA;wBACXC,MAAAA,EAAO,aAAA;wBACPC,MAAAA,EAAO,MAAA;wBACPxB,KAAAA,EAAM,MAAA;wBACNY,UAAAA,EAAW,OAAA;wBACXT,GAAAA,EAAK,CAAA;;0CAELc,eAAA,CAACC,iBAAAA,EAAAA;gCAAKP,SAAAA,EAAU,QAAA;gCAASC,UAAAA,EAAW,OAAA;gCAAQT,GAAAA,EAAK,CAAA;;kDAC/Cd,cAAA,CAACoC,uBAAAA,EAAAA;wCAAW7C,SAAAA,EAAU,YAAA;wCAAaiC,GAAAA,EAAI,IAAA;wCAAKa,OAAAA,EAAQ,OAAA;wCAAQC,UAAAA,EAAW,MAAA;AACpEtB,wCAAAA,QAAAA,EAAAA;;kDAEHhB,cAAA,CAACoC,uBAAAA,EAAAA;wCAAWC,OAAAA,EAAQ,IAAA;wCAAK9C,SAAAA,EAAU,YAAA;AAChC0B,wCAAAA,QAAAA,EAAAA,WAAAA,iBACCjB,cAAA,CAACd,YAAAA,EAAAA;AAAaqD,4CAAAA,SAAAA,EAAW,IAAIC,IAAAA,CAAKvB,WAAAA;6CAElCnB,aAAAA,CAAc;4CACZQ,EAAAA,EAAI,+CAAA;4CACJC,cAAAA,EAAgB;AAClB,yCAAA;;;;0CAINP,cAAA,CAACyC,kBAAAA,EAAAA;AAAO,gCAAA,GAAGrD,cAAcC,MAAAA,CAAO;AAAGA,gCAAAA,QAAAA,EAAAA;;;;;AA7BHiB,aAAAA,EAAAA,EAAAA,CAAAA;;AAoC9C,CAAA;AAEA;;AAEkG,qGAElG,MAAMoC,WAAAA,GAAc1D,uBAAAA,CAAO2D,kBAAAA,CAAM;;;;;;;AAOjC,CAAC;AAED,MAAMC,mBAAAA,GAAsB;IAC1B5B,IAAAA,EAAM,EAAA;IACN6B,IAAAA,EAAMC,cAAAA,CAAO,IAAIN,IAAAA,EAAAA,EAAQ,YAAA,CAAA;IACzBO,IAAAA,EAAM,EAAA;IACNC,WAAAA,EAAa,IAAA;IACb/B,WAAAA,EAAa,IAAA;IACbgC,QAAAA,EAAU;AACZ,CAAA;AAEA,MAAMC,YAAAA,GAAe,IAAA;AACnB,IAAA,MAAMC,QAAAA,GAAWC,0BAAAA,EAAAA;AACjB,IAAA,MAAM,CAACC,iBAAAA,EAAmBC,oBAAAA,CAAqB,GAAGC,gBAAAA,CAAMC,QAAQ,CAAC,KAAA,CAAA;IACjE,MAAM,EAAEC,kBAAkB,EAAE,GAAGC,2BAAAA,EAAAA;IAC/B,MAAM,EAAE5D,aAAa,EAAE,GAAGC,iBAAAA,EAAAA;AAC1B,IAAA,MAAM4D,QAAAA,GAAWC,0BAAAA,EAAAA;IACjB,MAAM,EAAEC,cAAc,EAAE,GAAGC,8BAAAA,EAAAA;AAC3B,IAAA,MAAM,CAAC,EAAEC,KAAK,EAAE,EAAEC,SAAS,GAAGC,0BAAAA,EAAAA;AAC9B,IAAA,MAAMC,WAAWC,2BAAAA,CAAoBJ,KAAAA,CAAAA;AACrC,IAAA,MAAM,EAAEK,IAAI,EAAEC,SAAAA,EAAWC,iBAAiB,EAAE,GAAGC,kCAAAA,EAAAA;AAC/C,IAAA,MAAM,CAACC,aAAAA,EAAe,EAAEH,WAAWI,gBAAgB,EAAE,CAAC,GAAGC,gCAAAA,EAAAA;IACzD,MAAM,EAAEC,UAAU,EAAE,GAAGC,mBAAAA,EAAAA;AACvB,IAAA,MAAM,EAAEC,eAAAA,GAAkB,CAAC,EAAE,GAAGF,UAAAA,CAAW,sBAAA,CAAA;IAG3C,MAAM,EAAEG,UAAU,EAAE,GAAGC,uBAAAA,EAAAA;AACvB,IAAA,MAAM,EACJC,cAAAA,EAAgB,EAAEC,SAAS,EAAE,EAC9B,GAAGC,mBAAAA,CAAQC,qBAAAA,CAAAA;IAEZ,MAAM,EAAEd,WAAWe,iBAAiB,EAAEC,SAAS,EAAExF,OAAO,EAAE,GAAGqE,QAAAA;AAC7D,IAAA,MAAMoB,SAAAA,GAAYpB,QAAAA,EAAUqB,WAAAA,EAAaC,IAAAA,EAAMF,SAAAA,IAAa,SAAA;;AAG5D/B,IAAAA,gBAAAA,CAAMkC,SAAS,CAAC,IAAA;QACd,IAAItC,QAAAA,EAAUuC,OAAOC,MAAAA,EAAQ;YAC3BlC,kBAAAA,CAAmB;gBACjBmC,IAAAA,EAAM,QAAA;AACNC,gBAAAA,KAAAA,EAAO/F,aAAAA,CAAc;oBACnBQ,EAAAA,EAAI,0DAAA;oBACJC,cAAAA,EAAgB;AAClB,iBAAA,CAAA;AACAuF,gBAAAA,OAAAA,EAAShG,aAAAA,CAAc;oBACrBQ,EAAAA,EAAI,4DAAA;oBACJC,cAAAA,EAAgB;AAClB,iBAAA;AACF,aAAA,CAAA;AACAoD,YAAAA,QAAAA,CAAS,EAAA,EAAI;gBAAEoC,OAAAA,EAAS,IAAA;gBAAML,KAAAA,EAAO;AAAK,aAAA,CAAA;AAC5C,QAAA;IACF,CAAA,EAAG;AAAC5F,QAAAA,aAAAA;AAAeqD,QAAAA,QAAAA,EAAUuC,KAAAA,EAAOC,MAAAA;AAAQhC,QAAAA,QAAAA;AAAUF,QAAAA;AAAmB,KAAA,CAAA;AAEzE,IAAA,MAAMuC,qBAAAA,GAAwB,IAAA;QAC5B1C,oBAAAA,CAAqB,CAAC2C,OAAS,CAACA,IAAAA,CAAAA;AAClC,IAAA,CAAA;AAEA,IAAA,IAAIb,qBAAqBd,iBAAAA,EAAmB;QAC1C,qBAAOtE,cAAA,CAACC,iBAAKiG,OAAO,EAAA,EAAA,CAAA;AACtB,IAAA;AAEA,IAAA,MAAMC,uBAAuB,SAACd,IAAanB,SAASqB,WAAW,EAAEC,MAAMY,oBAAAA,IAAyB,CAAA;AAChG,IAAA,MAAMC,mCAAmCF,oBAAAA,IAAwBtB,eAAAA;AAEjE,IAAA,MAAMyB,kBAAkB,CAACC,QAAAA,GAAAA;QACvBvC,QAAAA,CAAS;YACPwC,IAAAA,EAAM,CAAA;AACNC,YAAAA,QAAAA,EAAUvC,QAAAA,EAAUqB,WAAAA,EAAaC,IAAAA,EAAMkB,UAAAA,EAAYD,QAAAA,IAAY,EAAA;YAC/DE,OAAAA,EAAS;gBACPC,UAAAA,EAAY;AACVC,oBAAAA,QAAAA,EAAUN,QAAAA,KAAa;AACzB;AACF;AACF,SAAA,CAAA;AACF,IAAA,CAAA;IAEA,MAAMO,gBAAAA,GAAmB,OAAO,EAAE9F,IAAI,EAAEC,WAAW,EAAEgC,QAAQ,EAAc,GAAA;QACzE,MAAMiB,QAAAA,GAAW,MAAMM,aAAAA,CAAc;AACnCxD,YAAAA,IAAAA;AACAC,YAAAA,WAAAA;AACAgC,YAAAA;AACF,SAAA,CAAA;AACA,QAAA,IAAI,UAAUiB,QAAAA,EAAU;;YAEtBT,kBAAAA,CAAmB;gBACjBmC,IAAAA,EAAM,SAAA;AACNE,gBAAAA,OAAAA,EAAShG,aAAAA,CAAc;oBACrBQ,EAAAA,EAAI,6DAAA;oBACJC,cAAAA,EAAgB;AAClB,iBAAA;AACF,aAAA,CAAA;YAEAuE,UAAAA,CAAW,kBAAA,CAAA;AACXnB,YAAAA,QAAAA,CAASO,SAASE,IAAI,CAACA,IAAI,CAAC9D,EAAE,CAACyG,QAAQ,EAAA,CAAA;AACzC,QAAA,CAAA,MAAO,IAAIC,wBAAAA,CAAa9C,QAAAA,CAAS+C,KAAK,CAAA,EAAG;;YAEvCxD,kBAAAA,CAAmB;gBACjBmC,IAAAA,EAAM,QAAA;gBACNE,OAAAA,EAASjC,cAAAA,CAAeK,SAAS+C,KAAK;AACxC,aAAA,CAAA;QACF,CAAA,MAAO;;YAELxD,kBAAAA,CAAmB;gBACjBmC,IAAAA,EAAM,QAAA;AACNE,gBAAAA,OAAAA,EAAShG,aAAAA,CAAc;oBAAEQ,EAAAA,EAAI,oBAAA;oBAAsBC,cAAAA,EAAgB;AAAoB,iBAAA;AACzF,aAAA,CAAA;AACF,QAAA;AACF,IAAA,CAAA;IAEA,qBACEP,cAAA,CAACkH,oBAAQrG,IAAI,EAAA;AACX,QAAA,QAAA,gBAAAe,eAAA,CAACuF,iBAAAA,EAAAA;AAAKC,YAAAA,WAAAA,EAAWhC,iBAAAA,IAAqBd,iBAAAA;;AACpC,8BAAAtE,cAAA,CAACkH,oBAAQG,MAAM,EAAA;AACbxB,oBAAAA,KAAAA,EAAO/F,aAAAA,CAAc;wBACnBQ,EAAAA,EAAI,uCAAA;wBACJC,cAAAA,EAAgB;AAClB,qBAAA,CAAA;AACA+G,oBAAAA,eAAAA,gBACEtH,cAAA,CAACuH,yBAAAA,EAAAA;AACCC,wBAAAA,KAAAA,EAAO1H,aAAAA,CAAc;4BACnBQ,EAAAA,EAAI,iCAAA;4BACJC,cAAAA,EAAgB;AAClB,yBAAA;;AAGJkH,oBAAAA,QAAAA,EAAU3H,aAAAA,CAAc;wBACtBQ,EAAAA,EAAI,iDAAA;wBACJC,cAAAA,EAAgB;AAClB,qBAAA,CAAA;AACAmH,oBAAAA,aAAAA,EACEzC,0BACEjF,cAAA,CAAC2H,mBAAAA,EAAAA;AACCC,wBAAAA,SAAAA,gBAAW5H,cAAA,CAAC6H,UAAAA,EAAAA,EAAAA,CAAAA;wBACZC,OAAAA,EAAS9B,qBAAAA;wBACT+B,QAAAA,EAAU1B,gCAAAA;wBACV2B,SAAS,EAAA,IAAA;kCAERlI,aAAAA,CAAc;4BACbQ,EAAAA,EAAI,6CAAA;4BACJC,cAAAA,EAAgB;AAClB,yBAAA;AAEA,qBAAA,CAAA,GAAA;;AAGR,8BAAAP,cAAA,CAACkH,oBAAQe,OAAO,EAAA;4CACdrG,eAAA,CAAAsG,mBAAA,EAAA;;AACG7B,4BAAAA,gCAAAA,kBACCrG,cAAA,CAAC0C,WAAAA,EAAAA;gCACCyF,YAAAA,EAAc,CAAA;AACdC,gCAAAA,MAAAA,gBACEpI,cAAA,CAACf,iBAAAA,EAAAA;oCAAKoJ,IAAAA,EAAK,iCAAA;oCAAkC1G,UAAU,EAAA,IAAA;8CACpD7B,aAAAA,CAAc;wCACbQ,EAAAA,EAAI,0DAAA;wCACJC,cAAAA,EAAgB;AAClB,qCAAA;;AAGJsF,gCAAAA,KAAAA,EAAO/F,aAAAA,CACL;oCACEQ,EAAAA,EAAI,yDAAA;oCACJC,cAAAA,EACE;iCACJ,EACA;oCAAE+H,MAAAA,EAAQzD;AAAgB,iCAAA,CAAA;AAE5B0D,gCAAAA,OAAAA,EAAS,IAAA,CAAO,CAAA;gCAChBC,UAAAA,EAAW,EAAA;0CAEV1I,aAAAA,CAAc;oCACbQ,EAAAA,EAAI,2DAAA;oCACJC,cAAAA,EAAgB;AAClB,iCAAA;;AAGJ,0CAAAqB,eAAA,CAAC6G,kBAAK5H,IAAI,EAAA;gCAACwB,OAAAA,EAAQ,QAAA;gCAASqG,aAAAA,EAAepC,eAAAA;gCAAiBqC,KAAAA,EAAOrD,SAAAA;;kDACjE1D,eAAA,CAACgH,gBAAAA,EAAAA;wCAAIC,aAAAA,EAAe,CAAA;;AAClB,0DAAAjH,eAAA,CAAC6G,kBAAKK,IAAI,EAAA;AACRC,gDAAAA,YAAAA,EAAYjJ,aAAAA,CAAc;oDACxBQ,EAAAA,EAAI,iDAAA;oDACJC,cAAAA,EAAgB;AAClB,iDAAA,CAAA;;AAEA,kEAAAP,cAAA,CAACyI,kBAAKO,OAAO,EAAA;wDAACL,KAAAA,EAAM,SAAA;kEACjB7I,aAAAA,CACC;4DACEQ,EAAAA,EAAI,6CAAA;4DACJC,cAAAA,EAAgB;yDAClB,EACA;4DACE0I,KAAAA,EAAO9C;AACT,yDAAA;;AAGJ,kEAAAnG,cAAA,CAACyI,kBAAKO,OAAO,EAAA;wDAACL,KAAAA,EAAM,MAAA;kEACjB7I,aAAAA,CAAc;4DACbQ,EAAAA,EAAI,0CAAA;4DACJC,cAAAA,EAAgB;AAClB,yDAAA;;;;0DAGJP,cAAA,CAACkJ,oBAAAA,EAAAA,EAAAA;;;AAGH,kDAAAlJ,cAAA,CAACyI,kBAAKR,OAAO,EAAA;wCAACU,KAAAA,EAAM,SAAA;AAClB,wCAAA,QAAA,gBAAA3I,cAAA,CAACN,YAAAA,EAAAA;4CACCC,YAAAA,EAAa,SAAA;AACbC,4CAAAA,QAAAA,EAAUsE,UAAUqB,WAAAA,EAAanB,IAAAA;4CACjCvE,OAAAA,EAASA;;;AAIb,kDAAAG,cAAA,CAACyI,kBAAKR,OAAO,EAAA;wCAACU,KAAAA,EAAM,MAAA;AAClB,wCAAA,QAAA,gBAAA3I,cAAA,CAACN,YAAAA,EAAAA;4CACCC,YAAAA,EAAa,MAAA;AACbC,4CAAAA,QAAAA,EAAUsE,UAAUqB,WAAAA,EAAanB,IAAAA;4CACjCvE,OAAAA,EAASA;;;;;AAIf,0CAAA+B,eAAA,CAACuH,uBAAWtI,IAAI,EAAA;gCACb,GAAGqD,QAAAA,EAAUqB,WAAAA,EAAaC,IAAAA,EAAMkB,UAAU;gCAC3C0C,eAAAA,EAAiBlF,QAAAA,EAAUqB,WAAAA,EAAaC,IAAAA,EAAMkB,UAAAA,EAAYD,QAAAA;;AAE1D,kDAAAzG,cAAA,CAACmJ,uBAAWE,QAAQ,EAAA;wCAACC,OAAAA,EAAS;AAAC,4CAAA,GAAA;AAAK,4CAAA,IAAA;AAAM,4CAAA,IAAA;AAAM,4CAAA;AAAK;;AACrD,kDAAAtJ,cAAA,CAACmJ,uBAAWI,KAAK,EAAA,EAAA;;;;;;8BAIvBvJ,cAAA,CAACwJ,yBAAAA,EAAAA;oBACCC,IAAAA,EAAMpG,iBAAAA;oBACNqG,WAAAA,EAAa1D,qBAAAA;oBACb2D,YAAAA,EAAc7C,gBAAAA;oBACdzC,SAAAA,EAAWI,gBAAAA;oBACXmF,aAAAA,EAAe;AACb,wBAAA,GAAGhH,mBAAmB;AACtBK,wBAAAA,QAAAA,EAAUmB,IAAAA,EAAMA,IAAAA,CAAKyF,eAAAA,GAAkBzF,IAAAA,CAAKA,IAAI,CAACyF,eAAe,CAACC,KAAK,CAAC,GAAA,CAAI,CAAC,EAAE,GAAG;AACnF;;;;;AAKV;;;;;"}
@@ -194,7 +194,6 @@ const ReleasesPage = ()=>{
194
194
  const hasReachedMaximumPendingReleases = totalPendingReleases >= maximumReleases;
195
195
  const handleTabChange = (tabValue)=>{
196
196
  setQuery({
197
- ...query,
198
197
  page: 1,
199
198
  pageSize: response?.currentData?.meta?.pagination?.pageSize || 16,
200
199
  filters: {
@@ -1 +1 @@
1
- {"version":3,"file":"ReleasesPage.mjs","sources":["../../../admin/src/pages/ReleasesPage.tsx"],"sourcesContent":["import * as React from 'react';\n\nimport {\n Page,\n Pagination,\n useTracking,\n useAPIErrorHandler,\n useNotification,\n useQueryParams,\n useRBAC,\n isFetchError,\n Layouts,\n GradientBadge,\n} from '@strapi/admin/strapi-admin';\nimport { useLicenseLimits } from '@strapi/admin/strapi-admin/ee';\nimport {\n Alert,\n Badge,\n Box,\n Button,\n Divider,\n EmptyStateLayout,\n Flex,\n Grid,\n Main,\n Tabs,\n Typography,\n Link,\n} from '@strapi/design-system';\nimport { Plus } from '@strapi/icons';\nimport { EmptyDocuments } from '@strapi/icons/symbols';\nimport { format } from 'date-fns';\nimport { useIntl } from 'react-intl';\nimport { useNavigate, useLocation, NavLink } from 'react-router-dom';\nimport { styled } from 'styled-components';\n\nimport { GetReleases, type Release } from '../../../shared/contracts/releases';\nimport { RelativeTime as BaseRelativeTime } from '../components/RelativeTime';\nimport { ReleaseModal, FormValues } from '../components/ReleaseModal';\nimport { PERMISSIONS } from '../constants';\nimport {\n useGetReleasesQuery,\n useGetReleaseSettingsQuery,\n GetReleasesQueryParams,\n useCreateReleaseMutation,\n} from '../services/release';\n\n/* -------------------------------------------------------------------------------------------------\n * ReleasesGrid\n * -----------------------------------------------------------------------------------------------*/\ninterface ReleasesGridProps {\n sectionTitle: 'pending' | 'done';\n releases?: GetReleases.Response['data'];\n isError?: boolean;\n}\n\nconst LinkCard = styled(Link)`\n display: block;\n`;\n\nconst RelativeTime = styled(BaseRelativeTime)`\n display: inline-block;\n &::first-letter {\n text-transform: uppercase;\n }\n`;\n\nconst getBadgeProps = (status: Release['status']) => {\n let color;\n switch (status) {\n case 'ready':\n color = 'success';\n break;\n case 'blocked':\n color = 'warning';\n break;\n case 'failed':\n color = 'danger';\n break;\n case 'done':\n color = 'primary';\n break;\n case 'empty':\n default:\n color = 'neutral';\n }\n\n return {\n textColor: `${color}600`,\n backgroundColor: `${color}100`,\n borderColor: `${color}200`,\n };\n};\n\nconst ReleasesGrid = ({ sectionTitle, releases = [], isError = false }: ReleasesGridProps) => {\n const { formatMessage } = useIntl();\n\n if (isError) {\n return <Page.Error />;\n }\n\n if (releases?.length === 0) {\n return (\n <EmptyStateLayout\n content={formatMessage(\n {\n id: 'content-releases.page.Releases.tab.emptyEntries',\n defaultMessage: 'No releases',\n },\n {\n target: sectionTitle,\n }\n )}\n icon={<EmptyDocuments width=\"16rem\" />}\n />\n );\n }\n\n return (\n <Grid.Root gap={4}>\n {releases.map(({ id, name, scheduledAt, status }) => (\n <Grid.Item col={3} s={6} xs={12} key={id} direction=\"column\" alignItems=\"stretch\">\n <LinkCard tag={NavLink} to={`${id}`} isExternal={false}>\n <Flex\n direction=\"column\"\n justifyContent=\"space-between\"\n padding={4}\n hasRadius\n background=\"neutral0\"\n shadow=\"tableShadow\"\n height=\"100%\"\n width=\"100%\"\n alignItems=\"start\"\n gap={4}\n >\n <Flex direction=\"column\" alignItems=\"start\" gap={1}>\n <Typography textColor=\"neutral800\" tag=\"h3\" variant=\"delta\" fontWeight=\"bold\">\n {name}\n </Typography>\n <Typography variant=\"pi\" textColor=\"neutral600\">\n {scheduledAt ? (\n <RelativeTime timestamp={new Date(scheduledAt)} />\n ) : (\n formatMessage({\n id: 'content-releases.pages.Releases.not-scheduled',\n defaultMessage: 'Not scheduled',\n })\n )}\n </Typography>\n </Flex>\n <Badge {...getBadgeProps(status)}>{status}</Badge>\n </Flex>\n </LinkCard>\n </Grid.Item>\n ))}\n </Grid.Root>\n );\n};\n\n/* -------------------------------------------------------------------------------------------------\n * ReleasesPage\n * -----------------------------------------------------------------------------------------------*/\n\nconst StyledAlert = styled(Alert)`\n button {\n display: none;\n }\n p + div {\n margin-left: auto;\n }\n`;\n\nconst INITIAL_FORM_VALUES = {\n name: '',\n date: format(new Date(), 'yyyy-MM-dd'),\n time: '',\n isScheduled: true,\n scheduledAt: null,\n timezone: null,\n} satisfies FormValues;\n\nconst ReleasesPage = () => {\n const location = useLocation();\n const [releaseModalShown, setReleaseModalShown] = React.useState(false);\n const { toggleNotification } = useNotification();\n const { formatMessage } = useIntl();\n const navigate = useNavigate();\n const { formatAPIError } = useAPIErrorHandler();\n const [{ query }, setQuery] = useQueryParams<GetReleasesQueryParams>();\n const response = useGetReleasesQuery(query);\n const { data, isLoading: isLoadingSettings } = useGetReleaseSettingsQuery();\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: isLoadingReleases, isSuccess, isError } = response;\n const activeTab = response?.currentData?.meta?.activeTab || 'pending';\n\n // Check if we have some errors and show a notification to the user to explain the error\n React.useEffect(() => {\n if (location?.state?.errors) {\n toggleNotification({\n type: 'danger',\n title: formatMessage({\n id: 'content-releases.pages.Releases.notification.error.title',\n defaultMessage: 'Your request could not be processed.',\n }),\n message: formatMessage({\n id: 'content-releases.pages.Releases.notification.error.message',\n defaultMessage: 'Please try again or open another release.',\n }),\n });\n navigate('', { replace: true, state: null });\n }\n }, [formatMessage, location?.state?.errors, navigate, toggleNotification]);\n\n const toggleAddReleaseModal = () => {\n setReleaseModalShown((prev) => !prev);\n };\n\n if (isLoadingReleases || isLoadingSettings) {\n return <Page.Loading />;\n }\n\n const totalPendingReleases = (isSuccess && response.currentData?.meta?.pendingReleasesCount) || 0;\n const hasReachedMaximumPendingReleases = totalPendingReleases >= maximumReleases;\n\n const handleTabChange = (tabValue: string) => {\n setQuery({\n ...query,\n page: 1,\n pageSize: response?.currentData?.meta?.pagination?.pageSize || 16,\n filters: {\n releasedAt: {\n $notNull: tabValue !== 'pending',\n },\n },\n });\n };\n\n const handleAddRelease = async ({ name, scheduledAt, timezone }: FormValues) => {\n const response = await createRelease({\n name,\n scheduledAt,\n timezone,\n });\n if ('data' in response) {\n // When the response returns an object with 'data', handle success\n toggleNotification({\n type: 'success',\n message: formatMessage({\n id: 'content-releases.modal.release-created-notification-success',\n defaultMessage: 'Release created.',\n }),\n });\n\n trackUsage('didCreateRelease');\n navigate(response.data.data.id.toString());\n } else if (isFetchError(response.error)) {\n // When the response returns an object with 'error', handle fetch error\n toggleNotification({\n type: 'danger',\n message: formatAPIError(response.error),\n });\n } else {\n // Otherwise, the response returns an object with 'error', handle a generic error\n toggleNotification({\n type: 'danger',\n message: formatMessage({ id: 'notification.error', defaultMessage: 'An error occurred' }),\n });\n }\n };\n\n return (\n <Layouts.Root>\n <Main aria-busy={isLoadingReleases || isLoadingSettings}>\n <Layouts.Header\n title={formatMessage({\n id: 'content-releases.pages.Releases.title',\n defaultMessage: 'Releases',\n })}\n secondaryAction={\n <GradientBadge\n label={formatMessage({\n id: 'components.premiumFeature.title',\n defaultMessage: 'Premium feature',\n })}\n />\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 fullWidth\n >\n {formatMessage({\n id: 'content-releases.header.actions.add-release',\n defaultMessage: 'New release',\n })}\n </Button>\n ) : null\n }\n />\n <Layouts.Content>\n <>\n {hasReachedMaximumPendingReleases && (\n <StyledAlert\n marginBottom={6}\n action={\n <Link href=\"https://strapi.io/pricing-cloud\" isExternal>\n {formatMessage({\n id: 'content-releases.pages.Releases.max-limit-reached.action',\n defaultMessage: 'Explore plans',\n })}\n </Link>\n }\n title={formatMessage(\n {\n id: 'content-releases.pages.Releases.max-limit-reached.title',\n defaultMessage:\n 'You have reached the {number} pending {number, plural, one {release} other {releases}} limit.',\n },\n { number: maximumReleases }\n )}\n onClose={() => {}}\n closeLabel=\"\"\n >\n {formatMessage({\n id: 'content-releases.pages.Releases.max-limit-reached.message',\n defaultMessage: 'Upgrade to manage an unlimited number of releases.',\n })}\n </StyledAlert>\n )}\n <Tabs.Root variant=\"simple\" onValueChange={handleTabChange} value={activeTab}>\n <Box paddingBottom={8}>\n <Tabs.List\n aria-label={formatMessage({\n id: 'content-releases.pages.Releases.tab-group.label',\n defaultMessage: 'Releases list',\n })}\n >\n <Tabs.Trigger value=\"pending\">\n {formatMessage(\n {\n id: 'content-releases.pages.Releases.tab.pending',\n defaultMessage: 'Pending ({count})',\n },\n {\n count: totalPendingReleases,\n }\n )}\n </Tabs.Trigger>\n <Tabs.Trigger value=\"done\">\n {formatMessage({\n id: 'content-releases.pages.Releases.tab.done',\n defaultMessage: 'Done',\n })}\n </Tabs.Trigger>\n </Tabs.List>\n <Divider />\n </Box>\n {/* Pending releases */}\n <Tabs.Content value=\"pending\">\n <ReleasesGrid\n sectionTitle=\"pending\"\n releases={response?.currentData?.data}\n isError={isError}\n />\n </Tabs.Content>\n {/* Done releases */}\n <Tabs.Content value=\"done\">\n <ReleasesGrid\n sectionTitle=\"done\"\n releases={response?.currentData?.data}\n isError={isError}\n />\n </Tabs.Content>\n </Tabs.Root>\n <Pagination.Root\n {...response?.currentData?.meta?.pagination}\n defaultPageSize={response?.currentData?.meta?.pagination?.pageSize}\n >\n <Pagination.PageSize options={['8', '16', '32', '64']} />\n <Pagination.Links />\n </Pagination.Root>\n </>\n </Layouts.Content>\n <ReleaseModal\n open={releaseModalShown}\n handleClose={toggleAddReleaseModal}\n handleSubmit={handleAddRelease}\n isLoading={isSubmittingForm}\n initialValues={{\n ...INITIAL_FORM_VALUES,\n timezone: data?.data.defaultTimezone ? data.data.defaultTimezone.split('&')[1] : null,\n }}\n />\n </Main>\n </Layouts.Root>\n );\n};\n\nexport { ReleasesPage, getBadgeProps };\n"],"names":["LinkCard","styled","Link","RelativeTime","BaseRelativeTime","getBadgeProps","status","color","textColor","backgroundColor","borderColor","ReleasesGrid","sectionTitle","releases","isError","formatMessage","useIntl","_jsx","Page","Error","length","EmptyStateLayout","content","id","defaultMessage","target","icon","EmptyDocuments","width","Grid","Root","gap","map","name","scheduledAt","Item","col","s","xs","direction","alignItems","tag","NavLink","to","isExternal","_jsxs","Flex","justifyContent","padding","hasRadius","background","shadow","height","Typography","variant","fontWeight","timestamp","Date","Badge","StyledAlert","Alert","INITIAL_FORM_VALUES","date","format","time","isScheduled","timezone","ReleasesPage","location","useLocation","releaseModalShown","setReleaseModalShown","React","useState","toggleNotification","useNotification","navigate","useNavigate","formatAPIError","useAPIErrorHandler","query","setQuery","useQueryParams","response","useGetReleasesQuery","data","isLoading","isLoadingSettings","useGetReleaseSettingsQuery","createRelease","isSubmittingForm","useCreateReleaseMutation","getFeature","useLicenseLimits","maximumReleases","trackUsage","useTracking","allowedActions","canCreate","useRBAC","PERMISSIONS","isLoadingReleases","isSuccess","activeTab","currentData","meta","useEffect","state","errors","type","title","message","replace","toggleAddReleaseModal","prev","Loading","totalPendingReleases","pendingReleasesCount","hasReachedMaximumPendingReleases","handleTabChange","tabValue","page","pageSize","pagination","filters","releasedAt","$notNull","handleAddRelease","toString","isFetchError","error","Layouts","Main","aria-busy","Header","secondaryAction","GradientBadge","label","subtitle","primaryAction","Button","startIcon","Plus","onClick","disabled","fullWidth","Content","_Fragment","marginBottom","action","href","number","onClose","closeLabel","Tabs","onValueChange","value","Box","paddingBottom","List","aria-label","Trigger","count","Divider","Pagination","defaultPageSize","PageSize","options","Links","ReleaseModal","open","handleClose","handleSubmit","initialValues","defaultTimezone","split"],"mappings":"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"}
1
+ {"version":3,"file":"ReleasesPage.mjs","sources":["../../../admin/src/pages/ReleasesPage.tsx"],"sourcesContent":["import * as React from 'react';\n\nimport {\n Page,\n Pagination,\n useTracking,\n useAPIErrorHandler,\n useNotification,\n useQueryParams,\n useRBAC,\n isFetchError,\n Layouts,\n GradientBadge,\n} from '@strapi/admin/strapi-admin';\nimport { useLicenseLimits } from '@strapi/admin/strapi-admin/ee';\nimport {\n Alert,\n Badge,\n Box,\n Button,\n Divider,\n EmptyStateLayout,\n Flex,\n Grid,\n Main,\n Tabs,\n Typography,\n Link,\n} from '@strapi/design-system';\nimport { Plus } from '@strapi/icons';\nimport { EmptyDocuments } from '@strapi/icons/symbols';\nimport { format } from 'date-fns';\nimport { useIntl } from 'react-intl';\nimport { useNavigate, useLocation, NavLink } from 'react-router-dom';\nimport { styled } from 'styled-components';\n\nimport { GetReleases, type Release } from '../../../shared/contracts/releases';\nimport { RelativeTime as BaseRelativeTime } from '../components/RelativeTime';\nimport { ReleaseModal, FormValues } from '../components/ReleaseModal';\nimport { PERMISSIONS } from '../constants';\nimport {\n useGetReleasesQuery,\n useGetReleaseSettingsQuery,\n GetReleasesQueryParams,\n useCreateReleaseMutation,\n} from '../services/release';\n\n/* -------------------------------------------------------------------------------------------------\n * ReleasesGrid\n * -----------------------------------------------------------------------------------------------*/\ninterface ReleasesGridProps {\n sectionTitle: 'pending' | 'done';\n releases?: GetReleases.Response['data'];\n isError?: boolean;\n}\n\nconst LinkCard = styled(Link)`\n display: block;\n`;\n\nconst RelativeTime = styled(BaseRelativeTime)`\n display: inline-block;\n &::first-letter {\n text-transform: uppercase;\n }\n`;\n\nconst getBadgeProps = (status: Release['status']) => {\n let color;\n switch (status) {\n case 'ready':\n color = 'success';\n break;\n case 'blocked':\n color = 'warning';\n break;\n case 'failed':\n color = 'danger';\n break;\n case 'done':\n color = 'primary';\n break;\n case 'empty':\n default:\n color = 'neutral';\n }\n\n return {\n textColor: `${color}600`,\n backgroundColor: `${color}100`,\n borderColor: `${color}200`,\n };\n};\n\nconst ReleasesGrid = ({ sectionTitle, releases = [], isError = false }: ReleasesGridProps) => {\n const { formatMessage } = useIntl();\n\n if (isError) {\n return <Page.Error />;\n }\n\n if (releases?.length === 0) {\n return (\n <EmptyStateLayout\n content={formatMessage(\n {\n id: 'content-releases.page.Releases.tab.emptyEntries',\n defaultMessage: 'No releases',\n },\n {\n target: sectionTitle,\n }\n )}\n icon={<EmptyDocuments width=\"16rem\" />}\n />\n );\n }\n\n return (\n <Grid.Root gap={4}>\n {releases.map(({ id, name, scheduledAt, status }) => (\n <Grid.Item col={3} s={6} xs={12} key={id} direction=\"column\" alignItems=\"stretch\">\n <LinkCard tag={NavLink} to={`${id}`} isExternal={false}>\n <Flex\n direction=\"column\"\n justifyContent=\"space-between\"\n padding={4}\n hasRadius\n background=\"neutral0\"\n shadow=\"tableShadow\"\n height=\"100%\"\n width=\"100%\"\n alignItems=\"start\"\n gap={4}\n >\n <Flex direction=\"column\" alignItems=\"start\" gap={1}>\n <Typography textColor=\"neutral800\" tag=\"h3\" variant=\"delta\" fontWeight=\"bold\">\n {name}\n </Typography>\n <Typography variant=\"pi\" textColor=\"neutral600\">\n {scheduledAt ? (\n <RelativeTime timestamp={new Date(scheduledAt)} />\n ) : (\n formatMessage({\n id: 'content-releases.pages.Releases.not-scheduled',\n defaultMessage: 'Not scheduled',\n })\n )}\n </Typography>\n </Flex>\n <Badge {...getBadgeProps(status)}>{status}</Badge>\n </Flex>\n </LinkCard>\n </Grid.Item>\n ))}\n </Grid.Root>\n );\n};\n\n/* -------------------------------------------------------------------------------------------------\n * ReleasesPage\n * -----------------------------------------------------------------------------------------------*/\n\nconst StyledAlert = styled(Alert)`\n button {\n display: none;\n }\n p + div {\n margin-left: auto;\n }\n`;\n\nconst INITIAL_FORM_VALUES = {\n name: '',\n date: format(new Date(), 'yyyy-MM-dd'),\n time: '',\n isScheduled: true,\n scheduledAt: null,\n timezone: null,\n} satisfies FormValues;\n\nconst ReleasesPage = () => {\n const location = useLocation();\n const [releaseModalShown, setReleaseModalShown] = React.useState(false);\n const { toggleNotification } = useNotification();\n const { formatMessage } = useIntl();\n const navigate = useNavigate();\n const { formatAPIError } = useAPIErrorHandler();\n const [{ query }, setQuery] = useQueryParams<GetReleasesQueryParams>();\n const response = useGetReleasesQuery(query);\n const { data, isLoading: isLoadingSettings } = useGetReleaseSettingsQuery();\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: isLoadingReleases, isSuccess, isError } = response;\n const activeTab = response?.currentData?.meta?.activeTab || 'pending';\n\n // Check if we have some errors and show a notification to the user to explain the error\n React.useEffect(() => {\n if (location?.state?.errors) {\n toggleNotification({\n type: 'danger',\n title: formatMessage({\n id: 'content-releases.pages.Releases.notification.error.title',\n defaultMessage: 'Your request could not be processed.',\n }),\n message: formatMessage({\n id: 'content-releases.pages.Releases.notification.error.message',\n defaultMessage: 'Please try again or open another release.',\n }),\n });\n navigate('', { replace: true, state: null });\n }\n }, [formatMessage, location?.state?.errors, navigate, toggleNotification]);\n\n const toggleAddReleaseModal = () => {\n setReleaseModalShown((prev) => !prev);\n };\n\n if (isLoadingReleases || isLoadingSettings) {\n return <Page.Loading />;\n }\n\n const totalPendingReleases = (isSuccess && response.currentData?.meta?.pendingReleasesCount) || 0;\n const hasReachedMaximumPendingReleases = totalPendingReleases >= maximumReleases;\n\n const handleTabChange = (tabValue: string) => {\n setQuery({\n page: 1,\n pageSize: response?.currentData?.meta?.pagination?.pageSize || 16,\n filters: {\n releasedAt: {\n $notNull: tabValue !== 'pending',\n },\n },\n });\n };\n\n const handleAddRelease = async ({ name, scheduledAt, timezone }: FormValues) => {\n const response = await createRelease({\n name,\n scheduledAt,\n timezone,\n });\n if ('data' in response) {\n // When the response returns an object with 'data', handle success\n toggleNotification({\n type: 'success',\n message: formatMessage({\n id: 'content-releases.modal.release-created-notification-success',\n defaultMessage: 'Release created.',\n }),\n });\n\n trackUsage('didCreateRelease');\n navigate(response.data.data.id.toString());\n } else if (isFetchError(response.error)) {\n // When the response returns an object with 'error', handle fetch error\n toggleNotification({\n type: 'danger',\n message: formatAPIError(response.error),\n });\n } else {\n // Otherwise, the response returns an object with 'error', handle a generic error\n toggleNotification({\n type: 'danger',\n message: formatMessage({ id: 'notification.error', defaultMessage: 'An error occurred' }),\n });\n }\n };\n\n return (\n <Layouts.Root>\n <Main aria-busy={isLoadingReleases || isLoadingSettings}>\n <Layouts.Header\n title={formatMessage({\n id: 'content-releases.pages.Releases.title',\n defaultMessage: 'Releases',\n })}\n secondaryAction={\n <GradientBadge\n label={formatMessage({\n id: 'components.premiumFeature.title',\n defaultMessage: 'Premium feature',\n })}\n />\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 fullWidth\n >\n {formatMessage({\n id: 'content-releases.header.actions.add-release',\n defaultMessage: 'New release',\n })}\n </Button>\n ) : null\n }\n />\n <Layouts.Content>\n <>\n {hasReachedMaximumPendingReleases && (\n <StyledAlert\n marginBottom={6}\n action={\n <Link href=\"https://strapi.io/pricing-cloud\" isExternal>\n {formatMessage({\n id: 'content-releases.pages.Releases.max-limit-reached.action',\n defaultMessage: 'Explore plans',\n })}\n </Link>\n }\n title={formatMessage(\n {\n id: 'content-releases.pages.Releases.max-limit-reached.title',\n defaultMessage:\n 'You have reached the {number} pending {number, plural, one {release} other {releases}} limit.',\n },\n { number: maximumReleases }\n )}\n onClose={() => {}}\n closeLabel=\"\"\n >\n {formatMessage({\n id: 'content-releases.pages.Releases.max-limit-reached.message',\n defaultMessage: 'Upgrade to manage an unlimited number of releases.',\n })}\n </StyledAlert>\n )}\n <Tabs.Root variant=\"simple\" onValueChange={handleTabChange} value={activeTab}>\n <Box paddingBottom={8}>\n <Tabs.List\n aria-label={formatMessage({\n id: 'content-releases.pages.Releases.tab-group.label',\n defaultMessage: 'Releases list',\n })}\n >\n <Tabs.Trigger value=\"pending\">\n {formatMessage(\n {\n id: 'content-releases.pages.Releases.tab.pending',\n defaultMessage: 'Pending ({count})',\n },\n {\n count: totalPendingReleases,\n }\n )}\n </Tabs.Trigger>\n <Tabs.Trigger value=\"done\">\n {formatMessage({\n id: 'content-releases.pages.Releases.tab.done',\n defaultMessage: 'Done',\n })}\n </Tabs.Trigger>\n </Tabs.List>\n <Divider />\n </Box>\n {/* Pending releases */}\n <Tabs.Content value=\"pending\">\n <ReleasesGrid\n sectionTitle=\"pending\"\n releases={response?.currentData?.data}\n isError={isError}\n />\n </Tabs.Content>\n {/* Done releases */}\n <Tabs.Content value=\"done\">\n <ReleasesGrid\n sectionTitle=\"done\"\n releases={response?.currentData?.data}\n isError={isError}\n />\n </Tabs.Content>\n </Tabs.Root>\n <Pagination.Root\n {...response?.currentData?.meta?.pagination}\n defaultPageSize={response?.currentData?.meta?.pagination?.pageSize}\n >\n <Pagination.PageSize options={['8', '16', '32', '64']} />\n <Pagination.Links />\n </Pagination.Root>\n </>\n </Layouts.Content>\n <ReleaseModal\n open={releaseModalShown}\n handleClose={toggleAddReleaseModal}\n handleSubmit={handleAddRelease}\n isLoading={isSubmittingForm}\n initialValues={{\n ...INITIAL_FORM_VALUES,\n timezone: data?.data.defaultTimezone ? data.data.defaultTimezone.split('&')[1] : null,\n }}\n />\n </Main>\n </Layouts.Root>\n );\n};\n\nexport { ReleasesPage, getBadgeProps };\n"],"names":["LinkCard","styled","Link","RelativeTime","BaseRelativeTime","getBadgeProps","status","color","textColor","backgroundColor","borderColor","ReleasesGrid","sectionTitle","releases","isError","formatMessage","useIntl","_jsx","Page","Error","length","EmptyStateLayout","content","id","defaultMessage","target","icon","EmptyDocuments","width","Grid","Root","gap","map","name","scheduledAt","Item","col","s","xs","direction","alignItems","tag","NavLink","to","isExternal","_jsxs","Flex","justifyContent","padding","hasRadius","background","shadow","height","Typography","variant","fontWeight","timestamp","Date","Badge","StyledAlert","Alert","INITIAL_FORM_VALUES","date","format","time","isScheduled","timezone","ReleasesPage","location","useLocation","releaseModalShown","setReleaseModalShown","React","useState","toggleNotification","useNotification","navigate","useNavigate","formatAPIError","useAPIErrorHandler","query","setQuery","useQueryParams","response","useGetReleasesQuery","data","isLoading","isLoadingSettings","useGetReleaseSettingsQuery","createRelease","isSubmittingForm","useCreateReleaseMutation","getFeature","useLicenseLimits","maximumReleases","trackUsage","useTracking","allowedActions","canCreate","useRBAC","PERMISSIONS","isLoadingReleases","isSuccess","activeTab","currentData","meta","useEffect","state","errors","type","title","message","replace","toggleAddReleaseModal","prev","Loading","totalPendingReleases","pendingReleasesCount","hasReachedMaximumPendingReleases","handleTabChange","tabValue","page","pageSize","pagination","filters","releasedAt","$notNull","handleAddRelease","toString","isFetchError","error","Layouts","Main","aria-busy","Header","secondaryAction","GradientBadge","label","subtitle","primaryAction","Button","startIcon","Plus","onClick","disabled","fullWidth","Content","_Fragment","marginBottom","action","href","number","onClose","closeLabel","Tabs","onValueChange","value","Box","paddingBottom","List","aria-label","Trigger","count","Divider","Pagination","defaultPageSize","PageSize","options","Links","ReleaseModal","open","handleClose","handleSubmit","initialValues","defaultTimezone","split"],"mappings":";;;;;;;;;;;;;;;;AAwDA,MAAMA,QAAAA,GAAWC,MAAAA,CAAOC,IAAAA,CAAK;;AAE7B,CAAC;AAED,MAAMC,YAAAA,GAAeF,MAAAA,CAAOG,cAAAA,CAAiB;;;;;AAK7C,CAAC;AAED,MAAMC,gBAAgB,CAACC,MAAAA,GAAAA;IACrB,IAAIC,KAAAA;IACJ,OAAQD,MAAAA;QACN,KAAK,OAAA;YACHC,KAAAA,GAAQ,SAAA;AACR,YAAA;QACF,KAAK,SAAA;YACHA,KAAAA,GAAQ,SAAA;AACR,YAAA;QACF,KAAK,QAAA;YACHA,KAAAA,GAAQ,QAAA;AACR,YAAA;QACF,KAAK,MAAA;YACHA,KAAAA,GAAQ,SAAA;AACR,YAAA;QACF,KAAK,OAAA;AACL,QAAA;YACEA,KAAAA,GAAQ,SAAA;AACZ;IAEA,OAAO;QACLC,SAAAA,EAAW,CAAA,EAAGD,KAAAA,CAAM,GAAG,CAAC;QACxBE,eAAAA,EAAiB,CAAA,EAAGF,KAAAA,CAAM,GAAG,CAAC;QAC9BG,WAAAA,EAAa,CAAA,EAAGH,KAAAA,CAAM,GAAG;AAC3B,KAAA;AACF;AAEA,MAAMI,YAAAA,GAAe,CAAC,EAAEC,YAAY,EAAEC,WAAW,EAAE,EAAEC,OAAAA,GAAU,KAAK,EAAqB,GAAA;IACvF,MAAM,EAAEC,aAAa,EAAE,GAAGC,OAAAA,EAAAA;AAE1B,IAAA,IAAIF,OAAAA,EAAS;QACX,qBAAOG,GAAA,CAACC,KAAKC,KAAK,EAAA,EAAA,CAAA;AACpB,IAAA;IAEA,IAAIN,QAAAA,EAAUO,WAAW,CAAA,EAAG;AAC1B,QAAA,qBACEH,GAAA,CAACI,gBAAAA,EAAAA;AACCC,YAAAA,OAAAA,EAASP,aAAAA,CACP;gBACEQ,EAAAA,EAAI,iDAAA;gBACJC,cAAAA,EAAgB;aAClB,EACA;gBACEC,MAAAA,EAAQb;AACV,aAAA,CAAA;AAEFc,YAAAA,IAAAA,gBAAMT,GAAA,CAACU,cAAAA,EAAAA;gBAAeC,KAAAA,EAAM;;;AAGlC,IAAA;IAEA,qBACEX,GAAA,CAACY,KAAKC,IAAI,EAAA;QAACC,GAAAA,EAAK,CAAA;AACblB,QAAAA,QAAAA,EAAAA,QAAAA,CAASmB,GAAG,CAAC,CAAC,EAAET,EAAE,EAAEU,IAAI,EAAEC,WAAW,EAAE5B,MAAM,EAAE,iBAC9CW,GAAA,CAACY,KAAKM,IAAI,EAAA;gBAACC,GAAAA,EAAK,CAAA;gBAAGC,CAAAA,EAAG,CAAA;gBAAGC,EAAAA,EAAI,EAAA;gBAAaC,SAAAA,EAAU,QAAA;gBAASC,UAAAA,EAAW,SAAA;AACtE,gBAAA,QAAA,gBAAAvB,GAAA,CAACjB,QAAAA,EAAAA;oBAASyC,GAAAA,EAAKC,OAAAA;AAASC,oBAAAA,EAAAA,EAAI,GAAGpB,EAAAA,CAAAA,CAAI;oBAAEqB,UAAAA,EAAY,KAAA;AAC/C,oBAAA,QAAA,gBAAAC,IAAA,CAACC,IAAAA,EAAAA;wBACCP,SAAAA,EAAU,QAAA;wBACVQ,cAAAA,EAAe,eAAA;wBACfC,OAAAA,EAAS,CAAA;wBACTC,SAAS,EAAA,IAAA;wBACTC,UAAAA,EAAW,UAAA;wBACXC,MAAAA,EAAO,aAAA;wBACPC,MAAAA,EAAO,MAAA;wBACPxB,KAAAA,EAAM,MAAA;wBACNY,UAAAA,EAAW,OAAA;wBACXT,GAAAA,EAAK,CAAA;;0CAELc,IAAA,CAACC,IAAAA,EAAAA;gCAAKP,SAAAA,EAAU,QAAA;gCAASC,UAAAA,EAAW,OAAA;gCAAQT,GAAAA,EAAK,CAAA;;kDAC/Cd,GAAA,CAACoC,UAAAA,EAAAA;wCAAW7C,SAAAA,EAAU,YAAA;wCAAaiC,GAAAA,EAAI,IAAA;wCAAKa,OAAAA,EAAQ,OAAA;wCAAQC,UAAAA,EAAW,MAAA;AACpEtB,wCAAAA,QAAAA,EAAAA;;kDAEHhB,GAAA,CAACoC,UAAAA,EAAAA;wCAAWC,OAAAA,EAAQ,IAAA;wCAAK9C,SAAAA,EAAU,YAAA;AAChC0B,wCAAAA,QAAAA,EAAAA,WAAAA,iBACCjB,GAAA,CAACd,YAAAA,EAAAA;AAAaqD,4CAAAA,SAAAA,EAAW,IAAIC,IAAAA,CAAKvB,WAAAA;6CAElCnB,aAAAA,CAAc;4CACZQ,EAAAA,EAAI,+CAAA;4CACJC,cAAAA,EAAgB;AAClB,yCAAA;;;;0CAINP,GAAA,CAACyC,KAAAA,EAAAA;AAAO,gCAAA,GAAGrD,cAAcC,MAAAA,CAAO;AAAGA,gCAAAA,QAAAA,EAAAA;;;;;AA7BHiB,aAAAA,EAAAA,EAAAA,CAAAA;;AAoC9C,CAAA;AAEA;;AAEkG,qGAElG,MAAMoC,WAAAA,GAAc1D,MAAAA,CAAO2D,KAAAA,CAAM;;;;;;;AAOjC,CAAC;AAED,MAAMC,mBAAAA,GAAsB;IAC1B5B,IAAAA,EAAM,EAAA;IACN6B,IAAAA,EAAMC,MAAAA,CAAO,IAAIN,IAAAA,EAAAA,EAAQ,YAAA,CAAA;IACzBO,IAAAA,EAAM,EAAA;IACNC,WAAAA,EAAa,IAAA;IACb/B,WAAAA,EAAa,IAAA;IACbgC,QAAAA,EAAU;AACZ,CAAA;AAEA,MAAMC,YAAAA,GAAe,IAAA;AACnB,IAAA,MAAMC,QAAAA,GAAWC,WAAAA,EAAAA;AACjB,IAAA,MAAM,CAACC,iBAAAA,EAAmBC,oBAAAA,CAAqB,GAAGC,KAAAA,CAAMC,QAAQ,CAAC,KAAA,CAAA;IACjE,MAAM,EAAEC,kBAAkB,EAAE,GAAGC,eAAAA,EAAAA;IAC/B,MAAM,EAAE5D,aAAa,EAAE,GAAGC,OAAAA,EAAAA;AAC1B,IAAA,MAAM4D,QAAAA,GAAWC,WAAAA,EAAAA;IACjB,MAAM,EAAEC,cAAc,EAAE,GAAGC,kBAAAA,EAAAA;AAC3B,IAAA,MAAM,CAAC,EAAEC,KAAK,EAAE,EAAEC,SAAS,GAAGC,cAAAA,EAAAA;AAC9B,IAAA,MAAMC,WAAWC,mBAAAA,CAAoBJ,KAAAA,CAAAA;AACrC,IAAA,MAAM,EAAEK,IAAI,EAAEC,SAAAA,EAAWC,iBAAiB,EAAE,GAAGC,0BAAAA,EAAAA;AAC/C,IAAA,MAAM,CAACC,aAAAA,EAAe,EAAEH,WAAWI,gBAAgB,EAAE,CAAC,GAAGC,wBAAAA,EAAAA;IACzD,MAAM,EAAEC,UAAU,EAAE,GAAGC,gBAAAA,EAAAA;AACvB,IAAA,MAAM,EAAEC,eAAAA,GAAkB,CAAC,EAAE,GAAGF,UAAAA,CAAW,sBAAA,CAAA;IAG3C,MAAM,EAAEG,UAAU,EAAE,GAAGC,WAAAA,EAAAA;AACvB,IAAA,MAAM,EACJC,cAAAA,EAAgB,EAAEC,SAAS,EAAE,EAC9B,GAAGC,OAAAA,CAAQC,WAAAA,CAAAA;IAEZ,MAAM,EAAEd,WAAWe,iBAAiB,EAAEC,SAAS,EAAExF,OAAO,EAAE,GAAGqE,QAAAA;AAC7D,IAAA,MAAMoB,SAAAA,GAAYpB,QAAAA,EAAUqB,WAAAA,EAAaC,IAAAA,EAAMF,SAAAA,IAAa,SAAA;;AAG5D/B,IAAAA,KAAAA,CAAMkC,SAAS,CAAC,IAAA;QACd,IAAItC,QAAAA,EAAUuC,OAAOC,MAAAA,EAAQ;YAC3BlC,kBAAAA,CAAmB;gBACjBmC,IAAAA,EAAM,QAAA;AACNC,gBAAAA,KAAAA,EAAO/F,aAAAA,CAAc;oBACnBQ,EAAAA,EAAI,0DAAA;oBACJC,cAAAA,EAAgB;AAClB,iBAAA,CAAA;AACAuF,gBAAAA,OAAAA,EAAShG,aAAAA,CAAc;oBACrBQ,EAAAA,EAAI,4DAAA;oBACJC,cAAAA,EAAgB;AAClB,iBAAA;AACF,aAAA,CAAA;AACAoD,YAAAA,QAAAA,CAAS,EAAA,EAAI;gBAAEoC,OAAAA,EAAS,IAAA;gBAAML,KAAAA,EAAO;AAAK,aAAA,CAAA;AAC5C,QAAA;IACF,CAAA,EAAG;AAAC5F,QAAAA,aAAAA;AAAeqD,QAAAA,QAAAA,EAAUuC,KAAAA,EAAOC,MAAAA;AAAQhC,QAAAA,QAAAA;AAAUF,QAAAA;AAAmB,KAAA,CAAA;AAEzE,IAAA,MAAMuC,qBAAAA,GAAwB,IAAA;QAC5B1C,oBAAAA,CAAqB,CAAC2C,OAAS,CAACA,IAAAA,CAAAA;AAClC,IAAA,CAAA;AAEA,IAAA,IAAIb,qBAAqBd,iBAAAA,EAAmB;QAC1C,qBAAOtE,GAAA,CAACC,KAAKiG,OAAO,EAAA,EAAA,CAAA;AACtB,IAAA;AAEA,IAAA,MAAMC,uBAAuB,SAACd,IAAanB,SAASqB,WAAW,EAAEC,MAAMY,oBAAAA,IAAyB,CAAA;AAChG,IAAA,MAAMC,mCAAmCF,oBAAAA,IAAwBtB,eAAAA;AAEjE,IAAA,MAAMyB,kBAAkB,CAACC,QAAAA,GAAAA;QACvBvC,QAAAA,CAAS;YACPwC,IAAAA,EAAM,CAAA;AACNC,YAAAA,QAAAA,EAAUvC,QAAAA,EAAUqB,WAAAA,EAAaC,IAAAA,EAAMkB,UAAAA,EAAYD,QAAAA,IAAY,EAAA;YAC/DE,OAAAA,EAAS;gBACPC,UAAAA,EAAY;AACVC,oBAAAA,QAAAA,EAAUN,QAAAA,KAAa;AACzB;AACF;AACF,SAAA,CAAA;AACF,IAAA,CAAA;IAEA,MAAMO,gBAAAA,GAAmB,OAAO,EAAE9F,IAAI,EAAEC,WAAW,EAAEgC,QAAQ,EAAc,GAAA;QACzE,MAAMiB,QAAAA,GAAW,MAAMM,aAAAA,CAAc;AACnCxD,YAAAA,IAAAA;AACAC,YAAAA,WAAAA;AACAgC,YAAAA;AACF,SAAA,CAAA;AACA,QAAA,IAAI,UAAUiB,QAAAA,EAAU;;YAEtBT,kBAAAA,CAAmB;gBACjBmC,IAAAA,EAAM,SAAA;AACNE,gBAAAA,OAAAA,EAAShG,aAAAA,CAAc;oBACrBQ,EAAAA,EAAI,6DAAA;oBACJC,cAAAA,EAAgB;AAClB,iBAAA;AACF,aAAA,CAAA;YAEAuE,UAAAA,CAAW,kBAAA,CAAA;AACXnB,YAAAA,QAAAA,CAASO,SAASE,IAAI,CAACA,IAAI,CAAC9D,EAAE,CAACyG,QAAQ,EAAA,CAAA;AACzC,QAAA,CAAA,MAAO,IAAIC,YAAAA,CAAa9C,QAAAA,CAAS+C,KAAK,CAAA,EAAG;;YAEvCxD,kBAAAA,CAAmB;gBACjBmC,IAAAA,EAAM,QAAA;gBACNE,OAAAA,EAASjC,cAAAA,CAAeK,SAAS+C,KAAK;AACxC,aAAA,CAAA;QACF,CAAA,MAAO;;YAELxD,kBAAAA,CAAmB;gBACjBmC,IAAAA,EAAM,QAAA;AACNE,gBAAAA,OAAAA,EAAShG,aAAAA,CAAc;oBAAEQ,EAAAA,EAAI,oBAAA;oBAAsBC,cAAAA,EAAgB;AAAoB,iBAAA;AACzF,aAAA,CAAA;AACF,QAAA;AACF,IAAA,CAAA;IAEA,qBACEP,GAAA,CAACkH,QAAQrG,IAAI,EAAA;AACX,QAAA,QAAA,gBAAAe,IAAA,CAACuF,IAAAA,EAAAA;AAAKC,YAAAA,WAAAA,EAAWhC,iBAAAA,IAAqBd,iBAAAA;;AACpC,8BAAAtE,GAAA,CAACkH,QAAQG,MAAM,EAAA;AACbxB,oBAAAA,KAAAA,EAAO/F,aAAAA,CAAc;wBACnBQ,EAAAA,EAAI,uCAAA;wBACJC,cAAAA,EAAgB;AAClB,qBAAA,CAAA;AACA+G,oBAAAA,eAAAA,gBACEtH,GAAA,CAACuH,aAAAA,EAAAA;AACCC,wBAAAA,KAAAA,EAAO1H,aAAAA,CAAc;4BACnBQ,EAAAA,EAAI,iCAAA;4BACJC,cAAAA,EAAgB;AAClB,yBAAA;;AAGJkH,oBAAAA,QAAAA,EAAU3H,aAAAA,CAAc;wBACtBQ,EAAAA,EAAI,iDAAA;wBACJC,cAAAA,EAAgB;AAClB,qBAAA,CAAA;AACAmH,oBAAAA,aAAAA,EACEzC,0BACEjF,GAAA,CAAC2H,MAAAA,EAAAA;AACCC,wBAAAA,SAAAA,gBAAW5H,GAAA,CAAC6H,IAAAA,EAAAA,EAAAA,CAAAA;wBACZC,OAAAA,EAAS9B,qBAAAA;wBACT+B,QAAAA,EAAU1B,gCAAAA;wBACV2B,SAAS,EAAA,IAAA;kCAERlI,aAAAA,CAAc;4BACbQ,EAAAA,EAAI,6CAAA;4BACJC,cAAAA,EAAgB;AAClB,yBAAA;AAEA,qBAAA,CAAA,GAAA;;AAGR,8BAAAP,GAAA,CAACkH,QAAQe,OAAO,EAAA;4CACdrG,IAAA,CAAAsG,QAAA,EAAA;;AACG7B,4BAAAA,gCAAAA,kBACCrG,GAAA,CAAC0C,WAAAA,EAAAA;gCACCyF,YAAAA,EAAc,CAAA;AACdC,gCAAAA,MAAAA,gBACEpI,GAAA,CAACf,IAAAA,EAAAA;oCAAKoJ,IAAAA,EAAK,iCAAA;oCAAkC1G,UAAU,EAAA,IAAA;8CACpD7B,aAAAA,CAAc;wCACbQ,EAAAA,EAAI,0DAAA;wCACJC,cAAAA,EAAgB;AAClB,qCAAA;;AAGJsF,gCAAAA,KAAAA,EAAO/F,aAAAA,CACL;oCACEQ,EAAAA,EAAI,yDAAA;oCACJC,cAAAA,EACE;iCACJ,EACA;oCAAE+H,MAAAA,EAAQzD;AAAgB,iCAAA,CAAA;AAE5B0D,gCAAAA,OAAAA,EAAS,IAAA,CAAO,CAAA;gCAChBC,UAAAA,EAAW,EAAA;0CAEV1I,aAAAA,CAAc;oCACbQ,EAAAA,EAAI,2DAAA;oCACJC,cAAAA,EAAgB;AAClB,iCAAA;;AAGJ,0CAAAqB,IAAA,CAAC6G,KAAK5H,IAAI,EAAA;gCAACwB,OAAAA,EAAQ,QAAA;gCAASqG,aAAAA,EAAepC,eAAAA;gCAAiBqC,KAAAA,EAAOrD,SAAAA;;kDACjE1D,IAAA,CAACgH,GAAAA,EAAAA;wCAAIC,aAAAA,EAAe,CAAA;;AAClB,0DAAAjH,IAAA,CAAC6G,KAAKK,IAAI,EAAA;AACRC,gDAAAA,YAAAA,EAAYjJ,aAAAA,CAAc;oDACxBQ,EAAAA,EAAI,iDAAA;oDACJC,cAAAA,EAAgB;AAClB,iDAAA,CAAA;;AAEA,kEAAAP,GAAA,CAACyI,KAAKO,OAAO,EAAA;wDAACL,KAAAA,EAAM,SAAA;kEACjB7I,aAAAA,CACC;4DACEQ,EAAAA,EAAI,6CAAA;4DACJC,cAAAA,EAAgB;yDAClB,EACA;4DACE0I,KAAAA,EAAO9C;AACT,yDAAA;;AAGJ,kEAAAnG,GAAA,CAACyI,KAAKO,OAAO,EAAA;wDAACL,KAAAA,EAAM,MAAA;kEACjB7I,aAAAA,CAAc;4DACbQ,EAAAA,EAAI,0CAAA;4DACJC,cAAAA,EAAgB;AAClB,yDAAA;;;;0DAGJP,GAAA,CAACkJ,OAAAA,EAAAA,EAAAA;;;AAGH,kDAAAlJ,GAAA,CAACyI,KAAKR,OAAO,EAAA;wCAACU,KAAAA,EAAM,SAAA;AAClB,wCAAA,QAAA,gBAAA3I,GAAA,CAACN,YAAAA,EAAAA;4CACCC,YAAAA,EAAa,SAAA;AACbC,4CAAAA,QAAAA,EAAUsE,UAAUqB,WAAAA,EAAanB,IAAAA;4CACjCvE,OAAAA,EAASA;;;AAIb,kDAAAG,GAAA,CAACyI,KAAKR,OAAO,EAAA;wCAACU,KAAAA,EAAM,MAAA;AAClB,wCAAA,QAAA,gBAAA3I,GAAA,CAACN,YAAAA,EAAAA;4CACCC,YAAAA,EAAa,MAAA;AACbC,4CAAAA,QAAAA,EAAUsE,UAAUqB,WAAAA,EAAanB,IAAAA;4CACjCvE,OAAAA,EAASA;;;;;AAIf,0CAAA+B,IAAA,CAACuH,WAAWtI,IAAI,EAAA;gCACb,GAAGqD,QAAAA,EAAUqB,WAAAA,EAAaC,IAAAA,EAAMkB,UAAU;gCAC3C0C,eAAAA,EAAiBlF,QAAAA,EAAUqB,WAAAA,EAAaC,IAAAA,EAAMkB,UAAAA,EAAYD,QAAAA;;AAE1D,kDAAAzG,GAAA,CAACmJ,WAAWE,QAAQ,EAAA;wCAACC,OAAAA,EAAS;AAAC,4CAAA,GAAA;AAAK,4CAAA,IAAA;AAAM,4CAAA,IAAA;AAAM,4CAAA;AAAK;;AACrD,kDAAAtJ,GAAA,CAACmJ,WAAWI,KAAK,EAAA,EAAA;;;;;;8BAIvBvJ,GAAA,CAACwJ,YAAAA,EAAAA;oBACCC,IAAAA,EAAMpG,iBAAAA;oBACNqG,WAAAA,EAAa1D,qBAAAA;oBACb2D,YAAAA,EAAc7C,gBAAAA;oBACdzC,SAAAA,EAAWI,gBAAAA;oBACXmF,aAAAA,EAAe;AACb,wBAAA,GAAGhH,mBAAmB;AACtBK,wBAAAA,QAAAA,EAAUmB,IAAAA,EAAMA,IAAAA,CAAKyF,eAAAA,GAAkBzF,IAAAA,CAAKA,IAAI,CAACyF,eAAe,CAACC,KAAK,CAAC,GAAA,CAAI,CAAC,EAAE,GAAG;AACnF;;;;;AAKV;;;;"}
@@ -0,0 +1,182 @@
1
+ 'use strict';
2
+
3
+ var constants = require('./constants.js');
4
+
5
+ const RELEASE_EDITABLE_FIELDS = [
6
+ 'name',
7
+ 'scheduledAt',
8
+ 'timezone'
9
+ ];
10
+ /** Audit rows are never pruned by size, so the failure reason is capped */ const MAX_REASON_LENGTH = 100;
11
+ /**
12
+ * Returns the fields that changed in a release update.
13
+ * `isScheduled` is included when the release changes between scheduled and unscheduled.
14
+ */ const getReleaseChanges = (previous, next)=>{
15
+ const changes = {};
16
+ for (const field of RELEASE_EDITABLE_FIELDS){
17
+ const hasChanged = (previous?.[field] ?? null) !== (next[field] ?? null);
18
+ if (hasChanged) {
19
+ changes[field] = {
20
+ before: previous?.[field] ?? null,
21
+ after: next[field] ?? null
22
+ };
23
+ }
24
+ if (field === 'scheduledAt' && changes.scheduledAt) {
25
+ const wasScheduled = previous?.scheduledAt != null;
26
+ const isScheduled = next.scheduledAt != null;
27
+ if (wasScheduled !== isScheduled) {
28
+ changes.isScheduled = {
29
+ before: wasScheduled,
30
+ after: isScheduled
31
+ };
32
+ }
33
+ }
34
+ }
35
+ return changes;
36
+ };
37
+ /**
38
+ * Emits an audit event and waits for it to be processed.
39
+ * A failed audit write, or a failing listener, is logged here and doesn't affect the
40
+ * operation that emitted the event.
41
+ */ const emitAudit = async ({ strapi }, event, payload)=>{
42
+ try {
43
+ await strapi.eventHub.emit(event, payload);
44
+ } catch (error) {
45
+ strapi.log.error(`An event listener failed while handling ${event}`, {
46
+ error
47
+ });
48
+ }
49
+ };
50
+ /**
51
+ * Emits an audit event for a write that may be part of a bulk transaction.
52
+ * Inside one, the event waits for its commit, so a rollback leaves no rows for
53
+ * entries that were never added. Standalone, it is emitted right away.
54
+ */ const emitAuditOnCommit = async ({ strapi }, event, payload)=>{
55
+ if (!strapi.db.inTransaction()) {
56
+ await emitAudit({
57
+ strapi
58
+ }, event, payload);
59
+ return;
60
+ }
61
+ await strapi.db.transaction(({ onCommit })=>onCommit(()=>emitAudit({
62
+ strapi
63
+ }, event, payload)));
64
+ };
65
+ /**
66
+ * Runs work as a system principal so events emitted during the operation
67
+ * are recorded with a system actor.
68
+ */ const runAsSystem = async ({ strapi }, origin, work)=>{
69
+ let result;
70
+ await strapi.requestContext.run({
71
+ state: {
72
+ auditSource: origin
73
+ },
74
+ request: {
75
+ url: ''
76
+ }
77
+ }, async ()=>{
78
+ result = await work();
79
+ });
80
+ return result;
81
+ };
82
+ const registerAuditEvents = (auditLogsLifecycle)=>{
83
+ const releaseResource = (event)=>({
84
+ type: 'release',
85
+ id: event.releaseId,
86
+ name: event.name
87
+ });
88
+ const entryRef = (event)=>({
89
+ contentType: event.contentType,
90
+ documentId: event.entryDocumentId,
91
+ locale: event.locale ?? null
92
+ });
93
+ auditLogsLifecycle.registerEvent(constants.AUDITED_EVENTS.RELEASE_CREATE, (event)=>({
94
+ resource: releaseResource(event),
95
+ details: {
96
+ isScheduled: event.scheduledAt != null,
97
+ ...event.scheduledAt && {
98
+ scheduledAt: event.scheduledAt,
99
+ timezone: event.timezone
100
+ }
101
+ }
102
+ }));
103
+ auditLogsLifecycle.registerEvent(constants.AUDITED_EVENTS.RELEASE_UPDATE, (event)=>({
104
+ resource: releaseResource(event),
105
+ details: {
106
+ changes: event.changes
107
+ }
108
+ }));
109
+ auditLogsLifecycle.registerEvent(constants.AUDITED_EVENTS.RELEASE_DELETE, (event)=>({
110
+ resource: releaseResource(event)
111
+ }));
112
+ auditLogsLifecycle.registerEvent(constants.AUDITED_EVENTS.RELEASE_TRIGGER, (event)=>{
113
+ const base = {
114
+ resource: releaseResource(event),
115
+ outcome: event.outcome
116
+ };
117
+ if (event.outcome === 'failure') {
118
+ return {
119
+ ...base,
120
+ details: {
121
+ reason: event.reason?.slice(0, MAX_REASON_LENGTH),
122
+ // Only when the emitter can attribute the counts.
123
+ ...event.published != null && {
124
+ published: event.published,
125
+ unpublished: event.unpublished,
126
+ failed: event.failed
127
+ }
128
+ }
129
+ };
130
+ }
131
+ if (event.published != null && event.unpublished != null) {
132
+ return {
133
+ ...base,
134
+ details: {
135
+ published: event.published,
136
+ unpublished: event.unpublished,
137
+ failed: 0
138
+ }
139
+ };
140
+ }
141
+ return base;
142
+ });
143
+ auditLogsLifecycle.registerEvent(constants.AUDITED_EVENTS.RELEASE_ENTRY_ADD, (event)=>({
144
+ resource: releaseResource(event),
145
+ details: {
146
+ entry: entryRef(event),
147
+ actionType: event.type
148
+ }
149
+ }));
150
+ auditLogsLifecycle.registerEvent(constants.AUDITED_EVENTS.RELEASE_ENTRY_UPDATE, (event)=>({
151
+ resource: releaseResource(event),
152
+ details: {
153
+ entry: entryRef(event),
154
+ actionType: {
155
+ before: event.from,
156
+ after: event.to
157
+ }
158
+ }
159
+ }));
160
+ auditLogsLifecycle.registerEvent(constants.AUDITED_EVENTS.RELEASE_ENTRY_REMOVE, (event)=>({
161
+ resource: releaseResource(event),
162
+ details: {
163
+ entry: entryRef(event)
164
+ }
165
+ }));
166
+ auditLogsLifecycle.registerEvent(constants.AUDITED_EVENTS.RELEASE_SETTINGS_UPDATE, (event)=>({
167
+ resource: {
168
+ type: 'release'
169
+ },
170
+ details: {
171
+ changes: event.changes
172
+ }
173
+ }));
174
+ };
175
+
176
+ exports.RELEASE_EDITABLE_FIELDS = RELEASE_EDITABLE_FIELDS;
177
+ exports.emitAudit = emitAudit;
178
+ exports.emitAuditOnCommit = emitAuditOnCommit;
179
+ exports.getReleaseChanges = getReleaseChanges;
180
+ exports.registerAuditEvents = registerAuditEvents;
181
+ exports.runAsSystem = runAsSystem;
182
+ //# sourceMappingURL=audit-logs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"audit-logs.js","sources":["../../server/src/audit-logs.ts"],"sourcesContent":["import type { Core, Modules } from '@strapi/types';\n\nimport { AUDITED_EVENTS } from './constants';\n\n/**\n * Transformers for the release audit events.\n * Each builds {resource, details, outcome} from its emitted event.\n */\n\ninterface ReleaseEvent {\n releaseId: number;\n name?: string;\n scheduledAt?: string | null;\n timezone?: string | null;\n}\n\ninterface ReleaseEntryEvent {\n releaseId: number;\n name?: string;\n contentType: string;\n entryDocumentId: string;\n locale: string | null;\n}\n\nexport interface CreateDetails {\n isScheduled: boolean;\n scheduledAt?: string | null;\n timezone?: string | null;\n}\n\nexport interface FieldChange {\n before: string | boolean | null;\n after: string | boolean | null;\n}\n\nexport const RELEASE_EDITABLE_FIELDS = ['name', 'scheduledAt', 'timezone'] as const;\n\n/** Audit rows are never pruned by size, so the failure reason is capped */\nconst MAX_REASON_LENGTH = 100;\n\ntype ReleaseChangedField = (typeof RELEASE_EDITABLE_FIELDS)[number] | 'isScheduled';\n\nexport interface UpdateDetails {\n changes: Partial<Record<ReleaseChangedField, FieldChange>>;\n}\n\n/**\n * Returns the fields that changed in a release update.\n * `isScheduled` is included when the release changes between scheduled and unscheduled.\n */\nexport const getReleaseChanges = (\n previous: { name?: string; scheduledAt?: string | null; timezone?: string | null } | null,\n next: { name?: string; scheduledAt?: string | null; timezone?: string | null }\n) => {\n const changes: Partial<Record<ReleaseChangedField, FieldChange>> = {};\n\n for (const field of RELEASE_EDITABLE_FIELDS) {\n const hasChanged = (previous?.[field] ?? null) !== (next[field] ?? null);\n\n if (hasChanged) {\n changes[field] = { before: previous?.[field] ?? null, after: next[field] ?? null };\n }\n\n if (field === 'scheduledAt' && changes.scheduledAt) {\n const wasScheduled = previous?.scheduledAt != null;\n const isScheduled = next.scheduledAt != null;\n\n if (wasScheduled !== isScheduled) {\n changes.isScheduled = { before: wasScheduled, after: isScheduled };\n }\n }\n }\n\n return changes;\n};\n\nexport interface TriggerDetails {\n published: number;\n unpublished: number;\n failed: number;\n}\n\nexport interface TriggerFailureDetails {\n /**\n * Only the error name is stored, capped in length. Error objects may contain\n * sensitive data such as database error details, and a custom error class can put\n * arbitrary text in its name.\n */\n reason: string;\n // A failed run is not atomic, so counts are not reported. Reserved for partial releases.\n published?: number;\n unpublished?: number;\n failed?: number;\n}\n\ntype TriggerEvent = ReleaseEvent &\n (\n | { outcome: 'success'; published?: number; unpublished?: number }\n | {\n outcome: 'failure';\n reason: string;\n published?: number;\n unpublished?: number;\n failed?: number;\n }\n );\n\nexport interface SettingsUpdateDetails {\n changes: Partial<Record<'defaultTimezone', FieldChange>>;\n}\n\ninterface EntryRef {\n contentType: string;\n documentId: string;\n locale: string | null;\n}\n\nexport interface EntryAddDetails {\n entry: EntryRef;\n actionType: 'publish' | 'unpublish';\n}\n\nexport interface EntryUpdateDetails {\n entry: EntryRef;\n actionType: { before: 'publish' | 'unpublish'; after: 'publish' | 'unpublish' };\n}\n\nexport interface EntryRemoveDetails {\n entry: EntryRef;\n}\n\n/**\n * Emits an audit event and waits for it to be processed.\n * A failed audit write, or a failing listener, is logged here and doesn't affect the\n * operation that emitted the event.\n */\nexport const emitAudit = async (\n { strapi }: { strapi: Core.Strapi },\n event: string,\n payload: unknown\n): Promise<void> => {\n try {\n await strapi.eventHub.emit(event, payload);\n } catch (error) {\n strapi.log.error(`An event listener failed while handling ${event}`, { error });\n }\n};\n\n/**\n * Emits an audit event for a write that may be part of a bulk transaction.\n * Inside one, the event waits for its commit, so a rollback leaves no rows for\n * entries that were never added. Standalone, it is emitted right away.\n */\nexport const emitAuditOnCommit = async (\n { strapi }: { strapi: Core.Strapi },\n event: string,\n payload: unknown\n): Promise<void> => {\n if (!strapi.db.inTransaction()) {\n await emitAudit({ strapi }, event, payload);\n return;\n }\n\n await strapi.db.transaction(({ onCommit }) =>\n onCommit(() => emitAudit({ strapi }, event, payload))\n );\n};\n\n/**\n * Runs work as a system principal so events emitted during the operation\n * are recorded with a system actor.\n */\nexport const runAsSystem = async <T>(\n { strapi }: { strapi: Core.Strapi },\n origin: Modules.AuditLogs.SystemOrigin,\n work: () => Promise<T>\n): Promise<T> => {\n let result: T;\n\n await strapi.requestContext.run(\n { state: { auditSource: origin }, request: { url: '' } } as any,\n async () => {\n result = await work();\n }\n );\n\n return result!;\n};\n\n/**\n * The part of the audit-logs lifecycle service used by this plugin.\n * The full service type lives in the Admin EE package and cannot be imported here.\n */\ninterface AuditLogsLifecycle {\n registerEvent<TDetails>(\n name: string,\n transform: Modules.AuditLogs.EventTransformer<TDetails>\n ): void;\n}\n\nexport const registerAuditEvents = (auditLogsLifecycle: AuditLogsLifecycle) => {\n const releaseResource = (event: ReleaseEvent): Modules.AuditLogs.Resource => ({\n type: 'release',\n id: event.releaseId,\n name: event.name,\n });\n\n const entryRef = (event: ReleaseEntryEvent): EntryRef => ({\n contentType: event.contentType,\n documentId: event.entryDocumentId,\n locale: event.locale ?? null,\n });\n\n auditLogsLifecycle.registerEvent<CreateDetails>(\n AUDITED_EVENTS.RELEASE_CREATE,\n (event: ReleaseEvent) => ({\n resource: releaseResource(event),\n details: {\n isScheduled: event.scheduledAt != null,\n ...(event.scheduledAt && { scheduledAt: event.scheduledAt, timezone: event.timezone }),\n },\n })\n );\n\n auditLogsLifecycle.registerEvent<UpdateDetails>(\n AUDITED_EVENTS.RELEASE_UPDATE,\n (event: ReleaseEvent & UpdateDetails) => ({\n resource: releaseResource(event),\n details: { changes: event.changes },\n })\n );\n\n auditLogsLifecycle.registerEvent(AUDITED_EVENTS.RELEASE_DELETE, (event: ReleaseEvent) => ({\n resource: releaseResource(event),\n }));\n\n auditLogsLifecycle.registerEvent<TriggerDetails | TriggerFailureDetails>(\n AUDITED_EVENTS.RELEASE_TRIGGER,\n (event: TriggerEvent) => {\n const base = { resource: releaseResource(event), outcome: event.outcome };\n\n if (event.outcome === 'failure') {\n return {\n ...base,\n details: {\n reason: event.reason?.slice(0, MAX_REASON_LENGTH),\n // Only when the emitter can attribute the counts.\n ...(event.published != null && {\n published: event.published,\n unpublished: event.unpublished,\n failed: event.failed,\n }),\n },\n };\n }\n\n if (event.published != null && event.unpublished != null) {\n return {\n ...base,\n details: { published: event.published, unpublished: event.unpublished, failed: 0 },\n };\n }\n\n return base;\n }\n );\n\n auditLogsLifecycle.registerEvent<EntryAddDetails>(\n AUDITED_EVENTS.RELEASE_ENTRY_ADD,\n (event: ReleaseEntryEvent & { type: 'publish' | 'unpublish' }) => ({\n resource: releaseResource(event),\n details: { entry: entryRef(event), actionType: event.type },\n })\n );\n\n auditLogsLifecycle.registerEvent<EntryUpdateDetails>(\n AUDITED_EVENTS.RELEASE_ENTRY_UPDATE,\n (\n event: ReleaseEntryEvent & {\n from: 'publish' | 'unpublish';\n to: 'publish' | 'unpublish';\n }\n ) => ({\n resource: releaseResource(event),\n details: { entry: entryRef(event), actionType: { before: event.from, after: event.to } },\n })\n );\n\n auditLogsLifecycle.registerEvent<EntryRemoveDetails>(\n AUDITED_EVENTS.RELEASE_ENTRY_REMOVE,\n (event: ReleaseEntryEvent) => ({\n resource: releaseResource(event),\n details: { entry: entryRef(event) },\n })\n );\n\n auditLogsLifecycle.registerEvent<SettingsUpdateDetails>(\n AUDITED_EVENTS.RELEASE_SETTINGS_UPDATE,\n (event: SettingsUpdateDetails) => ({\n resource: { type: 'release' },\n details: { changes: event.changes },\n })\n );\n};\n"],"names":["RELEASE_EDITABLE_FIELDS","MAX_REASON_LENGTH","getReleaseChanges","previous","next","changes","field","hasChanged","before","after","scheduledAt","wasScheduled","isScheduled","emitAudit","strapi","event","payload","eventHub","emit","error","log","emitAuditOnCommit","db","inTransaction","transaction","onCommit","runAsSystem","origin","work","result","requestContext","run","state","auditSource","request","url","registerAuditEvents","auditLogsLifecycle","releaseResource","type","id","releaseId","name","entryRef","contentType","documentId","entryDocumentId","locale","registerEvent","AUDITED_EVENTS","RELEASE_CREATE","resource","details","timezone","RELEASE_UPDATE","RELEASE_DELETE","RELEASE_TRIGGER","base","outcome","reason","slice","published","unpublished","failed","RELEASE_ENTRY_ADD","entry","actionType","RELEASE_ENTRY_UPDATE","from","to","RELEASE_ENTRY_REMOVE","RELEASE_SETTINGS_UPDATE"],"mappings":"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"}