Skip to content
This repository has been archived by the owner on Nov 27, 2023. It is now read-only.

Commit

Permalink
feat: Support editing steps from multiple flows
Browse files Browse the repository at this point in the history
  • Loading branch information
lordrip committed May 10, 2023
1 parent ed17316 commit 19e69cc
Show file tree
Hide file tree
Showing 4 changed files with 60 additions and 41 deletions.
60 changes: 31 additions & 29 deletions src/components/Visualization.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { useFlowsStore, useIntegrationJsonStore, useSettingsStore, useVisualizat
import { IStepProps, IVizStepNode } from '@kaoto/types';
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
import ReactFlow, { Background, Viewport } from 'reactflow';
import { shallow } from 'zustand/shallow';

const Visualization = () => {
// `nodes` is an array of UI-specific objects that represent
Expand All @@ -35,12 +36,13 @@ const Visualization = () => {
});

const useMultipleFlows = useSettingsStore((state) => state.settings.useMultipleFlows);
const flows = useFlowsStore((state) => state.flows);
const visualizationStore = useVisualizationStore.getState();
const { selectedStepUuid, setSelectedStepUuid } = useVisualizationStore(({ selectedStepUuid, setSelectedStepUuid }) => ({ selectedStepUuid, setSelectedStepUuid }), shallow);
const { onNodesChange, onEdgesChange } = useVisualizationStore(({ onNodesChange, onEdgesChange }) => ({ onNodesChange, onEdgesChange }), shallow);
const layout = useVisualizationStore((state) => state.layout);
const nodes = useVisualizationStore((state) => state.nodes);
const edges = useVisualizationStore((state) => state.edges);
const integrationJson = useIntegrationJsonStore((state) => state.integrationJson);
const flows = useFlowsStore((state) => state.flows);
const visualizationService = useMemo(() => new VisualizationService(), []);
const stepsService = useMemo(() => new StepsService(), []);

Expand All @@ -57,23 +59,35 @@ const Visualization = () => {
* This is usually caused because of code sync or changes through a step extension
*/
useEffect(() => {
if (!selectedStep.UUID) {
if (!selectedStepUuid) {
return;
}

const step = stepsService.findStepWithUUID(selectedStep.UUID);
const step = stepsService.findStepWithUUID(selectedStep.integrationId, selectedStepUuid);
if (step) {
setSelectedStep(step);
} else {
setSelectedStep({ maxBranches: 0, minBranches: 0, name: '', type: '', UUID: '', integrationId: '' });
visualizationStore.setSelectedStepUuid('');
setSelectedStepUuid('');
setIsPanelExpanded(false);
}
}, [integrationJson, flows, selectedStep.integrationId, selectedStepUuid, setSelectedStepUuid, stepsService]);

const handleDeleteStep = useCallback((UUID?: string) => {
if (!UUID) return;

if (selectedStepUuid === UUID) {
setIsPanelExpanded(false);
setSelectedStep({ maxBranches: 0, minBranches: 0, name: '', type: '', UUID: '', integrationId: '' });
setSelectedStepUuid('');
}
}, [integrationJson, selectedStep.UUID, stepsService]);

stepsService.deleteStep(UUID);
}, [selectedStepUuid, setSelectedStepUuid, stepsService]);

useEffect(() => {
visualizationService.redrawDiagram(handleDeleteStep, true).catch((e) => console.error(e));
}, [integrationJson, layout, useMultipleFlows, flows]);
}, [handleDeleteStep, integrationJson, flows, layout, useMultipleFlows, visualizationService]);

const nodeTypes = useMemo(() => ({ step: VisualizationStep }), []);
const edgeTypes = useMemo(
Expand All @@ -84,22 +98,10 @@ const Visualization = () => {
[]
);

const handleDeleteStep = (UUID?: string) => {
if (!UUID) return;

if (selectedStep.UUID === UUID) {
setIsPanelExpanded(false);
setSelectedStep({ maxBranches: 0, minBranches: 0, name: '', type: '', UUID: '', integrationId: '' });
visualizationStore.setSelectedStepUuid('');
}

stepsService.deleteStep(UUID);
};

const onClosePanelClick = useCallback(() => {
setIsPanelExpanded(false);
visualizationStore.setSelectedStepUuid('');
}, []);
setSelectedStepUuid('');
}, [setSelectedStepUuid]);

/**
* Called when a catalog step is dragged over the visualization canvas
Expand All @@ -125,10 +127,10 @@ const Visualization = () => {
if (!e.target.classList.contains('stepNode__clickable')) return;

if (!node.data.isPlaceholder) {
const step = stepsService.findStepWithUUID(node.data.step.UUID);
const step = stepsService.findStepWithUUID(node.data.step.integrationId, node.data.step.UUID);
if (step) {
setSelectedStep(step);
visualizationStore.setSelectedStepUuid(step.UUID);
setSelectedStepUuid(step.UUID);
}

/** If the details panel is collapsed, we expanded for the user */
Expand All @@ -137,13 +139,13 @@ const Visualization = () => {
/**
* If the details panel is already expanded and the step it's already
* selected, we collapse it for the user */
if (isPanelExpanded && selectedStep.UUID === node.data.step.UUID) {
if (isPanelExpanded && selectedStepUuid === node.data.step.UUID) {
setIsPanelExpanded(false);
visualizationStore.setSelectedStepUuid('');
setSelectedStepUuid('');
}
}
},
[isPanelExpanded, selectedStep.UUID, stepsService, visualizationStore]
[isPanelExpanded, selectedStepUuid, setSelectedStepUuid, stepsService]
);

/**
Expand Down Expand Up @@ -184,9 +186,9 @@ const Visualization = () => {
nodeTypes={nodeTypes}
onDragOver={onDragOver}
onNodeClick={onNodeClick}
onNodesChange={visualizationStore.onNodesChange}
onEdgesChange={visualizationStore.onEdgesChange}
snapToGrid={true}
onNodesChange={onNodesChange}
onEdgesChange={onEdgesChange}
snapToGrid
snapGrid={[15, 15]}
deleteKeyCode={null}
zoomOnDoubleClick={false}
Expand Down
33 changes: 23 additions & 10 deletions src/services/stepsService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import {
useFlowsStore,
useIntegrationJsonStore,
useNestedStepsStore,
useSettingsStore,
useVisualizationStore,
} from '@kaoto/store';
import {
Expand Down Expand Up @@ -259,12 +260,14 @@ export class StepsService {
* `UUID` is originally set using the Step UUID.
* @param UUID
*/
findStepWithUUID(UUID: string): IStepProps | null {
const flatSteps = StepsService.flattenSteps(
useIntegrationJsonStore.getState().integrationJson.steps
);
const stepIdx = flatSteps.map((s: IStepProps) => s.UUID).indexOf(UUID);
return stepIdx !== -1 ? flatSteps[stepIdx] : null;
findStepWithUUID(integrationId: string, UUID: string): IStepProps | undefined {
const integration = this.getIntegration(integrationId);
if (integration === undefined) {
return undefined;
}

const flatSteps = StepsService.flattenSteps(integration.steps);
return flatSteps.find((step) => UUID === step.UUID);
}

/**
Expand Down Expand Up @@ -323,7 +326,10 @@ export class StepsService {
newStep.UUID = selectedStep.UUID;
const currentStepNested = this.getStepNested(currentStep.UUID);
if (currentStepNested) {
const stepsCopy = useIntegrationJsonStore.getState().integrationJson.steps.slice();
const integration = this.getIntegration(currentStep.integrationId);
if (integration === undefined) return;

const stepsCopy = integration?.steps.slice();
let newParentStep = getDeepValue(stepsCopy, currentStepNested.pathToParentStep);
const newBranch = newParentStep.branches[currentStepNested.branchIndex];
newParentStep.branches[currentStepNested.branchIndex].steps = [...newBranch.steps, newStep];
Expand Down Expand Up @@ -429,7 +435,11 @@ export class StepsService {
}

getIntegration(integrationId: string): IIntegration | undefined {
return useFlowsStore.getState().flows.find((integration) => integration.id === integrationId);
if (useSettingsStore.getState().settings.useMultipleFlows) {
return useFlowsStore.getState().flows.find((integration) => integration.id === integrationId);
}

return useIntegrationJsonStore.getState().integrationJson;
}

/**
Expand Down Expand Up @@ -622,8 +632,11 @@ export class StepsService {
* Submits current integration steps to the backend and updates with received views.
*/
async updateViews() {
fetchViews(useIntegrationJsonStore.getState().integrationJson.steps).then((views) => {
useIntegrationJsonStore.getState().updateViews(views);
fetchViews(useIntegrationJsonStore.getState().integrationJson.steps).then((views: IViewProps[]) => {
if (Array.isArray(views)) {
useIntegrationJsonStore.getState().updateViews(views);
useFlowsStore.getState().updateViews(views);
}
});
}

Expand Down
4 changes: 4 additions & 0 deletions src/store/flowsStore.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ export interface IFlowsStore {
insertStep: IInsertOptions;
deleteStep: (integrationId: string, stepUUID: string) => void;
deleteAllIntegrations: () => void;
updateViews: (views: IViewProps[]) => void;
}

export const flowsInitialState: Pick<IFlowsStore, 'flows' | 'properties' | 'views'> = {
Expand Down Expand Up @@ -113,6 +114,9 @@ export const useFlowsStore = create<IFlowsStore>()(
});
},
deleteAllIntegrations: () => set((state) => ({ ...state, ...flowsInitialState })),
updateViews: (views: IViewProps[]) => {
set({ views });
},
}),
{
partialize: (state) => {
Expand Down
4 changes: 2 additions & 2 deletions src/store/integrationJsonStore.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -167,8 +167,8 @@ export const useIntegrationJsonStore = create<IIntegrationJsonStore>()(

return set({ integrationJson: { ...newIntegration, steps: uuidSteps } });
},
updateViews: (viewData: IViewProps[]) => {
set({ views: viewData });
updateViews: (views: IViewProps[]) => {
set({ views });
},
}),
{
Expand Down

0 comments on commit 19e69cc

Please sign in to comment.