@strapi/review-workflows 0.0.0-next.3fdd03038d558a8190aa7e17574020c5f65395e6 → 0.0.0-next.4119cc523a8fec549bb2f1869c6e789650f7f4de

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 (64) hide show
  1. package/dist/_chunks/{Layout-8i0EXRRs.js → Layout-B4fpKB9J.js} +3 -3
  2. package/dist/_chunks/Layout-B4fpKB9J.js.map +1 -0
  3. package/dist/_chunks/{Layout-C9m07iTY.mjs → Layout-Dko22Aly.mjs} +3 -3
  4. package/dist/_chunks/Layout-Dko22Aly.mjs.map +1 -0
  5. package/dist/_chunks/{en-xcewH2pC.js → en-CYgjfSep.js} +5 -2
  6. package/dist/_chunks/en-CYgjfSep.js.map +1 -0
  7. package/dist/_chunks/{en-D9ZrQAV6.mjs → en-D9dxziEb.mjs} +5 -2
  8. package/dist/_chunks/en-D9dxziEb.mjs.map +1 -0
  9. package/dist/_chunks/{id-CmtaTf1x.js → id-BKq7JAqZ.js} +73 -13
  10. package/dist/_chunks/id-BKq7JAqZ.js.map +1 -0
  11. package/dist/_chunks/{id-DV0Ndeav.mjs → id-DINFSsrh.mjs} +73 -13
  12. package/dist/_chunks/id-DINFSsrh.mjs.map +1 -0
  13. package/dist/_chunks/{index-B8WmHbCU.js → index-BpIILEs0.js} +3 -3
  14. package/dist/_chunks/{index-B8WmHbCU.js.map → index-BpIILEs0.js.map} +1 -1
  15. package/dist/_chunks/{index-BCUO98DV.js → index-BpL7C1EG.js} +3 -3
  16. package/dist/_chunks/{index-BCUO98DV.js.map → index-BpL7C1EG.js.map} +1 -1
  17. package/dist/_chunks/{index-CqYVkW3E.mjs → index-DAcEdoqJ.mjs} +3 -3
  18. package/dist/_chunks/{index-CqYVkW3E.mjs.map → index-DAcEdoqJ.mjs.map} +1 -1
  19. package/dist/_chunks/{index-CA5Axcoc.mjs → index-ZcZKwmTD.mjs} +3 -3
  20. package/dist/_chunks/{index-CA5Axcoc.mjs.map → index-ZcZKwmTD.mjs.map} +1 -1
  21. package/dist/_chunks/{router-Jdt6SbIA.mjs → router-BPH_u176.mjs} +3 -3
  22. package/dist/_chunks/{router-Jdt6SbIA.mjs.map → router-BPH_u176.mjs.map} +1 -1
  23. package/dist/_chunks/{router-BOXlNnrU.js → router-DeEgX8Ao.js} +3 -3
  24. package/dist/_chunks/{router-BOXlNnrU.js.map → router-DeEgX8Ao.js.map} +1 -1
  25. package/dist/admin/index.js +1 -1
  26. package/dist/admin/index.mjs +1 -1
  27. package/dist/admin/src/services/settings.d.ts +7 -3
  28. package/dist/server/index.js +107 -48
  29. package/dist/server/index.js.map +1 -1
  30. package/dist/server/index.mjs +107 -48
  31. package/dist/server/index.mjs.map +1 -1
  32. package/dist/server/src/bootstrap.d.ts.map +1 -1
  33. package/dist/server/src/constants/workflows.d.ts +1 -0
  34. package/dist/server/src/constants/workflows.d.ts.map +1 -1
  35. package/dist/server/src/content-types/index.d.ts +6 -0
  36. package/dist/server/src/content-types/index.d.ts.map +1 -1
  37. package/dist/server/src/content-types/workflow/index.d.ts +6 -0
  38. package/dist/server/src/content-types/workflow/index.d.ts.map +1 -1
  39. package/dist/server/src/controllers/assignees.d.ts.map +1 -1
  40. package/dist/server/src/controllers/stages.d.ts.map +1 -1
  41. package/dist/server/src/index.d.ts +28 -6
  42. package/dist/server/src/index.d.ts.map +1 -1
  43. package/dist/server/src/services/assignees.d.ts +8 -4
  44. package/dist/server/src/services/assignees.d.ts.map +1 -1
  45. package/dist/server/src/services/document-service-middleware.d.ts +1 -0
  46. package/dist/server/src/services/document-service-middleware.d.ts.map +1 -1
  47. package/dist/server/src/services/index.d.ts +16 -6
  48. package/dist/server/src/services/index.d.ts.map +1 -1
  49. package/dist/server/src/services/metrics/index.d.ts +4 -4
  50. package/dist/server/src/services/metrics/index.d.ts.map +1 -1
  51. package/dist/server/src/services/stages.d.ts +6 -1
  52. package/dist/server/src/services/stages.d.ts.map +1 -1
  53. package/dist/server/src/services/workflows.d.ts.map +1 -1
  54. package/dist/server/src/validation/review-workflows.d.ts +4 -0
  55. package/dist/server/src/validation/review-workflows.d.ts.map +1 -1
  56. package/dist/shared/contracts/review-workflows.d.ts +8 -3
  57. package/dist/shared/contracts/review-workflows.d.ts.map +1 -1
  58. package/package.json +8 -8
  59. package/dist/_chunks/Layout-8i0EXRRs.js.map +0 -1
  60. package/dist/_chunks/Layout-C9m07iTY.mjs.map +0 -1
  61. package/dist/_chunks/en-D9ZrQAV6.mjs.map +0 -1
  62. package/dist/_chunks/en-xcewH2pC.js.map +0 -1
  63. package/dist/_chunks/id-CmtaTf1x.js.map +0 -1
  64. package/dist/_chunks/id-DV0Ndeav.mjs.map +0 -1
@@ -6,8 +6,8 @@ import { LinkButton, TFooter, Typography, Flex, IconButton, Dialog } from "@stra
6
6
  import { Plus, Pencil, Trash } from "@strapi/icons";
7
7
  import { useIntl } from "react-intl";
8
8
  import { useNavigate, NavLink, Link } from "react-router-dom";
9
- import { u as useGetContentTypesQuery, a as useTypedSelector, C as CHARGEBEE_WORKFLOW_ENTITLEMENT_NAME, L as LimitsModal } from "./index-CqYVkW3E.mjs";
10
- import { u as useReviewWorkflows, H as Header, R as Root } from "./Layout-C9m07iTY.mjs";
9
+ import { u as useGetContentTypesQuery, a as useTypedSelector, C as CHARGEBEE_WORKFLOW_ENTITLEMENT_NAME, L as LimitsModal } from "./index-DAcEdoqJ.mjs";
10
+ import { u as useReviewWorkflows, H as Header, R as Root } from "./Layout-Dko22Aly.mjs";
11
11
  const ReviewWorkflowsListView = () => {
12
12
  const { formatMessage } = useIntl();
13
13
  const navigate = useNavigate();
@@ -211,4 +211,4 @@ export {
211
211
  ProtectedListPage,
212
212
  ReviewWorkflowsListView
213
213
  };
214
- //# sourceMappingURL=index-CA5Axcoc.mjs.map
214
+ //# sourceMappingURL=index-ZcZKwmTD.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"index-CA5Axcoc.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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"}
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-CA5Axcoc.mjs").then((mod) => ({ default: mod.ProtectedListPage }))
5
+ () => import("./index-ZcZKwmTD.mjs").then((mod) => ({ default: mod.ProtectedListPage }))
6
6
  );
7
7
  const ProtectedEditPage = lazy(
8
- () => import("./id-DV0Ndeav.mjs").then((mod) => ({ default: mod.ProtectedEditPage }))
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-Jdt6SbIA.mjs.map
24
+ //# sourceMappingURL=router-BPH_u176.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"router-Jdt6SbIA.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;"}
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-B8WmHbCU.js")).then((mod) => ({ default: mod.ProtectedListPage }))
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("./id-CmtaTf1x.js")).then((mod) => ({ default: mod.ProtectedEditPage }))
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-BOXlNnrU.js.map
24
+ //# sourceMappingURL=router-DeEgX8Ao.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"router-BOXlNnrU.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;;"}
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;;"}
@@ -1,4 +1,4 @@
1
1
  "use strict";
2
- const index = require("../_chunks/index-BCUO98DV.js");
2
+ const index = require("../_chunks/index-BpL7C1EG.js");
3
3
  module.exports = index.admin;
4
4
  //# sourceMappingURL=index.js.map
@@ -1,4 +1,4 @@
1
- import { h } from "../_chunks/index-CqYVkW3E.mjs";
1
+ import { h } from "../_chunks/index-DAcEdoqJ.mjs";
2
2
  export {
3
3
  h as default
4
4
  };
@@ -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?: string | undefined;
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, };
@@ -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);
@@ -6640,6 +6641,12 @@ const workflow = {
6640
6641
  relation: "oneToMany",
6641
6642
  mappedBy: "workflow"
6642
6643
  },
6644
+ stageRequiredToPublish: {
6645
+ type: "relation",
6646
+ target: "plugin::review-workflows.workflow-stage",
6647
+ relation: "oneToOne",
6648
+ required: false
6649
+ },
6643
6650
  contentTypes: {
6644
6651
  type: "json",
6645
6652
  required: true,
@@ -6789,6 +6796,7 @@ const bootstrap = async (args) => {
6789
6796
  const docsMiddlewares = getService("document-service-middlewares");
6790
6797
  strapi.documents.use(docsMiddlewares.assignStageOnCreate);
6791
6798
  strapi.documents.use(docsMiddlewares.handleStageOnUpdate);
6799
+ strapi.documents.use(docsMiddlewares.checkStageBeforePublish);
6792
6800
  };
6793
6801
  const destroy = async ({ strapi: strapi2 }) => {
6794
6802
  };
@@ -7021,9 +7029,9 @@ const processFilters = ({ strapi: strapi2 }, filters = {}) => {
7021
7029
  };
7022
7030
  const processPopulate = (populate) => {
7023
7031
  if (!populate) {
7024
- return populate;
7032
+ return WORKFLOW_POPULATE;
7025
7033
  }
7026
- return WORKFLOW_POPULATE;
7034
+ return populate;
7027
7035
  };
7028
7036
  const workflows$1 = ({ strapi: strapi2 }) => {
7029
7037
  const workflowsContentTypes = workflowsContentTypesFactory({ strapi: strapi2 });
@@ -7074,14 +7082,27 @@ const workflows$1 = ({ strapi: strapi2 }) => {
7074
7082
  const stages2 = await getService("stages", { strapi: strapi2 }).createMany(opts.data.stages);
7075
7083
  const mapIds = fp.map(fp.get("id"));
7076
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
+ }
7077
7094
  if (opts.data.contentTypes) {
7078
7095
  await workflowsContentTypes.migrate({
7079
7096
  destContentTypes: opts.data.contentTypes,
7080
7097
  stageId: stages2[0].id
7081
7098
  });
7082
7099
  }
7083
- metrics.sendDidCreateWorkflow();
7084
- return strapi2.db.query(WORKFLOW_MODEL_UID).create(strapi2.get("query-params").transform(WORKFLOW_MODEL_UID, createOpts));
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;
7085
7106
  });
7086
7107
  },
7087
7108
  /**
@@ -7094,6 +7115,7 @@ const workflows$1 = ({ strapi: strapi2 }) => {
7094
7115
  async update(workflow2, opts) {
7095
7116
  const stageService = getService("stages", { strapi: strapi2 });
7096
7117
  let updateOpts = { ...opts, populate: { ...WORKFLOW_POPULATE } };
7118
+ let updatedStages = [];
7097
7119
  let updatedStageIds;
7098
7120
  await workflowValidator.validateWorkflowCount();
7099
7121
  return strapi2.db.transaction(async () => {
@@ -7102,9 +7124,28 @@ const workflows$1 = ({ strapi: strapi2 }) => {
7102
7124
  opts.data.stages.forEach(
7103
7125
  (stage) => this.assertStageBelongsToWorkflow(stage.id, workflow2)
7104
7126
  );
7105
- updatedStageIds = await stageService.replaceStages(workflow2.stages, opts.data.stages, workflow2.contentTypes).then((stages2) => stages2.map((stage) => stage.id));
7127
+ updatedStages = await stageService.replaceStages(
7128
+ workflow2.stages,
7129
+ opts.data.stages,
7130
+ workflow2.contentTypes
7131
+ );
7132
+ updatedStageIds = updatedStages.map((stage) => stage.id);
7106
7133
  updateOpts = fp.set("data.stages", updatedStageIds, updateOpts);
7107
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
+ }
7108
7149
  if (opts.data.contentTypes) {
7109
7150
  await workflowsContentTypes.migrate({
7110
7151
  srcContentTypes: workflow2.contentTypes,
@@ -7112,12 +7153,17 @@ const workflows$1 = ({ strapi: strapi2 }) => {
7112
7153
  stageId: updatedStageIds ? updatedStageIds[0] : workflow2.stages[0].id
7113
7154
  });
7114
7155
  }
7115
- metrics.sendDidEditWorkflow();
7156
+ metrics.sendDidEditWorkflow(workflow2.id, !!opts.data.stageRequiredToPublishName);
7116
7157
  const query = strapi2.get("query-params").transform(WORKFLOW_MODEL_UID, updateOpts);
7117
- return strapi2.db.query(WORKFLOW_MODEL_UID).update({
7158
+ const updatedWorkflow = await strapi2.db.query(WORKFLOW_MODEL_UID).update({
7118
7159
  ...query,
7119
7160
  where: { id: workflow2.id }
7120
7161
  });
7162
+ await strapi2.plugin("content-releases").service("release-action").validateActionsByContentTypes([
7163
+ ...workflow2.contentTypes,
7164
+ ...opts.data.contentTypes || []
7165
+ ]);
7166
+ return updatedWorkflow;
7121
7167
  });
7122
7168
  },
7123
7169
  /**
@@ -7140,10 +7186,12 @@ const workflows$1 = ({ strapi: strapi2 }) => {
7140
7186
  destContentTypes: []
7141
7187
  });
7142
7188
  const query = strapi2.get("query-params").transform(WORKFLOW_MODEL_UID, opts);
7143
- return strapi2.db.query(WORKFLOW_MODEL_UID).delete({
7189
+ const deletedWorkflow = await strapi2.db.query(WORKFLOW_MODEL_UID).delete({
7144
7190
  ...query,
7145
7191
  where: { id: workflow2.id }
7146
7192
  });
7193
+ await strapi2.plugin("content-releases").service("release-action").validateActionsByContentTypes(workflow2.contentTypes);
7194
+ return deletedWorkflow;
7147
7195
  });
7148
7196
  },
7149
7197
  /**
@@ -7355,8 +7403,9 @@ const stages$1 = ({ strapi: strapi2 }) => {
7355
7403
  /**
7356
7404
  * Update the stage of an entity
7357
7405
  */
7358
- async updateEntity(documentId, locale, model, stageId) {
7406
+ async updateEntity(entityToUpdate, model, stageId) {
7359
7407
  const stage = await this.findById(stageId);
7408
+ const { documentId, locale } = entityToUpdate;
7360
7409
  await workflowValidator.validateWorkflowCount();
7361
7410
  if (!stage) {
7362
7411
  throw new ApplicationError$2(`Selected stage does not exist`);
@@ -7369,6 +7418,10 @@ const stages$1 = ({ strapi: strapi2 }) => {
7369
7418
  data: { [ENTITY_STAGE_ATTRIBUTE]: fp.pick(["id"], stage) },
7370
7419
  populate: [ENTITY_STAGE_ATTRIBUTE]
7371
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
+ });
7372
7425
  metrics.sendDidChangeEntryStage();
7373
7426
  return entity;
7374
7427
  },
@@ -7515,32 +7568,28 @@ const assignees$1 = ({ strapi: strapi2 }) => {
7515
7568
  /**
7516
7569
  * Update the assignee of an entity
7517
7570
  */
7518
- async updateEntityAssignee(documentId, locale, model, assigneeId) {
7519
- if (fp.isNil(assigneeId)) {
7520
- return this.deleteEntityAssignee(documentId, locale, model);
7521
- }
7522
- const userExists = await getAdminService("user", { strapi: strapi2 }).exists({ id: assigneeId });
7523
- if (!userExists) {
7524
- throw new ApplicationError(`Selected user does not exist`);
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
+ }
7525
7578
  }
7526
- metrics.sendDidEditAssignee(await this.findEntityAssigneeId(documentId, model), assigneeId);
7527
- return strapi2.documents(model).update({
7579
+ const oldAssigneeId = await this.findEntityAssigneeId(entityToUpdate.id, model);
7580
+ metrics.sendDidEditAssignee(oldAssigneeId, assigneeId || null);
7581
+ const entity = await strapi2.documents(model).update({
7528
7582
  documentId,
7529
7583
  locale,
7530
- data: { [ENTITY_ASSIGNEE_ATTRIBUTE]: assigneeId },
7584
+ data: { [ENTITY_ASSIGNEE_ATTRIBUTE]: assigneeId || null },
7531
7585
  populate: [ENTITY_ASSIGNEE_ATTRIBUTE],
7532
7586
  fields: []
7533
7587
  });
7534
- },
7535
- async deleteEntityAssignee(documentId, locale, model) {
7536
- metrics.sendDidEditAssignee(await this.findEntityAssigneeId(documentId, model), null);
7537
- return strapi2.documents(model).update({
7538
- documentId,
7539
- locale,
7540
- data: { [ENTITY_ASSIGNEE_ATTRIBUTE]: null },
7541
- populate: [ENTITY_ASSIGNEE_ATTRIBUTE],
7542
- 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)
7543
7591
  });
7592
+ return entity;
7544
7593
  }
7545
7594
  };
7546
7595
  };
@@ -7613,11 +7662,11 @@ const sendDidDeleteStage = async () => {
7613
7662
  const sendDidChangeEntryStage = async () => {
7614
7663
  strapi.telemetry.send("didChangeEntryStage", {});
7615
7664
  };
7616
- const sendDidCreateWorkflow = async () => {
7617
- strapi.telemetry.send("didCreateWorkflow", {});
7665
+ const sendDidCreateWorkflow = async (workflowId, hasRequiredStageToPublish) => {
7666
+ strapi.telemetry.send("didCreateWorkflow", { workflowId, hasRequiredStageToPublish });
7618
7667
  };
7619
- const sendDidEditWorkflow = async () => {
7620
- strapi.telemetry.send("didEditWorkflow", {});
7668
+ const sendDidEditWorkflow = async (workflowId, hasRequiredStageToPublish) => {
7669
+ strapi.telemetry.send("didEditWorkflow", { workflowId, hasRequiredStageToPublish });
7621
7670
  };
7622
7671
  const sendDidEditAssignee = async (fromId, toId) => {
7623
7672
  strapi.telemetry.send("didEditAssignee", { from: fromId, to: toId });
@@ -7870,9 +7919,27 @@ const handleStageOnUpdate = async (ctx, next) => {
7870
7919
  }
7871
7920
  return next();
7872
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
+ };
7873
7939
  const documentServiceMiddleware = () => ({
7874
7940
  assignStageOnCreate,
7875
- handleStageOnUpdate
7941
+ handleStageOnUpdate,
7942
+ checkStageBeforePublish
7876
7943
  });
7877
7944
  const services = {
7878
7945
  workflows: workflows$1,
@@ -7922,12 +7989,14 @@ const validateContentTypes = utils.yup.array().of(
7922
7989
  const validateWorkflowCreateSchema = utils.yup.object().shape({
7923
7990
  name: utils.yup.string().max(255).min(1, "Workflow name can not be empty").required(),
7924
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"),
7925
- contentTypes: validateContentTypes
7992
+ contentTypes: validateContentTypes,
7993
+ stageRequiredToPublishName: utils.yup.string().min(1).nullable()
7926
7994
  });
7927
7995
  const validateWorkflowUpdateSchema = utils.yup.object().shape({
7928
7996
  name: utils.yup.string().max(255).min(1, "Workflow name can not be empty"),
7929
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"),
7930
- contentTypes: validateContentTypes
7998
+ contentTypes: validateContentTypes,
7999
+ stageRequiredToPublishName: utils.yup.string().min(1).nullable()
7931
8000
  });
7932
8001
  const validateUpdateAssigneeOnEntitySchema = utils.yup.object().shape({
7933
8002
  id: utils.yup.number().integer().min(1).nullable()
@@ -8130,12 +8199,7 @@ const stages = {
8130
8199
  );
8131
8200
  const workflow2 = await workflowService.assertContentTypeBelongsToWorkflow(modelUID);
8132
8201
  workflowService.assertStageBelongsToWorkflow(stageId, workflow2);
8133
- const updatedEntity = await stagesService.updateEntity(
8134
- entity.documentId,
8135
- entity.locale,
8136
- modelUID,
8137
- stageId
8138
- );
8202
+ const updatedEntity = await stagesService.updateEntity(entity, modelUID, stageId);
8139
8203
  ctx.body = { data: await sanitizeOutput(updatedEntity) };
8140
8204
  },
8141
8205
  /**
@@ -8232,12 +8296,7 @@ const assignees = {
8232
8296
  "You should pass a valid id to the body of the put request."
8233
8297
  );
8234
8298
  await workflowService.assertContentTypeBelongsToWorkflow(model);
8235
- const updatedEntity = await assigneeService.updateEntityAssignee(
8236
- documentId,
8237
- locale || null,
8238
- model,
8239
- assigneeId
8240
- );
8299
+ const updatedEntity = await assigneeService.updateEntityAssignee(entity, model, assigneeId);
8241
8300
  ctx.body = { data: await sanitizeOutput(updatedEntity) };
8242
8301
  }
8243
8302
  };