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

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

commit 4ff0b8b4ac415c4d60bfd73f37da5e3039ade2ec
Author: Tanishq Gandhi <[email protected]>
AuthorDate: Thu Sep 3 01:48:47 2026 +0000

    fix(frontend): refresh a dataset's paths after a rename, and block renaming 
mid-upload (#8347)
    
    ### What changes were proposed in this PR?
    
    Every file path on a dataset's detail page embeds the dataset name, and
    preview and single-file
    download resolve a dataset by (owner, name). `onSaveDatasetName()`
    updated the displayed name and
    nothing else, so after a rename the page kept serving the old paths: the
    file tree and the path above
    the preview still said the old name, clicking a file hung on "File
    content is loading" (404, then
    500), and the Data Card's "Latest version file" was stale too. Only a
    reload recovered.
    
    The same rename was also allowed while an upload was running. The upload
    is addressed by the name it
    started with, so the data uploaded fine and then the completing call
    failed with
    `400 {"code":400,"message":"Dataset not found"}`, leaving the panel on
    "Uploading: 1 file(s)" forever
    and a row behind in `dataset_upload_session`.
    
    - `dataset-detail.component.ts` — after a successful rename, refetch the
    browsed version's file tree
    and the Data Card's latest-version facts. The selected version is kept
    deliberately;
    `retrieveDatasetVersionList()` would also refresh both but resets the
    picker to the newest version,
      which a rename is no reason to do.
    - `dataset-detail.component.ts` / `.html` — bind the uploader's existing
    `uploadsInFlightChange`,
    disable the name field and Save while an upload is running, show a hint
    saying why, and guard
      `onSaveDatasetName()` on the same invariant.
    
    Note the browsed file resets to the version's first file after a rename,
    because the dataset page
    does not track the open file's relative path the way the model page
    does. That is a small change in
    behaviour from a page that was previously broken; tracking the open path
    can follow separately if it
    is worth it.
    
    **Before** — renamed, but the path still says `sensor-readings` and the
    preview hangs (console output
    overlaid so it fits in one screenshot); the Data Card keeps the old path
    too:
    <img width="1440" height="900" alt="image"
    
src="https://github.com/user-attachments/assets/330c06d6-a65a-409c-bf80-53b46c4d334c";
    />
    <img width="1440" height="900" alt="image"
    
src="https://github.com/user-attachments/assets/53da25ab-2220-45f3-96c0-6f7012202bc0";
    />
    
    **After** — the path and the Data Card both follow the new name, and the
    file opens:
    
    <!-- attach issue2-2-stale-tree-after.png -->
    <!-- attach issue2-4-data-card-after.png -->
    
    **After** — renaming is blocked while an upload is in flight:
    
    <img width="1440" height="900" alt="image"
    
src="https://github.com/user-attachments/assets/7b0a7540-82fe-4403-8de3-eb9e2dae119b";
    />
    
    ### Any related issues, documentation, discussions?
    
    Closes #8345.
    
    ### How was this PR tested?
    
    Three cases added to `dataset-detail.component.spec.ts`:
    
    - `refetches the file tree and the latest-version facts, which both
    embed the old name` — asserts both
    fetches happen with the browsed `dvid`, and that the selected version is
    unchanged. Removing the
      two refresh calls fails this test.
    - `refuses to rename while an upload is in flight, which would strand
    it`.
    - `locks the name field while an upload is in flight` — drives the real
    uploader output through the
      rendered template and checks the input and Save button are disabled.
    
    ```
    cd frontend
    npx ng test --include 
src/app/dashboard/component/user/user-dataset/user-dataset-explorer/dataset-detail.component.spec.ts
    # Tests  145 passed (145)
    ```
    
    Also checked by hand against a local stack, with the file uploads
    throttled so the upload stays in
    flight: renaming now leaves the tree, the path header and the Data Card
    all on the new name and files
    still open, and the name field is greyed out with the hint while an
    upload runs.
    
    ### Was this PR authored or co-authored using generative AI tooling?
    
    Generated-by: Claude Code (Opus 5)
---
 .../dataset-detail.component.html                  | 11 +++++-
 .../dataset-detail.component.spec.ts               | 43 ++++++++++++++++++++++
 .../dataset-detail.component.ts                    | 11 ++++++
 3 files changed, 64 insertions(+), 1 deletion(-)

diff --git 
a/frontend/src/app/dashboard/component/user/user-dataset/user-dataset-explorer/dataset-detail.component.html
 
b/frontend/src/app/dashboard/component/user/user-dataset/user-dataset-explorer/dataset-detail.component.html
index 5263213bbb..1053ea7c27 100644
--- 
a/frontend/src/app/dashboard/component/user/user-dataset/user-dataset-explorer/dataset-detail.component.html
+++ 
b/frontend/src/app/dashboard/component/user/user-dataset/user-dataset-explorer/dataset-detail.component.html
@@ -455,7 +455,8 @@
               [resourceName]="datasetName"
               [endpoint]="datasetEndpoint"
               [createVersion]="createDatasetVersion"
-              (versionCreated)="onVersionCreated()">
+              (versionCreated)="onVersionCreated()"
+              (uploadsInFlightChange)="uploadsInFlight = $event">
             </texera-version-uploader>
           </div>
         </nz-sider>
@@ -473,14 +474,22 @@
           <div class="settings-name-label">
             <label>Dataset name</label>
             <p class="settings-hint">Lowercase letters, numbers and 
hyphens.</p>
+            <p
+              *ngIf="uploadsInFlight"
+              class="settings-hint">
+              An upload is in progress — finish or cancel it in Versions &amp; 
Files first, or it will be left
+              incomplete.
+            </p>
           </div>
           <div class="settings-name-controls">
             <input
               nz-input
+              [disabled]="uploadsInFlight"
               [(ngModel)]="editedDatasetName" />
             <button
               nz-button
               nzType="primary"
+              [disabled]="uploadsInFlight"
               (click)="onSaveDatasetName()">
               Save
             </button>
diff --git 
a/frontend/src/app/dashboard/component/user/user-dataset/user-dataset-explorer/dataset-detail.component.spec.ts
 
b/frontend/src/app/dashboard/component/user/user-dataset/user-dataset-explorer/dataset-detail.component.spec.ts
index 617ae66559..11be93b137 100644
--- 
a/frontend/src/app/dashboard/component/user/user-dataset/user-dataset-explorer/dataset-detail.component.spec.ts
+++ 
b/frontend/src/app/dashboard/component/user/user-dataset/user-dataset-explorer/dataset-detail.component.spec.ts
@@ -1544,6 +1544,37 @@ describe("DatasetDetailComponent behavior", () => {
 
       expect(datasetServiceStub.updateDatasetName).not.toHaveBeenCalled();
     });
+
+    it("refetches the file tree and the latest-version facts, which both embed 
the old name", () => {
+      datasetServiceStub.updateDatasetName.mockReturnValue(of({}));
+      createComponent();
+      component.did = 5;
+      component.selectedVersion = makeVersion({ dvid: 12 });
+      component.editedDatasetName = "new-name";
+      datasetServiceStub.retrieveDatasetVersionFileTree.mockClear();
+      datasetServiceStub.retrieveDatasetLatestVersion.mockClear();
+
+      component.onSaveDatasetName();
+
+      
expect(datasetServiceStub.retrieveDatasetVersionFileTree).toHaveBeenCalledWith(5,
 12, component.isLogin);
+      
expect(datasetServiceStub.retrieveDatasetLatestVersion).toHaveBeenCalledWith(5);
+      // The browsed version stays put: a rename is not a reason to jump to 
the newest one.
+      expect(component.selectedVersion?.dvid).toBe(12);
+    });
+
+    it("refuses to rename while an upload is in flight, which would strand 
it", () => {
+      createComponent();
+      component.did = 5;
+      component.uploadsInFlight = true;
+      component.editedDatasetName = "new-name";
+
+      component.onSaveDatasetName();
+
+      expect(datasetServiceStub.updateDatasetName).not.toHaveBeenCalled();
+      expect(notificationServiceStub.error).toHaveBeenCalledWith(
+        "Finish or cancel the upload in progress before renaming this dataset"
+      );
+    });
   });
 
   describe("onDeleteDataset", () => {
@@ -2521,6 +2552,18 @@ describe("DatasetDetailComponent rendered template", () 
=> {
       expect(datasetService.updateDatasetDescription).toHaveBeenCalledWith(5, 
"brand new");
     });
 
+    it("locks the name field while an upload is in flight", () => {
+      const el = render({ did: 5, datasetName: "ds", userDatasetAccessLevel: 
"WRITE" });
+      openTab("Versions & Files");
+
+      
fixture.debugElement.query(By.css("texera-version-uploader")).triggerEventHandler("uploadsInFlightChange",
 true);
+      flush();
+      openTab("Settings");
+
+      expect(q<HTMLInputElement>(el, ".settings-name-controls 
input").disabled).toBe(true);
+      expect(q<HTMLButtonElement>(el, ".settings-name-controls 
button").disabled).toBe(true);
+    });
+
     it("deletes the dataset only once the confirmation is accepted", () => {
       const el = render({ did: 5, datasetName: "ds", userDatasetAccessLevel: 
"WRITE", isOwner: true });
       openTab("Settings");
diff --git 
a/frontend/src/app/dashboard/component/user/user-dataset/user-dataset-explorer/dataset-detail.component.ts
 
b/frontend/src/app/dashboard/component/user/user-dataset/user-dataset-explorer/dataset-detail.component.ts
index 72f89eb57b..9d38dab9ad 100644
--- 
a/frontend/src/app/dashboard/component/user/user-dataset/user-dataset-explorer/dataset-detail.component.ts
+++ 
b/frontend/src/app/dashboard/component/user/user-dataset/user-dataset-explorer/dataset-detail.component.ts
@@ -141,6 +141,7 @@ export class DatasetDetailComponent implements OnInit {
 
   public versions: ReadonlyArray<DatasetVersion> = [];
   public selectedVersion: DatasetVersion | undefined;
+  public uploadsInFlight = false;
   public fileTreeNodeList: DatasetFileNode[] = [];
   public selectedVersionCreationTime: string = "";
   // The following three fields describe the latest version for the Data Card, 
all
@@ -599,6 +600,10 @@ export class DatasetDetailComponent implements OnInit {
     if (!this.did) {
       return;
     }
+    if (this.uploadsInFlight) {
+      this.notificationService.error("Finish or cancel the upload in progress 
before renaming this dataset");
+      return;
+    }
     // Reject invalid names outright instead of silently rewriting them, 
matching
     // the shared validation used by the other rename entry points (PR #6426).
     const name = this.editedDatasetName;
@@ -615,6 +620,12 @@ export class DatasetDetailComponent implements OnInit {
         next: () => {
           this.datasetName = name;
           this.editedDatasetName = name;
+          // Every file path embeds the dataset name, and preview and 
single-file download resolve
+          // a dataset by (owner, name) — a stale tree 404s until reload.
+          if (this.selectedVersion) {
+            this.onVersionSelected(this.selectedVersion);
+          }
+          this.retrieveLatestVersionFile();
           this.notificationService.success(`Dataset name updated to 
'${name}'`);
         },
         error: (err: unknown) => {

Reply via email to