feat: The Big One UI #47
@@ -4,7 +4,7 @@ import {
|
|||||||
Panel,
|
Panel,
|
||||||
ReactFlow,
|
ReactFlow,
|
||||||
ReactFlowProvider,
|
ReactFlowProvider,
|
||||||
MarkerType,
|
MarkerType, getOutgoers
|
||||||
} from '@xyflow/react';
|
} from '@xyflow/react';
|
||||||
import '@xyflow/react/dist/style.css';
|
import '@xyflow/react/dist/style.css';
|
||||||
import {type CSSProperties, useEffect, useState} from "react";
|
import {type CSSProperties, useEffect, useState} from "react";
|
||||||
@@ -12,6 +12,7 @@ import {useShallow} from 'zustand/react/shallow';
|
|||||||
import orderPhaseNodeArray from "../../utils/orderPhaseNodes.ts";
|
import orderPhaseNodeArray from "../../utils/orderPhaseNodes.ts";
|
||||||
import useProgramStore from "../../utils/programStore.ts";
|
import useProgramStore from "../../utils/programStore.ts";
|
||||||
import {DndToolbar} from './visualProgrammingUI/components/DragDropSidebar.tsx';
|
import {DndToolbar} from './visualProgrammingUI/components/DragDropSidebar.tsx';
|
||||||
|
import {type EditorWarning, globalWarning} from "./visualProgrammingUI/components/EditorWarnings.tsx";
|
||||||
import {WarningsSidebar} from "./visualProgrammingUI/components/WarningSidebar.tsx";
|
import {WarningsSidebar} from "./visualProgrammingUI/components/WarningSidebar.tsx";
|
||||||
import type {PhaseNode} from "./visualProgrammingUI/nodes/PhaseNode.tsx";
|
import type {PhaseNode} from "./visualProgrammingUI/nodes/PhaseNode.tsx";
|
||||||
import useFlowStore from './visualProgrammingUI/VisProgStores.tsx';
|
import useFlowStore from './visualProgrammingUI/VisProgStores.tsx';
|
||||||
@@ -90,6 +91,26 @@ const VisProgUI = () => {
|
|||||||
window.addEventListener('keydown', handler);
|
window.addEventListener('keydown', handler);
|
||||||
return () => window.removeEventListener('keydown', handler);
|
return () => window.removeEventListener('keydown', handler);
|
||||||
});
|
});
|
||||||
|
const {unregisterWarning, registerWarning} = useFlowStore();
|
||||||
|
useEffect(() => {
|
||||||
|
|
||||||
|
if (checkPhaseChain()) {
|
||||||
|
unregisterWarning(globalWarning,'INCOMPLETE_PROGRAM');
|
||||||
|
} else {
|
||||||
|
// create global warning for incomplete program chain
|
||||||
|
const incompleteProgramWarning : EditorWarning = {
|
||||||
|
scope: {
|
||||||
|
id: globalWarning,
|
||||||
|
handleId: undefined
|
||||||
|
},
|
||||||
|
type: 'INCOMPLETE_PROGRAM',
|
||||||
|
severity: "ERROR",
|
||||||
|
description: "there is no complete phase chain from the startNode to the EndNode"
|
||||||
|
}
|
||||||
|
|
||||||
|
registerWarning(incompleteProgramWarning);
|
||||||
|
}
|
||||||
|
},[edges, registerWarning, unregisterWarning])
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -184,6 +205,24 @@ function graphReducer() {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const checkPhaseChain = (): boolean => {
|
||||||
|
const {nodes, edges} = useFlowStore.getState();
|
||||||
|
|
||||||
|
function checkForCompleteChain(currentNodeId: string): boolean {
|
||||||
|
const outgoingPhases = getOutgoers({id: currentNodeId}, nodes, edges)
|
||||||
|
.filter(node => ["end", "phase"].includes(node.type!));
|
||||||
|
|
||||||
|
if (outgoingPhases.length === 0) return false;
|
||||||
|
if (outgoingPhases.some(node => node.type === "end" )) return true;
|
||||||
|
|
||||||
|
const next = outgoingPhases.map(node => checkForCompleteChain(node.id))
|
||||||
|
.find(result => result);
|
||||||
|
console.log(next);
|
||||||
|
return !!next;
|
||||||
|
}
|
||||||
|
|
||||||
|
return checkForCompleteChain('start');
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ function createNode(id: string, type: string, position: XYPosition, data: Record
|
|||||||
const endNode = createNode('end', 'end', {x: 590, y: 100}, {label: "End"}, false)
|
const endNode = createNode('end', 'end', {x: 590, y: 100}, {label: "End"}, false)
|
||||||
const initialPhaseNode = createNode(crypto.randomUUID(), 'phase', {x:235, y:100}, {label: "Phase 1", children : [], isFirstPhase: false, nextPhaseId: null})
|
const initialPhaseNode = createNode(crypto.randomUUID(), 'phase', {x:235, y:100}, {label: "Phase 1", children : [], isFirstPhase: false, nextPhaseId: null})
|
||||||
|
|
||||||
const initialNodes : Node[] = [startNode, endNode, initialPhaseNode,];
|
const initialNodes : Node[] = [startNode, endNode, initialPhaseNode];
|
||||||
|
|
||||||
// Initial edges, leave empty as setting initial edges...
|
// Initial edges, leave empty as setting initial edges...
|
||||||
// ...breaks logic that is dependent on connection events
|
// ...breaks logic that is dependent on connection events
|
||||||
@@ -312,4 +312,7 @@ const useFlowStore = create<FlowState>(UndoRedo((set, get) => ({
|
|||||||
}))
|
}))
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
export default useFlowStore;
|
export default useFlowStore;
|
||||||
|
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ export type WarningType =
|
|||||||
| 'MISSING_INPUT'
|
| 'MISSING_INPUT'
|
||||||
| 'MISSING_OUTPUT'
|
| 'MISSING_OUTPUT'
|
||||||
| 'PLAN_IS_UNDEFINED'
|
| 'PLAN_IS_UNDEFINED'
|
||||||
|
| 'INCOMPLETE_PROGRAM'
|
||||||
| string
|
| string
|
||||||
|
|
||||||
export type WarningSeverity =
|
export type WarningSeverity =
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import {useEffect} from "react";
|
|||||||
import { Toolbar } from '../components/NodeComponents';
|
import { Toolbar } from '../components/NodeComponents';
|
||||||
import styles from '../../VisProg.module.css';
|
import styles from '../../VisProg.module.css';
|
||||||
import {SingleConnectionHandle} from "../components/RuleBasedHandle.tsx";
|
import {SingleConnectionHandle} from "../components/RuleBasedHandle.tsx";
|
||||||
import type {EditorWarning} from "../components/EditorWarnings.tsx";
|
import {type EditorWarning} from "../components/EditorWarnings.tsx";
|
||||||
import {allowOnlyConnectionsFromHandle} from "../HandleRules.ts";
|
import {allowOnlyConnectionsFromHandle} from "../HandleRules.ts";
|
||||||
import useFlowStore from "../VisProgStores.tsx";
|
import useFlowStore from "../VisProgStores.tsx";
|
||||||
|
|
||||||
@@ -49,8 +49,6 @@ export default function StartNode(props: NodeProps<StartNode>) {
|
|||||||
else { unregisterWarning(props.id, `${noConnectionWarning.type}:source`); }
|
else { unregisterWarning(props.id, `${noConnectionWarning.type}:source`); }
|
||||||
}, [connections.length, props.id, registerWarning, unregisterWarning]);
|
}, [connections.length, props.id, registerWarning, unregisterWarning]);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Toolbar nodeId={props.id} allowDelete={false}/>
|
<Toolbar nodeId={props.id} allowDelete={false}/>
|
||||||
|
|||||||
Reference in New Issue
Block a user