398 lines
18 KiB
JavaScript
398 lines
18 KiB
JavaScript
'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
|