diff --git a/src/lib/data/workflow.mts b/src/lib/data/workflow.mts index 58a2f77..042bdbd 100644 --- a/src/lib/data/workflow.mts +++ b/src/lib/data/workflow.mts @@ -8,7 +8,7 @@ import {JsonProp, Serialisable} from '../decorators/to-json.mjs'; import type {ReadonlyBehaviorSubject} from '../registries/workflow-registry.mjs'; import {WorkflowStep} from './workflow-step.mjs'; -type Init = Partial>; +type Init = Partial>; export interface WorkflowJson extends Pick { steps: CompressedJsonArray; @@ -33,12 +33,16 @@ export class Workflow { @JsonProp() public name: string; + @JsonProp() + public rm: boolean; + public readonly steps$: ReadonlyBehaviorSubject; private readonly _steps$: BehaviorSubject; - public constructor({name, steps}: Init = {}) { + public constructor({name, rm, steps}: Init = {}) { this.name = name ?? ''; + this.rm = rm ?? false; this.steps$ = this._steps$ = new BehaviorSubject(steps?.length ? steps : [new WorkflowStep()]); } diff --git a/src/lib/execution/workflow-execution.mts b/src/lib/execution/workflow-execution.mts index 01f5934..684faaf 100644 --- a/src/lib/execution/workflow-execution.mts +++ b/src/lib/execution/workflow-execution.mts @@ -28,6 +28,7 @@ import type {WorkflowStep} from '../data/workflow-step.mjs'; import type {Workflow} from '../data/workflow.mjs'; import AutoIncrement from '../decorators/auto-increment.mjs'; import PersistClassName from '../decorators/PersistClassName.mjs'; +import WorkflowRegistry from '../registries/workflow-registry.mjs'; import {debugLog, errorLog} from '../util/log.mjs'; import prependErrorWith from '../util/rxjs/prepend-error-with.mjs'; import ShareReplayLike from '../util/share-replay-like-observable.mjs'; @@ -176,7 +177,11 @@ export class WorkflowExecution extends ShareReplayLike { } } - this.patchOnInitEventsOnEnd(); + if (this.workflow.rm) { + WorkflowRegistry.inst.rmByListId(this.workflow.listId); + } else { + this.patchOnInitEventsOnEnd(); + } } /** diff --git a/src/lib/registries/workflow-registry.mts b/src/lib/registries/workflow-registry.mts index 775bf2e..bc08755 100644 --- a/src/lib/registries/workflow-registry.mts +++ b/src/lib/registries/workflow-registry.mts @@ -118,6 +118,11 @@ export default class WorkflowRegistry { this._workflows$.next(out); } + public rmByListId(listId: number): void { + const idx = this.workflows.findIndex(w => w.listId === listId); + this.rmByIdx(idx); + } + /** Save the workflows to mod storage */ public save(): void { store(this.workflows); diff --git a/src/ui/components/workflow-editor/header-block.tsx b/src/ui/components/workflow-editor/header-block.tsx index ca13b53..26b9190 100644 --- a/src/ui/components/workflow-editor/header-block.tsx +++ b/src/ui/components/workflow-editor/header-block.tsx @@ -1,3 +1,4 @@ +import type {Signal} from '@preact/signals'; import {useSignal} from '@preact/signals'; import {memo} from 'preact/compat'; import {useCallback} from 'preact/hooks'; @@ -12,48 +13,79 @@ export interface WorkflowEditorHeaderBlockProps { onSave(e: Event): void; } -const WorkflowEditorHeaderBlock = memo(({ - children, - onSave, -}) => { +const WorkflowEditorHeaderBlock = memo(({children, onSave}) => ( +
+ + + + +
+ {children} + {'Save'} +
+
+
+)); +WorkflowEditorHeaderBlock.displayName = 'WorkflowEditorHeaderBlock'; + +export default WorkflowEditorHeaderBlock; + +const WorkflowNameEditor = memo(function WorkflowNameEditor() { + const [touched$, onBlur] = useTouched(); const workflow$ = useWorkflow(); - const inpTouched = useSignal(false); const reRender = useReRender(); - const onBlur = useCallback(() => { - inpTouched.value = true; - }, EMPTY_ARR); const onChange = useCallback((e: Event): void => { workflow$.peek().name = (e.target as HTMLInputElement).value; reRender(); }, [workflow$]); - const workflow = workflow$.value; + const name = workflow$.value.name; return ( -
- -
- {'Workflow name'} -
- -
-
- -
- {children} - {'Save'} -
-
+
+ {'Workflow name'} +
+ +
); }); -WorkflowEditorHeaderBlock.displayName = 'WorkflowEditorHeaderBlock'; -export default WorkflowEditorHeaderBlock; +const WorkflowRemovableEditor = memo(function WorkflowRemovableEditor() { + const workflow$ = useWorkflow(); + const reRender = useReRender(); + + const onChange = useCallback((e: Event): void => { + workflow$.peek().rm = (e.target as HTMLInputElement).checked; + reRender(); + }, [workflow$]); + + return ( +
+ +
+ ); +}); + +function useTouched(): [Signal, () => void] { + const touched$ = useSignal(false); + const onBlur = useCallback(() => { + touched$.value = true; + }, EMPTY_ARR); + + return [touched$, onBlur]; +} diff --git a/src/ui/pages/workflows-dashboard.tsx b/src/ui/pages/workflows-dashboard.tsx index f44a84b..f1bb1bd 100644 --- a/src/ui/pages/workflows-dashboard.tsx +++ b/src/ui/pages/workflows-dashboard.tsx @@ -63,6 +63,19 @@ export default function WorkflowsDashboard(): VNode { ); } +function useWorkflowRemovalCorrector( + workflows: Workflow[], + activeWorkflow$: Signal +): void { + const activeId = activeWorkflow$.value?.listId; + + useEffect(() => { + if (activeId !== undefined && !workflows.some(wf => wf.listId === activeId)) { + activeWorkflow$.value = undefined; + } + }, [activeId, workflows]); +} + interface EditorProps { workflows: Workflow[]; } @@ -89,6 +102,8 @@ function DashboardShell({workflows}: EditorProps): VNode { }; }); + useWorkflowRemovalCorrector(workflows, activeWorkflow); + return (