Merge pull request #16107 from strapi/feature/review-workflow-settings-papercuts

Review Workflows Settings: Fix papercut issues
This commit is contained in:
Gustav Hansen 2023-03-16 18:12:40 +01:00 committed by GitHub
commit 079449c2ad
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 93 additions and 77 deletions

View File

@ -14,7 +14,7 @@ if (window.strapi.features.isEnabled(window.strapi.features.SSO)) {
if (window.strapi.features.isEnabled(window.strapi.features.REVIEW_WORKFLOWS)) {
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',
id: 'review-workflows',
isDisplayed: false,

View File

@ -1,13 +1,6 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
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 {
background: #ffffff;
padding-top: 12px;
@ -32,6 +25,13 @@ exports[`Admin | Settings | Review Workflow | AddStage should render a list of s
gap: 8px;
}
.c6 {
font-size: 0.75rem;
line-height: 1.33;
font-weight: 600;
color: #8e8ea9;
}
.c7 {
border: 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"
class="c3 c4"
fill="none"
height="1em"
height="1rem"
viewBox="0 0 24 24"
width="1em"
width="1rem"
xmlns="http://www.w3.org/2000/svg"
>
<circle
@ -116,7 +116,7 @@ exports[`Admin | Settings | Review Workflow | AddStage should render a list of s
r="12"
/>
<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"
/>
</svg>

View File

@ -1,6 +1,5 @@
import React, { useState } from 'react';
import PropTypes from 'prop-types';
import styled from 'styled-components';
import { useField } from 'formik';
import { useIntl } from 'react-intl';
import { useDispatch } from 'react-redux';
@ -8,30 +7,15 @@ import {
Accordion,
AccordionToggle,
AccordionContent,
Box,
Grid,
GridItem,
IconButton,
TextInput,
} from '@strapi/design-system';
import { Trash } from '@strapi/icons';
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 }) {
const { formatMessage } = useIntl();
const [isOpen, setIsOpen] = useState(isOpenDefault);
@ -40,44 +24,52 @@ function Stage({ id, name, index, canDelete, isOpen: isOpenDefault = false }) {
const dispatch = useDispatch();
return (
<StyledAccordion>
<Accordion size="S" variant="primary" onToggle={() => setIsOpen(!isOpen)} expanded={isOpen}>
<AccordionToggle
title={name}
togglePosition="left"
action={
canDelete ? (
<DeleteButton
noBorder
onClick={() => dispatch(deleteStage(id))}
label={formatMessage({
id: 'Settings.review-workflows.stage.delete',
defaultMessage: 'Delete stage',
})}
icon={<Trash />}
/>
) : null
}
/>
<AccordionContent padding={6} background="neutral0">
<Grid gap={4}>
<GridItem col={6}>
<TextInput
{...field}
id={fieldIdentifier}
value={name}
label={formatMessage({
id: 'Settings.review-workflows.stage.name.label',
defaultMessage: 'Stage name',
})}
error={meta.error ?? false}
onBlur={(event) => dispatch(updateStage(id, { name: event.target.value }))}
/>
</GridItem>
</Grid>
</AccordionContent>
</Accordion>
</StyledAccordion>
<Accordion
size="S"
variant="primary"
onToggle={() => setIsOpen(!isOpen)}
expanded={isOpen}
shadow="tableShadow"
>
<AccordionToggle
title={name}
togglePosition="left"
action={
canDelete ? (
<IconButton
backgroundColor="transparent"
noBorder
onClick={() => dispatch(deleteStage(id))}
label={formatMessage({
id: 'Settings.review-workflows.stage.delete',
defaultMessage: 'Delete stage',
})}
icon={<Trash />}
/>
) : null
}
/>
<AccordionContent padding={6} background="neutral0">
<Grid gap={4}>
<GridItem col={6}>
<TextInput
{...field}
id={fieldIdentifier}
value={name}
label={formatMessage({
id: 'Settings.review-workflows.stage.name.label',
defaultMessage: 'Stage name',
})}
error={meta.error ?? false}
onChange={(event) => {
field.onChange(event);
dispatch(updateStage(id, { name: event.target.value }));
}}
/>
</GridItem>
</Grid>
</AccordionContent>
</Accordion>
);
}

View File

@ -3,7 +3,7 @@ import PropTypes from 'prop-types';
import styled from 'styled-components';
import { useIntl } from 'react-intl';
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 '../AddStage';
@ -29,7 +29,14 @@ function Stages({ stages }) {
<StagesContainer spacing={4} width="100%">
<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) => {
const id = stage?.id ?? stage.__temp_key__;
@ -45,10 +52,10 @@ function Stages({ stages }) {
</Box>
);
})}
</Stack>
</Flex>
</StagesContainer>
<Flex spacing={6}>
<Flex direction="column" gap={6}>
<AddStage type="button" onClick={() => dispatch(addStage({ name: '' }))}>
{formatMessage({
id: 'Settings.review-workflows.stage.add',

View File

@ -1,5 +1,5 @@
import React from 'react';
import { render } from '@testing-library/react';
import { fireEvent, render } from '@testing-library/react';
import { IntlProvider } from 'react-intl';
import { Provider } from 'react-redux';
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 { Stages } from '../Stages';
import { reducer } from '../../../reducer';
import { ACTION_SET_WORKFLOWS, ACTION_ADD_STAGE } from '../../../constants';
import { addStage } from '../../../actions';
import { ACTION_SET_WORKFLOWS } from '../../../constants';
import * as actions from '../../../actions';
// without mocking actions as ESM it is impossible to spy on named exports
jest.mock('../../../actions', () => ({
__esModule: true,
...jest.requireActual('../../../actions'),
addStage: jest.fn(),
}));
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 () => {
const { getByRole } = setup();
addStage.mockReturnValue({ type: ACTION_ADD_STAGE });
const spy = jest.spyOn(actions, 'addStage');
await user.click(
getByRole('button', {
@ -96,7 +96,24 @@ describe('Admin | Settings | Review Workflow | Stages', () => {
})
);
expect(addStage).toBeCalledTimes(1);
expect(addStage).toBeCalledWith({ name: '' });
expect(spy).toBeCalledTimes(1);
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',
});
});
});