Skip to content

Commit dbea4ea

Browse files
committed
better data fetching
1 parent 4c3859f commit dbea4ea

File tree

13 files changed

+89
-62
lines changed

13 files changed

+89
-62
lines changed

backend/src/workflow/manager/api/services/workflow/workflow.py

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,21 @@ def _serialize_workflow(workflow, base):
2121
"description": getattr(workflow, "description", ""),
2222
"initial_state": workflow.initial_state,
2323
"states": [
24-
{"id": s.id, "title": s.title, "transitions": s.transitions}
24+
{
25+
"id": s.id,
26+
"title": s.title,
27+
"description": getattr(s, "description", ""),
28+
"transitions": s.transitions
29+
}
2530
for s in workflow.states.objectValues()
2631
],
2732
"transitions": [
28-
{"id": t.id, "title": t.title, "new_state_id": t.new_state_id}
33+
{
34+
"id": t.id,
35+
"title": t.title,
36+
"description": getattr(t, "description", ""),
37+
"new_state_id": t.new_state_id
38+
}
2939
for t in workflow.transitions.objectValues()
3040
],
3141
"assigned_types": workflow_base.get_assigned_types_for(workflow.id),

frontend/packages/volto-workflow-manager/src/components/States/CreateState.tsx

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ import {
1717
import { toast } from 'react-toastify';
1818
import Toast from '@plone/volto/components/manage/Toast/Toast';
1919
import { useIntl, defineMessages } from 'react-intl';
20-
import { addState, getWorkflows } from '../../actions';
20+
import { addState, getWorkflow } from '../../actions';
2121
import { useAppDispatch, useAppSelector } from '../../types';
2222
import type { GlobalRootState } from '../../types';
2323
import type { CreateStateProps } from '../../types/state';
@@ -45,11 +45,13 @@ const CreateState = ({ workflowId, isOpen, onClose }: CreateStateProps) => {
4545
const [newStateDescription, setNewStateDescription] = useState('');
4646
const [isSubmitting, setIsSubmitting] = useState(false);
4747

48-
const currentWorkflow = useAppSelector((state: GlobalRootState) =>
49-
state.workflow.workflows.items.find((wf) => wf.id === workflowId),
48+
const currentWorkflow = useAppSelector(
49+
(state: GlobalRootState) => state.workflow.workflow.currentWorkflow,
5050
);
5151

52-
const addStateStatus = useAppSelector((state: RootState) => state.state?.add);
52+
const addStateStatus = useAppSelector(
53+
(state: GlobalRootState) => state.state?.add,
54+
);
5355

5456
useEffect(() => {
5557
if (!isOpen) {
@@ -145,7 +147,7 @@ const CreateState = ({ workflowId, isOpen, onClose }: CreateStateProps) => {
145147
const result = await dispatch(addState(currentWorkflow.id, stateData));
146148

147149
if (result && !result.error) {
148-
await dispatch(getWorkflows());
150+
await dispatch(getWorkflow(currentWorkflow.id));
149151
} else {
150152
setIsSubmitting(false);
151153
// The useEffect hook will handle the toast for the API error

frontend/packages/volto-workflow-manager/src/components/States/State.tsx

Lines changed: 12 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ const propertiesSchema = {
5050

5151
const State: React.FC<StateProps> = ({
5252
workflowId,
53+
workflow,
5354
onDataChange,
5455
isDisabled,
5556
}) => {
@@ -60,15 +61,13 @@ const State: React.FC<StateProps> = ({
6061
null,
6162
);
6263

63-
const { statesInfo, currentWorkflow, transitionsInfo, isLoadingData } =
64-
useSelector((state: GlobalRootState) => ({
64+
const { statesInfo, transitionsInfo, isLoadingData } = useSelector(
65+
(state: GlobalRootState) => ({
6566
statesInfo: state.state.list,
66-
currentWorkflow: state.workflow.workflows.items.find(
67-
(w) => w.id === workflowId,
68-
),
6967
transitionsInfo: state.transition.list,
7068
isLoadingData: state.state.list.loading || state.transition.list.loading,
71-
}));
69+
}),
70+
);
7271

7372
useEffect(() => {
7473
if (workflowId) {
@@ -81,12 +80,12 @@ const State: React.FC<StateProps> = ({
8180
const currentState = statesInfo.data?.states.find(
8281
(s) => s.id === selectedStateId,
8382
);
84-
if (currentState && currentWorkflow) {
83+
if (currentState && workflow) {
8584
const data: StateData = {
8685
properties: {
8786
title: currentState.title || '',
8887
description: currentState.description || '',
89-
isInitialState: currentWorkflow.initial_state === currentState.id,
88+
isInitialState: workflow.initial_state === currentState.id,
9089
},
9190
transitions: { selected: currentState.transitions || [] },
9291
permissions: currentState.permission_roles || {},
@@ -98,7 +97,7 @@ const State: React.FC<StateProps> = ({
9897
setLocalStateData(null);
9998
setInitialStateData(null);
10099
}
101-
}, [selectedStateId, statesInfo.data, currentWorkflow]);
100+
}, [selectedStateId, statesInfo.data, workflow]);
102101

103102
useEffect(() => {
104103
if (
@@ -184,22 +183,18 @@ const State: React.FC<StateProps> = ({
184183
<PermissionRolesTab
185184
data={localStateData?.permissions}
186185
managedPermissions={
187-
currentWorkflow?.context_data?.managed_permissions || []
188-
}
189-
availableRoles={
190-
currentWorkflow?.context_data?.available_roles || []
186+
workflow?.context_data?.managed_permissions || []
191187
}
188+
availableRoles={workflow?.context_data?.available_roles || []}
192189
onChange={(permissions) => handleStateChange({ permissions })}
193190
isDisabled={areTabsDisabled}
194191
/>
195192
</Item>
196193
<Item key="group-roles">
197194
<GroupRolesTab
198195
data={localStateData?.groupRoles}
199-
groups={currentWorkflow?.context_data?.groups || []}
200-
availableRoles={
201-
currentWorkflow?.context_data?.available_roles || []
202-
}
196+
groups={workflow?.context_data?.groups || []}
197+
availableRoles={workflow?.context_data?.available_roles || []}
203198
onChange={(groupRoles) => handleStateChange({ groupRoles })}
204199
isDisabled={areTabsDisabled}
205200
/>

frontend/packages/volto-workflow-manager/src/components/Transitions/CreateTransition.tsx

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import { toast } from 'react-toastify';
1818
import Toast from '@plone/volto/components/manage/Toast/Toast';
1919
import { useIntl, defineMessages } from 'react-intl';
2020
import { createAndLinkTransition } from '../../actions/transition';
21+
import { getWorkflow } from '../../actions/workflow';
2122
import {
2223
type GlobalRootState,
2324
useAppDispatch,
@@ -66,8 +67,8 @@ const CreateTransition = ({
6667
null,
6768
);
6869

69-
const currentWorkflow = useAppSelector((state: GlobalRootState) =>
70-
state.workflow.workflows.items.find((wf) => wf.id === workflowId),
70+
const currentWorkflow = useAppSelector(
71+
(state: GlobalRootState) => state.workflow.workflow.currentWorkflow,
7172
);
7273

7374
useEffect(() => {
@@ -146,6 +147,7 @@ const CreateTransition = ({
146147
content={intl.formatMessage(messages.creationSuccessContent)}
147148
/>,
148149
);
150+
await dispatch(getWorkflow(workflowId));
149151
onClose();
150152
}
151153
};

frontend/packages/volto-workflow-manager/src/components/Transitions/Transition.tsx

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import type { TransitionData, TransitionProps } from '../../types/transition';
2222

2323
const Transition: React.FC<TransitionProps> = ({
2424
workflowId,
25+
workflow,
2526
onDataChange,
2627
isDisabled,
2728
}) => {
@@ -34,15 +35,13 @@ const Transition: React.FC<TransitionProps> = ({
3435
const [initialTransitionData, setInitialTransitionData] =
3536
useState<TransitionData | null>(null);
3637

37-
const { transitionsInfo, statesInfo, currentWorkflow, isLoading } =
38-
useSelector((state: GlobalRootState) => ({
38+
const { transitionsInfo, statesInfo, isLoading } = useSelector(
39+
(state: GlobalRootState) => ({
3940
transitionsInfo: state.transition.list,
4041
statesInfo: state.state.list,
41-
currentWorkflow: state.workflow.workflows.items.find(
42-
(w) => w.id === workflowId,
43-
),
4442
isLoading: state.transition.list.loading || state.state.list.loading,
45-
}));
43+
}),
44+
);
4645

4746
useEffect(() => {
4847
if (workflowId) {
@@ -211,12 +210,10 @@ const Transition: React.FC<TransitionProps> = ({
211210
<Item key="guards">
212211
<GuardsTab
213212
data={localTransitionData?.guards}
214-
availableRoles={
215-
currentWorkflow?.context_data?.available_roles || []
216-
}
217-
availableGroups={currentWorkflow?.context_data?.groups || []}
213+
availableRoles={workflow?.context_data?.available_roles || []}
214+
availableGroups={workflow?.context_data?.groups || []}
218215
availablePermissions={
219-
currentWorkflow?.context_data?.managed_permissions || []
216+
workflow?.context_data?.managed_permissions || []
220217
}
221218
onChange={(guards) => handleTransitionChange({ guards })}
222219
isDisabled={isTabDisabled}

frontend/packages/volto-workflow-manager/src/components/Workflow/WorkflowHeader.tsx

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
import { Flex, Heading, Text, View } from '@adobe/react-spectrum';
2+
import type { WorkflowHeaderProps } from '../../types/workflow';
23

3-
const WorkflowHeader = ({ workflows, selectedWorkflowId }) => {
4-
const currentWorkflow = workflows.find((w) => w.id === selectedWorkflowId);
5-
4+
const WorkflowHeader: React.FC<WorkflowHeaderProps> = ({ workflow }) => {
65
return (
76
<Flex
87
direction="row"
@@ -14,7 +13,7 @@ const WorkflowHeader = ({ workflows, selectedWorkflowId }) => {
1413
<Heading level={2}>Workflow Manager</Heading>
1514
<Text>
1615
You are currently working on the "
17-
<strong>{currentWorkflow?.title || 'Unknown'}</strong>" workflow.
16+
<strong>{workflow?.title || 'Unknown'}</strong>" workflow.
1817
</Text>
1918
</View>
2019
</Flex>

frontend/packages/volto-workflow-manager/src/components/Workflow/WorkflowSettings.tsx

Lines changed: 15 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ import Icon from '@plone/volto/components/theme/Icon/Icon';
1717
import save from '@plone/volto/icons/save.svg';
1818
import clear from '@plone/volto/icons/clear.svg';
1919
import { updateState } from '../../actions/state';
20-
import { getWorkflows, updateWorkflow } from '../../actions/workflow';
20+
import { getWorkflow, updateWorkflow } from '../../actions/workflow';
2121
import { updateTransition } from '../../actions/transition';
2222
import State from '../States/State';
2323
import Transition from '../Transitions/Transition';
@@ -34,28 +34,26 @@ const WorkflowSettings: React.FC = (props) => {
3434
const [activeTab, setActiveTab] = useState<React.Key>('workflow');
3535
const [payloadToSave, setPayloadToSave] = useState<any | null>(null);
3636

37+
useEffect(() => {
38+
if (workflowId) {
39+
dispatch(getWorkflow(workflowId));
40+
}
41+
}, [dispatch, workflowId]);
42+
3743
const {
38-
currentWorkflow,
39-
isLoadingWorkflow,
44+
workflow,
45+
isLoading,
4046
isSavingWorkflow,
4147
isSavingState,
4248
isSavingTransition,
4349
} = useSelector((state: GlobalRootState) => ({
44-
currentWorkflow: state.workflow.workflows.items.find(
45-
(w) => w.id === workflowId,
46-
),
47-
isLoadingWorkflow: state.workflow.workflows.loading,
50+
workflow: state.workflow.workflow.currentWorkflow,
51+
isLoading: state.workflow.workflow.loading,
4852
isSavingWorkflow: state.workflow.operation.loading,
4953
isSavingState: state.state.update.loading,
5054
isSavingTransition: state.transition.update.loading,
5155
}));
5256

53-
useEffect(() => {
54-
if (workflowId) {
55-
dispatch(getWorkflows());
56-
}
57-
}, [dispatch, workflowId]);
58-
5957
const handleDataChange = useCallback((payload: any | null) => {
6058
setPayloadToSave(payload);
6159
}, []);
@@ -80,16 +78,13 @@ const WorkflowSettings: React.FC = (props) => {
8078
const isSaving = isSavingWorkflow || isSavingState || isSavingTransition;
8179
const isSaveDisabled = !payloadToSave || isSaving;
8280

83-
if (isLoadingWorkflow && !currentWorkflow) {
81+
if (isLoading || !workflow || workflow.id !== workflowId) {
8482
return <ProgressCircle isIndeterminate aria-label="Loading workflow..." />;
8583
}
8684

8785
return (
8886
<View padding="size-400">
89-
<WorkflowHeader
90-
workflows={currentWorkflow ? [currentWorkflow] : []}
91-
selectedWorkflowId={workflowId}
92-
/>
87+
<WorkflowHeader workflow={workflow} />
9388
<Tabs
9489
aria-label="Workflow Settings"
9590
marginTop="size-300"
@@ -112,13 +107,15 @@ const WorkflowSettings: React.FC = (props) => {
112107
<Item key="states">
113108
<State
114109
workflowId={workflowId}
110+
workflow={workflow}
115111
onDataChange={handleDataChange}
116112
isDisabled={isSaving}
117113
/>
118114
</Item>
119115
<Item key="transitions">
120116
<Transition
121117
workflowId={workflowId}
118+
workflow={workflow}
122119
onDataChange={handleDataChange}
123120
isDisabled={isSaving}
124121
/>

frontend/packages/volto-workflow-manager/src/constants/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ export const UPDATE_WORKFLOW_SECURITY = 'UPDATE_WORKFLOW_SECURITY' as const;
77
export const ASSIGN_WORKFLOW = 'ASSIGN_WORKFLOW' as const;
88
export const VALIDATE_WORKFLOW = 'VALIDATE_WORKFLOW' as const;
99
export const CLEAR_VALIDATION = 'CLEAR_VALIDATION' as const;
10+
export const SELECT_WORKFLOW_ITEM = 'SELECT_WORKFLOW_ITEM' as const;
11+
export const CLEAR_WORKFLOW_SELECTION = 'CLEAR_WORKFLOW_SELECTION' as const;
1012
export const CLEAR_LAST_CREATED_WORKFLOW = 'CLEAR_LAST_CREATED_WORKFLOW';
1113

1214
export const LIST_STATES = 'LIST_STATES';

frontend/packages/volto-workflow-manager/src/reducers/workflow.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ import {
1010
VALIDATE_WORKFLOW,
1111
CLEAR_VALIDATION,
1212
CLEAR_LAST_CREATED_WORKFLOW,
13+
SELECT_WORKFLOW_ITEM,
14+
CLEAR_WORKFLOW_SELECTION,
1315
} from '../constants';
1416
import type { WorkflowReduxState } from '../types/workflow';
1517

@@ -37,6 +39,7 @@ const initialState: WorkflowReduxState = {
3739
result: null,
3840
},
3941
lastCreatedWorkflowId: null,
42+
selectedItem: null,
4043
};
4144

4245
export default function workflow(
@@ -351,6 +354,17 @@ export default function workflow(
351354
...state,
352355
lastCreatedWorkflowId: null,
353356
};
357+
case SELECT_WORKFLOW_ITEM:
358+
return {
359+
...state,
360+
selectedItem: action.payload,
361+
};
362+
363+
case CLEAR_WORKFLOW_SELECTION:
364+
return {
365+
...state,
366+
selectedItem: null,
367+
};
354368

355369
default:
356370
return state;

frontend/packages/volto-workflow-manager/src/types/graph.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
11
export interface WorkflowState {
22
id: string;
33
title: string;
4+
description?: string;
45
transitions: string[];
56
}
67

78
export interface WorkflowTransition {
89
id: string;
910
title: string;
11+
description?: string;
1012
new_state_id: string;
1113
}
1214

@@ -31,4 +33,5 @@ export interface EdgeData {
3133
[key: string]: unknown;
3234
label?: string;
3335
description?: string;
36+
transitionId?: string;
3437
}

0 commit comments

Comments
 (0)