Files
pole-book/server/node_modules/@strapi/content-releases/dist/admin/pages/ReleasesPage.mjs

376 lines
16 KiB
JavaScript

import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
import * as React from 'react';
import { useNotification, useAPIErrorHandler, useQueryParams, useTracking, useRBAC, Page, Layouts, Pagination, isFetchError } from '@strapi/admin/strapi-admin';
import { useLicenseLimits } from '@strapi/admin/strapi-admin/ee';
import { Link, Alert, Main, Button, Tabs, Box, Divider, EmptyStateLayout, Grid, Flex, Typography, Badge } from '@strapi/design-system';
import { Plus } from '@strapi/icons';
import { EmptyDocuments } from '@strapi/icons/symbols';
import { format } from 'date-fns';
import { useIntl } from 'react-intl';
import { useLocation, useNavigate, NavLink } from 'react-router-dom';
import { styled } from 'styled-components';
import { RelativeTime as RelativeTime$1 } from '../components/RelativeTime.mjs';
import { ReleaseModal } from '../components/ReleaseModal.mjs';
import { PERMISSIONS } from '../constants.mjs';
import { useGetReleasesQuery, useGetReleaseSettingsQuery, useCreateReleaseMutation } from '../services/release.mjs';
const LinkCard = styled(Link)`
display: block;
`;
const RelativeTime = styled(RelativeTime$1)`
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 } = useIntl();
if (isError) {
return /*#__PURE__*/ jsx(Page.Error, {});
}
if (releases?.length === 0) {
return /*#__PURE__*/ jsx(EmptyStateLayout, {
content: formatMessage({
id: 'content-releases.page.Releases.tab.emptyEntries',
defaultMessage: 'No releases'
}, {
target: sectionTitle
}),
icon: /*#__PURE__*/ jsx(EmptyDocuments, {
width: "16rem"
})
});
}
return /*#__PURE__*/ jsx(Grid.Root, {
gap: 4,
children: releases.map(({ id, name, scheduledAt, status })=>/*#__PURE__*/ jsx(Grid.Item, {
col: 3,
s: 6,
xs: 12,
direction: "column",
alignItems: "stretch",
children: /*#__PURE__*/ jsx(LinkCard, {
tag: NavLink,
to: `${id}`,
isExternal: false,
children: /*#__PURE__*/ jsxs(Flex, {
direction: "column",
justifyContent: "space-between",
padding: 4,
hasRadius: true,
background: "neutral0",
shadow: "tableShadow",
height: "100%",
width: "100%",
alignItems: "start",
gap: 4,
children: [
/*#__PURE__*/ jsxs(Flex, {
direction: "column",
alignItems: "start",
gap: 1,
children: [
/*#__PURE__*/ jsx(Typography, {
textColor: "neutral800",
tag: "h3",
variant: "delta",
fontWeight: "bold",
children: name
}),
/*#__PURE__*/ jsx(Typography, {
variant: "pi",
textColor: "neutral600",
children: scheduledAt ? /*#__PURE__*/ jsx(RelativeTime, {
timestamp: new Date(scheduledAt)
}) : formatMessage({
id: 'content-releases.pages.Releases.not-scheduled',
defaultMessage: 'Not scheduled'
})
})
]
}),
/*#__PURE__*/ jsx(Badge, {
...getBadgeProps(status),
children: status
})
]
})
})
}, id))
});
};
/* -------------------------------------------------------------------------------------------------
* ReleasesPage
* -----------------------------------------------------------------------------------------------*/ const StyledAlert = styled(Alert)`
button {
display: none;
}
p + div {
margin-left: auto;
}
`;
const INITIAL_FORM_VALUES = {
name: '',
date: format(new Date(), 'yyyy-MM-dd'),
time: '',
isScheduled: true,
scheduledAt: null,
timezone: null
};
const ReleasesPage = ()=>{
const location = useLocation();
const [releaseModalShown, setReleaseModalShown] = React.useState(false);
const { toggleNotification } = useNotification();
const { formatMessage } = useIntl();
const navigate = useNavigate();
const { formatAPIError } = useAPIErrorHandler();
const [{ query }, setQuery] = useQueryParams();
const response = useGetReleasesQuery(query);
const { data, isLoading: isLoadingSettings } = useGetReleaseSettingsQuery();
const [createRelease, { isLoading: isSubmittingForm }] = useCreateReleaseMutation();
const { getFeature } = useLicenseLimits();
const { maximumReleases = 3 } = getFeature('cms-content-releases');
const { trackUsage } = useTracking();
const { allowedActions: { canCreate } } = useRBAC(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.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__*/ jsx(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 (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__*/ jsxs(Main, {
"aria-busy": isLoadingReleases || isLoadingSettings,
children: [
/*#__PURE__*/ jsx(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__*/ jsx(Button, {
startIcon: /*#__PURE__*/ jsx(Plus, {}),
onClick: toggleAddReleaseModal,
disabled: hasReachedMaximumPendingReleases,
children: formatMessage({
id: 'content-releases.header.actions.add-release',
defaultMessage: 'New release'
})
}) : null
}),
/*#__PURE__*/ jsx(Layouts.Content, {
children: /*#__PURE__*/ jsxs(Fragment, {
children: [
hasReachedMaximumPendingReleases && /*#__PURE__*/ jsx(StyledAlert, {
marginBottom: 6,
action: /*#__PURE__*/ jsx(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__*/ jsxs(Tabs.Root, {
variant: "simple",
onValueChange: handleTabChange,
value: activeTab,
children: [
/*#__PURE__*/ jsxs(Box, {
paddingBottom: 8,
children: [
/*#__PURE__*/ jsxs(Tabs.List, {
"aria-label": formatMessage({
id: 'content-releases.pages.Releases.tab-group.label',
defaultMessage: 'Releases list'
}),
children: [
/*#__PURE__*/ jsx(Tabs.Trigger, {
value: "pending",
children: formatMessage({
id: 'content-releases.pages.Releases.tab.pending',
defaultMessage: 'Pending ({count})'
}, {
count: totalPendingReleases
})
}),
/*#__PURE__*/ jsx(Tabs.Trigger, {
value: "done",
children: formatMessage({
id: 'content-releases.pages.Releases.tab.done',
defaultMessage: 'Done'
})
})
]
}),
/*#__PURE__*/ jsx(Divider, {})
]
}),
/*#__PURE__*/ jsx(Tabs.Content, {
value: "pending",
children: /*#__PURE__*/ jsx(ReleasesGrid, {
sectionTitle: "pending",
releases: response?.currentData?.data,
isError: isError
})
}),
/*#__PURE__*/ jsx(Tabs.Content, {
value: "done",
children: /*#__PURE__*/ jsx(ReleasesGrid, {
sectionTitle: "done",
releases: response?.currentData?.data,
isError: isError
})
})
]
}),
/*#__PURE__*/ jsxs(Pagination.Root, {
...response?.currentData?.meta?.pagination,
defaultPageSize: response?.currentData?.meta?.pagination?.pageSize,
children: [
/*#__PURE__*/ jsx(Pagination.PageSize, {
options: [
'8',
'16',
'32',
'64'
]
}),
/*#__PURE__*/ jsx(Pagination.Links, {})
]
})
]
})
}),
/*#__PURE__*/ jsx(ReleaseModal, {
open: releaseModalShown,
handleClose: toggleAddReleaseModal,
handleSubmit: handleAddRelease,
isLoading: isSubmittingForm,
initialValues: {
...INITIAL_FORM_VALUES,
timezone: data?.data.defaultTimezone ? data.data.defaultTimezone.split('&')[1] : null
}
})
]
});
};
export { ReleasesPage, getBadgeProps };
//# sourceMappingURL=ReleasesPage.mjs.map