This is an automated email from the ASF dual-hosted git repository.

github-merge-queue[bot] pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/texera.git


The following commit(s) were added to refs/heads/main by this push:
     new 02fe9c7cb5 chore(frontend): remove the workspace toolbar "Import 
Workflow" button (#7310)
02fe9c7cb5 is described below

commit 02fe9c7cb5dabe5374b3e858660e0b85890da57d
Author: Eugene Gu <[email protected]>
AuthorDate: Tue Aug 4 16:36:43 2026 -0700

    chore(frontend): remove the workspace toolbar "Import Workflow" button 
(#7310)
    
    ### What changes were proposed in this PR?
    
    This PR removes the "Import Workflow" button from the workspace toolbar.
    
    The button imported a workflow JSON file into the currently opened
    workflow, but it fabricated the workflow's metadata from scratch: it set
    `wid` to `undefined`, renamed the workflow to the imported file's name,
    and reset `description` and the published state. Because `wid` was
    wiped, the auto-persist that fired after the import sent no wid to
    `/workflow/persist`, so the backend inserted a brand-new workflow: every
    import silently created a duplicate workflow in the user's list and
    switched the editor URL to it, while the originally opened workflow's
    content had already been overwritten (#6846).
    
    In discussion #6873 the button should simply be removed instead of
    patched: the dashboard workflow-list page already has an upload button
    that covers "create a workflow from a JSON file" (single JSON or a zip
    of several), so the toolbar button provides no capability that is lost
    by removing it.
    
    Concretely:
    
    - `menu.component.html`: remove the `<nz-upload>` block wrapping the
    import button.
    - `menu.component.ts`: remove the `onClickImportWorkflow` handler and
    the imports only it used (`NzUploadFile`/`NzUploadComponent` from
    ng-zorro, `NzUploadComponent` in the standalone `imports` array,
    `DEFAULT_WORKFLOW_NAME`).
    - `menu.component.scss`: remove the now-dead `nz-upload` selector.
    - `menu.component.spec.ts`: add regression tests asserting the toolbar
    renders no `nz-upload` control / no `button[title="import workflow"]`,
    and the component defines no `onClickImportWorkflow` member.
    
    No backend changes. The dashboard upload feature is untouched.
    
    After (import button removed):
    
    <img width="1512" height="900" alt="Screenshot 2026-08-04 at 1 50 51 PM"
    
src="https://github.com/user-attachments/assets/84bdcfa7-ac66-42f9-8f1e-dfe255f4a7da";
    />
    
    ### Any related issues, documentation, discussions?
    
    Fixes #6846. Implements the outcome of discussion #6873.
    
    ### How was this PR tested?
    
    New regression tests were written first and confirmed failing against
    the pre-change code, then passing after the removal; a mutation check
    (temporarily re-adding the button) confirmed the tests catch a
    re-introduction. The full `menu.component.spec.ts` passes (57/57), all
    specs under `workspace/component/menu` and
    `workspace/component/left-panel` pass (116/116), `tsc --noEmit` reports
    zero errors, and the CI-equivalent production build (`ng build
    --configuration=production`) completes with zero errors. Manually
    verified in the local dev environment that the toolbar no longer shows
    the import button and that the dashboard workflow-list upload button
    still creates a workflow from a JSON file.
    
    ### Was this PR authored or co-authored using generative AI tooling?
    
    Co-authored by: Claude Code (Claude Fable 5)
---
 .../workspace/component/menu/menu.component.html   | 12 -----
 .../workspace/component/menu/menu.component.scss   |  1 -
 .../component/menu/menu.component.spec.ts          | 17 +++++++
 .../app/workspace/component/menu/menu.component.ts | 58 +---------------------
 4 files changed, 18 insertions(+), 70 deletions(-)

diff --git a/frontend/src/app/workspace/component/menu/menu.component.html 
b/frontend/src/app/workspace/component/menu/menu.component.html
index 85a856eaba..33fbf539f6 100644
--- a/frontend/src/app/workspace/component/menu/menu.component.html
+++ b/frontend/src/app/workspace/component/menu/menu.component.html
@@ -121,18 +121,6 @@
             nz-icon
             nzType="delete"></i>
         </button>
-        <nz-upload
-          [nzDisabled]="!isWorkflowModifiable"
-          [nzBeforeUpload]="onClickImportWorkflow">
-          <button
-            nz-button
-            [disabled]="!isWorkflowModifiable"
-            title="import workflow">
-            <i
-              nz-icon
-              nzType="upload"></i>
-          </button>
-        </nz-upload>
         <button
           (click)="onClickExportWorkflow()"
           nz-button
diff --git a/frontend/src/app/workspace/component/menu/menu.component.scss 
b/frontend/src/app/workspace/component/menu/menu.component.scss
index 414a1c9cef..1b3c45a52d 100644
--- a/frontend/src/app/workspace/component/menu/menu.component.scss
+++ b/frontend/src/app/workspace/component/menu/menu.component.scss
@@ -81,7 +81,6 @@
 #user-buttons,
 #execution-buttons,
 nz-button-group,
-nz-upload,
 texera-computing-unit-selection {
   display: inline-flex;
   align-items: center;
diff --git a/frontend/src/app/workspace/component/menu/menu.component.spec.ts 
b/frontend/src/app/workspace/component/menu/menu.component.spec.ts
index caa86bf614..f766651b26 100644
--- a/frontend/src/app/workspace/component/menu/menu.component.spec.ts
+++ b/frontend/src/app/workspace/component/menu/menu.component.spec.ts
@@ -373,6 +373,23 @@ describe("MenuComponent", () => {
     expect(setNameSpy).toHaveBeenCalledWith("renamed");
   });
 
+  // Regression coverage for #6846 (resolved by discussion #6873): the 
toolbar's
+  // import button wiped `wid` before auto-persist and thereby created a 
spurious
+  // duplicate workflow, so it was removed. Creating a workflow from a JSON 
file
+  // is covered by the dashboard workflow-list upload button instead.
+  describe("import workflow removal", () => {
+    it("does not render an import upload control in the toolbar", () => {
+      const element: HTMLElement = fixture.nativeElement;
+
+      expect(element.querySelector("nz-upload")).toBeNull();
+      expect(element.querySelector("button[title='import 
workflow']")).toBeNull();
+    });
+
+    it("does not define an onClickImportWorkflow handler", () => {
+      expect((component as any).onClickImportWorkflow).toBeUndefined();
+    });
+  });
+
   describe("onClickExportWorkflow (save)", () => {
     it("serializes the workflow content as JSON and downloads it under the 
workflow name", () => {
       const fakeContent = {
diff --git a/frontend/src/app/workspace/component/menu/menu.component.ts 
b/frontend/src/app/workspace/component/menu/menu.component.ts
index a205b2b8bb..8e5f16199d 100644
--- a/frontend/src/app/workspace/component/menu/menu.component.ts
+++ b/frontend/src/app/workspace/component/menu/menu.component.ts
@@ -21,10 +21,7 @@ import { DatePipe, Location, NgIf, NgFor, NgTemplateOutlet } 
from "@angular/comm
 import { Component, ElementRef, Input, OnDestroy, OnInit, ViewChild } from 
"@angular/core";
 import { Router, RouterLink } from "@angular/router";
 import { UserService } from "../../../common/service/user/user.service";
-import {
-  DEFAULT_WORKFLOW_NAME,
-  WorkflowPersistService,
-} from "../../../common/service/workflow-persist/workflow-persist.service";
+import { WorkflowPersistService } from 
"../../../common/service/workflow-persist/workflow-persist.service";
 import { Workflow, WorkflowContent } from "../../../common/type/workflow";
 import { ExecuteWorkflowService } from 
"../../service/execute-workflow/execute-workflow.service";
 import { UndoRedoService } from "../../service/undo-redo/undo-redo.service";
@@ -38,7 +35,6 @@ import { UntilDestroy, untilDestroyed } from 
"@ngneat/until-destroy";
 import { WorkflowUtilService } from 
"../../service/workflow-graph/util/workflow-util.service";
 import { WorkflowVersionService } from 
"../../../dashboard/service/user/workflow-version/workflow-version.service";
 import { UserProjectService } from 
"../../../dashboard/service/user/project/user-project.service";
-import { NzUploadFile, NzUploadComponent } from "ng-zorro-antd/upload";
 import { saveAs } from "file-saver";
 import { NotificationService } from 
"src/app/common/service/notification/notification.service";
 import { OperatorMenuService } from 
"../../service/operator-menu/operator-menu.service";
@@ -108,7 +104,6 @@ import { NzTooltipDirective } from "ng-zorro-antd/tooltip";
     CoeditorUserIconComponent,
     UserIconComponent,
     RouterLink,
-    NzUploadComponent,
     NzDropdownDirective,
     NzDropdownMenuComponent,
     NzMenuDirective,
@@ -584,57 +579,6 @@ export class MenuComponent implements OnInit, OnDestroy {
     this.workflowActionService.deleteOperatorsAndLinks(allOperatorIDs);
   }
 
-  public onClickImportWorkflow = (file: NzUploadFile): boolean => {
-    const reader = new FileReader();
-    reader.readAsText(file as any);
-    reader.onload = () => {
-      try {
-        const result = reader.result;
-        if (typeof result !== "string") {
-          throw new Error("incorrect format: file is not a string");
-        }
-
-        const workflowContent = JSON.parse(result) as WorkflowContent;
-
-        // set the workflow name using the file name without the extension
-        const fileExtensionIndex = file.name.lastIndexOf(".");
-        var workflowName: string;
-        if (fileExtensionIndex === -1) {
-          workflowName = file.name;
-        } else {
-          workflowName = file.name.substring(0, fileExtensionIndex);
-        }
-        if (workflowName.trim() === "") {
-          workflowName = DEFAULT_WORKFLOW_NAME;
-        }
-
-        const workflow: Workflow = {
-          content: workflowContent,
-          name: workflowName,
-          description: undefined,
-          wid: undefined,
-          creationTime: undefined,
-          lastModifiedTime: undefined,
-          readonly: false,
-          isPublished: 0,
-        };
-
-        this.workflowActionService.enableWorkflowModification();
-        // load the fetched workflow
-        this.workflowActionService.reloadWorkflow(workflow, true);
-        // clear stack
-        this.undoRedoService.clearUndoStack();
-        this.undoRedoService.clearRedoStack();
-      } catch (error) {
-        this.notificationService.error(
-          "An error occurred when importing the workflow. Please import a 
workflow json file."
-        );
-        console.error(error);
-      }
-    };
-    return false;
-  };
-
   public onClickExportWorkflow(): void {
     const workflowContent: WorkflowContent = 
this.workflowActionService.getWorkflowContent();
     const workflowContentJson = JSON.stringify(workflowContent, null, 2);

Reply via email to