feat(editor): live step status on the graph during runs

Step run events were previously visible only on the run tab.
Operators who triggered a run there and then switched to
the graph tab saw a static graph — the canvas had no idea
something was executing.

Wire the run events through the FlowEditorController so all
three tabs share the same status snapshot:

 - New StepRunStatus enum on the controller
   (idle / running / done / failed / awaiting).
 - controller.stepStatuses exposes the live map.
 - controller.updateStepStatus is called from the run tab's
   event handler — one source of truth, both views read it.
 - FlowCanvas drops its own stepStatuses parameter and
   pulls from the controller instead, so the canvas now
   shows the running pulse + done check + error cross + pause
   icon in each step's header live, in lockstep with the
   step list on the run tab.

When a fresh run starts (controller.running = true) the
status map is cleared so stale events from a previous run
don't paint the new one.

Signed-off-by: flemming-it <sf@flemming.it>
This commit is contained in:
flemming-it 2026-06-01 01:47:30 +02:00
parent e7cd9ca13c
commit 6b70ba65fd
4 changed files with 57 additions and 13 deletions

View file

@ -24,6 +24,12 @@ import 'model/auto_layout.dart';
import 'model/flow_graph.dart';
import 'model/layout_store.dart';
/// Mirrors `FlowNodeStatus` from the flow_node widget, but
/// lives in the controller so the run tab can update it
/// without importing widgets. The canvas adapts between
/// the two.
enum StepRunStatus { idle, running, done, failed, awaiting }
class FlowEditorController extends ChangeNotifier {
/// Active flow file name (without `.yaml`). `null` while
/// the editor is empty.
@ -64,6 +70,14 @@ class FlowEditorController extends ChangeNotifier {
bool get isRunning => _running;
bool _running = false;
/// Live per-step status for the in-flight or most-recent
/// run. The canvas pulls colours and icons out of this map
/// so the graph view shows real-time progress even when
/// the operator triggered the run from the run tab.
Map<String, StepRunStatus> get stepStatuses =>
Map.unmodifiable(_stepStatuses);
final Map<String, StepRunStatus> _stepStatuses = {};
/// Flag flipped during graph -> YAML emission so we don't
/// loop: the text change listener skips a reparse if it's
/// already mid-emit.
@ -121,6 +135,17 @@ class FlowEditorController extends ChangeNotifier {
set running(bool v) {
if (_running == v) return;
_running = v;
if (v) {
_stepStatuses.clear();
}
notifyListeners();
}
/// Update the live status of one step. Called by the run
/// tab as events arrive from the host's FlowRunDriver.
void updateStepStatus(String stepId, StepRunStatus status) {
if (_stepStatuses[stepId] == status) return;
_stepStatuses[stepId] = status;
notifyListeners();
}