mirror of
https://github.com/strapi/strapi.git
synced 2025-08-01 13:29:01 +00:00
Merge pull request #16107 from strapi/feature/review-workflow-settings-papercuts
Review Workflows Settings: Fix papercut issues
This commit is contained in:
commit
079449c2ad
@ -14,7 +14,7 @@ if (window.strapi.features.isEnabled(window.strapi.features.SSO)) {
|
|||||||
|
|
||||||
if (window.strapi.features.isEnabled(window.strapi.features.REVIEW_WORKFLOWS)) {
|
if (window.strapi.features.isEnabled(window.strapi.features.REVIEW_WORKFLOWS)) {
|
||||||
items.push({
|
items.push({
|
||||||
intlLabel: { id: 'Settings.review-workflows.title', defaultMessage: 'Review Workflow' },
|
intlLabel: { id: 'Settings.review-workflows.page.title', defaultMessage: 'Review Workflows' },
|
||||||
to: '/settings/review-workflows',
|
to: '/settings/review-workflows',
|
||||||
id: 'review-workflows',
|
id: 'review-workflows',
|
||||||
isDisplayed: false,
|
isDisplayed: false,
|
||||||
|
@ -1,13 +1,6 @@
|
|||||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||||
|
|
||||||
exports[`Admin | Settings | Review Workflow | AddStage should render a list of stages 1`] = `
|
exports[`Admin | Settings | Review Workflow | AddStage should render a list of stages 1`] = `
|
||||||
.c6 {
|
|
||||||
font-size: 0.75rem;
|
|
||||||
line-height: 1.33;
|
|
||||||
font-weight: 600;
|
|
||||||
color: #8e8ea9;
|
|
||||||
}
|
|
||||||
|
|
||||||
.c0 {
|
.c0 {
|
||||||
background: #ffffff;
|
background: #ffffff;
|
||||||
padding-top: 12px;
|
padding-top: 12px;
|
||||||
@ -32,6 +25,13 @@ exports[`Admin | Settings | Review Workflow | AddStage should render a list of s
|
|||||||
gap: 8px;
|
gap: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.c6 {
|
||||||
|
font-size: 0.75rem;
|
||||||
|
line-height: 1.33;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #8e8ea9;
|
||||||
|
}
|
||||||
|
|
||||||
.c7 {
|
.c7 {
|
||||||
border: 0;
|
border: 0;
|
||||||
-webkit-clip: rect(0 0 0 0);
|
-webkit-clip: rect(0 0 0 0);
|
||||||
@ -104,9 +104,9 @@ exports[`Admin | Settings | Review Workflow | AddStage should render a list of s
|
|||||||
aria-hidden="true"
|
aria-hidden="true"
|
||||||
class="c3 c4"
|
class="c3 c4"
|
||||||
fill="none"
|
fill="none"
|
||||||
height="1em"
|
height="1rem"
|
||||||
viewBox="0 0 24 24"
|
viewBox="0 0 24 24"
|
||||||
width="1em"
|
width="1rem"
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
>
|
>
|
||||||
<circle
|
<circle
|
||||||
@ -116,7 +116,7 @@ exports[`Admin | Settings | Review Workflow | AddStage should render a list of s
|
|||||||
r="12"
|
r="12"
|
||||||
/>
|
/>
|
||||||
<path
|
<path
|
||||||
d="M17 12.569c0 .124-.1.224-.225.224h-3.981v3.982c0 .124-.101.225-.226.225h-1.136a.225.225 0 01-.226-.225v-3.981H7.226A.225.225 0 017 12.567v-1.136c0-.125.1-.226.225-.226h3.982V7.226c0-.124.1-.225.224-.225h1.138c.124 0 .224.1.224.225v3.982h3.982c.124 0 .225.1.225.224v1.138z"
|
d="M17 12.569c0 .124-.1.224-.225.224h-3.981v3.982c0 .124-.101.225-.226.225h-1.136a.225.225 0 0 1-.226-.225v-3.981H7.226A.225.225 0 0 1 7 12.567v-1.136c0-.125.1-.226.225-.226h3.982V7.226c0-.124.1-.225.224-.225h1.138c.124 0 .224.1.224.225v3.982h3.982c.124 0 .225.1.225.224v1.138Z"
|
||||||
fill="#F6F6F9"
|
fill="#F6F6F9"
|
||||||
/>
|
/>
|
||||||
</svg>
|
</svg>
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
import React, { useState } from 'react';
|
import React, { useState } from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import styled from 'styled-components';
|
|
||||||
import { useField } from 'formik';
|
import { useField } from 'formik';
|
||||||
import { useIntl } from 'react-intl';
|
import { useIntl } from 'react-intl';
|
||||||
import { useDispatch } from 'react-redux';
|
import { useDispatch } from 'react-redux';
|
||||||
@ -8,30 +7,15 @@ import {
|
|||||||
Accordion,
|
Accordion,
|
||||||
AccordionToggle,
|
AccordionToggle,
|
||||||
AccordionContent,
|
AccordionContent,
|
||||||
Box,
|
|
||||||
Grid,
|
Grid,
|
||||||
GridItem,
|
GridItem,
|
||||||
IconButton,
|
IconButton,
|
||||||
TextInput,
|
TextInput,
|
||||||
} from '@strapi/design-system';
|
} from '@strapi/design-system';
|
||||||
|
|
||||||
import { Trash } from '@strapi/icons';
|
import { Trash } from '@strapi/icons';
|
||||||
|
|
||||||
import { deleteStage, updateStage } from '../../../actions';
|
import { deleteStage, updateStage } from '../../../actions';
|
||||||
|
|
||||||
// TODO: Delete once https://github.com/strapi/design-system/pull/858
|
|
||||||
// is merged and released.
|
|
||||||
const StyledAccordion = styled(Box)`
|
|
||||||
> div:first-child {
|
|
||||||
box-shadow: ${({ theme }) => theme.shadows.tableShadow};
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
|
|
||||||
// TODO: Keep an eye on https://github.com/strapi/design-system/pull/878
|
|
||||||
const DeleteButton = styled(IconButton)`
|
|
||||||
background-color: transparent;
|
|
||||||
`;
|
|
||||||
|
|
||||||
function Stage({ id, name, index, canDelete, isOpen: isOpenDefault = false }) {
|
function Stage({ id, name, index, canDelete, isOpen: isOpenDefault = false }) {
|
||||||
const { formatMessage } = useIntl();
|
const { formatMessage } = useIntl();
|
||||||
const [isOpen, setIsOpen] = useState(isOpenDefault);
|
const [isOpen, setIsOpen] = useState(isOpenDefault);
|
||||||
@ -40,44 +24,52 @@ function Stage({ id, name, index, canDelete, isOpen: isOpenDefault = false }) {
|
|||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<StyledAccordion>
|
<Accordion
|
||||||
<Accordion size="S" variant="primary" onToggle={() => setIsOpen(!isOpen)} expanded={isOpen}>
|
size="S"
|
||||||
<AccordionToggle
|
variant="primary"
|
||||||
title={name}
|
onToggle={() => setIsOpen(!isOpen)}
|
||||||
togglePosition="left"
|
expanded={isOpen}
|
||||||
action={
|
shadow="tableShadow"
|
||||||
canDelete ? (
|
>
|
||||||
<DeleteButton
|
<AccordionToggle
|
||||||
noBorder
|
title={name}
|
||||||
onClick={() => dispatch(deleteStage(id))}
|
togglePosition="left"
|
||||||
label={formatMessage({
|
action={
|
||||||
id: 'Settings.review-workflows.stage.delete',
|
canDelete ? (
|
||||||
defaultMessage: 'Delete stage',
|
<IconButton
|
||||||
})}
|
backgroundColor="transparent"
|
||||||
icon={<Trash />}
|
noBorder
|
||||||
/>
|
onClick={() => dispatch(deleteStage(id))}
|
||||||
) : null
|
label={formatMessage({
|
||||||
}
|
id: 'Settings.review-workflows.stage.delete',
|
||||||
/>
|
defaultMessage: 'Delete stage',
|
||||||
<AccordionContent padding={6} background="neutral0">
|
})}
|
||||||
<Grid gap={4}>
|
icon={<Trash />}
|
||||||
<GridItem col={6}>
|
/>
|
||||||
<TextInput
|
) : null
|
||||||
{...field}
|
}
|
||||||
id={fieldIdentifier}
|
/>
|
||||||
value={name}
|
<AccordionContent padding={6} background="neutral0">
|
||||||
label={formatMessage({
|
<Grid gap={4}>
|
||||||
id: 'Settings.review-workflows.stage.name.label',
|
<GridItem col={6}>
|
||||||
defaultMessage: 'Stage name',
|
<TextInput
|
||||||
})}
|
{...field}
|
||||||
error={meta.error ?? false}
|
id={fieldIdentifier}
|
||||||
onBlur={(event) => dispatch(updateStage(id, { name: event.target.value }))}
|
value={name}
|
||||||
/>
|
label={formatMessage({
|
||||||
</GridItem>
|
id: 'Settings.review-workflows.stage.name.label',
|
||||||
</Grid>
|
defaultMessage: 'Stage name',
|
||||||
</AccordionContent>
|
})}
|
||||||
</Accordion>
|
error={meta.error ?? false}
|
||||||
</StyledAccordion>
|
onChange={(event) => {
|
||||||
|
field.onChange(event);
|
||||||
|
dispatch(updateStage(id, { name: event.target.value }));
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</GridItem>
|
||||||
|
</Grid>
|
||||||
|
</AccordionContent>
|
||||||
|
</Accordion>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,7 +3,7 @@ import PropTypes from 'prop-types';
|
|||||||
import styled from 'styled-components';
|
import styled from 'styled-components';
|
||||||
import { useIntl } from 'react-intl';
|
import { useIntl } from 'react-intl';
|
||||||
import { useDispatch } from 'react-redux';
|
import { useDispatch } from 'react-redux';
|
||||||
import { Box, Flex, Stack } from '@strapi/design-system';
|
import { Box, Flex } from '@strapi/design-system';
|
||||||
|
|
||||||
import { addStage } from '../../actions';
|
import { addStage } from '../../actions';
|
||||||
import { AddStage } from '../AddStage';
|
import { AddStage } from '../AddStage';
|
||||||
@ -29,7 +29,14 @@ function Stages({ stages }) {
|
|||||||
<StagesContainer spacing={4} width="100%">
|
<StagesContainer spacing={4} width="100%">
|
||||||
<Background background="neutral200" height="100%" width={2} zIndex={1} />
|
<Background background="neutral200" height="100%" width={2} zIndex={1} />
|
||||||
|
|
||||||
<Stack spacing={6} zIndex={2} position="relative" as="ol">
|
<Flex
|
||||||
|
direction="column"
|
||||||
|
alignItems="stretch"
|
||||||
|
gap={6}
|
||||||
|
zIndex={2}
|
||||||
|
position="relative"
|
||||||
|
as="ol"
|
||||||
|
>
|
||||||
{stages.map((stage, index) => {
|
{stages.map((stage, index) => {
|
||||||
const id = stage?.id ?? stage.__temp_key__;
|
const id = stage?.id ?? stage.__temp_key__;
|
||||||
|
|
||||||
@ -45,10 +52,10 @@ function Stages({ stages }) {
|
|||||||
</Box>
|
</Box>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
</Stack>
|
</Flex>
|
||||||
</StagesContainer>
|
</StagesContainer>
|
||||||
|
|
||||||
<Flex spacing={6}>
|
<Flex direction="column" gap={6}>
|
||||||
<AddStage type="button" onClick={() => dispatch(addStage({ name: '' }))}>
|
<AddStage type="button" onClick={() => dispatch(addStage({ name: '' }))}>
|
||||||
{formatMessage({
|
{formatMessage({
|
||||||
id: 'Settings.review-workflows.stage.add',
|
id: 'Settings.review-workflows.stage.add',
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { render } from '@testing-library/react';
|
import { fireEvent, render } from '@testing-library/react';
|
||||||
import { IntlProvider } from 'react-intl';
|
import { IntlProvider } from 'react-intl';
|
||||||
import { Provider } from 'react-redux';
|
import { Provider } from 'react-redux';
|
||||||
import { FormikProvider, useFormik } from 'formik';
|
import { FormikProvider, useFormik } from 'formik';
|
||||||
@ -10,12 +10,13 @@ import { ThemeProvider, lightTheme } from '@strapi/design-system';
|
|||||||
import configureStore from '../../../../../../../../../admin/src/core/store/configureStore';
|
import configureStore from '../../../../../../../../../admin/src/core/store/configureStore';
|
||||||
import { Stages } from '../Stages';
|
import { Stages } from '../Stages';
|
||||||
import { reducer } from '../../../reducer';
|
import { reducer } from '../../../reducer';
|
||||||
import { ACTION_SET_WORKFLOWS, ACTION_ADD_STAGE } from '../../../constants';
|
import { ACTION_SET_WORKFLOWS } from '../../../constants';
|
||||||
import { addStage } from '../../../actions';
|
import * as actions from '../../../actions';
|
||||||
|
|
||||||
|
// without mocking actions as ESM it is impossible to spy on named exports
|
||||||
jest.mock('../../../actions', () => ({
|
jest.mock('../../../actions', () => ({
|
||||||
|
__esModule: true,
|
||||||
...jest.requireActual('../../../actions'),
|
...jest.requireActual('../../../actions'),
|
||||||
addStage: jest.fn(),
|
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const STAGES_FIXTURE = [
|
const STAGES_FIXTURE = [
|
||||||
@ -87,8 +88,7 @@ describe('Admin | Settings | Review Workflow | Stages', () => {
|
|||||||
|
|
||||||
it('should append a new stage when clicking "add new stage"', async () => {
|
it('should append a new stage when clicking "add new stage"', async () => {
|
||||||
const { getByRole } = setup();
|
const { getByRole } = setup();
|
||||||
|
const spy = jest.spyOn(actions, 'addStage');
|
||||||
addStage.mockReturnValue({ type: ACTION_ADD_STAGE });
|
|
||||||
|
|
||||||
await user.click(
|
await user.click(
|
||||||
getByRole('button', {
|
getByRole('button', {
|
||||||
@ -96,7 +96,24 @@ describe('Admin | Settings | Review Workflow | Stages', () => {
|
|||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(addStage).toBeCalledTimes(1);
|
expect(spy).toBeCalledTimes(1);
|
||||||
expect(addStage).toBeCalledWith({ name: '' });
|
expect(spy).toBeCalledWith({ name: '' });
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should update the name of a stage by changing the input value', async () => {
|
||||||
|
const { queryByRole, getByRole } = setup();
|
||||||
|
const spy = jest.spyOn(actions, 'updateStage');
|
||||||
|
|
||||||
|
await user.click(getByRole('button', { name: /stage-2/i }));
|
||||||
|
|
||||||
|
const input = queryByRole('textbox', {
|
||||||
|
name: /stage name/i,
|
||||||
|
});
|
||||||
|
|
||||||
|
fireEvent.change(input, { target: { value: 'New name' } });
|
||||||
|
|
||||||
|
expect(spy).toBeCalledWith(2, {
|
||||||
|
name: 'New name',
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
Loading…
x
Reference in New Issue
Block a user