yangzhang75 commented on code in PR #8456:
URL: https://github.com/apache/texera/pull/8456#discussion_r3991637138


##########
frontend/src/app/dashboard/component/user/list-item/list-item.component.html:
##########
@@ -194,6 +195,17 @@
         nz-icon
         nzType="eye"></i>
     </button>
+    <button
+      *ngIf="entry.type==='workflow' && config.env.formViewEnabled"
+      nz-button
+      nzType="text"
+      [title]="defaultsToForm ? 'Open on the canvas by default' : 'Open in the 
Form View by default'"
+      [class.defaults-to-form-on]="defaultsToForm"
+      (click)="onToggleDefaultView()">

Review Comment:
   Right, the endpoint needs WRITE. Fixed in 379293fe7: the toggle (row and 
card) is gated on `entry.accessLevel === 'WRITE'`, with a DOM test for both 
access levels.



##########
frontend/src/app/dashboard/component/user/list-item/list-item.component.ts:
##########
@@ -163,6 +174,46 @@ export class ListItemComponent implements OnChanges {
     }
   }
 
+  /**
+   * A workflow opens in its default view. A form-default one is marked with 
the Form View icon
+   * and its owner's card deep-links straight into the form; the operator 
canvas is still one
+   * click away from there. A canvas-default one is left as the descriptor set 
it. Hub links are
+   * untouched; only the owner's own entry point moves.
+   */
+  private applyDefaultView(): void {
+    if (this.entry.type !== "workflow" || !this.config.env.formViewEnabled) {
+      return;
+    }
+    this.defaultsToForm = this.entry.workflow?.workflow?.defaultView === 
DefaultView.FORM;
+    if (this.defaultsToForm) {
+      this.iconType = "solution";
+    }
+    if (this.entryLink[0] === USER_WORKSPACE) {
+      this.entryLink = this.defaultsToForm
+        ? [USER_WORKSPACE, String(this.entry.id), "form"]
+        : [USER_WORKSPACE, String(this.entry.id)];
+    }
+  }
+
+  public onToggleDefaultView(): void {
+    const next = this.defaultsToForm ? DefaultView.CANVAS : DefaultView.FORM;
+    this.workflowPersistService
+      .setDefaultView(this.entry.id as number, next)

Review Comment:
   Fixed in 379293fe7: the card now follows the same rule as the row through a 
shared `default-view-landing.ts` (Form View icon, deep link, WRITE-only 
toggle), and the row's default-view tests are mirrored on the card.



##########
frontend/src/app/workspace/component/menu/menu.component.scss:
##########
@@ -210,8 +211,63 @@ texera-coeditor-user-icon {
   }
 }
 
-.jupyter-notebook-icon {
-  height: 1.1em;
-  width: auto;
-  vertical-align: -0.2em;
+/* One workflow, two ways of working on it. Rendered identically in the 
operator canvas

Review Comment:
   Fixed in 379293fe7: the `.jupyter-notebook-icon` sizing rule is back; the 
view switch styles are added below it instead of replacing it.



##########
frontend/src/app/workspace/component/menu/menu.component.ts:
##########
@@ -622,6 +622,24 @@ export class MenuComponent implements OnInit, OnDestroy {
     saveAs(new Blob([workflowContentJson], { type: "text/plain;charset=utf-8" 
}), fileName);
   }
 
+  /**
+   * Open the Form View -- a full page load, not a route: the two views share 
root-level
+   * singletons (graph, Yjs shared model), and routing left the old 
collaboration client
+   * alive (you appeared as your own coeditor). A fresh document is the clean 
handover.
+   */
+  public onClickOpenFormView(): void {
+    const wid = this.workflowActionService.getWorkflowMetadata().wid;
+    if (wid !== undefined) {
+      // Persist before the full-page nav, matching the form's 
openRegularCanvas (which saves
+      // first). The workspace's beforeunload handler also persists, but 
saving here shrinks the
+      // race between an unsaved debounced edit and the unload so the other 
view opens up to date.
+      this.persistWorkflow();
+      /* v8 ignore start -- full-document navigation; jsdom cannot navigate */
+      window.location.href = `${USER_WORKSPACE}/${wid}/form`;

Review Comment:
   Fixed in 379293fe7: the switch now navigates in the persist's `complete` and 
stays on the canvas with the error shown when the save fails (tests for both). 
The form's own switch does the same in #8455.



##########
frontend/src/app/workspace/component/power-button/computing-unit-selection.component.ts:
##########
@@ -294,9 +300,53 @@ export class ComputingUnitSelectionComponent implements 
OnInit {
   selectComputingUnit(wid: number | undefined, cuid: number | undefined): void 
{
     if (isDefined(cuid) && wid !== DEFAULT_WORKFLOW.wid) {
       this.computingUnitStatusService.selectComputingUnit(wid, cuid);
+      this.rememberComputingUnit(wid, cuid);
     }
   }
 
+  /**
+   * The live selection lives only in ComputingUnitStatusService, re-derived 
on load from the
+   * last execution -- but that only exists once the workflow has run (pick a 
unit, reload
+   * before running, and it is gone). Canvas<->Form View switches reload, so 
we remember the
+   * last explicit choice per workflow to keep the two views agreeing. One 
unit per workflow.
+   */
+  private static computingUnitStorageKey(wid: number): string {
+    return `computing-unit-of-workflow-${wid}`;
+  }
+
+  private rememberComputingUnit(wid: number | undefined, cuid: number): void {
+    if (!isDefined(wid)) {
+      return;
+    }
+    try {
+      
localStorage.setItem(ComputingUnitSelectionComponent.computingUnitStorageKey(wid),
 String(cuid));
+    } catch {
+      // Private browsing or a full quota; remembering is an optimisation, not 
a
+      // requirement -- the last-execution lookup still applies on the next 
load.
+    }
+  }
+
+  private recallComputingUnit(wid: number): number | undefined {
+    let stored: string | null = null;
+    try {
+      stored = 
localStorage.getItem(ComputingUnitSelectionComponent.computingUnitStorageKey(wid));
+    } catch {
+      return undefined;
+    }
+    // A cuid is a positive integer. Number() would also accept "0" and "1.5", 
and handing
+    // either on would mean chasing a unit that cannot exist.
+    const cuid = Number(stored);
+    if (!stored || !Number.isInteger(cuid) || cuid <= 0) {
+      return undefined;
+    }
+    // A remembered unit that has since been terminated must not win over the 
fallbacks,
+    // but an empty list means the units have not arrived yet rather than that 
it is gone.
+    if (this.allComputingUnits.length > 0 && !this.allComputingUnits.some(u => 
u.computingUnit.cuid === cuid)) {
+      return undefined;

Review Comment:
   Fixed in 379293fe7: the remembered unit is checked against the first 
non-empty unit list; a unit that is no longer listed is forgotten and the last 
execution's unit is used, and a decision still pending when the workflow 
changes is dropped. Tests cover the wait, the fallback and the stale case.



-- 
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