diff --git a/src/pages/VisProgPage/visualProgrammingUI/EditorWarnings.tsx b/src/pages/VisProgPage/visualProgrammingUI/EditorWarnings.tsx index 554cc2c..2ff7397 100644 --- a/src/pages/VisProgPage/visualProgrammingUI/EditorWarnings.tsx +++ b/src/pages/VisProgPage/visualProgrammingUI/EditorWarnings.tsx @@ -1,25 +1,43 @@ - +/* contains all logic for the VisProgEditor warning system +* +* Missing but desirable features: +* - Global Warnings, e.g. not node specific +* - could be done by creating a global scope entry with GLOBAL as nodeId +* - Warning filtering: +* - if there is no completely connected chain of startNode-[PhaseNodes]-EndNode +* then hide any startNode, phaseNode, or endNode specific warnings +* */ // --| Type definitions |-- import type {FlowState} from "./VisProgTypes.tsx"; + +export type WarningId = NodeId | "GLOBAL_WARNINGS"; export type NodeId = string; + + export type WarningType = | 'MISSING_INPUT' | 'MISSING_OUTPUT' + | 'PLAN_IS_UNDEFINED' | string -export type WarningSeverity = - | 'INFO' // Acceptable, but probably not desirable - | 'WARNING' // Prevents running program, should be fixed before running program is allowed +export type WarningSeverity = + | 'INFO' // Acceptable, but important to be aware of + | 'WARNING' // Acceptable, but probably undesirable behavior + | 'ERROR' // Prevents running program, should be fixed before running program is allowed + +export type WarningScope = { + id: string; + handleId?: string; +} export type EditorWarning = { - nodeId: NodeId; + scope: WarningScope; type: WarningType; severity: WarningSeverity; description: string; - handleId?: string; }; /** @@ -28,8 +46,9 @@ export type EditorWarning = { */ export type WarningKey = { type: WarningType, handleId: string | null }; // for warnings that can occur on a per-handle basis -export type WarningRegistry = Map>; -export type SeverityIndex = Map>; + +export type WarningRegistry = Map>; +export type SeverityIndex = Map>; type ZustandSet = (partial: Partial | ((state: FlowState) => Partial)) => void; type ZustandGet = () => FlowState; @@ -58,35 +77,37 @@ export type EditorWarningRegistry = { * unregisters a warning from the warningRegistry and the SeverityIndex * @param {EditorWarning} warning */ - unregisterWarning: (nodeId: NodeId, warningKey: WarningKey) => void + unregisterWarning: (id: WarningId, warningKey: WarningKey) => void /** * unregisters warnings from the warningRegistry and the SeverityIndex * @param {EditorWarning} warning */ - unregisterWarningsForNode: (nodeId: string) => void; + unregisterWarningsForId: (id: WarningId) => void; } // --| implemented logic |-- -export function editorWarningRegistry(get: ZustandGet, set: ZustandSet) : EditorWarningRegistry {return { +export const globalWarningKey = (type: WarningType) : WarningKey => { return {type: type, handleId: null}}; +export const globalWarning = "GLOBAL_WARNINGS"; + + +export function editorWarningRegistry(get: ZustandGet, set: ZustandSet) : EditorWarningRegistry { return { editorWarningRegistry: new Map>(), severityIndex: new Map([ - ['INFO', new Set<{ nodeId: NodeId, warningKey: WarningKey}>()], - ['WARNING', new Set<{ nodeId: NodeId, warningKey: WarningKey}>()] + ['INFO', new Set<{ id: WarningId, warningKey: WarningKey}>()], + ['WARNING', new Set<{ id: WarningId, warningKey: WarningKey}>()] ]), getWarningsBySeverity: (warningSeverity) => { const wRegistry = get().editorWarningRegistry; const sIndex = get().severityIndex; - const warningKeys = sIndex.get(warningSeverity); - const warnings: EditorWarning[] = []; warningKeys?.forEach( - ({nodeId, warningKey}) => { - const warning = wRegistry.get(nodeId)?.get(warningKey); + ({id, warningKey}) => { + const warning = wRegistry.get(id)?.get(warningKey); if (warning) { warnings.push(warning); @@ -97,24 +118,29 @@ export function editorWarningRegistry(get: ZustandGet, set: ZustandSet) : Editor return warnings; }, - isProgramValid: () => { return true}, + isProgramValid: () => { + const sIndex = get().severityIndex; + return sIndex.get("ERROR")!.size === 0; + }, + + getWarnings: () => Array.from(get().editorWarningRegistry.values()) + .flatMap(innerMap => Array.from(innerMap.values())), - getWarnings: () => { return []}, registerWarning: (warning) => { - const { nodeId, type, severity, handleId } = warning; + const { scope: {id, handleId}, type, severity } = warning; const warningKey = handleId ? { type, handleId } : { type, handleId: null}; const wRegistry = get().editorWarningRegistry; const sIndex = get().severityIndex; - // add to registry - if (!wRegistry.has(nodeId)) { - wRegistry.set(nodeId, new Map()); + // add to warning registry + if (!wRegistry.has(id)) { + wRegistry.set(id, new Map()); } - wRegistry.get(nodeId)!.set(warningKey, warning); + wRegistry.get(id)!.set(warningKey, warning); // add to severityIndex - sIndex.get(severity)!.add({nodeId,warningKey}); + sIndex.get(severity)!.add({id,warningKey}); set({ editorWarningRegistry: wRegistry, @@ -122,18 +148,18 @@ export function editorWarningRegistry(get: ZustandGet, set: ZustandSet) : Editor }) }, - unregisterWarning: (nodeId, warningKey) => { + unregisterWarning: (id, warningKey) => { const wRegistry = get().editorWarningRegistry; const sIndex = get().severityIndex; - const warning = wRegistry.get(nodeId)!.get(warningKey); - // remove from registry - wRegistry.get(nodeId)!.delete(warningKey); + const warning = wRegistry.get(id)!.get(warningKey); + // remove from warning registry + wRegistry.get(id)!.delete(warningKey); // remove from severityIndex - sIndex.get(warning!.severity)!.delete({nodeId,warningKey}); + sIndex.get(warning!.severity)!.delete({id,warningKey}); set({ editorWarningRegistry: wRegistry, @@ -141,21 +167,21 @@ export function editorWarningRegistry(get: ZustandGet, set: ZustandSet) : Editor }) }, - unregisterWarningsForNode: (nodeId) => { + unregisterWarningsForId: (id) => { const wRegistry = get().editorWarningRegistry; const sIndex = get().severityIndex; - const nodeWarnings = wRegistry.get(nodeId); + const nodeWarnings = wRegistry.get(id); // remove from severity index if (nodeWarnings) { nodeWarnings.forEach((warning, warningKey) => { - sIndex.get(warning.severity)?.delete({nodeId, warningKey}); + sIndex.get(warning.severity)?.delete({id, warningKey}); }); } - // remove from registry - wRegistry.delete(nodeId); + // remove from warning registry + wRegistry.delete(id); set({ editorWarningRegistry: wRegistry,