@strapi/review-workflows 0.0.0-experimental.abc → 0.0.0-experimental.af7e4e2471a04cc7f17b8ed3474530810efc02bc
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.
- package/dist/_chunks/{Layout-AREWDuuq.js → Layout-B4fpKB9J.js} +3 -3
- package/dist/_chunks/Layout-B4fpKB9J.js.map +1 -0
- package/dist/_chunks/{Layout-D5aa9iUm.mjs → Layout-Dko22Aly.mjs} +3 -3
- package/dist/_chunks/Layout-Dko22Aly.mjs.map +1 -0
- package/dist/_chunks/{en-xcewH2pC.js → en-CYgjfSep.js} +5 -2
- package/dist/_chunks/en-CYgjfSep.js.map +1 -0
- package/dist/_chunks/{en-D9ZrQAV6.mjs → en-D9dxziEb.mjs} +5 -2
- package/dist/_chunks/en-D9dxziEb.mjs.map +1 -0
- package/dist/_chunks/{_id-C7pCAzXV.js → id-BKq7JAqZ.js} +76 -17
- package/dist/_chunks/id-BKq7JAqZ.js.map +1 -0
- package/dist/_chunks/{_id-DDNHKV_W.mjs → id-DINFSsrh.mjs} +76 -17
- package/dist/_chunks/id-DINFSsrh.mjs.map +1 -0
- package/dist/_chunks/{index-Bv3cQ3c-.js → index-BpIILEs0.js} +8 -28
- package/dist/_chunks/index-BpIILEs0.js.map +1 -0
- package/dist/_chunks/{index-CIBLMG85.js → index-BpL7C1EG.js} +26 -23
- package/dist/_chunks/index-BpL7C1EG.js.map +1 -0
- package/dist/_chunks/{index-Cx5QECZI.mjs → index-DAcEdoqJ.mjs} +26 -23
- package/dist/_chunks/index-DAcEdoqJ.mjs.map +1 -0
- package/dist/_chunks/{index-CeaoNBIP.mjs → index-ZcZKwmTD.mjs} +10 -30
- package/dist/_chunks/index-ZcZKwmTD.mjs.map +1 -0
- package/dist/_chunks/{router-BEoNwQZ1.mjs → router-BPH_u176.mjs} +3 -3
- package/dist/_chunks/router-BPH_u176.mjs.map +1 -0
- package/dist/_chunks/{router-gRPIa2_c.js → router-DeEgX8Ao.js} +3 -3
- package/dist/_chunks/router-DeEgX8Ao.js.map +1 -0
- package/dist/admin/index.js +1 -1
- package/dist/admin/index.mjs +1 -1
- package/dist/admin/src/services/settings.d.ts +7 -3
- package/dist/server/index.js +180 -67
- package/dist/server/index.js.map +1 -1
- package/dist/server/index.mjs +180 -67
- package/dist/server/index.mjs.map +1 -1
- package/dist/server/src/bootstrap.d.ts.map +1 -1
- package/dist/server/src/constants/workflows.d.ts +1 -0
- package/dist/server/src/constants/workflows.d.ts.map +1 -1
- package/dist/server/src/content-types/index.d.ts +6 -0
- package/dist/server/src/content-types/index.d.ts.map +1 -1
- package/dist/server/src/content-types/workflow/index.d.ts +6 -0
- package/dist/server/src/content-types/workflow/index.d.ts.map +1 -1
- package/dist/server/src/controllers/assignees.d.ts.map +1 -1
- package/dist/server/src/controllers/stages.d.ts.map +1 -1
- package/dist/server/src/index.d.ts +28 -6
- package/dist/server/src/index.d.ts.map +1 -1
- package/dist/server/src/register.d.ts.map +1 -1
- package/dist/server/src/services/assignees.d.ts +8 -4
- package/dist/server/src/services/assignees.d.ts.map +1 -1
- package/dist/server/src/services/document-service-middleware.d.ts +1 -0
- package/dist/server/src/services/document-service-middleware.d.ts.map +1 -1
- package/dist/server/src/services/index.d.ts +16 -6
- package/dist/server/src/services/index.d.ts.map +1 -1
- package/dist/server/src/services/metrics/index.d.ts +4 -4
- package/dist/server/src/services/metrics/index.d.ts.map +1 -1
- package/dist/server/src/services/metrics/weekly-metrics.d.ts.map +1 -1
- package/dist/server/src/services/stages.d.ts +7 -7
- package/dist/server/src/services/stages.d.ts.map +1 -1
- package/dist/server/src/services/workflows.d.ts.map +1 -1
- package/dist/server/src/validation/review-workflows.d.ts +4 -0
- package/dist/server/src/validation/review-workflows.d.ts.map +1 -1
- package/dist/shared/contracts/review-workflows.d.ts +8 -3
- package/dist/shared/contracts/review-workflows.d.ts.map +1 -1
- package/package.json +9 -9
- package/dist/_chunks/Layout-AREWDuuq.js.map +0 -1
- package/dist/_chunks/Layout-D5aa9iUm.mjs.map +0 -1
- package/dist/_chunks/_id-C7pCAzXV.js.map +0 -1
- package/dist/_chunks/_id-DDNHKV_W.mjs.map +0 -1
- package/dist/_chunks/en-D9ZrQAV6.mjs.map +0 -1
- package/dist/_chunks/en-xcewH2pC.js.map +0 -1
- package/dist/_chunks/index-Bv3cQ3c-.js.map +0 -1
- package/dist/_chunks/index-CIBLMG85.js.map +0 -1
- package/dist/_chunks/index-CeaoNBIP.mjs.map +0 -1
- package/dist/_chunks/index-Cx5QECZI.mjs.map +0 -1
- package/dist/_chunks/router-BEoNwQZ1.mjs.map +0 -1
- package/dist/_chunks/router-gRPIa2_c.js.map +0 -1
- package/strapi-server.js +0 -3
- /package/dist/admin/src/routes/settings/{:id.d.ts → id.d.ts} +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index-ZcZKwmTD.mjs","sources":["../../admin/src/routes/settings/index.tsx"],"sourcesContent":["/* eslint-disable check-file/no-index */\n/* eslint-disable check-file/filename-naming-convention */\nimport * as React from 'react';\n\nimport { Page, useTracking, ConfirmDialog, useRBAC, Table } from '@strapi/admin/strapi-admin';\nimport { useLicenseLimits } from '@strapi/admin/strapi-admin/ee';\nimport { Flex, IconButton, TFooter, Typography, LinkButton, Dialog } from '@strapi/design-system';\nimport { Pencil, Plus, Trash } from '@strapi/icons';\nimport { useIntl } from 'react-intl';\nimport { NavLink, Link, useNavigate } from 'react-router-dom';\n\nimport { LimitsModal } from '../../components/LimitsModal';\nimport { CHARGEBEE_WORKFLOW_ENTITLEMENT_NAME } from '../../constants';\nimport { useTypedSelector } from '../../modules/hooks';\nimport { ContentType, useGetContentTypesQuery } from '../../services/content-manager';\n\nimport * as Layout from './components/Layout';\nimport { useReviewWorkflows } from './hooks/useReviewWorkflows';\n\nexport const ReviewWorkflowsListView = () => {\n const { formatMessage } = useIntl();\n const navigate = useNavigate();\n const { trackUsage } = useTracking();\n const [workflowToDelete, setWorkflowToDelete] = React.useState<string | null>(null);\n const [showLimitModal, setShowLimitModal] = React.useState<boolean>(false);\n const { data, isLoading: isLoadingModels } = useGetContentTypesQuery();\n const { meta, workflows, isLoading, delete: deleteAction } = useReviewWorkflows();\n const { getFeature, isLoading: isLicenseLoading } = useLicenseLimits();\n const permissions = useTypedSelector(\n (state) => state.admin_app.permissions.settings?.['review-workflows']\n );\n const {\n allowedActions: { canCreate, canRead, canUpdate, canDelete },\n } = useRBAC(permissions);\n\n const limits = getFeature('review-workflows');\n const numberOfWorkflows = limits?.[CHARGEBEE_WORKFLOW_ENTITLEMENT_NAME] as string;\n\n const handleDeleteWorkflow = (workflowId: string) => {\n setWorkflowToDelete(workflowId);\n };\n\n const toggleConfirmDeleteDialog = () => {\n setWorkflowToDelete(null);\n };\n\n const handleConfirmDeleteDialog = async () => {\n if (!workflowToDelete) return;\n\n await deleteAction(workflowToDelete);\n\n setWorkflowToDelete(null);\n };\n\n const handleCreateClick: React.MouseEventHandler<HTMLAnchorElement> &\n ((event: React.MouseEvent<HTMLButtonElement, MouseEvent>) => void) = (event) => {\n event.preventDefault();\n /**\n * If the current license has a workflow limit:\n * check if the total count of workflows exceeds that limit. If so,\n * prevent the navigation and show the limits overlay.\n *\n * If the current license does not have a limit (e.g. offline license):\n * allow the user to navigate to the create-view. In case they exceed the\n * current hard-limit of 200 they will see an error thrown by the API.\n */\n\n if (numberOfWorkflows && meta && meta?.workflowCount >= parseInt(numberOfWorkflows, 10)) {\n event.preventDefault();\n setShowLimitModal(true);\n } else {\n navigate('create');\n trackUsage('willCreateWorkflow');\n }\n };\n\n /**\n * If the current license has a limit:\n * check if the total count of workflows or stages exceeds that limit and display\n * the limits modal on page load. It can be closed by the user, but the\n * API will throw an error in case they try to create a new workflow or update the\n * stages.\n *\n * If the current license does not have a limit (e.g. offline license):\n * do nothing (for now). In case they are trying to create the 201st workflow/ stage\n * the API will throw an error.\n *\n */\n React.useEffect(() => {\n if (!isLoading && !isLicenseLoading) {\n if (numberOfWorkflows && meta && meta?.workflowCount > parseInt(numberOfWorkflows, 10)) {\n setShowLimitModal(true);\n }\n }\n }, [isLicenseLoading, isLoading, meta, meta?.workflowCount, numberOfWorkflows]);\n\n const headers = [\n {\n label: formatMessage({\n id: 'Settings.review-workflows.list.page.list.column.name.title',\n defaultMessage: 'Name',\n }),\n name: 'name',\n },\n {\n label: formatMessage({\n id: 'Settings.review-workflows.list.page.list.column.stages.title',\n defaultMessage: 'Stages',\n }),\n name: 'stages',\n },\n {\n label: formatMessage({\n id: 'Settings.review-workflows.list.page.list.column.contentTypes.title',\n defaultMessage: 'Content Types',\n }),\n name: 'content-types',\n },\n ];\n\n if (isLoading || isLoadingModels) {\n return <Page.Loading />;\n }\n\n const contentTypes = Object.values(data ?? {}).reduce<ContentType[]>((acc, curr) => {\n acc.push(...curr);\n return acc;\n }, []);\n\n return (\n <>\n <Layout.Header\n primaryAction={\n canCreate ? (\n <LinkButton\n startIcon={<Plus />}\n size=\"S\"\n tag={NavLink}\n to=\"create\"\n onClick={handleCreateClick}\n >\n {formatMessage({\n id: 'Settings.review-workflows.list.page.create',\n defaultMessage: 'Create new workflow',\n })}\n </LinkButton>\n ) : null\n }\n subtitle={formatMessage({\n id: 'Settings.review-workflows.list.page.subtitle',\n defaultMessage: 'Manage your content review process',\n })}\n title={formatMessage({\n id: 'Settings.review-workflows.list.page.title',\n defaultMessage: 'Review Workflows',\n })}\n />\n\n <Layout.Root>\n <Table.Root\n isLoading={isLoading}\n rows={workflows}\n footer={\n canCreate ? (\n <TFooter icon={<Plus />} onClick={handleCreateClick}>\n {formatMessage({\n id: 'Settings.review-workflows.list.page.create',\n defaultMessage: 'Create new workflow',\n })}\n </TFooter>\n ) : null\n }\n headers={headers}\n >\n <Table.Content>\n <Table.Head>\n {headers.map((head) => (\n <Table.HeaderCell key={head.name} {...head} />\n ))}\n </Table.Head>\n\n <Table.Body>\n {workflows.map((workflow) => (\n <Table.Row\n onClick={() => {\n navigate(`${workflow.id}`);\n }}\n key={workflow.id}\n >\n <Table.Cell width=\"25rem\">\n <Typography textColor=\"neutral800\" fontWeight=\"bold\" ellipsis>\n {workflow.name}\n </Typography>\n </Table.Cell>\n <Table.Cell>\n <Typography textColor=\"neutral800\">{workflow.stages.length}</Typography>\n </Table.Cell>\n <Table.Cell>\n <Typography textColor=\"neutral800\">\n {workflow.contentTypes\n .map((uid: string) => {\n const contentType = contentTypes.find(\n (contentType) => contentType.uid === uid\n );\n\n return contentType?.info.displayName ?? '';\n })\n .join(', ')}\n </Typography>\n </Table.Cell>\n <Table.Cell>\n <Flex alignItems=\"center\" justifyContent=\"end\">\n {canRead || canUpdate ? (\n <IconButton\n tag={Link}\n to={workflow.id.toString()}\n label={formatMessage(\n {\n id: 'Settings.review-workflows.list.page.list.column.actions.edit.label',\n defaultMessage: 'Edit {name}',\n },\n { name: workflow.name }\n )}\n variant=\"ghost\"\n >\n <Pencil />\n </IconButton>\n ) : null}\n {workflows.length > 1 && canDelete ? (\n <IconButton\n withTooltip={false}\n label={formatMessage(\n {\n id: 'Settings.review-workflows.list.page.list.column.actions.delete.label',\n defaultMessage: 'Delete {name}',\n },\n { name: 'Default workflow' }\n )}\n variant=\"ghost\"\n onClick={(e) => {\n e.stopPropagation();\n handleDeleteWorkflow(String(workflow.id));\n }}\n >\n <Trash />\n </IconButton>\n ) : null}\n </Flex>\n </Table.Cell>\n </Table.Row>\n ))}\n </Table.Body>\n </Table.Content>\n </Table.Root>\n\n <Dialog.Root open={!!workflowToDelete} onOpenChange={toggleConfirmDeleteDialog}>\n <ConfirmDialog onConfirm={handleConfirmDeleteDialog}>\n {formatMessage({\n id: 'Settings.review-workflows.list.page.delete.confirm.body',\n defaultMessage:\n 'If you remove this worfklow, all stage-related information will be removed for this content-type. Are you sure you want to remove it?',\n })}\n </ConfirmDialog>\n </Dialog.Root>\n\n <LimitsModal.Root open={showLimitModal} onOpenChange={() => setShowLimitModal(false)}>\n <LimitsModal.Title>\n {formatMessage({\n id: 'Settings.review-workflows.list.page.workflows.limit.title',\n defaultMessage: 'You’ve reached the limit of workflows in your plan',\n })}\n </LimitsModal.Title>\n\n <LimitsModal.Body>\n {formatMessage({\n id: 'Settings.review-workflows.list.page.workflows.limit.body',\n defaultMessage: 'Delete a workflow or contact Sales to enable more workflows.',\n })}\n </LimitsModal.Body>\n </LimitsModal.Root>\n </Layout.Root>\n </>\n );\n};\n\nconst ProtectedListPage = () => {\n const permissions = useTypedSelector(\n (state) => state.admin_app.permissions.settings?.['review-workflows']?.main\n );\n\n return (\n <Page.Protect permissions={permissions}>\n <ReviewWorkflowsListView />\n </Page.Protect>\n );\n};\n\nexport { ProtectedListPage };\n"],"names":["Layout.Header","Layout.Root","contentType"],"mappings":"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"}
|
|
@@ -2,10 +2,10 @@ import { jsx } from "react/jsx-runtime";
|
|
|
2
2
|
import { lazy } from "react";
|
|
3
3
|
import { Routes, Route } from "react-router-dom";
|
|
4
4
|
const ProtectedListPage = lazy(
|
|
5
|
-
() => import("./index-
|
|
5
|
+
() => import("./index-ZcZKwmTD.mjs").then((mod) => ({ default: mod.ProtectedListPage }))
|
|
6
6
|
);
|
|
7
7
|
const ProtectedEditPage = lazy(
|
|
8
|
-
() => import("./
|
|
8
|
+
() => import("./id-DINFSsrh.mjs").then((mod) => ({ default: mod.ProtectedEditPage }))
|
|
9
9
|
);
|
|
10
10
|
const routes = [
|
|
11
11
|
{
|
|
@@ -21,4 +21,4 @@ const Router = () => /* @__PURE__ */ jsx(Routes, { children: routes.map((route)
|
|
|
21
21
|
export {
|
|
22
22
|
Router
|
|
23
23
|
};
|
|
24
|
-
//# sourceMappingURL=router-
|
|
24
|
+
//# sourceMappingURL=router-BPH_u176.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"router-BPH_u176.mjs","sources":["../../admin/src/router.tsx"],"sourcesContent":["/* eslint-disable check-file/filename-naming-convention */\nimport { lazy } from 'react';\n\nimport { Routes, Route, PathRouteProps } from 'react-router-dom';\n\nconst ProtectedListPage = lazy(() =>\n import('./routes/settings').then((mod) => ({ default: mod.ProtectedListPage }))\n);\nconst ProtectedEditPage = lazy(() =>\n import('./routes/settings/id').then((mod) => ({ default: mod.ProtectedEditPage }))\n);\n\nconst routes: PathRouteProps[] = [\n {\n path: '/',\n Component: ProtectedListPage,\n },\n {\n path: ':id',\n Component: ProtectedEditPage,\n },\n];\n\nconst Router = () => (\n <Routes>\n {routes.map((route) => (\n <Route key={route.path} {...route} />\n ))}\n </Routes>\n);\n\nexport { Router };\n"],"names":[],"mappings":";;;AAKA,MAAM,oBAAoB;AAAA,EAAK,MAC7B,OAAO,sBAAmB,EAAE,KAAK,CAAC,SAAS,EAAE,SAAS,IAAI,kBAAA,EAAoB;AAChF;AACA,MAAM,oBAAoB;AAAA,EAAK,MAC7B,OAAO,mBAAsB,EAAE,KAAK,CAAC,SAAS,EAAE,SAAS,IAAI,kBAAA,EAAoB;AACnF;AAEA,MAAM,SAA2B;AAAA,EAC/B;AAAA,IACE,MAAM;AAAA,IACN,WAAW;AAAA,EACb;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,WAAW;AAAA,EACb;AACF;AAEA,MAAM,SAAS,MACZ,oBAAA,QAAA,EACE,iBAAO,IAAI,CAAC,UACX,oBAAC,SAAwB,GAAG,MAAA,GAAhB,MAAM,IAAiB,CACpC,EACH,CAAA;"}
|
|
@@ -4,10 +4,10 @@ const jsxRuntime = require("react/jsx-runtime");
|
|
|
4
4
|
const React = require("react");
|
|
5
5
|
const reactRouterDom = require("react-router-dom");
|
|
6
6
|
const ProtectedListPage = React.lazy(
|
|
7
|
-
() => Promise.resolve().then(() => require("./index-
|
|
7
|
+
() => Promise.resolve().then(() => require("./index-BpIILEs0.js")).then((mod) => ({ default: mod.ProtectedListPage }))
|
|
8
8
|
);
|
|
9
9
|
const ProtectedEditPage = React.lazy(
|
|
10
|
-
() => Promise.resolve().then(() => require("./
|
|
10
|
+
() => Promise.resolve().then(() => require("./id-BKq7JAqZ.js")).then((mod) => ({ default: mod.ProtectedEditPage }))
|
|
11
11
|
);
|
|
12
12
|
const routes = [
|
|
13
13
|
{
|
|
@@ -21,4 +21,4 @@ const routes = [
|
|
|
21
21
|
];
|
|
22
22
|
const Router = () => /* @__PURE__ */ jsxRuntime.jsx(reactRouterDom.Routes, { children: routes.map((route) => /* @__PURE__ */ jsxRuntime.jsx(reactRouterDom.Route, { ...route }, route.path)) });
|
|
23
23
|
exports.Router = Router;
|
|
24
|
-
//# sourceMappingURL=router-
|
|
24
|
+
//# sourceMappingURL=router-DeEgX8Ao.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"router-DeEgX8Ao.js","sources":["../../admin/src/router.tsx"],"sourcesContent":["/* eslint-disable check-file/filename-naming-convention */\nimport { lazy } from 'react';\n\nimport { Routes, Route, PathRouteProps } from 'react-router-dom';\n\nconst ProtectedListPage = lazy(() =>\n import('./routes/settings').then((mod) => ({ default: mod.ProtectedListPage }))\n);\nconst ProtectedEditPage = lazy(() =>\n import('./routes/settings/id').then((mod) => ({ default: mod.ProtectedEditPage }))\n);\n\nconst routes: PathRouteProps[] = [\n {\n path: '/',\n Component: ProtectedListPage,\n },\n {\n path: ':id',\n Component: ProtectedEditPage,\n },\n];\n\nconst Router = () => (\n <Routes>\n {routes.map((route) => (\n <Route key={route.path} {...route} />\n ))}\n </Routes>\n);\n\nexport { Router };\n"],"names":["lazy","jsx","Routes","Route"],"mappings":";;;;;AAKA,MAAM,oBAAoBA,MAAA;AAAA,EAAK,MAC7B,QAAO,QAAA,EAAA,KAAA,MAAA,QAAA,qBAAmB,GAAE,KAAK,CAAC,SAAS,EAAE,SAAS,IAAI,kBAAA,EAAoB;AAChF;AACA,MAAM,oBAAoBA,MAAA;AAAA,EAAK,MAC7B,QAAO,QAAA,EAAA,KAAA,MAAA,QAAA,kBAAsB,GAAE,KAAK,CAAC,SAAS,EAAE,SAAS,IAAI,kBAAA,EAAoB;AACnF;AAEA,MAAM,SAA2B;AAAA,EAC/B;AAAA,IACE,MAAM;AAAA,IACN,WAAW;AAAA,EACb;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,WAAW;AAAA,EACb;AACF;AAEA,MAAM,SAAS,MACZC,2BAAAA,IAAAC,eAAAA,QAAA,EACE,iBAAO,IAAI,CAAC,UACXD,2BAAA,IAACE,wBAAwB,GAAG,MAAA,GAAhB,MAAM,IAAiB,CACpC,EACH,CAAA;;"}
|
package/dist/admin/index.js
CHANGED
package/dist/admin/index.mjs
CHANGED
|
@@ -1727,13 +1727,17 @@ declare const useGetWorkflowsQuery: import("@reduxjs/toolkit/dist/query/react/bu
|
|
|
1727
1727
|
}) | undefined;
|
|
1728
1728
|
} & import("@strapi/types/dist/modules/entity-service/params/filters").AbstractAttributesFiltering<"admin::review-workflow">) | undefined;
|
|
1729
1729
|
} & {
|
|
1730
|
-
populate?:
|
|
1730
|
+
populate?: import("@strapi/types/dist/modules/entity-service/params/populate").ArrayNotation<"admin::review-workflow"> | undefined;
|
|
1731
1731
|
}), import("@reduxjs/toolkit/query").BaseQueryFn<string | import("@strapi/admin/strapi-admin").QueryArguments, unknown, import("@strapi/admin/strapi-admin").BaseQueryError, {}, {}>, "ReviewWorkflow" | "ReviewWorkflowStages" | "Document" | "ContentTypeSettings", {
|
|
1732
1732
|
workflows: GetAll.Response['data'];
|
|
1733
1733
|
meta?: GetAll.Response['meta'];
|
|
1734
1734
|
}, "adminApi">>, useCreateWorkflowMutation: import("@reduxjs/toolkit/dist/query/react/buildHooks").UseMutation<import("@reduxjs/toolkit/query").MutationDefinition<{
|
|
1735
|
-
data: Omit<import("../../../shared/contracts/review-workflows").Workflow, "id" | "createdAt" | "updatedAt"
|
|
1735
|
+
data: Omit<import("../../../shared/contracts/review-workflows").Workflow, "id" | "createdAt" | "updatedAt"> & {
|
|
1736
|
+
stageRequiredToPublishName?: string | null | undefined;
|
|
1737
|
+
};
|
|
1736
1738
|
}, import("@reduxjs/toolkit/query").BaseQueryFn<string | import("@strapi/admin/strapi-admin").QueryArguments, unknown, import("@strapi/admin/strapi-admin").BaseQueryError, {}, {}>, "ReviewWorkflow" | "ReviewWorkflowStages" | "Document" | "ContentTypeSettings", import("../../../shared/contracts/review-workflows").Workflow, "adminApi">>, useDeleteWorkflowMutation: import("@reduxjs/toolkit/dist/query/react/buildHooks").UseMutation<import("@reduxjs/toolkit/query").MutationDefinition<Delete.Params, import("@reduxjs/toolkit/query").BaseQueryFn<string | import("@strapi/admin/strapi-admin").QueryArguments, unknown, import("@strapi/admin/strapi-admin").BaseQueryError, {}, {}>, "ReviewWorkflow" | "ReviewWorkflowStages" | "Document" | "ContentTypeSettings", import("../../../shared/contracts/review-workflows").Workflow, "adminApi">>, useUpdateWorkflowMutation: import("@reduxjs/toolkit/dist/query/react/buildHooks").UseMutation<import("@reduxjs/toolkit/query").MutationDefinition<{
|
|
1737
|
-
data: Partial<import("../../../shared/contracts/review-workflows").Workflow
|
|
1739
|
+
data: Partial<Omit<import("../../../shared/contracts/review-workflows").Workflow, "stageRequiredToPublish">> & {
|
|
1740
|
+
stageRequiredToPublishName?: string | null | undefined;
|
|
1741
|
+
};
|
|
1738
1742
|
} & Update.Params, import("@reduxjs/toolkit/query").BaseQueryFn<string | import("@strapi/admin/strapi-admin").QueryArguments, unknown, import("@strapi/admin/strapi-admin").BaseQueryError, {}, {}>, "ReviewWorkflow" | "ReviewWorkflowStages" | "Document" | "ContentTypeSettings", import("../../../shared/contracts/review-workflows").Workflow, "adminApi">>;
|
|
1739
1743
|
export { useGetWorkflowsQuery, useCreateWorkflowMutation, useDeleteWorkflowMutation, useUpdateWorkflowMutation, type GetWorkflowsParams, };
|
package/dist/server/index.js
CHANGED
|
@@ -6387,7 +6387,8 @@ const WORKFLOW_POPULATE = {
|
|
|
6387
6387
|
}
|
|
6388
6388
|
}
|
|
6389
6389
|
}
|
|
6390
|
-
}
|
|
6390
|
+
},
|
|
6391
|
+
stageRequiredToPublish: true
|
|
6391
6392
|
};
|
|
6392
6393
|
function checkVersionThreshold(startVersion, currentVersion, thresholdVersion) {
|
|
6393
6394
|
return semver$1.gte(currentVersion, thresholdVersion) && semver$1.lt(startVersion, thresholdVersion);
|
|
@@ -6562,8 +6563,40 @@ function extendReviewWorkflowContentTypes({ strapi: strapi2 }) {
|
|
|
6562
6563
|
});
|
|
6563
6564
|
}
|
|
6564
6565
|
}
|
|
6566
|
+
function persistRWOnDowngrade({ strapi: strapi2 }) {
|
|
6567
|
+
const { removePersistedTablesWithSuffix, persistTables } = getAdminService("persist-tables");
|
|
6568
|
+
return async ({ contentTypes: contentTypes2 }) => {
|
|
6569
|
+
const getStageTableToPersist = (contentTypeUID) => {
|
|
6570
|
+
const { attributes, tableName } = strapi2.db.metadata.get(contentTypeUID);
|
|
6571
|
+
const joinTableName = attributes[ENTITY_STAGE_ATTRIBUTE].joinTable.name;
|
|
6572
|
+
return {
|
|
6573
|
+
name: joinTableName,
|
|
6574
|
+
dependsOn: [{ name: tableName }]
|
|
6575
|
+
};
|
|
6576
|
+
};
|
|
6577
|
+
const getAssigneeTableToPersist = (contentTypeUID) => {
|
|
6578
|
+
const { attributes, tableName } = strapi2.db.metadata.get(contentTypeUID);
|
|
6579
|
+
const joinTableName = attributes[ENTITY_ASSIGNEE_ATTRIBUTE].joinTable.name;
|
|
6580
|
+
return {
|
|
6581
|
+
name: joinTableName,
|
|
6582
|
+
dependsOn: [{ name: tableName }]
|
|
6583
|
+
};
|
|
6584
|
+
};
|
|
6585
|
+
const enabledRWContentTypes = fp.pipe([
|
|
6586
|
+
getVisibleContentTypesUID,
|
|
6587
|
+
fp.filter((uid) => hasStageAttribute(contentTypes2[uid]))
|
|
6588
|
+
])(contentTypes2);
|
|
6589
|
+
const stageJoinTablesToPersist = enabledRWContentTypes.map(getStageTableToPersist);
|
|
6590
|
+
await removePersistedTablesWithSuffix("_strapi_stage_lnk");
|
|
6591
|
+
await persistTables(stageJoinTablesToPersist);
|
|
6592
|
+
const assigneeJoinTablesToPersist = enabledRWContentTypes.map(getAssigneeTableToPersist);
|
|
6593
|
+
await removePersistedTablesWithSuffix("_strapi_assignee_lnk");
|
|
6594
|
+
await persistTables(assigneeJoinTablesToPersist);
|
|
6595
|
+
};
|
|
6596
|
+
}
|
|
6565
6597
|
const register = async ({ strapi: strapi2 }) => {
|
|
6566
6598
|
strapi2.hook("strapi::content-types.beforeSync").register(migrateStageAttribute);
|
|
6599
|
+
strapi2.hook("strapi::content-types.afterSync").register(persistRWOnDowngrade({ strapi: strapi2 }));
|
|
6567
6600
|
strapi2.hook("strapi::content-types.afterSync").register(migrateReviewWorkflowStagesColor).register(migrateReviewWorkflowStagesRoles).register(migrateReviewWorkflowName).register(migrateWorkflowsContentTypes).register(migrateDeletedCTInWorkflows);
|
|
6568
6601
|
reviewWorkflowsMiddlewares.contentTypeMiddleware(strapi2);
|
|
6569
6602
|
extendReviewWorkflowContentTypes({ strapi: strapi2 });
|
|
@@ -6608,6 +6641,12 @@ const workflow = {
|
|
|
6608
6641
|
relation: "oneToMany",
|
|
6609
6642
|
mappedBy: "workflow"
|
|
6610
6643
|
},
|
|
6644
|
+
stageRequiredToPublish: {
|
|
6645
|
+
type: "relation",
|
|
6646
|
+
target: "plugin::review-workflows.workflow-stage",
|
|
6647
|
+
relation: "oneToOne",
|
|
6648
|
+
required: false
|
|
6649
|
+
},
|
|
6611
6650
|
contentTypes: {
|
|
6612
6651
|
type: "json",
|
|
6613
6652
|
required: true,
|
|
@@ -6757,6 +6796,7 @@ const bootstrap = async (args) => {
|
|
|
6757
6796
|
const docsMiddlewares = getService("document-service-middlewares");
|
|
6758
6797
|
strapi.documents.use(docsMiddlewares.assignStageOnCreate);
|
|
6759
6798
|
strapi.documents.use(docsMiddlewares.handleStageOnUpdate);
|
|
6799
|
+
strapi.documents.use(docsMiddlewares.checkStageBeforePublish);
|
|
6760
6800
|
};
|
|
6761
6801
|
const destroy = async ({ strapi: strapi2 }) => {
|
|
6762
6802
|
};
|
|
@@ -6901,7 +6941,7 @@ const reviewWorkflows = {
|
|
|
6901
6941
|
{
|
|
6902
6942
|
name: "admin::hasPermissions",
|
|
6903
6943
|
config: {
|
|
6904
|
-
actions: ["admin::users.read"
|
|
6944
|
+
actions: ["admin::users.read"]
|
|
6905
6945
|
}
|
|
6906
6946
|
}
|
|
6907
6947
|
]
|
|
@@ -6989,9 +7029,9 @@ const processFilters = ({ strapi: strapi2 }, filters = {}) => {
|
|
|
6989
7029
|
};
|
|
6990
7030
|
const processPopulate = (populate) => {
|
|
6991
7031
|
if (!populate) {
|
|
6992
|
-
return
|
|
7032
|
+
return WORKFLOW_POPULATE;
|
|
6993
7033
|
}
|
|
6994
|
-
return
|
|
7034
|
+
return populate;
|
|
6995
7035
|
};
|
|
6996
7036
|
const workflows$1 = ({ strapi: strapi2 }) => {
|
|
6997
7037
|
const workflowsContentTypes = workflowsContentTypesFactory({ strapi: strapi2 });
|
|
@@ -7042,14 +7082,27 @@ const workflows$1 = ({ strapi: strapi2 }) => {
|
|
|
7042
7082
|
const stages2 = await getService("stages", { strapi: strapi2 }).createMany(opts.data.stages);
|
|
7043
7083
|
const mapIds = fp.map(fp.get("id"));
|
|
7044
7084
|
createOpts = fp.set("data.stages", mapIds(stages2), createOpts);
|
|
7085
|
+
if (opts.data.stageRequiredToPublishName) {
|
|
7086
|
+
const stageRequiredToPublish = stages2.find(
|
|
7087
|
+
(stage) => stage.name === opts.data.stageRequiredToPublishName
|
|
7088
|
+
);
|
|
7089
|
+
if (!stageRequiredToPublish) {
|
|
7090
|
+
throw new utils.errors.ApplicationError("Stage required to publish does not exist");
|
|
7091
|
+
}
|
|
7092
|
+
createOpts = fp.set("data.stageRequiredToPublish", stageRequiredToPublish.id, createOpts);
|
|
7093
|
+
}
|
|
7045
7094
|
if (opts.data.contentTypes) {
|
|
7046
7095
|
await workflowsContentTypes.migrate({
|
|
7047
7096
|
destContentTypes: opts.data.contentTypes,
|
|
7048
7097
|
stageId: stages2[0].id
|
|
7049
7098
|
});
|
|
7050
7099
|
}
|
|
7051
|
-
|
|
7052
|
-
|
|
7100
|
+
const createdWorkflow = await strapi2.db.query(WORKFLOW_MODEL_UID).create(strapi2.get("query-params").transform(WORKFLOW_MODEL_UID, createOpts));
|
|
7101
|
+
metrics.sendDidCreateWorkflow(createdWorkflow.id, !!opts.data.stageRequiredToPublishName);
|
|
7102
|
+
if (opts.data.stageRequiredToPublishName) {
|
|
7103
|
+
await strapi2.plugin("content-releases").service("release-action").validateActionsByContentTypes(opts.data.contentTypes);
|
|
7104
|
+
}
|
|
7105
|
+
return createdWorkflow;
|
|
7053
7106
|
});
|
|
7054
7107
|
},
|
|
7055
7108
|
/**
|
|
@@ -7062,6 +7115,7 @@ const workflows$1 = ({ strapi: strapi2 }) => {
|
|
|
7062
7115
|
async update(workflow2, opts) {
|
|
7063
7116
|
const stageService = getService("stages", { strapi: strapi2 });
|
|
7064
7117
|
let updateOpts = { ...opts, populate: { ...WORKFLOW_POPULATE } };
|
|
7118
|
+
let updatedStages = [];
|
|
7065
7119
|
let updatedStageIds;
|
|
7066
7120
|
await workflowValidator.validateWorkflowCount();
|
|
7067
7121
|
return strapi2.db.transaction(async () => {
|
|
@@ -7070,9 +7124,28 @@ const workflows$1 = ({ strapi: strapi2 }) => {
|
|
|
7070
7124
|
opts.data.stages.forEach(
|
|
7071
7125
|
(stage) => this.assertStageBelongsToWorkflow(stage.id, workflow2)
|
|
7072
7126
|
);
|
|
7073
|
-
|
|
7127
|
+
updatedStages = await stageService.replaceStages(
|
|
7128
|
+
workflow2.stages,
|
|
7129
|
+
opts.data.stages,
|
|
7130
|
+
workflow2.contentTypes
|
|
7131
|
+
);
|
|
7132
|
+
updatedStageIds = updatedStages.map((stage) => stage.id);
|
|
7074
7133
|
updateOpts = fp.set("data.stages", updatedStageIds, updateOpts);
|
|
7075
7134
|
}
|
|
7135
|
+
if (opts.data.stageRequiredToPublishName !== void 0) {
|
|
7136
|
+
const stages2 = updatedStages ?? workflow2.stages;
|
|
7137
|
+
if (opts.data.stageRequiredToPublishName === null) {
|
|
7138
|
+
updateOpts = fp.set("data.stageRequiredToPublish", null, updateOpts);
|
|
7139
|
+
} else {
|
|
7140
|
+
const stageRequiredToPublish = stages2.find(
|
|
7141
|
+
(stage) => stage.name === opts.data.stageRequiredToPublishName
|
|
7142
|
+
);
|
|
7143
|
+
if (!stageRequiredToPublish) {
|
|
7144
|
+
throw new utils.errors.ApplicationError("Stage required to publish does not exist");
|
|
7145
|
+
}
|
|
7146
|
+
updateOpts = fp.set("data.stageRequiredToPublish", stageRequiredToPublish.id, updateOpts);
|
|
7147
|
+
}
|
|
7148
|
+
}
|
|
7076
7149
|
if (opts.data.contentTypes) {
|
|
7077
7150
|
await workflowsContentTypes.migrate({
|
|
7078
7151
|
srcContentTypes: workflow2.contentTypes,
|
|
@@ -7080,12 +7153,17 @@ const workflows$1 = ({ strapi: strapi2 }) => {
|
|
|
7080
7153
|
stageId: updatedStageIds ? updatedStageIds[0] : workflow2.stages[0].id
|
|
7081
7154
|
});
|
|
7082
7155
|
}
|
|
7083
|
-
metrics.sendDidEditWorkflow();
|
|
7156
|
+
metrics.sendDidEditWorkflow(workflow2.id, !!opts.data.stageRequiredToPublishName);
|
|
7084
7157
|
const query = strapi2.get("query-params").transform(WORKFLOW_MODEL_UID, updateOpts);
|
|
7085
|
-
|
|
7158
|
+
const updatedWorkflow = await strapi2.db.query(WORKFLOW_MODEL_UID).update({
|
|
7086
7159
|
...query,
|
|
7087
7160
|
where: { id: workflow2.id }
|
|
7088
7161
|
});
|
|
7162
|
+
await strapi2.plugin("content-releases").service("release-action").validateActionsByContentTypes([
|
|
7163
|
+
...workflow2.contentTypes,
|
|
7164
|
+
...opts.data.contentTypes || []
|
|
7165
|
+
]);
|
|
7166
|
+
return updatedWorkflow;
|
|
7089
7167
|
});
|
|
7090
7168
|
},
|
|
7091
7169
|
/**
|
|
@@ -7108,10 +7186,12 @@ const workflows$1 = ({ strapi: strapi2 }) => {
|
|
|
7108
7186
|
destContentTypes: []
|
|
7109
7187
|
});
|
|
7110
7188
|
const query = strapi2.get("query-params").transform(WORKFLOW_MODEL_UID, opts);
|
|
7111
|
-
|
|
7189
|
+
const deletedWorkflow = await strapi2.db.query(WORKFLOW_MODEL_UID).delete({
|
|
7112
7190
|
...query,
|
|
7113
7191
|
where: { id: workflow2.id }
|
|
7114
7192
|
});
|
|
7193
|
+
await strapi2.plugin("content-releases").service("release-action").validateActionsByContentTypes(workflow2.contentTypes);
|
|
7194
|
+
return deletedWorkflow;
|
|
7115
7195
|
});
|
|
7116
7196
|
},
|
|
7117
7197
|
/**
|
|
@@ -7322,25 +7402,26 @@ const stages$1 = ({ strapi: strapi2 }) => {
|
|
|
7322
7402
|
},
|
|
7323
7403
|
/**
|
|
7324
7404
|
* Update the stage of an entity
|
|
7325
|
-
*
|
|
7326
|
-
* @param {object} entityInfo
|
|
7327
|
-
* @param {number} entityInfo.id - Entity id
|
|
7328
|
-
* @param {string} entityInfo.modelUID - the content-type of the entity
|
|
7329
|
-
* @param {number} stageId - The id of the stage to assign to the entity
|
|
7330
7405
|
*/
|
|
7331
|
-
async updateEntity(
|
|
7406
|
+
async updateEntity(entityToUpdate, model, stageId) {
|
|
7332
7407
|
const stage = await this.findById(stageId);
|
|
7408
|
+
const { documentId, locale } = entityToUpdate;
|
|
7333
7409
|
await workflowValidator.validateWorkflowCount();
|
|
7334
7410
|
if (!stage) {
|
|
7335
7411
|
throw new ApplicationError$2(`Selected stage does not exist`);
|
|
7336
7412
|
}
|
|
7337
|
-
const entity = await strapi2.
|
|
7338
|
-
|
|
7339
|
-
|
|
7340
|
-
|
|
7341
|
-
|
|
7413
|
+
const entity = await strapi2.documents(model).update({
|
|
7414
|
+
documentId,
|
|
7415
|
+
locale,
|
|
7416
|
+
// Stage doesn't have DP or i18n enabled, connecting it through the `id`
|
|
7417
|
+
// will be safer than relying on the `documentId` + `locale` + `status` transformation
|
|
7418
|
+
data: { [ENTITY_STAGE_ATTRIBUTE]: fp.pick(["id"], stage) },
|
|
7342
7419
|
populate: [ENTITY_STAGE_ATTRIBUTE]
|
|
7343
7420
|
});
|
|
7421
|
+
const { tableName } = strapi2.db.metadata.get(model);
|
|
7422
|
+
await strapi2.db.connection(tableName).where({ id: entityToUpdate.id }).update({
|
|
7423
|
+
updated_at: new Date(entityToUpdate.updatedAt)
|
|
7424
|
+
});
|
|
7344
7425
|
metrics.sendDidChangeEntryStage();
|
|
7345
7426
|
return entity;
|
|
7346
7427
|
},
|
|
@@ -7487,32 +7568,28 @@ const assignees$1 = ({ strapi: strapi2 }) => {
|
|
|
7487
7568
|
/**
|
|
7488
7569
|
* Update the assignee of an entity
|
|
7489
7570
|
*/
|
|
7490
|
-
async updateEntityAssignee(
|
|
7491
|
-
|
|
7492
|
-
|
|
7493
|
-
|
|
7494
|
-
|
|
7495
|
-
|
|
7496
|
-
|
|
7571
|
+
async updateEntityAssignee(entityToUpdate, model, assigneeId) {
|
|
7572
|
+
const { documentId, locale } = entityToUpdate;
|
|
7573
|
+
if (!fp.isNil(assigneeId)) {
|
|
7574
|
+
const userExists = await getAdminService("user", { strapi: strapi2 }).exists({ id: assigneeId });
|
|
7575
|
+
if (!userExists) {
|
|
7576
|
+
throw new ApplicationError(`Selected user does not exist`);
|
|
7577
|
+
}
|
|
7497
7578
|
}
|
|
7498
|
-
|
|
7499
|
-
|
|
7579
|
+
const oldAssigneeId = await this.findEntityAssigneeId(entityToUpdate.id, model);
|
|
7580
|
+
metrics.sendDidEditAssignee(oldAssigneeId, assigneeId || null);
|
|
7581
|
+
const entity = await strapi2.documents(model).update({
|
|
7500
7582
|
documentId,
|
|
7501
7583
|
locale,
|
|
7502
|
-
data: { [ENTITY_ASSIGNEE_ATTRIBUTE]: assigneeId },
|
|
7584
|
+
data: { [ENTITY_ASSIGNEE_ATTRIBUTE]: assigneeId || null },
|
|
7503
7585
|
populate: [ENTITY_ASSIGNEE_ATTRIBUTE],
|
|
7504
7586
|
fields: []
|
|
7505
7587
|
});
|
|
7506
|
-
|
|
7507
|
-
|
|
7508
|
-
|
|
7509
|
-
return strapi2.documents(model).update({
|
|
7510
|
-
documentId,
|
|
7511
|
-
locale,
|
|
7512
|
-
data: { [ENTITY_ASSIGNEE_ATTRIBUTE]: null },
|
|
7513
|
-
populate: [ENTITY_ASSIGNEE_ATTRIBUTE],
|
|
7514
|
-
fields: []
|
|
7588
|
+
const { tableName } = strapi2.db.metadata.get(model);
|
|
7589
|
+
await strapi2.db.connection(tableName).where({ id: entityToUpdate.id }).update({
|
|
7590
|
+
updated_at: new Date(entityToUpdate.updatedAt)
|
|
7515
7591
|
});
|
|
7592
|
+
return entity;
|
|
7516
7593
|
}
|
|
7517
7594
|
};
|
|
7518
7595
|
};
|
|
@@ -7585,11 +7662,11 @@ const sendDidDeleteStage = async () => {
|
|
|
7585
7662
|
const sendDidChangeEntryStage = async () => {
|
|
7586
7663
|
strapi.telemetry.send("didChangeEntryStage", {});
|
|
7587
7664
|
};
|
|
7588
|
-
const sendDidCreateWorkflow = async () => {
|
|
7589
|
-
strapi.telemetry.send("didCreateWorkflow", {});
|
|
7665
|
+
const sendDidCreateWorkflow = async (workflowId, hasRequiredStageToPublish) => {
|
|
7666
|
+
strapi.telemetry.send("didCreateWorkflow", { workflowId, hasRequiredStageToPublish });
|
|
7590
7667
|
};
|
|
7591
|
-
const sendDidEditWorkflow = async () => {
|
|
7592
|
-
strapi.telemetry.send("didEditWorkflow", {});
|
|
7668
|
+
const sendDidEditWorkflow = async (workflowId, hasRequiredStageToPublish) => {
|
|
7669
|
+
strapi.telemetry.send("didEditWorkflow", { workflowId, hasRequiredStageToPublish });
|
|
7593
7670
|
};
|
|
7594
7671
|
const sendDidEditAssignee = async (fromId, toId) => {
|
|
7595
7672
|
strapi.telemetry.send("didEditAssignee", { from: fromId, to: toId });
|
|
@@ -7614,13 +7691,13 @@ const reviewWorkflowsMetrics = {
|
|
|
7614
7691
|
sendDidSendReviewWorkflowPropertiesOnceAWeek,
|
|
7615
7692
|
sendDidEditAssignee
|
|
7616
7693
|
};
|
|
7617
|
-
function _typeof(
|
|
7694
|
+
function _typeof(o) {
|
|
7618
7695
|
"@babel/helpers - typeof";
|
|
7619
|
-
return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function(
|
|
7620
|
-
return typeof
|
|
7621
|
-
} : function(
|
|
7622
|
-
return
|
|
7623
|
-
}, _typeof(
|
|
7696
|
+
return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function(o2) {
|
|
7697
|
+
return typeof o2;
|
|
7698
|
+
} : function(o2) {
|
|
7699
|
+
return o2 && "function" == typeof Symbol && o2.constructor === Symbol && o2 !== Symbol.prototype ? "symbol" : typeof o2;
|
|
7700
|
+
}, _typeof(o);
|
|
7624
7701
|
}
|
|
7625
7702
|
function toInteger(dirtyNumber) {
|
|
7626
7703
|
if (dirtyNumber === null || dirtyNumber === true || dirtyNumber === false) {
|
|
@@ -7755,7 +7832,12 @@ const reviewWorkflowsWeeklyMetrics = ({ strapi: strapi2 }) => {
|
|
|
7755
7832
|
},
|
|
7756
7833
|
async registerCron() {
|
|
7757
7834
|
const weeklySchedule = await this.ensureWeeklyStoredCronSchedule();
|
|
7758
|
-
strapi2.cron.add({
|
|
7835
|
+
strapi2.cron.add({
|
|
7836
|
+
reviewWorkflowsWeekly: {
|
|
7837
|
+
task: this.sendMetrics.bind(this),
|
|
7838
|
+
options: weeklySchedule
|
|
7839
|
+
}
|
|
7840
|
+
});
|
|
7759
7841
|
}
|
|
7760
7842
|
};
|
|
7761
7843
|
};
|
|
@@ -7811,6 +7893,7 @@ const handleStageOnUpdate = async (ctx, next) => {
|
|
|
7811
7893
|
strapi.eventHub.emit(WORKFLOW_UPDATE_STAGE, {
|
|
7812
7894
|
model: model.modelName,
|
|
7813
7895
|
uid: model.uid,
|
|
7896
|
+
// TODO v6: Rename to "entry", which is what is used for regular CRUD updates
|
|
7814
7897
|
entity: {
|
|
7815
7898
|
// @ts-expect-error
|
|
7816
7899
|
id: result?.id,
|
|
@@ -7836,9 +7919,27 @@ const handleStageOnUpdate = async (ctx, next) => {
|
|
|
7836
7919
|
}
|
|
7837
7920
|
return next();
|
|
7838
7921
|
};
|
|
7922
|
+
const checkStageBeforePublish = async (ctx, next) => {
|
|
7923
|
+
if (ctx.action !== "publish") {
|
|
7924
|
+
return next();
|
|
7925
|
+
}
|
|
7926
|
+
const workflow2 = await getService("workflows").getAssignedWorkflow(ctx.contentType.uid, {
|
|
7927
|
+
populate: "stageRequiredToPublish"
|
|
7928
|
+
});
|
|
7929
|
+
if (!workflow2 || !workflow2.stageRequiredToPublish) {
|
|
7930
|
+
return next();
|
|
7931
|
+
}
|
|
7932
|
+
const { documentId } = ctx.params;
|
|
7933
|
+
const entryStage = await getEntityStage(ctx.contentType.uid, documentId, ctx.params);
|
|
7934
|
+
if (entryStage.id !== workflow2.stageRequiredToPublish.id) {
|
|
7935
|
+
throw new utils.errors.ValidationError("Entry is not at the required stage to publish");
|
|
7936
|
+
}
|
|
7937
|
+
return next();
|
|
7938
|
+
};
|
|
7839
7939
|
const documentServiceMiddleware = () => ({
|
|
7840
7940
|
assignStageOnCreate,
|
|
7841
|
-
handleStageOnUpdate
|
|
7941
|
+
handleStageOnUpdate,
|
|
7942
|
+
checkStageBeforePublish
|
|
7842
7943
|
});
|
|
7843
7944
|
const services = {
|
|
7844
7945
|
workflows: workflows$1,
|
|
@@ -7888,12 +7989,14 @@ const validateContentTypes = utils.yup.array().of(
|
|
|
7888
7989
|
const validateWorkflowCreateSchema = utils.yup.object().shape({
|
|
7889
7990
|
name: utils.yup.string().max(255).min(1, "Workflow name can not be empty").required(),
|
|
7890
7991
|
stages: utils.yup.array().of(stageObject).uniqueProperty("name", "Stage name must be unique").min(1, "Can not create a workflow without stages").max(200, "Can not have more than 200 stages").required("Can not create a workflow without stages"),
|
|
7891
|
-
contentTypes: validateContentTypes
|
|
7992
|
+
contentTypes: validateContentTypes,
|
|
7993
|
+
stageRequiredToPublishName: utils.yup.string().min(1).nullable()
|
|
7892
7994
|
});
|
|
7893
7995
|
const validateWorkflowUpdateSchema = utils.yup.object().shape({
|
|
7894
7996
|
name: utils.yup.string().max(255).min(1, "Workflow name can not be empty"),
|
|
7895
7997
|
stages: utils.yup.array().of(stageObject).uniqueProperty("name", "Stage name must be unique").min(1, "Can not update a workflow without stages").max(200, "Can not have more than 200 stages"),
|
|
7896
|
-
contentTypes: validateContentTypes
|
|
7998
|
+
contentTypes: validateContentTypes,
|
|
7999
|
+
stageRequiredToPublishName: utils.yup.string().min(1).nullable()
|
|
7897
8000
|
});
|
|
7898
8001
|
const validateUpdateAssigneeOnEntitySchema = utils.yup.object().shape({
|
|
7899
8002
|
id: utils.yup.number().integer().min(1).nullable()
|
|
@@ -8096,7 +8199,7 @@ const stages = {
|
|
|
8096
8199
|
);
|
|
8097
8200
|
const workflow2 = await workflowService.assertContentTypeBelongsToWorkflow(modelUID);
|
|
8098
8201
|
workflowService.assertStageBelongsToWorkflow(stageId, workflow2);
|
|
8099
|
-
const updatedEntity = await stagesService.updateEntity(
|
|
8202
|
+
const updatedEntity = await stagesService.updateEntity(entity, modelUID, stageId);
|
|
8100
8203
|
ctx.body = { data: await sanitizeOutput(updatedEntity) };
|
|
8101
8204
|
},
|
|
8102
8205
|
/**
|
|
@@ -8116,10 +8219,9 @@ const stages = {
|
|
|
8116
8219
|
if (strapi.plugin("content-manager").service("permission-checker").create({ userAbility: ctx.state.userAbility, model: modelUID }).cannot.read()) {
|
|
8117
8220
|
return ctx.forbidden();
|
|
8118
8221
|
}
|
|
8119
|
-
const locale = await validateLocale(query?.locale);
|
|
8222
|
+
const locale = await validateLocale(query?.locale) ?? void 0;
|
|
8120
8223
|
const entity = await strapi.documents(modelUID).findOne({
|
|
8121
8224
|
documentId,
|
|
8122
|
-
// @ts-expect-error - locale should be also null in the doc service types
|
|
8123
8225
|
locale,
|
|
8124
8226
|
populate: [ENTITY_STAGE_ATTRIBUTE]
|
|
8125
8227
|
});
|
|
@@ -8128,12 +8230,13 @@ const stages = {
|
|
|
8128
8230
|
}
|
|
8129
8231
|
const entityStageId = entity[ENTITY_STAGE_ATTRIBUTE]?.id;
|
|
8130
8232
|
const canTransition = stagePermissions2.can(STAGE_TRANSITION_UID, entityStageId);
|
|
8131
|
-
const [workflowCount,
|
|
8233
|
+
const [workflowCount, workflowResult] = await Promise.all([
|
|
8132
8234
|
workflowService.count(),
|
|
8133
8235
|
workflowService.getAssignedWorkflow(modelUID, {
|
|
8134
8236
|
populate: "stages"
|
|
8135
8237
|
})
|
|
8136
8238
|
]);
|
|
8239
|
+
const workflowStages = workflowResult ? workflowResult.stages : [];
|
|
8137
8240
|
const meta = {
|
|
8138
8241
|
stageCount: workflowStages.length,
|
|
8139
8242
|
workflowCount
|
|
@@ -8169,22 +8272,32 @@ const assignees = {
|
|
|
8169
8272
|
async updateEntity(ctx) {
|
|
8170
8273
|
const assigneeService = getService("assignees");
|
|
8171
8274
|
const workflowService = getService("workflows");
|
|
8275
|
+
const stagePermissions2 = getService("stage-permissions");
|
|
8172
8276
|
const { model_uid: model, id: documentId } = ctx.params;
|
|
8173
|
-
const
|
|
8277
|
+
const locale = await validateLocale(ctx.request.query?.locale) ?? void 0;
|
|
8174
8278
|
const { sanitizeOutput } = strapi.plugin("content-manager").service("permission-checker").create({ userAbility: ctx.state.userAbility, model });
|
|
8279
|
+
const entity = await strapi.documents(model).findOne({
|
|
8280
|
+
documentId,
|
|
8281
|
+
locale,
|
|
8282
|
+
populate: [ENTITY_STAGE_ATTRIBUTE]
|
|
8283
|
+
});
|
|
8284
|
+
if (!entity) {
|
|
8285
|
+
ctx.throw(404, "Entity not found");
|
|
8286
|
+
}
|
|
8287
|
+
const canTransitionStage = stagePermissions2.can(
|
|
8288
|
+
STAGE_TRANSITION_UID,
|
|
8289
|
+
entity[ENTITY_STAGE_ATTRIBUTE]?.id
|
|
8290
|
+
);
|
|
8291
|
+
if (!canTransitionStage) {
|
|
8292
|
+
ctx.throw(403, "Stage transition permission is required");
|
|
8293
|
+
}
|
|
8175
8294
|
const { id: assigneeId } = await validateUpdateAssigneeOnEntity(
|
|
8176
8295
|
ctx.request?.body?.data,
|
|
8177
8296
|
"You should pass a valid id to the body of the put request."
|
|
8178
8297
|
);
|
|
8179
|
-
await validateLocale(locale);
|
|
8180
8298
|
await workflowService.assertContentTypeBelongsToWorkflow(model);
|
|
8181
|
-
const
|
|
8182
|
-
|
|
8183
|
-
locale || null,
|
|
8184
|
-
model,
|
|
8185
|
-
assigneeId
|
|
8186
|
-
);
|
|
8187
|
-
ctx.body = { data: await sanitizeOutput(entity) };
|
|
8299
|
+
const updatedEntity = await assigneeService.updateEntityAssignee(entity, model, assigneeId);
|
|
8300
|
+
ctx.body = { data: await sanitizeOutput(updatedEntity) };
|
|
8188
8301
|
}
|
|
8189
8302
|
};
|
|
8190
8303
|
const controllers = {
|