Settings: Connect Review Workflow UI, data loader and redux

This commit is contained in:
Gustav Hansen 2023-01-30 15:12:06 +01:00
parent cab472d804
commit 0e122dc344
8 changed files with 124 additions and 35 deletions

View File

@ -226,6 +226,7 @@
"Settings.profile.form.section.profile.page.title": "Profile page",
"Settings.review-workflows.page.title": "Review Workflow",
"Settings.review-workflows.page.subtitle": "{count, plural, one {# stage} other {# stages}}",
"Settings.review-workflows.page.isLoading": "Workflow is loading",
"Settings.review-workflows.stage.name.label": "Stage name",
"Settings.roles.create.description": "Define the rights given to the role",
"Settings.roles.create.title": "Create a role",

View File

@ -1,35 +1,39 @@
import React from 'react';
import React, { useEffect } from 'react';
import { useIntl } from 'react-intl';
import { useSelector, useDispatch } from 'react-redux';
import { SettingsPageTitle } from '@strapi/helper-plugin';
import { Button, ContentLayout, HeaderLayout, Layout, Main } from '@strapi/design-system';
import { Button, ContentLayout, HeaderLayout, Layout, Loader, Main } from '@strapi/design-system';
import { Check } from '@strapi/icons';
import { Stages } from './components/Stages';
const STAGES = [
{
uid: 'id-1',
name: 'To do',
},
{
uid: 'id-2',
name: 'Ready to review',
},
{
uid: 'id-3',
name: 'In progress',
},
{
uid: 'id-4',
name: 'Reviewed',
},
];
import { reducer } from './reducer';
import { REDUX_NAMESPACE } from './constants';
import { useInjectReducer } from '../../../../../../admin/src/hooks/useInjectReducer';
import { useReviewWorkflows } from './hooks/useReviewWorkflows';
import { setWorkflowLoadingState, setWorkflowStages } from './actions';
export function ReviewWorkflowsPage() {
const { formatMessage } = useIntl();
const { workflows: workflowsData } = useReviewWorkflows();
const workflow = useSelector((state) => state?.[REDUX_NAMESPACE]);
const dispatch = useDispatch();
useInjectReducer(REDUX_NAMESPACE, reducer);
useEffect(() => {
dispatch(setWorkflowLoadingState(workflowsData.status));
if (workflowsData.status === 'success') {
dispatch(setWorkflowStages(workflowsData.data));
}
}, [workflowsData.status, workflowsData.data, dispatch]);
// useInjectReducer() runs on the first rendering after useSelector
// which will return undefined. This helps to avoid too many optional
// chaining operators down the component.
if (!workflow) {
return null;
}
return (
<Layout>
@ -58,11 +62,20 @@ export function ReviewWorkflowsPage() {
id: 'Settings.review-workflows.page.subtitle',
defaultMessage: '{count, plural, one {# stage} other {# stages}}',
},
{ count: STAGES.length }
{ count: workflow.workflows.stages.length }
)}
/>
<ContentLayout>
<Stages stages={STAGES} />
{workflow.workflows.state === 'loading' ? (
<Loader>
{formatMessage({
id: 'Settings.review-workflows.page.isLoading',
defaultMessage: 'Workflow is loading',
})}
</Loader>
) : (
<Stages stages={workflow.workflows.stages} />
)}
</ContentLayout>
</Main>
</Layout>

View File

@ -0,0 +1,19 @@
import { ACTION_SET_LOADING_STATE, ACTION_SET_STAGES } from '../constants';
export function setWorkflowLoadingState(state) {
return {
type: ACTION_SET_LOADING_STATE,
payload: {
state,
},
};
}
export function setWorkflowStages(stages) {
return {
type: ACTION_SET_STAGES,
payload: {
stages,
},
};
}

View File

@ -22,7 +22,7 @@ const StyledAccordion = styled(Box)`
}
`;
function Stage({ uid, name }) {
function Stage({ id, name }) {
const { formatMessage } = useIntl();
const [isOpen, setIsOpen] = useState(false);
@ -34,7 +34,7 @@ function Stage({ uid, name }) {
<Grid gap={4}>
<GridItem col={6}>
<TextInput
name={`stage_name[${uid}]`}
name={`stage_name[${id}]`}
disabled
label={formatMessage({
id: 'Settings.review-workflows.stage.name.label',

View File

@ -23,9 +23,9 @@ function Stages({ stages }) {
<Background background="neutral200" height="100%" width={2} zIndex={1} />
<Stack spacing={6} zIndex={2} position="relative" as="ol">
{stages.map(({ uid, ...stage }) => (
<Box key={`stage-${uid}`} as="li">
<Stage {...{ ...stage, uid }} />
{stages.map(({ id, ...stage }) => (
<Box key={`stage-${id}`} as="li">
<Stage {...{ ...stage, id }} />
</Box>
))}
</Stack>

View File

@ -1,6 +1,11 @@
import PropTypes from 'prop-types';
export const REDUX_NAMESPACE = 'settings_review-workflows';
export const ACTION_SET_LOADING_STATE = `Settings/Review_Workflows/SET_STATE`;
export const ACTION_SET_STAGES = `Settings/Review_Workflows/SET_DATA`;
export const StageType = PropTypes.shape({
uid: PropTypes.string.isRequired,
id: PropTypes.string.isRequired,
name: PropTypes.string.isRequired,
});

View File

@ -2,12 +2,36 @@ import { useQuery } from 'react-query';
import { useFetchClient } from '@strapi/helper-plugin';
export function useReviewWorkflows(workflowUid) {
export function useReviewWorkflows(workflowId) {
const { get } = useFetchClient();
async function fetchWorkflows() {
/* TODO: mocked for now until the API is ready */
return [
{
id: 'id-1',
name: 'To do',
},
{
id: 'id-2',
name: 'Ready to review',
},
{
id: 'id-3',
name: 'In progress',
},
{
id: 'id-4',
name: 'Reviewed',
},
];
// eslint-disable-next-line no-unreachable
try {
const { data } = await get(`/admin/review-workflows/workflows/${workflowUid ?? ''}`);
const { data } = await get(`/admin/review-workflows/workflows/${workflowId ?? ''}`);
return data;
} catch (err) {
@ -15,7 +39,7 @@ export function useReviewWorkflows(workflowUid) {
}
}
const workflows = useQuery(['review-workflows', workflowUid ?? 'default'], fetchWorkflows);
const workflows = useQuery(['review-workflows', workflowId ?? 'default'], fetchWorkflows);
return {
workflows,

View File

@ -0,0 +1,27 @@
import produce from 'immer';
import { ACTION_SET_STAGES, ACTION_SET_LOADING_STATE } from '../constants';
const initialState = {
workflows: {
state: 'loading',
stages: [],
},
};
export function reducer(state = initialState, action) {
return produce(state, (draft) => {
switch (action.type) {
case ACTION_SET_LOADING_STATE:
draft.workflows.state = action.payload.state;
break;
case ACTION_SET_STAGES:
draft.workflows.stages = action.payload.stages;
break;
default:
break;
}
});
}