'use strict'; var jsxRuntime = require('react/jsx-runtime'); var React = require('react'); var strapiAdmin = require('@strapi/admin/strapi-admin'); var ee = require('@strapi/admin/strapi-admin/ee'); var designSystem = require('@strapi/design-system'); var icons = require('@strapi/icons'); var symbols = require('@strapi/icons/symbols'); var dateFns = require('date-fns'); var reactIntl = require('react-intl'); var reactRouterDom = require('react-router-dom'); var styledComponents = require('styled-components'); var RelativeTime$1 = require('../components/RelativeTime.js'); var ReleaseModal = require('../components/ReleaseModal.js'); var constants = require('../constants.js'); var release = require('../services/release.js'); function _interopNamespaceDefault(e) { var n = Object.create(null); if (e) { Object.keys(e).forEach(function (k) { if (k !== 'default') { var d = Object.getOwnPropertyDescriptor(e, k); Object.defineProperty(n, k, d.get ? d : { enumerable: true, get: function () { return e[k]; } }); } }); } n.default = e; return Object.freeze(n); } var React__namespace = /*#__PURE__*/_interopNamespaceDefault(React); const LinkCard = styledComponents.styled(designSystem.Link)` display: block; `; const RelativeTime = styledComponents.styled(RelativeTime$1.RelativeTime)` display: inline-block; &::first-letter { text-transform: uppercase; } `; const getBadgeProps = (status)=>{ let color; switch(status){ case 'ready': color = 'success'; break; case 'blocked': color = 'warning'; break; case 'failed': color = 'danger'; break; case 'done': color = 'primary'; break; case 'empty': default: color = 'neutral'; } return { textColor: `${color}600`, backgroundColor: `${color}100`, borderColor: `${color}200` }; }; const ReleasesGrid = ({ sectionTitle, releases = [], isError = false })=>{ const { formatMessage } = reactIntl.useIntl(); if (isError) { return /*#__PURE__*/ jsxRuntime.jsx(strapiAdmin.Page.Error, {}); } if (releases?.length === 0) { return /*#__PURE__*/ jsxRuntime.jsx(designSystem.EmptyStateLayout, { content: formatMessage({ id: 'content-releases.page.Releases.tab.emptyEntries', defaultMessage: 'No releases' }, { target: sectionTitle }), icon: /*#__PURE__*/ jsxRuntime.jsx(symbols.EmptyDocuments, { width: "16rem" }) }); } return /*#__PURE__*/ jsxRuntime.jsx(designSystem.Grid.Root, { gap: 4, children: releases.map(({ id, name, scheduledAt, status })=>/*#__PURE__*/ jsxRuntime.jsx(designSystem.Grid.Item, { col: 3, s: 6, xs: 12, direction: "column", alignItems: "stretch", children: /*#__PURE__*/ jsxRuntime.jsx(LinkCard, { tag: reactRouterDom.NavLink, to: `${id}`, isExternal: false, children: /*#__PURE__*/ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", justifyContent: "space-between", padding: 4, hasRadius: true, background: "neutral0", shadow: "tableShadow", height: "100%", width: "100%", alignItems: "start", gap: 4, children: [ /*#__PURE__*/ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", alignItems: "start", gap: 1, children: [ /*#__PURE__*/ jsxRuntime.jsx(designSystem.Typography, { textColor: "neutral800", tag: "h3", variant: "delta", fontWeight: "bold", children: name }), /*#__PURE__*/ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", textColor: "neutral600", children: scheduledAt ? /*#__PURE__*/ jsxRuntime.jsx(RelativeTime, { timestamp: new Date(scheduledAt) }) : formatMessage({ id: 'content-releases.pages.Releases.not-scheduled', defaultMessage: 'Not scheduled' }) }) ] }), /*#__PURE__*/ jsxRuntime.jsx(designSystem.Badge, { ...getBadgeProps(status), children: status }) ] }) }) }, id)) }); }; /* ------------------------------------------------------------------------------------------------- * ReleasesPage * -----------------------------------------------------------------------------------------------*/ const StyledAlert = styledComponents.styled(designSystem.Alert)` button { display: none; } p + div { margin-left: auto; } `; const INITIAL_FORM_VALUES = { name: '', date: dateFns.format(new Date(), 'yyyy-MM-dd'), time: '', isScheduled: true, scheduledAt: null, timezone: null }; const ReleasesPage = ()=>{ const location = reactRouterDom.useLocation(); const [releaseModalShown, setReleaseModalShown] = React__namespace.useState(false); const { toggleNotification } = strapiAdmin.useNotification(); const { formatMessage } = reactIntl.useIntl(); const navigate = reactRouterDom.useNavigate(); const { formatAPIError } = strapiAdmin.useAPIErrorHandler(); const [{ query }, setQuery] = strapiAdmin.useQueryParams(); const response = release.useGetReleasesQuery(query); const { data, isLoading: isLoadingSettings } = release.useGetReleaseSettingsQuery(); const [createRelease, { isLoading: isSubmittingForm }] = release.useCreateReleaseMutation(); const { getFeature } = ee.useLicenseLimits(); const { maximumReleases = 3 } = getFeature('cms-content-releases'); const { trackUsage } = strapiAdmin.useTracking(); const { allowedActions: { canCreate } } = strapiAdmin.useRBAC(constants.PERMISSIONS); const { isLoading: isLoadingReleases, isSuccess, isError } = response; const activeTab = response?.currentData?.meta?.activeTab || 'pending'; // Check if we have some errors and show a notification to the user to explain the error React__namespace.useEffect(()=>{ if (location?.state?.errors) { toggleNotification({ type: 'danger', title: formatMessage({ id: 'content-releases.pages.Releases.notification.error.title', defaultMessage: 'Your request could not be processed.' }), message: formatMessage({ id: 'content-releases.pages.Releases.notification.error.message', defaultMessage: 'Please try again or open another release.' }) }); navigate('', { replace: true, state: null }); } }, [ formatMessage, location?.state?.errors, navigate, toggleNotification ]); const toggleAddReleaseModal = ()=>{ setReleaseModalShown((prev)=>!prev); }; if (isLoadingReleases || isLoadingSettings) { return /*#__PURE__*/ jsxRuntime.jsx(strapiAdmin.Page.Loading, {}); } const totalPendingReleases = isSuccess && response.currentData?.meta?.pendingReleasesCount || 0; const hasReachedMaximumPendingReleases = totalPendingReleases >= maximumReleases; const handleTabChange = (tabValue)=>{ setQuery({ ...query, page: 1, pageSize: response?.currentData?.meta?.pagination?.pageSize || 16, filters: { releasedAt: { $notNull: tabValue !== 'pending' } } }); }; const handleAddRelease = async ({ name, scheduledAt, timezone })=>{ const response = await createRelease({ name, scheduledAt, timezone }); if ('data' in response) { // When the response returns an object with 'data', handle success toggleNotification({ type: 'success', message: formatMessage({ id: 'content-releases.modal.release-created-notification-success', defaultMessage: 'Release created.' }) }); trackUsage('didCreateRelease'); navigate(response.data.data.id.toString()); } else if (strapiAdmin.isFetchError(response.error)) { // When the response returns an object with 'error', handle fetch error toggleNotification({ type: 'danger', message: formatAPIError(response.error) }); } else { // Otherwise, the response returns an object with 'error', handle a generic error toggleNotification({ type: 'danger', message: formatMessage({ id: 'notification.error', defaultMessage: 'An error occurred' }) }); } }; return /*#__PURE__*/ jsxRuntime.jsxs(designSystem.Main, { "aria-busy": isLoadingReleases || isLoadingSettings, children: [ /*#__PURE__*/ jsxRuntime.jsx(strapiAdmin.Layouts.Header, { title: formatMessage({ id: 'content-releases.pages.Releases.title', defaultMessage: 'Releases' }), subtitle: formatMessage({ id: 'content-releases.pages.Releases.header-subtitle', defaultMessage: 'Create and manage content updates' }), primaryAction: canCreate ? /*#__PURE__*/ jsxRuntime.jsx(designSystem.Button, { startIcon: /*#__PURE__*/ jsxRuntime.jsx(icons.Plus, {}), onClick: toggleAddReleaseModal, disabled: hasReachedMaximumPendingReleases, children: formatMessage({ id: 'content-releases.header.actions.add-release', defaultMessage: 'New release' }) }) : null }), /*#__PURE__*/ jsxRuntime.jsx(strapiAdmin.Layouts.Content, { children: /*#__PURE__*/ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [ hasReachedMaximumPendingReleases && /*#__PURE__*/ jsxRuntime.jsx(StyledAlert, { marginBottom: 6, action: /*#__PURE__*/ jsxRuntime.jsx(designSystem.Link, { href: "https://strapi.io/pricing-cloud", isExternal: true, children: formatMessage({ id: 'content-releases.pages.Releases.max-limit-reached.action', defaultMessage: 'Explore plans' }) }), title: formatMessage({ id: 'content-releases.pages.Releases.max-limit-reached.title', defaultMessage: 'You have reached the {number} pending {number, plural, one {release} other {releases}} limit.' }, { number: maximumReleases }), onClose: ()=>{}, closeLabel: "", children: formatMessage({ id: 'content-releases.pages.Releases.max-limit-reached.message', defaultMessage: 'Upgrade to manage an unlimited number of releases.' }) }), /*#__PURE__*/ jsxRuntime.jsxs(designSystem.Tabs.Root, { variant: "simple", onValueChange: handleTabChange, value: activeTab, children: [ /*#__PURE__*/ jsxRuntime.jsxs(designSystem.Box, { paddingBottom: 8, children: [ /*#__PURE__*/ jsxRuntime.jsxs(designSystem.Tabs.List, { "aria-label": formatMessage({ id: 'content-releases.pages.Releases.tab-group.label', defaultMessage: 'Releases list' }), children: [ /*#__PURE__*/ jsxRuntime.jsx(designSystem.Tabs.Trigger, { value: "pending", children: formatMessage({ id: 'content-releases.pages.Releases.tab.pending', defaultMessage: 'Pending ({count})' }, { count: totalPendingReleases }) }), /*#__PURE__*/ jsxRuntime.jsx(designSystem.Tabs.Trigger, { value: "done", children: formatMessage({ id: 'content-releases.pages.Releases.tab.done', defaultMessage: 'Done' }) }) ] }), /*#__PURE__*/ jsxRuntime.jsx(designSystem.Divider, {}) ] }), /*#__PURE__*/ jsxRuntime.jsx(designSystem.Tabs.Content, { value: "pending", children: /*#__PURE__*/ jsxRuntime.jsx(ReleasesGrid, { sectionTitle: "pending", releases: response?.currentData?.data, isError: isError }) }), /*#__PURE__*/ jsxRuntime.jsx(designSystem.Tabs.Content, { value: "done", children: /*#__PURE__*/ jsxRuntime.jsx(ReleasesGrid, { sectionTitle: "done", releases: response?.currentData?.data, isError: isError }) }) ] }), /*#__PURE__*/ jsxRuntime.jsxs(strapiAdmin.Pagination.Root, { ...response?.currentData?.meta?.pagination, defaultPageSize: response?.currentData?.meta?.pagination?.pageSize, children: [ /*#__PURE__*/ jsxRuntime.jsx(strapiAdmin.Pagination.PageSize, { options: [ '8', '16', '32', '64' ] }), /*#__PURE__*/ jsxRuntime.jsx(strapiAdmin.Pagination.Links, {}) ] }) ] }) }), /*#__PURE__*/ jsxRuntime.jsx(ReleaseModal.ReleaseModal, { open: releaseModalShown, handleClose: toggleAddReleaseModal, handleSubmit: handleAddRelease, isLoading: isSubmittingForm, initialValues: { ...INITIAL_FORM_VALUES, timezone: data?.data.defaultTimezone ? data.data.defaultTimezone.split('&')[1] : null } }) ] }); }; exports.ReleasesPage = ReleasesPage; exports.getBadgeProps = getBadgeProps; //# sourceMappingURL=ReleasesPage.js.map