@strapi/admin 4.6.1 → 4.9.0-alpha.0
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/admin/src/assets/images/onboarding-preview.png +0 -0
- package/admin/src/content-manager/components/CollectionTypeFormWrapper/index.js +4 -14
- package/admin/src/content-manager/components/DynamicTable/CellContent/RelationMultiple/index.js +1 -1
- package/admin/src/content-manager/components/DynamicZone/components/DynamicComponent.js +2 -0
- package/admin/src/content-manager/components/EditViewDataManagerProvider/reducer.js +39 -9
- package/admin/src/content-manager/components/EditViewDataManagerProvider/utils/cleanData.js +9 -15
- package/admin/src/content-manager/components/SingleTypeFormWrapper/index.js +4 -12
- package/admin/src/content-manager/pages/EditView/DeleteLink/index.js +6 -8
- package/admin/src/content-manager/pages/ListView/index.js +6 -11
- package/admin/src/index.js +1 -0
- package/admin/src/pages/Admin/Onboarding/constants.js +46 -0
- package/admin/src/pages/Admin/Onboarding/index.js +161 -89
- package/admin/src/pages/Admin/index.js +5 -2
- package/admin/src/pages/SettingsPage/components/SettingsNav/index.js +15 -2
- package/admin/src/pages/SettingsPage/pages/Users/components/MagicLink/MagicLinkWrapper.js +3 -20
- package/admin/src/permissions/defaultPermissions.js +2 -15
- package/admin/src/translations/ar.json +4 -4
- package/admin/src/translations/ca.json +4 -4
- package/admin/src/translations/cs.json +4 -4
- package/admin/src/translations/de.json +4 -4
- package/admin/src/translations/dk.json +4 -4
- package/admin/src/translations/en.json +14 -5
- package/admin/src/translations/es.json +4 -4
- package/admin/src/translations/eu.json +4 -4
- package/admin/src/translations/fr.json +4 -4
- package/admin/src/translations/gu.json +4 -4
- package/admin/src/translations/he.json +4 -4
- package/admin/src/translations/hi.json +4 -4
- package/admin/src/translations/hu.json +4 -4
- package/admin/src/translations/id.json +4 -4
- package/admin/src/translations/it.json +4 -4
- package/admin/src/translations/ja.json +4 -4
- package/admin/src/translations/ko.json +4 -4
- package/admin/src/translations/ml.json +4 -4
- package/admin/src/translations/ms.json +4 -4
- package/admin/src/translations/nl.json +4 -4
- package/admin/src/translations/no.json +4 -4
- package/admin/src/translations/pl.json +4 -4
- package/admin/src/translations/pt-BR.json +4 -4
- package/admin/src/translations/pt.json +4 -4
- package/admin/src/translations/ru.json +785 -789
- package/admin/src/translations/sa.json +4 -4
- package/admin/src/translations/sk.json +4 -4
- package/admin/src/translations/sv.json +4 -4
- package/admin/src/translations/th.json +4 -4
- package/admin/src/translations/tr.json +4 -4
- package/admin/src/translations/uk.json +4 -4
- package/admin/src/translations/vi.json +4 -4
- package/admin/src/translations/zh-Hans.json +4 -4
- package/admin/src/translations/zh.json +4 -4
- package/build/1683.d59d0f23.chunk.js +268 -0
- package/build/19eb2dfcf2603eb55733.png +0 -0
- package/build/{4855.bd092921.chunk.js → 2223.1bfea951.chunk.js} +88 -88
- package/build/2743.646a1015.chunk.js +45 -0
- package/build/3075.3ee481f1.chunk.js +108 -0
- package/build/3632.2e378cf8.chunk.js +138 -0
- package/build/{4318.f96a9d4d.chunk.js → 4318.cd55ce02.chunk.js} +1 -1
- package/build/9707.b36ed71e.chunk.js +96 -0
- package/build/Admin-authenticatedApp.a73577e1.chunk.js +79 -0
- package/build/{Admin_InternalErrorPage.157152a8.chunk.js → Admin_InternalErrorPage.178ddb90.chunk.js} +1 -1
- package/build/{Admin_homePage.b1730882.chunk.js → Admin_homePage.c2f5f27d.chunk.js} +2 -2
- package/build/{Admin_marketplace.ea0316c2.chunk.js → Admin_marketplace.1df49c42.chunk.js} +1 -1
- package/build/{Admin_pluginsPage.5c24f963.chunk.js → Admin_pluginsPage.8d824408.chunk.js} +2 -2
- package/build/{Admin_profilePage.59af1978.chunk.js → Admin_profilePage.cb667bc5.chunk.js} +2 -2
- package/build/Admin_settingsPage.f90615fb.chunk.js +178 -0
- package/build/{Upload_ConfigureTheView.3f2b6e6a.chunk.js → Upload_ConfigureTheView.d306009d.chunk.js} +1 -1
- package/build/admin-app.06f07029.chunk.js +112 -0
- package/build/admin-edit-roles-page.35199b9d.chunk.js +1 -0
- package/build/admin-edit-users.9e48b00d.chunk.js +10 -0
- package/build/admin-users.cf7b4151.chunk.js +11 -0
- package/build/{api-tokens-create-page.d248362d.chunk.js → api-tokens-create-page.a31c7fba.chunk.js} +1 -1
- package/build/{api-tokens-edit-page.8516fa20.chunk.js → api-tokens-edit-page.64fef287.chunk.js} +1 -1
- package/build/{api-tokens-list-page.44a79fda.chunk.js → api-tokens-list-page.e600ad3e.chunk.js} +2 -2
- package/build/ar-json.39e54aba.chunk.js +1 -0
- package/build/{audit-logs-settings-page.c3dce30d.chunk.js → audit-logs-settings-page.d4da4579.chunk.js} +1 -1
- package/build/{ca-json.f6a0f472.chunk.js → ca-json.4d999055.chunk.js} +1 -1
- package/build/content-manager.255c3a59.chunk.js +1139 -0
- package/build/{content-type-builder-list-view.79e84b36.chunk.js → content-type-builder-list-view.8d7a3d68.chunk.js} +5 -5
- package/build/content-type-builder.3c8558a5.chunk.js +126 -0
- package/build/cs-json.4b44411c.chunk.js +1 -0
- package/build/{de-json.30e1f35b.chunk.js → de-json.866f8a28.chunk.js} +1 -1
- package/build/{dk-json.e6d9ffa4.chunk.js → dk-json.10f7b1d1.chunk.js} +1 -1
- package/build/email-settings-page.b19f2eb2.chunk.js +10 -0
- package/build/en-json.1997583c.chunk.js +1 -0
- package/build/es-json.ea15c957.chunk.js +1 -0
- package/build/{eu-json.fceecd8b.chunk.js → eu-json.3bc24d60.chunk.js} +1 -1
- package/build/{fr-json.78545ef8.chunk.js → fr-json.e88fbdfd.chunk.js} +1 -1
- package/build/{gu-json.676518f2.chunk.js → gu-json.94f0d242.chunk.js} +1 -1
- package/build/{he-json.ad22e8cc.chunk.js → he-json.f0de8cdb.chunk.js} +1 -1
- package/build/{hi-json.19b51c09.chunk.js → hi-json.df3a7be2.chunk.js} +1 -1
- package/build/{hu-json.f947088f.chunk.js → hu-json.680e6eef.chunk.js} +1 -1
- package/build/{i18n-settings-page.b8d8753e.chunk.js → i18n-settings-page.a6b49eac.chunk.js} +1 -1
- package/build/{id-json.504daa84.chunk.js → id-json.e0d83d41.chunk.js} +1 -1
- package/build/index.html +1 -1
- package/build/{it-json.2fd90f4d.chunk.js → it-json.8be59205.chunk.js} +1 -1
- package/build/{ja-json.c9f12d0b.chunk.js → ja-json.97ee41ba.chunk.js} +1 -1
- package/build/{ko-json.ef463065.chunk.js → ko-json.4cbbf4f2.chunk.js} +1 -1
- package/build/main.7f308c20.js +4322 -0
- package/build/{ml-json.490f666c.chunk.js → ml-json.e3747091.chunk.js} +1 -1
- package/build/ms-json.0eddffd9.chunk.js +1 -0
- package/build/{nl-json.c416295a.chunk.js → nl-json.371a15ee.chunk.js} +1 -1
- package/build/{no-json.1a2258ba.chunk.js → no-json.9b3cd181.chunk.js} +1 -1
- package/build/{pl-json.8cf0c871.chunk.js → pl-json.e535cbce.chunk.js} +1 -1
- package/build/{pt-BR-json.51fab8d0.chunk.js → pt-BR-json.e5fafa46.chunk.js} +1 -1
- package/build/pt-json.ee554a41.chunk.js +1 -0
- package/build/review-workflows-settings.7b4be1b0.chunk.js +63 -0
- package/build/{ru-json.aa5cd123.chunk.js → ru-json.866f0ff1.chunk.js} +1 -1
- package/build/runtime~main.bf374148.js +2 -0
- package/build/{sa-json.f3fa5407.chunk.js → sa-json.7efeb257.chunk.js} +1 -1
- package/build/{sk-json.9ec60d9f.chunk.js → sk-json.7bbeb0af.chunk.js} +1 -1
- package/build/{sso-settings-page.b85ad080.chunk.js → sso-settings-page.ad2143dd.chunk.js} +1 -1
- package/build/{sv-json.c6b0c237.chunk.js → sv-json.dc40951f.chunk.js} +1 -1
- package/build/{th-json.6e68155c.chunk.js → th-json.f664b96d.chunk.js} +1 -1
- package/build/{tr-json.9f41dc08.chunk.js → tr-json.b79eae31.chunk.js} +1 -1
- package/build/uk-json.b7e38370.chunk.js +1 -0
- package/build/upload-settings.eb1a7908.chunk.js +84 -0
- package/build/upload.700e2c84.chunk.js +33 -0
- package/build/{users-advanced-settings-page.fce9908e.chunk.js → users-advanced-settings-page.aae212f2.chunk.js} +1 -1
- package/build/{users-email-settings-page.343d0ad2.chunk.js → users-email-settings-page.8a9b0da1.chunk.js} +1 -1
- package/build/{users-providers-settings-page.e5a9a3f1.chunk.js → users-providers-settings-page.e6be909d.chunk.js} +10 -10
- package/build/{users-roles-settings-page.66312f31.chunk.js → users-roles-settings-page.97d06a80.chunk.js} +3 -3
- package/build/vi-json.ee4c5537.chunk.js +1 -0
- package/build/webhook-edit-page.9eb0f789.chunk.js +75 -0
- package/build/webhook-list-page.66082323.chunk.js +42 -0
- package/build/{zh-Hans-json.9c0eac99.chunk.js → zh-Hans-json.30a18940.chunk.js} +1 -1
- package/build/{zh-json.f88f563d.chunk.js → zh-json.49d84433.chunk.js} +1 -1
- package/ee/admin/hooks/useSettingsMenu/utils/customAdminLinks.js +12 -12
- package/ee/admin/hooks/useSettingsMenu/utils/customGlobalLinks.js +21 -13
- package/ee/admin/pages/SettingsPage/pages/ReviewWorkflows/ReviewWorkflows.js +137 -0
- package/ee/admin/pages/SettingsPage/pages/ReviewWorkflows/actions/index.js +42 -0
- package/ee/admin/pages/SettingsPage/pages/ReviewWorkflows/components/AddStage/AddStage.js +87 -0
- package/ee/admin/pages/SettingsPage/pages/ReviewWorkflows/components/AddStage/index.js +1 -0
- package/ee/admin/pages/SettingsPage/pages/ReviewWorkflows/components/Stages/Stage/Stage.js +90 -0
- package/ee/admin/pages/SettingsPage/pages/ReviewWorkflows/components/Stages/Stage/index.js +1 -0
- package/ee/admin/pages/SettingsPage/pages/ReviewWorkflows/components/Stages/Stages.js +77 -0
- package/ee/admin/pages/SettingsPage/pages/ReviewWorkflows/components/Stages/index.js +1 -0
- package/ee/admin/pages/SettingsPage/pages/ReviewWorkflows/constants.js +6 -0
- package/ee/admin/pages/SettingsPage/pages/ReviewWorkflows/hooks/useReviewWorkflows.js +63 -0
- package/ee/admin/pages/SettingsPage/pages/ReviewWorkflows/index.js +3 -0
- package/ee/admin/pages/SettingsPage/pages/ReviewWorkflows/reducer/index.js +102 -0
- package/ee/admin/pages/SettingsPage/pages/ReviewWorkflows/utils/getWorkflowValidationSchema.js +25 -0
- package/ee/admin/pages/SettingsPage/utils/customRoutes.js +16 -2
- package/ee/admin/permissions/customPermissions.js +7 -0
- package/ee/server/bootstrap.js +7 -1
- package/ee/server/config/admin-actions.js +10 -0
- package/ee/server/constants/default-stages.json +14 -0
- package/ee/server/constants/default-workflow.json +1 -0
- package/ee/server/constants/workflows.js +7 -0
- package/ee/server/content-types/index.js +9 -0
- package/ee/server/content-types/workflow/index.js +34 -0
- package/ee/server/content-types/workflow-stage/index.js +36 -0
- package/ee/server/controllers/index.js +2 -0
- package/ee/server/controllers/workflows/index.js +36 -0
- package/ee/server/controllers/workflows/stages/index.js +57 -0
- package/ee/server/index.js +1 -0
- package/ee/server/routes/index.js +87 -0
- package/ee/server/services/index.js +3 -0
- package/ee/server/services/review-workflows/review-workflows.js +54 -0
- package/ee/server/services/review-workflows/stages.js +133 -0
- package/ee/server/services/review-workflows/workflows.js +25 -0
- package/ee/server/utils/index.js +8 -0
- package/ee/server/utils/test.js +11 -0
- package/ee/server/validation/review-workflows.js +17 -0
- package/package.json +15 -15
- package/server/config/admin-actions.js +0 -16
- package/server/controllers/admin.js +0 -55
- package/server/routes/admin.js +0 -28
- package/webpack.config.js +0 -3
- package/build/1683.c8aa7b7c.chunk.js +0 -268
- package/build/2743.6d1632f9.chunk.js +0 -45
- package/build/3075.dc3894fe.chunk.js +0 -108
- package/build/3632.0317b618.chunk.js +0 -138
- package/build/9707.7290fd92.chunk.js +0 -96
- package/build/Admin-authenticatedApp.ce646f66.chunk.js +0 -75
- package/build/Admin_settingsPage.d1493824.chunk.js +0 -178
- package/build/admin-app.25934eaa.chunk.js +0 -112
- package/build/admin-edit-roles-page.446b69dc.chunk.js +0 -1
- package/build/admin-edit-users.2ed69bfd.chunk.js +0 -10
- package/build/admin-users.fc003b10.chunk.js +0 -11
- package/build/ar-json.932794f7.chunk.js +0 -1
- package/build/content-manager.35ff9726.chunk.js +0 -1139
- package/build/content-type-builder.855db321.chunk.js +0 -126
- package/build/cs-json.79879fb6.chunk.js +0 -1
- package/build/email-settings-page.d1fcc7a3.chunk.js +0 -10
- package/build/en-json.1f137a90.chunk.js +0 -1
- package/build/es-json.e275481d.chunk.js +0 -1
- package/build/main.7b151630.js +0 -4377
- package/build/ms-json.db87d8d3.chunk.js +0 -1
- package/build/pt-json.62927d1e.chunk.js +0 -1
- package/build/runtime~main.a20d633b.js +0 -2
- package/build/uk-json.b2fcd567.chunk.js +0 -1
- package/build/upload-settings.ef64bbf9.chunk.js +0 -84
- package/build/upload.c5730dfa.chunk.js +0 -33
- package/build/vi-json.f08d7d03.chunk.js +0 -1
- package/build/webhook-edit-page.73e51e64.chunk.js +0 -75
- package/build/webhook-list-page.1134f130.chunk.js +0 -42
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import {
|
|
2
|
+
ACTION_SET_WORKFLOWS,
|
|
3
|
+
ACTION_DELETE_STAGE,
|
|
4
|
+
ACTION_ADD_STAGE,
|
|
5
|
+
ACTION_UPDATE_STAGE,
|
|
6
|
+
} from '../constants';
|
|
7
|
+
|
|
8
|
+
export function setWorkflows({ status, data }) {
|
|
9
|
+
return {
|
|
10
|
+
type: ACTION_SET_WORKFLOWS,
|
|
11
|
+
payload: {
|
|
12
|
+
status,
|
|
13
|
+
workflows: data,
|
|
14
|
+
},
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export function deleteStage(stageId) {
|
|
19
|
+
return {
|
|
20
|
+
type: ACTION_DELETE_STAGE,
|
|
21
|
+
payload: {
|
|
22
|
+
stageId,
|
|
23
|
+
},
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export function addStage(stage = {}) {
|
|
28
|
+
return {
|
|
29
|
+
type: ACTION_ADD_STAGE,
|
|
30
|
+
payload: stage,
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export function updateStage(stageId, payload) {
|
|
35
|
+
return {
|
|
36
|
+
type: ACTION_UPDATE_STAGE,
|
|
37
|
+
payload: {
|
|
38
|
+
stageId,
|
|
39
|
+
...payload,
|
|
40
|
+
},
|
|
41
|
+
};
|
|
42
|
+
}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import PropTypes from 'prop-types';
|
|
3
|
+
import styled from 'styled-components';
|
|
4
|
+
|
|
5
|
+
import { Box, Flex, Typography } from '@strapi/design-system';
|
|
6
|
+
import { PlusCircle } from '@strapi/icons';
|
|
7
|
+
|
|
8
|
+
const StyledAddIcon = styled(PlusCircle)`
|
|
9
|
+
> circle {
|
|
10
|
+
fill: ${({ theme }) => theme.colors.neutral150};
|
|
11
|
+
}
|
|
12
|
+
> path {
|
|
13
|
+
fill: ${({ theme }) => theme.colors.neutral600};
|
|
14
|
+
}
|
|
15
|
+
`;
|
|
16
|
+
|
|
17
|
+
const StyledButton = styled(Box)`
|
|
18
|
+
border-radius: 26px;
|
|
19
|
+
|
|
20
|
+
svg {
|
|
21
|
+
height: ${({ theme }) => theme.spaces[6]};
|
|
22
|
+
width: ${({ theme }) => theme.spaces[6]};
|
|
23
|
+
|
|
24
|
+
> path {
|
|
25
|
+
fill: ${({ theme }) => theme.colors.neutral600};
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
&:hover {
|
|
30
|
+
color: ${({ theme }) => theme.colors.primary600} !important;
|
|
31
|
+
${Typography} {
|
|
32
|
+
color: ${({ theme }) => theme.colors.primary600} !important;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
${StyledAddIcon} {
|
|
36
|
+
> circle {
|
|
37
|
+
fill: ${({ theme }) => theme.colors.primary600};
|
|
38
|
+
}
|
|
39
|
+
> path {
|
|
40
|
+
fill: ${({ theme }) => theme.colors.neutral100};
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
&:active {
|
|
46
|
+
${Typography} {
|
|
47
|
+
color: ${({ theme }) => theme.colors.primary600};
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
${StyledAddIcon} {
|
|
51
|
+
> circle {
|
|
52
|
+
fill: ${({ theme }) => theme.colors.primary600};
|
|
53
|
+
}
|
|
54
|
+
> path {
|
|
55
|
+
fill: ${({ theme }) => theme.colors.neutral100};
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
`;
|
|
60
|
+
|
|
61
|
+
export function AddStage({ children, ...props }) {
|
|
62
|
+
return (
|
|
63
|
+
<StyledButton
|
|
64
|
+
as="button"
|
|
65
|
+
background="neutral0"
|
|
66
|
+
border="neutral150"
|
|
67
|
+
paddingBottom={3}
|
|
68
|
+
paddingLeft={4}
|
|
69
|
+
paddingRight={4}
|
|
70
|
+
paddingTop={3}
|
|
71
|
+
shadow="filterShadow"
|
|
72
|
+
{...props}
|
|
73
|
+
>
|
|
74
|
+
<Flex gap={2}>
|
|
75
|
+
<StyledAddIcon aria-hidden />
|
|
76
|
+
|
|
77
|
+
<Typography variant="pi" fontWeight="bold" textColor="neutral500">
|
|
78
|
+
{children}
|
|
79
|
+
</Typography>
|
|
80
|
+
</Flex>
|
|
81
|
+
</StyledButton>
|
|
82
|
+
);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
AddStage.propTypes = {
|
|
86
|
+
children: PropTypes.node.isRequired,
|
|
87
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './AddStage';
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import React, { useState } from 'react';
|
|
2
|
+
import PropTypes from 'prop-types';
|
|
3
|
+
import styled from 'styled-components';
|
|
4
|
+
import { useField } from 'formik';
|
|
5
|
+
import { useIntl } from 'react-intl';
|
|
6
|
+
import { useDispatch } from 'react-redux';
|
|
7
|
+
import {
|
|
8
|
+
Accordion,
|
|
9
|
+
AccordionToggle,
|
|
10
|
+
AccordionContent,
|
|
11
|
+
Box,
|
|
12
|
+
Grid,
|
|
13
|
+
GridItem,
|
|
14
|
+
IconButton,
|
|
15
|
+
TextInput,
|
|
16
|
+
} from '@strapi/design-system';
|
|
17
|
+
|
|
18
|
+
import { Trash } from '@strapi/icons';
|
|
19
|
+
|
|
20
|
+
import { deleteStage, updateStage } from '../../../actions';
|
|
21
|
+
|
|
22
|
+
// TODO: Delete once https://github.com/strapi/design-system/pull/858
|
|
23
|
+
// is merged and released.
|
|
24
|
+
const StyledAccordion = styled(Box)`
|
|
25
|
+
> div:first-child {
|
|
26
|
+
box-shadow: ${({ theme }) => theme.shadows.tableShadow};
|
|
27
|
+
}
|
|
28
|
+
`;
|
|
29
|
+
|
|
30
|
+
// TODO: Keep an eye on https://github.com/strapi/design-system/pull/878
|
|
31
|
+
const DeleteButton = styled(IconButton)`
|
|
32
|
+
background-color: transparent;
|
|
33
|
+
`;
|
|
34
|
+
|
|
35
|
+
function Stage({ id, name, index, canDelete, isOpen: isOpenDefault = false }) {
|
|
36
|
+
const { formatMessage } = useIntl();
|
|
37
|
+
const [isOpen, setIsOpen] = useState(isOpenDefault);
|
|
38
|
+
const fieldIdentifier = `stages.${index}.name`;
|
|
39
|
+
const [field, meta] = useField(fieldIdentifier);
|
|
40
|
+
const dispatch = useDispatch();
|
|
41
|
+
|
|
42
|
+
return (
|
|
43
|
+
<StyledAccordion>
|
|
44
|
+
<Accordion size="S" variant="primary" onToggle={() => setIsOpen(!isOpen)} expanded={isOpen}>
|
|
45
|
+
<AccordionToggle
|
|
46
|
+
title={name}
|
|
47
|
+
togglePosition="left"
|
|
48
|
+
action={
|
|
49
|
+
canDelete ? (
|
|
50
|
+
<DeleteButton
|
|
51
|
+
noBorder
|
|
52
|
+
onClick={() => dispatch(deleteStage(id))}
|
|
53
|
+
label={formatMessage({
|
|
54
|
+
id: 'Settings.review-workflows.stage.delete',
|
|
55
|
+
defaultMessage: 'Delete stage',
|
|
56
|
+
})}
|
|
57
|
+
icon={<Trash />}
|
|
58
|
+
/>
|
|
59
|
+
) : null
|
|
60
|
+
}
|
|
61
|
+
/>
|
|
62
|
+
<AccordionContent padding={6} background="neutral0">
|
|
63
|
+
<Grid gap={4}>
|
|
64
|
+
<GridItem col={6}>
|
|
65
|
+
<TextInput
|
|
66
|
+
{...field}
|
|
67
|
+
id={fieldIdentifier}
|
|
68
|
+
value={name}
|
|
69
|
+
label={formatMessage({
|
|
70
|
+
id: 'Settings.review-workflows.stage.name.label',
|
|
71
|
+
defaultMessage: 'Stage name',
|
|
72
|
+
})}
|
|
73
|
+
error={meta.error ?? false}
|
|
74
|
+
onBlur={(event) => dispatch(updateStage(id, { name: event.target.value }))}
|
|
75
|
+
/>
|
|
76
|
+
</GridItem>
|
|
77
|
+
</Grid>
|
|
78
|
+
</AccordionContent>
|
|
79
|
+
</Accordion>
|
|
80
|
+
</StyledAccordion>
|
|
81
|
+
);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
export { Stage };
|
|
85
|
+
|
|
86
|
+
Stage.propTypes = PropTypes.shape({
|
|
87
|
+
id: PropTypes.number.isRequired,
|
|
88
|
+
name: PropTypes.string.isRequired,
|
|
89
|
+
canDelete: PropTypes.bool.isRequired,
|
|
90
|
+
}).isRequired;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './Stage';
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import PropTypes from 'prop-types';
|
|
3
|
+
import styled from 'styled-components';
|
|
4
|
+
import { useIntl } from 'react-intl';
|
|
5
|
+
import { useDispatch } from 'react-redux';
|
|
6
|
+
import { Box, Flex, Stack } from '@strapi/design-system';
|
|
7
|
+
|
|
8
|
+
import { addStage } from '../../actions';
|
|
9
|
+
import { AddStage } from '../AddStage';
|
|
10
|
+
import { Stage } from './Stage';
|
|
11
|
+
|
|
12
|
+
const StagesContainer = styled(Box)`
|
|
13
|
+
position: relative;
|
|
14
|
+
`;
|
|
15
|
+
|
|
16
|
+
const Background = styled(Box)`
|
|
17
|
+
left: 50%;
|
|
18
|
+
position: absolute;
|
|
19
|
+
top: 0;
|
|
20
|
+
transform: translateX(-50%);
|
|
21
|
+
`;
|
|
22
|
+
|
|
23
|
+
function Stages({ stages }) {
|
|
24
|
+
const { formatMessage } = useIntl();
|
|
25
|
+
const dispatch = useDispatch();
|
|
26
|
+
|
|
27
|
+
return (
|
|
28
|
+
<Flex direction="column" gap={6} width="100%">
|
|
29
|
+
<StagesContainer spacing={4} width="100%">
|
|
30
|
+
<Background background="neutral200" height="100%" width={2} zIndex={1} />
|
|
31
|
+
|
|
32
|
+
<Stack spacing={6} zIndex={2} position="relative" as="ol">
|
|
33
|
+
{stages.map((stage, index) => {
|
|
34
|
+
const id = stage?.id ?? stage.__temp_key__;
|
|
35
|
+
|
|
36
|
+
return (
|
|
37
|
+
<Box key={`stage-${id}`} as="li">
|
|
38
|
+
<Stage
|
|
39
|
+
{...stage}
|
|
40
|
+
id={id}
|
|
41
|
+
index={index}
|
|
42
|
+
canDelete={stages.length > 1}
|
|
43
|
+
isOpen={!stage.id}
|
|
44
|
+
/>
|
|
45
|
+
</Box>
|
|
46
|
+
);
|
|
47
|
+
})}
|
|
48
|
+
</Stack>
|
|
49
|
+
</StagesContainer>
|
|
50
|
+
|
|
51
|
+
<Flex spacing={6}>
|
|
52
|
+
<AddStage type="button" onClick={() => dispatch(addStage({ name: '' }))}>
|
|
53
|
+
{formatMessage({
|
|
54
|
+
id: 'Settings.review-workflows.stage.add',
|
|
55
|
+
defaultMessage: 'Add new stage',
|
|
56
|
+
})}
|
|
57
|
+
</AddStage>
|
|
58
|
+
</Flex>
|
|
59
|
+
</Flex>
|
|
60
|
+
);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export { Stages };
|
|
64
|
+
|
|
65
|
+
Stages.defaultProps = {
|
|
66
|
+
stages: [],
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
Stages.propTypes = {
|
|
70
|
+
stages: PropTypes.arrayOf(
|
|
71
|
+
PropTypes.shape({
|
|
72
|
+
id: PropTypes.number,
|
|
73
|
+
__temp_key__: PropTypes.number,
|
|
74
|
+
name: PropTypes.string.isRequired,
|
|
75
|
+
})
|
|
76
|
+
),
|
|
77
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './Stages';
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export const REDUX_NAMESPACE = 'settings_review-workflows';
|
|
2
|
+
|
|
3
|
+
export const ACTION_SET_WORKFLOWS = `Settings/Review_Workflows/SET_WORKFLOWS`;
|
|
4
|
+
export const ACTION_DELETE_STAGE = `Settings/Review_Workflows/WORKFLOW_DELETE_STAGE`;
|
|
5
|
+
export const ACTION_ADD_STAGE = `Settings/Review_Workflows/WORKFLOW_ADD_STAGE`;
|
|
6
|
+
export const ACTION_UPDATE_STAGE = `Settings/Review_Workflows/WORKFLOW_UPDATE_STAGE`;
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { useQuery, useMutation, useQueryClient } from 'react-query';
|
|
2
|
+
import { useFetchClient, useNotification } from '@strapi/helper-plugin';
|
|
3
|
+
|
|
4
|
+
const QUERY_BASE_KEY = 'review-workflows';
|
|
5
|
+
const API_BASE_URL = '/admin/review-workflows';
|
|
6
|
+
|
|
7
|
+
export function useReviewWorkflows(workflowId) {
|
|
8
|
+
const { get, put } = useFetchClient();
|
|
9
|
+
const toggleNotification = useNotification();
|
|
10
|
+
const client = useQueryClient();
|
|
11
|
+
const workflowQueryKey = [QUERY_BASE_KEY, workflowId ?? 'default'];
|
|
12
|
+
|
|
13
|
+
async function fetchWorkflows({ params = { populate: 'stages' } }) {
|
|
14
|
+
const {
|
|
15
|
+
data: { data },
|
|
16
|
+
} = await get(`${API_BASE_URL}/workflows/${workflowId ?? ''}`, { params });
|
|
17
|
+
|
|
18
|
+
return data;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
async function updateRemoteWorkflowStages({ workflowId, stages }) {
|
|
22
|
+
const {
|
|
23
|
+
data: { data },
|
|
24
|
+
} = await put(`${API_BASE_URL}/workflows/${workflowId}/stages`, {
|
|
25
|
+
data: stages,
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
return data;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function updateWorkflowStages(workflowId, stages) {
|
|
32
|
+
return workflowUpdateMutation.mutateAsync({ workflowId, stages });
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function refetchWorkflow() {
|
|
36
|
+
client.refetchQueries(workflowQueryKey);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const workflows = useQuery(workflowQueryKey, fetchWorkflows);
|
|
40
|
+
|
|
41
|
+
const workflowUpdateMutation = useMutation(updateRemoteWorkflowStages, {
|
|
42
|
+
async onError() {
|
|
43
|
+
// TODO: this should return the proper error thrown by the API
|
|
44
|
+
toggleNotification({
|
|
45
|
+
type: 'warning',
|
|
46
|
+
message: { id: 'notification.error', defaultMessage: 'An error occured' },
|
|
47
|
+
});
|
|
48
|
+
},
|
|
49
|
+
|
|
50
|
+
async onSuccess() {
|
|
51
|
+
toggleNotification({
|
|
52
|
+
type: 'success',
|
|
53
|
+
message: { id: 'notification.success.saved', defaultMessage: 'Saved' },
|
|
54
|
+
});
|
|
55
|
+
},
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
return {
|
|
59
|
+
workflows,
|
|
60
|
+
updateWorkflowStages,
|
|
61
|
+
refetchWorkflow,
|
|
62
|
+
};
|
|
63
|
+
}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import { current, produce } from 'immer';
|
|
2
|
+
import isEqual from 'lodash/isEqual';
|
|
3
|
+
|
|
4
|
+
import {
|
|
5
|
+
ACTION_SET_WORKFLOWS,
|
|
6
|
+
ACTION_DELETE_STAGE,
|
|
7
|
+
ACTION_ADD_STAGE,
|
|
8
|
+
ACTION_UPDATE_STAGE,
|
|
9
|
+
} from '../constants';
|
|
10
|
+
|
|
11
|
+
export const initialState = {
|
|
12
|
+
status: 'loading',
|
|
13
|
+
serverState: {
|
|
14
|
+
currentWorkflow: null,
|
|
15
|
+
workflows: [],
|
|
16
|
+
},
|
|
17
|
+
clientState: {
|
|
18
|
+
currentWorkflow: { data: null, isDirty: false, hasDeletedServerStages: false },
|
|
19
|
+
},
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
export function reducer(state = initialState, action) {
|
|
23
|
+
return produce(state, (draft) => {
|
|
24
|
+
const { payload } = action;
|
|
25
|
+
|
|
26
|
+
switch (action.type) {
|
|
27
|
+
case ACTION_SET_WORKFLOWS: {
|
|
28
|
+
const { status, workflows } = payload;
|
|
29
|
+
|
|
30
|
+
draft.status = status;
|
|
31
|
+
|
|
32
|
+
if (workflows) {
|
|
33
|
+
const defaultWorkflow = workflows[0];
|
|
34
|
+
|
|
35
|
+
draft.serverState.workflows = workflows;
|
|
36
|
+
draft.serverState.currentWorkflow = defaultWorkflow;
|
|
37
|
+
draft.clientState.currentWorkflow.data = defaultWorkflow;
|
|
38
|
+
}
|
|
39
|
+
break;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
case ACTION_DELETE_STAGE: {
|
|
43
|
+
const { stageId } = payload;
|
|
44
|
+
const { currentWorkflow } = state.clientState;
|
|
45
|
+
|
|
46
|
+
draft.clientState.currentWorkflow.data.stages = currentWorkflow.data.stages.filter(
|
|
47
|
+
(stage) => (stage?.id ?? stage.__temp_key__) !== stageId
|
|
48
|
+
);
|
|
49
|
+
|
|
50
|
+
if (!currentWorkflow.hasDeletedServerStages) {
|
|
51
|
+
draft.clientState.currentWorkflow.hasDeletedServerStages =
|
|
52
|
+
!!state.serverState.currentWorkflow.stages.find((stage) => stage.id === stageId);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
break;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
case ACTION_ADD_STAGE: {
|
|
59
|
+
const { currentWorkflow } = state.clientState;
|
|
60
|
+
|
|
61
|
+
if (!currentWorkflow.data) {
|
|
62
|
+
draft.clientState.currentWorkflow.data = {
|
|
63
|
+
stages: [],
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
draft.clientState.currentWorkflow.data.stages.push({
|
|
68
|
+
...payload,
|
|
69
|
+
__temp_key__: (currentWorkflow.data?.stages?.length ?? 0) + 1,
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
break;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
case ACTION_UPDATE_STAGE: {
|
|
76
|
+
const { currentWorkflow } = state.clientState;
|
|
77
|
+
const { stageId, ...modified } = payload;
|
|
78
|
+
|
|
79
|
+
draft.clientState.currentWorkflow.data.stages = currentWorkflow.data.stages.map((stage) =>
|
|
80
|
+
(stage.id ?? stage.__temp_key__) === stageId
|
|
81
|
+
? {
|
|
82
|
+
...stage,
|
|
83
|
+
...modified,
|
|
84
|
+
}
|
|
85
|
+
: stage
|
|
86
|
+
);
|
|
87
|
+
|
|
88
|
+
break;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
default:
|
|
92
|
+
break;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
if (state.clientState.currentWorkflow.data) {
|
|
96
|
+
draft.clientState.currentWorkflow.isDirty = !isEqual(
|
|
97
|
+
current(draft.clientState.currentWorkflow).data,
|
|
98
|
+
state.serverState.currentWorkflow
|
|
99
|
+
);
|
|
100
|
+
}
|
|
101
|
+
});
|
|
102
|
+
}
|
package/ee/admin/pages/SettingsPage/pages/ReviewWorkflows/utils/getWorkflowValidationSchema.js
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import * as yup from 'yup';
|
|
2
|
+
|
|
3
|
+
export function getWorkflowValidationSchema({ formatMessage }) {
|
|
4
|
+
return yup.object({
|
|
5
|
+
stages: yup.array().of(
|
|
6
|
+
yup.object().shape({
|
|
7
|
+
name: yup
|
|
8
|
+
.string()
|
|
9
|
+
.required(
|
|
10
|
+
formatMessage({
|
|
11
|
+
id: 'Settings.review-workflows.validation.stage.name',
|
|
12
|
+
defaultMessage: 'Name is required',
|
|
13
|
+
})
|
|
14
|
+
)
|
|
15
|
+
.max(
|
|
16
|
+
255,
|
|
17
|
+
formatMessage({
|
|
18
|
+
id: 'Settings.review-workflows.validation.stage.max-length',
|
|
19
|
+
defaultMessage: 'Name can not be longer than 255 characters',
|
|
20
|
+
})
|
|
21
|
+
),
|
|
22
|
+
})
|
|
23
|
+
),
|
|
24
|
+
});
|
|
25
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
const routes = [];
|
|
2
2
|
|
|
3
|
-
if (strapi.features.isEnabled(strapi.features.SSO)) {
|
|
3
|
+
if (window.strapi.features.isEnabled(window.strapi.features.SSO)) {
|
|
4
4
|
routes.push({
|
|
5
5
|
async Component() {
|
|
6
6
|
const component = await import(
|
|
@@ -14,7 +14,21 @@ if (strapi.features.isEnabled(strapi.features.SSO)) {
|
|
|
14
14
|
});
|
|
15
15
|
}
|
|
16
16
|
|
|
17
|
-
if (
|
|
17
|
+
if (window.strapi.isEE) {
|
|
18
|
+
routes.push({
|
|
19
|
+
async Component() {
|
|
20
|
+
const component = await import(
|
|
21
|
+
/* webpackChunkName: "review-workflows-settings" */ '../pages/ReviewWorkflows'
|
|
22
|
+
);
|
|
23
|
+
|
|
24
|
+
return component;
|
|
25
|
+
},
|
|
26
|
+
to: '/settings/review-workflows',
|
|
27
|
+
exact: true,
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
if (window.strapi.features.isEnabled(strapi.features.AUDIT_LOGS)) {
|
|
18
32
|
routes.push({
|
|
19
33
|
async Component() {
|
|
20
34
|
const component = await import(
|
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
const customPermissions = {
|
|
2
2
|
settings: {
|
|
3
|
+
auditLogs: {
|
|
4
|
+
main: [{ action: 'admin::audit-logs.read', subject: null }],
|
|
5
|
+
read: [{ action: 'admin::audit-logs.read', subject: null }],
|
|
6
|
+
},
|
|
7
|
+
'review-workflows': {
|
|
8
|
+
main: [{ action: 'admin::review-workflows.read', subject: null }],
|
|
9
|
+
},
|
|
3
10
|
sso: {
|
|
4
11
|
main: [{ action: 'admin::provider-login.read', subject: null }],
|
|
5
12
|
read: [{ action: 'admin::provider-login.read', subject: null }],
|
package/ee/server/bootstrap.js
CHANGED
|
@@ -17,7 +17,13 @@ module.exports = async () => {
|
|
|
17
17
|
await actionProvider.registerMany(actions.auditLogs);
|
|
18
18
|
}
|
|
19
19
|
|
|
20
|
-
|
|
20
|
+
if (features.isEnabled('review-workflows')) {
|
|
21
|
+
const { bootstrap: rwBootstrap } = getService('review-workflows');
|
|
22
|
+
|
|
23
|
+
await rwBootstrap();
|
|
24
|
+
await actionProvider.registerMany(actions.reviewWorkflows);
|
|
25
|
+
}
|
|
21
26
|
|
|
27
|
+
// TODO: check admin seats
|
|
22
28
|
await executeCEBootstrap();
|
|
23
29
|
};
|
|
@@ -29,4 +29,14 @@ module.exports = {
|
|
|
29
29
|
subCategory: 'options',
|
|
30
30
|
},
|
|
31
31
|
],
|
|
32
|
+
reviewWorkflows: [
|
|
33
|
+
{
|
|
34
|
+
uid: 'review-workflows.read',
|
|
35
|
+
displayName: 'Read',
|
|
36
|
+
pluginName: 'admin',
|
|
37
|
+
section: 'settings',
|
|
38
|
+
category: 'review workflows',
|
|
39
|
+
subCategory: 'options',
|
|
40
|
+
},
|
|
41
|
+
],
|
|
32
42
|
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
module.exports = {
|
|
4
|
+
schema: {
|
|
5
|
+
collectionName: 'strapi_workflows',
|
|
6
|
+
info: {
|
|
7
|
+
name: 'Workflow',
|
|
8
|
+
description: '',
|
|
9
|
+
singularName: 'workflow',
|
|
10
|
+
pluralName: 'workflows',
|
|
11
|
+
displayName: 'Workflow',
|
|
12
|
+
},
|
|
13
|
+
options: {},
|
|
14
|
+
pluginOptions: {
|
|
15
|
+
'content-manager': {
|
|
16
|
+
visible: false,
|
|
17
|
+
},
|
|
18
|
+
'content-type-builder': {
|
|
19
|
+
visible: false,
|
|
20
|
+
},
|
|
21
|
+
},
|
|
22
|
+
attributes: {
|
|
23
|
+
uid: {
|
|
24
|
+
type: 'string',
|
|
25
|
+
},
|
|
26
|
+
stages: {
|
|
27
|
+
type: 'relation',
|
|
28
|
+
target: 'admin::workflow-stage',
|
|
29
|
+
relation: 'oneToMany',
|
|
30
|
+
mappedBy: 'workflow',
|
|
31
|
+
},
|
|
32
|
+
},
|
|
33
|
+
},
|
|
34
|
+
};
|