mengw15 commented on code in PR #8441:
URL: https://github.com/apache/texera/pull/8441#discussion_r3960964082


##########
frontend/src/app/workspace/component/workflow-form/workflow-form.component.ts:
##########
@@ -376,11 +450,61 @@ export class WorkflowFormComponent implements OnInit, 
OnDestroy {
     this.parameters = this.formBindingService.resolveFields();
     this.instructionTitle = config.instruction?.title ?? "";
     this.instructionBody = config.instruction?.body ?? "";
+    this.refreshShownResults();
     // A reader always sees the instruction as rendered markdown.
     void this.renderInstruction();
     this.buildForm();
   }
 
+  /**
+   * Decide which operators' result cards to show. The engine materializes a 
result for every terminal
+   * operator (no enabled downstream) as well as every view-result operator, 
so a terminal's result is
+   * always available; the form shows terminals by default and layers the 
author's chosen view-result
+   * steps on top. This is a pure display filter that reads the graph and 
never writes it, so a normal
+   * canvas user's result-viewing is unaffected. A step that is neither viewed 
nor terminal (or was
+   * deleted) drops out rather than rendering a stale card.
+   */
+  private refreshShownResults(): void {
+    const graph = this.workflowActionService.getTexeraGraph();
+    const viewed = graph.getOperatorsToViewResult();
+    // A result exists for an operator that is view-result (the eye) or 
terminal (no enabled
+    // downstream); the engine materializes both (WorkflowCompiler stores 
terminal operators plus
+    // opsToViewResult). A view-result id is always a live operator; a 
terminal id comes from
+    // terminalOperatorIds (live, enabled operators only), so both branches 
reference real steps.
+    const terminals = new Set(this.terminalOperatorIds());
+    const availableOnCanvas = (id: string): boolean => viewed.has(id) || 
terminals.has(id);
+    const chosen = this.formBindingService.getConfig().resultOperatorIds;
+    // The terminal (final) operator's result always shows -- the engine 
always materializes it, so it
+    // cannot be turned off. resultOperatorIds adds extra intermediate 
(view-result) steps on top. The
+    // downstream hasNonEmptyResult filter drops steps that produced no data.
+    this.shownResultIds = [...new Set([...terminals, 
...chosen])].filter(availableOnCanvas);
+  }
+
+  /** The workflow's terminal operators: enabled operators with no enabled 
downstream link. Matches the
+   *  backend's storage rule (WorkflowCompiler treats out-degree-0 operators 
of the enabled plan as
+   *  terminal and always materializes them), so a disabled link or operator 
does not mislead this. */
+  private terminalOperatorIds(): string[] {
+    const graph = this.workflowActionService.getTexeraGraph();
+    const hasEnabledDownstream = new Set(graph.getAllEnabledLinks().map(link 
=> link.source.operatorID));
+    return graph
+      .getAllOperators()
+      .filter(op => !(op.isDisabled ?? false) && 
!hasEnabledDownstream.has(op.operatorID))
+      .map(op => op.operatorID);
+  }
+
+  /** Terminal = a live, enabled operator with no enabled downstream link. */
+  private isTerminalOperator(operatorID: string): boolean {

Review Comment:
   These two (`isTerminalOperator` / `hasEnabledDownstream`) have no callers — 
`refreshShownResults` uses the batch `terminalOperatorIds()`, and nothing else 
(tests included) reaches them. Worth dropping them rather than keeping a second 
copy of the terminal rule that can drift from the one in use.



##########
frontend/src/app/workspace/component/workflow-form/workflow-form.component.ts:
##########
@@ -376,11 +450,61 @@ export class WorkflowFormComponent implements OnInit, 
OnDestroy {
     this.parameters = this.formBindingService.resolveFields();
     this.instructionTitle = config.instruction?.title ?? "";
     this.instructionBody = config.instruction?.body ?? "";
+    this.refreshShownResults();
     // A reader always sees the instruction as rendered markdown.
     void this.renderInstruction();
     this.buildForm();
   }
 
+  /**
+   * Decide which operators' result cards to show. The engine materializes a 
result for every terminal
+   * operator (no enabled downstream) as well as every view-result operator, 
so a terminal's result is
+   * always available; the form shows terminals by default and layers the 
author's chosen view-result
+   * steps on top. This is a pure display filter that reads the graph and 
never writes it, so a normal
+   * canvas user's result-viewing is unaffected. A step that is neither viewed 
nor terminal (or was
+   * deleted) drops out rather than rendering a stale card.
+   */
+  private refreshShownResults(): void {
+    const graph = this.workflowActionService.getTexeraGraph();
+    const viewed = graph.getOperatorsToViewResult();
+    // A result exists for an operator that is view-result (the eye) or 
terminal (no enabled
+    // downstream); the engine materializes both (WorkflowCompiler stores 
terminal operators plus
+    // opsToViewResult). A view-result id is always a live operator; a 
terminal id comes from
+    // terminalOperatorIds (live, enabled operators only), so both branches 
reference real steps.
+    const terminals = new Set(this.terminalOperatorIds());

Review Comment:
   One note on the triggers, not blocking: terminal-ness is derived from links, 
but none of the three refresh triggers fires on a link edit — a co-editor 
wiring a downstream link onto a shown terminal leaves its card up until the 
next trigger. That said, the lingering card is semantically sound — the last 
run's result still exists and that is what the card shows — and the next run 
corrects the set. So fine to leave as is (or fold into #8439); flagging mainly 
so the trigger gap is a known choice rather than an accident.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to