You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@texera.apache.org by gi...@apache.org on 2026/07/27 21:59:25 UTC

(texera) branch gh-readonly-queue/main/pr-6493-e08d3e6b423b960aa95a41d97b6275b7818b9476 created (now c2d4a262a2)

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

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


      at c2d4a262a2 refactor(frontend): extract dataset settings into Settings tab (#6493)

This branch includes the following new commits:

     new c2d4a262a2 refactor(frontend): extract dataset settings into Settings tab (#6493)

The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.



(texera) 01/01: refactor(frontend): extract dataset settings into Settings tab (#6493)

Posted by gi...@apache.org.
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-6493-e08d3e6b423b960aa95a41d97b6275b7818b9476
in repository https://gitbox.apache.org/repos/asf/texera.git

commit c2d4a262a2ded9ca099c3d2fa81e01b2de16757c
Author: Ranjani Veena Belavadi <16...@users.noreply.github.com>
AuthorDate: Mon Jul 27 14:59:03 2026 -0700

    refactor(frontend): extract dataset settings into Settings tab (#6493)
    
    ### What changes were proposed in this PR?
    Extracted the dataset settings/admin functionality on the dataset detail
    page into a dedicated Settings tab, alongside existing content (now
    under a Data Card tab). Part of the parent tab-based layout refactor
    (#6394).
    
    Visibility toggle, downloadable toggle, and description editor moved
    from the header's gear-icon popover into the new Settings tab. The gear
    icon and popover are removed.
    Added dataset rename (input + Save), calling the existing
    `DatasetService.updateDatasetName()` and reusing the name-sanitization
    logic already used in the dataset version creator.
    Added dataset delete, calling the existing
    `DatasetService.deleteDatasets()` with the same `nz-popconfirm`
    confirmation pattern used on the Datasets list page; redirects to the
    list on success.
    
    Before: settings were scattered, visibility/downloadable behind a gear
    icon, description editable only in the header, rename/delete only
    reachable from the Datasets list page.
    <img width="1915" height="1015" alt="settings_tab_recording_old"
    src="https://github.com/user-attachments/assets/3d29d0f3-0fbb-4caa-8c8f-ee0348df0ab1"
    />
    
    
    After: all dataset settings are consolidated in one Settings tab on the
    detail page itself.
    <img width="1915" height="1018" alt="settings_tab_recording"
    src="https://github.com/user-attachments/assets/348effd0-e8fd-4583-baff-118af9c83fee"
    />
    
    
    
    ### Any related issues, documentation, discussions?
    Closes #6395
    
    
    ### How was this PR tested?
    
    Added 7 unit tests to `dataset-detail.component.spec.ts` covering the
    two new methods (`onSaveDatasetName`, `onDeleteDataset`): name
    sanitization, success/error paths, and navigation on delete. The
    relocated toggles/description editor already had existing test coverage
    prior to this PR, so no new tests were needed there. 66/66 tests passing
    (59 pre-existing, 7 new).
    
    Also manually tested on UI, since the relocated functionality itself is
    unchanged behavior:
    - Renamed a dataset; confirmed persistence and correct sanitization of
    invalid characters.
    - Edited and saved the description; confirmed it reflects on the
    Datasets list page.
    - Toggled visibility and downloadable; confirmed state persists and
    header badges update accordingly.
    - Deleted a test dataset; confirmed confirmation prompt, successful
    deletion, and redirect to the Datasets list with the dataset removed.
    - Confirmed the Data Card tab (file browser, version history, uploads)
    is unaffected.
    
    
    ### Was this PR authored or co-authored using generative AI tooling?
    Generated-by: Claude Code (Claude Opus 4.8)
    
    ---------
    
    Signed-off-by: Ranjani Veena Belavadi <16...@users.noreply.github.com>
    Co-authored-by: Xuan Gu <16...@users.noreply.github.com>
---
 .../dataset-detail.component.html                  | 770 +++++++++++----------
 .../dataset-detail.component.scss                  |  77 +++
 .../dataset-detail.component.spec.ts               | 145 +++-
 .../dataset-detail.component.ts                    |  66 +-
 4 files changed, 703 insertions(+), 355 deletions(-)

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 3c2a031617..f50dcbd0a6 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
@@ -74,47 +74,6 @@
               nzTheme="outline"></i>
             {{ formatCount(likeCount) }}
           </nz-tag>
-
-          <button
-            *ngIf="userHasWriteAccess()"
-            nz-button
-            nzType="text"
-            class="tag-settings-btn"
-            nz-popover
-            nzPopoverTrigger="click"
-            nzPopoverPlacement="bottomRight"
-            [nzPopoverContent]="tagSettingsPopover"
-            nz-tooltip
-            nzTooltipTitle="Settings">
-            <i
-              nz-icon
-              nzType="setting"
-              nzTheme="outline"></i>
-          </button>
-
-          <ng-template #tagSettingsPopover>
-            <div>
-              <div class="tag-settings-title">Quick Settings</div>
-              <div class="tag-settings-row">
-                <span>Visibility:</span>
-                <nz-switch
-                  [ngModel]="datasetIsPublic"
-                  (ngModelChange)="onPublicStatusChange($event)"
-                  [nzDisabled]="userDatasetAccessLevel !== 'WRITE'"
-                  nzCheckedChildren="public"
-                  nzUnCheckedChildren="private"></nz-switch>
-              </div>
-              <div class="tag-settings-row">
-                <span>Downloadable:</span>
-                <nz-switch
-                  [ngModel]="datasetIsDownloadable"
-                  (ngModelChange)="onDownloadableStatusChange($event)"
-                  [nzDisabled]="!isOwner"
-                  nzCheckedChildren="allowed"
-                  nzUnCheckedChildren="blocked"></nz-switch>
-              </div>
-            </div>
-          </ng-template>
         </div>
       </div>
       <img
@@ -127,366 +86,477 @@
     <div class="description-section">
       <texera-markdown-description
         [description]="datasetDescription"
-        [editable]="userDatasetAccessLevel === 'WRITE'"
-        [enableViewMore]="true"
-        (descriptionChange)="onDatasetDescriptionChange($event)">
+        [editable]="false"
+        [enableViewMore]="true">
       </texera-markdown-description>
     </div>
   </nz-card>
 </div>
-<nz-layout>
-  <nz-content
-    [ngClass]="{'grayed-out': false, 'disabled-click': false}"
-    style="background-color: white">
-    <nz-card>
-      <div style="display: flex; justify-content: space-between; align-items: center">
-        <div class="file-info">
-          <h3 class="file-title">
-            <span class="file-title-main">
-              <b>{{ currentDisplayedFileName }}</b>
 
+<nz-tabs>
+  <nz-tab nzTitle="Data Card">
+    <nz-layout>
+      <nz-content
+        [ngClass]="{'grayed-out': false, 'disabled-click': false}"
+        style="background-color: white">
+        <nz-card>
+          <div style="display: flex; justify-content: space-between; align-items: center">
+            <div class="file-info">
+              <h3 class="file-title">
+                <span class="file-title-main">
+                  <b>{{ currentDisplayedFileName }}</b>
+
+                  <button
+                    nz-button
+                    nzType="text"
+                    nzSize="small"
+                    class="copy-path-btn"
+                    nz-tooltip
+                    nzTooltipTitle="Copy file path"
+                    *ngIf="currentDisplayedFileName"
+                    (click)="copyCurrentFilePath()">
+                    <i
+                      nz-icon
+                      nzType="copy"
+                      nzTheme="twotone">
+                    </i>
+                  </button>
+                </span>
+
+                <span
+                  *ngIf="currentFileSize"
+                  class="file-size">
+                  <i
+                    nz-icon
+                    nzType="file"
+                    nzTheme="outline"
+                    class="icon-file"></i>
+                  {{ formatSize(currentFileSize) }}
+                </span>
+              </h3>
+            </div>
+            <div style="display: flex">
               <button
                 nz-button
-                nzType="text"
-                nzSize="small"
-                class="copy-path-btn"
-                nz-tooltip
-                nzTooltipTitle="Copy file path"
-                *ngIf="currentDisplayedFileName"
-                (click)="copyCurrentFilePath()">
+                *ngIf="selectedVersion"
+                nz-tooltip="Download the file"
+                [disabled]="!isLogin || !isDownloadAllowed()"
+                (click)="onClickDownloadCurrentFile()">
                 <i
                   nz-icon
-                  nzType="copy"
-                  nzTheme="twotone">
+                  nzTheme="outline"
+                  nzType="download">
                 </i>
               </button>
-            </span>
-
-            <span
-              *ngIf="currentFileSize"
-              class="file-size">
-              <i
-                nz-icon
-                nzType="file"
-                nzTheme="outline"
-                class="icon-file"></i>
-              {{ formatSize(currentFileSize) }}
-            </span>
-          </h3>
-        </div>
-        <div style="display: flex">
-          <button
-            nz-button
-            *ngIf="selectedVersion"
-            nz-tooltip="Download the file"
-            [disabled]="!isLogin || !isDownloadAllowed()"
-            (click)="onClickDownloadCurrentFile()">
-            <i
-              nz-icon
-              nzTheme="outline"
-              nzType="download">
-            </i>
-          </button>
-          <button
-            nz-button
-            *ngIf="!isMaximized && selectedVersion"
-            nz-tooltip="Maximize View"
-            (click)="onClickScaleTheView()">
-            <i
-              nz-icon
-              nzTheme="outline"
-              nzType="expand">
-            </i>
-          </button>
-          <button
-            nz-button
-            *ngIf="isMaximized && selectedVersion"
-            nz-tooltip="Minimize View"
-            (click)="onClickScaleTheView()">
-            <i
-              nz-icon
-              nzTheme="outline"
-              nzType="compress">
-            </i>
-          </button>
-          <button
-            *ngIf="!isRightBarCollapsed"
-            nz-button
-            nz-tooltip="Hide the right bar"
-            (click)="onClickHideRightBar()">
-            <i
-              nz-icon
-              nzTheme="outline"
-              nzType="right">
-            </i>
-          </button>
-          <button
-            *ngIf="isRightBarCollapsed"
-            nz-button
-            nz-tooltip="Show Tree"
-            (click)="onClickHideRightBar()">
-            <i
-              nz-icon
-              nzTheme="outline"
-              nzType="left">
-            </i>
-          </button>
-        </div>
-      </div>
-    </nz-card>
-    <nz-empty
-      class="empty-version-indicator"
-      *ngIf="!selectedVersion"
-      nzNotFoundContent="No version is selected"></nz-empty>
-
-    <texera-user-dataset-file-renderer
-      *ngIf="selectedVersion"
-      [isMaximized]="isMaximized"
-      [did]="did"
-      [dvid]="selectedVersion.dvid"
-      [filePath]="currentDisplayedFileName"
-      [fileSize]="currentFileSize"
-      [isLogin]="isLogin"
-      class="file-renderer">
-    </texera-user-dataset-file-renderer>
-  </nz-content>
-  <nz-sider
-    *ngIf="!isRightBarCollapsed"
-    nzTheme="light"
-    [nzWidth]="siderWidth"
-    nz-resizable
-    [nzMinWidth]="MIN_SIDER_WIDTH"
-    [nzMaxWidth]="MAX_SIDER_WIDTH"
-    (nzResize)="onSideResize($event)">
-    <nz-resize-handle nzDirection="left">
-      <div class="sider-resize-line">
-        <i
-          class="sider-resize-handle"
-          nz-icon
-          nzType="more"
-          nzTheme="outline"></i>
-      </div>
-    </nz-resize-handle>
-    <div class="right-sider">
-      <nz-collapse nzGhost>
-        <nz-collapse-panel
-          nzHeader="Current Versions"
-          nzActive="true">
-          <div class="version-storage">
-            <h6 style="font-weight: lighter; font-size: 0.9em">Choose a Version:</h6>
-            <div class="select-and-button-container">
-              <nz-select
-                nzShowSearch
-                nzAllowClear
-                nzPlaceHolder="Select a version"
-                (ngModelChange)="onVersionSelected($event)"
-                [(ngModel)]="selectedVersion">
-                <nz-option
-                  *ngFor="let version of versions"
-                  [nzValue]="version"
-                  [nzLabel]="version.name"></nz-option>
-              </nz-select>
               <button
                 nz-button
-                nz-tooltip="Download Dataset"
-                (click)="onClickDownloadVersionAsZip()"
-                *ngIf="selectedVersion"
-                [disabled]="!isLogin || !isDownloadAllowed()"
-                class="spaced-button">
+                *ngIf="!isMaximized && selectedVersion"
+                nz-tooltip="Maximize View"
+                (click)="onClickScaleTheView()">
                 <i
                   nz-icon
-                  nzType="download"
-                  nzTheme="outline"></i>
+                  nzTheme="outline"
+                  nzType="expand">
+                </i>
               </button>
-            </div>
-            <ng-container *ngIf="selectedVersion">
-              <div class="version-size">
+              <button
+                nz-button
+                *ngIf="isMaximized && selectedVersion"
+                nz-tooltip="Minimize View"
+                (click)="onClickScaleTheView()">
                 <i
                   nz-icon
-                  nzType="database"
                   nzTheme="outline"
-                  class="icon-database"></i>
-                Version Size: {{ formatSize(currentDatasetVersionSize) }}
-              </div>
-              <div
-                *ngIf="selectedVersionCreationTime"
-                class="version-date">
+                  nzType="compress">
+                </i>
+              </button>
+              <button
+                *ngIf="!isRightBarCollapsed"
+                nz-button
+                nz-tooltip="Hide the right bar"
+                (click)="onClickHideRightBar()">
                 <i
                   nz-icon
-                  nzType="calendar"
                   nzTheme="outline"
-                  class="icon-database"></i>
-                Created at: {{ selectedVersionCreationTime }}
-              </div>
-            </ng-container>
+                  nzType="right">
+                </i>
+              </button>
+              <button
+                *ngIf="isRightBarCollapsed"
+                nz-button
+                nz-tooltip="Show Tree"
+                (click)="onClickHideRightBar()">
+                <i
+                  nz-icon
+                  nzTheme="outline"
+                  nzType="left">
+                </i>
+              </button>
+            </div>
           </div>
-          <texera-user-dataset-version-filetree
-            [fileTreeNodes]="fileTreeNodeList"
-            [isTreeNodeDeletable]="true"
-            (selectedTreeNode)="onVersionFileTreeNodeSelected($event)"
-            (deletedTreeNode)="onPreviouslyUploadedFileDeleted($event)"
-            (setCoverImage)="onSetCoverImage($event)">
-          </texera-user-dataset-version-filetree>
-        </nz-collapse-panel>
-      </nz-collapse>
-
-      <nz-divider></nz-divider>
-      <nz-collapse
-        *ngIf="userDatasetAccessLevel === 'WRITE'"
-        nzGhost>
-        <nz-collapse-panel
-          nzActive="true"
-          nzHeader="Create New Version">
-          <texera-user-files-uploader
-            [did]="did"
-            [ownerEmail]="ownerEmail"
-            [datasetName]="datasetName"
-            (uploadedFiles)="onNewUploadFilesChanged($event)">
-          </texera-user-files-uploader>
+        </nz-card>
+        <nz-empty
+          class="empty-version-indicator"
+          *ngIf="!selectedVersion"
+          nzNotFoundContent="No version is selected"></nz-empty>
 
-          <nz-collapse
-            nzGhost
-            class="upload-status-panels">
+        <texera-user-dataset-file-renderer
+          *ngIf="selectedVersion"
+          [isMaximized]="isMaximized"
+          [did]="did"
+          [dvid]="selectedVersion.dvid"
+          [filePath]="currentDisplayedFileName"
+          [fileSize]="currentFileSize"
+          [isLogin]="isLogin"
+          class="file-renderer">
+        </texera-user-dataset-file-renderer>
+      </nz-content>
+      <nz-sider
+        *ngIf="!isRightBarCollapsed"
+        nzTheme="light"
+        [nzWidth]="siderWidth"
+        nz-resizable
+        [nzMinWidth]="MIN_SIDER_WIDTH"
+        [nzMaxWidth]="MAX_SIDER_WIDTH"
+        (nzResize)="onSideResize($event)">
+        <nz-resize-handle nzDirection="left">
+          <div class="sider-resize-line">
+            <i
+              class="sider-resize-handle"
+              nz-icon
+              nzType="more"
+              nzTheme="outline"></i>
+          </div>
+        </nz-resize-handle>
+        <div class="right-sider">
+          <nz-collapse nzGhost>
             <nz-collapse-panel
-              *ngIf="queuedCount > 0"
-              [nzHeader]="'Pending: ' + queuedCount + ' file(s)'"
-              (nzActiveChange)="onPendingPanelActiveChange($event)">
-              <!-- Virtualized so only visible rows are in the DOM (#5586). The viewport
-                   measures height 0 while the panel is collapsed, so it is re-measured
-                   on expand. -->
-              <cdk-virtual-scroll-viewport
-                class="upload-progress-wrapper-pending"
-                [itemSize]="PENDING_ROW_HEIGHT_PX"
-                [minBufferPx]="PENDING_LIST_MAX_HEIGHT_PX"
-                [maxBufferPx]="2 * PENDING_LIST_MAX_HEIGHT_PX"
-                [style.height.px]="pendingListHeightPx">
-                <div
-                  class="pending-file-row"
-                  *cdkVirtualFor="let fileName of queuedFileNames; trackBy: trackByPendingFile">
-                  <span
-                    class="pending-file-name"
-                    nz-tooltip
-                    [nzTooltipTitle]="fileName"
-                    >{{ fileName }}</span
-                  >
+              nzHeader="Current Versions"
+              nzActive="true">
+              <div class="version-storage">
+                <h6 style="font-weight: lighter; font-size: 0.9em">Choose a Version:</h6>
+                <div class="select-and-button-container">
+                  <nz-select
+                    nzShowSearch
+                    nzAllowClear
+                    nzPlaceHolder="Select a version"
+                    (ngModelChange)="onVersionSelected($event)"
+                    [(ngModel)]="selectedVersion">
+                    <nz-option
+                      *ngFor="let version of versions"
+                      [nzValue]="version"
+                      [nzLabel]="version.name"></nz-option>
+                  </nz-select>
                   <button
                     nz-button
-                    nzType="text"
-                    nzShape="circle"
-                    nz-tooltip
-                    [nzTooltipTitle]="'Remove from queue'"
-                    (click)="cancelExistingUpload(fileName)">
-                    <span
+                    nz-tooltip="Download Dataset"
+                    (click)="onClickDownloadVersionAsZip()"
+                    *ngIf="selectedVersion"
+                    [disabled]="!isLogin || !isDownloadAllowed()"
+                    class="spaced-button">
+                    <i
                       nz-icon
-                      nzType="close"
-                      nzTheme="outline"></span>
+                      nzType="download"
+                      nzTheme="outline"></i>
                   </button>
                 </div>
-              </cdk-virtual-scroll-viewport>
+                <ng-container *ngIf="selectedVersion">
+                  <div class="version-size">
+                    <i
+                      nz-icon
+                      nzType="database"
+                      nzTheme="outline"
+                      class="icon-database"></i>
+                    Version Size: {{ formatSize(currentDatasetVersionSize) }}
+                  </div>
+                  <div
+                    *ngIf="selectedVersionCreationTime"
+                    class="version-date">
+                    <i
+                      nz-icon
+                      nzType="calendar"
+                      nzTheme="outline"
+                      class="icon-database"></i>
+                    Created at: {{ selectedVersionCreationTime }}
+                  </div>
+                </ng-container>
+              </div>
+              <texera-user-dataset-version-filetree
+                [fileTreeNodes]="fileTreeNodeList"
+                [isTreeNodeDeletable]="true"
+                (selectedTreeNode)="onVersionFileTreeNodeSelected($event)"
+                (deletedTreeNode)="onPreviouslyUploadedFileDeleted($event)"
+                (setCoverImage)="onSetCoverImage($event)">
+              </texera-user-dataset-version-filetree>
             </nz-collapse-panel>
+          </nz-collapse>
 
-            <nz-divider
-              class="section-divider"
-              *ngIf="queuedCount > 0"></nz-divider>
-
+          <nz-divider></nz-divider>
+          <nz-collapse
+            *ngIf="userDatasetAccessLevel === 'WRITE'"
+            nzGhost>
             <nz-collapse-panel
-              *ngIf="activeCount > 0"
-              [nzHeader]="'Uploading: ' + activeCount + ' file(s)'">
-              <div class="upload-progress-wrapper">
-                <div *ngFor="let task of uploadTasks; trackBy: trackByTask">
-                  <div class="progress-header">
-                    <span><b>{{ task.status }}</b>: {{ task.filePath }}</span>
-                    <button
-                      nz-button
-                      nzType="text"
-                      nzShape="circle"
-                      [nz-tooltip]="
+              nzActive="true"
+              nzHeader="Create New Version">
+              <texera-user-files-uploader
+                [did]="did"
+                [ownerEmail]="ownerEmail"
+                [datasetName]="datasetName"
+                (uploadedFiles)="onNewUploadFilesChanged($event)">
+              </texera-user-files-uploader>
+
+              <nz-collapse
+                nzGhost
+                class="upload-status-panels">
+                <nz-collapse-panel
+                  *ngIf="queuedCount > 0"
+                  [nzHeader]="'Pending: ' + queuedCount + ' file(s)'"
+                  (nzActiveChange)="onPendingPanelActiveChange($event)">
+                  <!-- Virtualized so only visible rows are in the DOM (#5586). The viewport
+                   measures height 0 while the panel is collapsed, so it is re-measured
+                   on expand. -->
+                  <cdk-virtual-scroll-viewport
+                    class="upload-progress-wrapper-pending"
+                    [itemSize]="PENDING_ROW_HEIGHT_PX"
+                    [minBufferPx]="PENDING_LIST_MAX_HEIGHT_PX"
+                    [maxBufferPx]="2 * PENDING_LIST_MAX_HEIGHT_PX"
+                    [style.height.px]="pendingListHeightPx">
+                    <div
+                      class="pending-file-row"
+                      *cdkVirtualFor="let fileName of queuedFileNames; trackBy: trackByPendingFile">
+                      <span
+                        class="pending-file-name"
+                        nz-tooltip
+                        [nzTooltipTitle]="fileName"
+                        >{{ fileName }}</span
+                      >
+                      <button
+                        nz-button
+                        nzType="text"
+                        nzShape="circle"
+                        nz-tooltip
+                        [nzTooltipTitle]="'Remove from queue'"
+                        (click)="cancelExistingUpload(fileName)">
+                        <span
+                          nz-icon
+                          nzType="close"
+                          nzTheme="outline"></span>
+                      </button>
+                    </div>
+                  </cdk-virtual-scroll-viewport>
+                </nz-collapse-panel>
+
+                <nz-divider
+                  class="section-divider"
+                  *ngIf="queuedCount > 0"></nz-divider>
+
+                <nz-collapse-panel
+                  *ngIf="activeCount > 0"
+                  [nzHeader]="'Uploading: ' + activeCount + ' file(s)'">
+                  <div class="upload-progress-wrapper">
+                    <div *ngFor="let task of uploadTasks; trackBy: trackByTask">
+                      <div class="progress-header">
+                        <span><b>{{ task.status }}</b>: {{ task.filePath }}</span>
+                        <button
+                          nz-button
+                          nzType="text"
+                          nzShape="circle"
+                          [nz-tooltip]="
                 (task.status === 'aborted' || task.status === 'finished')
                 ? 'Close'
                 : 'Cancel the upload'
                 "
-                      (click)="onClickAbortUploadProgress(task)">
-                      <i
-                        nz-icon
-                        nzType="close"
-                        nzTheme="outline"></i>
-                    </button>
-                  </div>
+                          (click)="onClickAbortUploadProgress(task)">
+                          <i
+                            nz-icon
+                            nzType="close"
+                            nzTheme="outline"></i>
+                        </button>
+                      </div>
 
-                  <div
-                    class="upload-stats"
-                    *ngIf="task.status !== 'initializing'">
-                    <nz-progress
-                      [nzPercent]="task.percentage"
-                      [nzStatus]="getUploadStatus(task.status)"></nz-progress>
-                    <nz-tag
-                      *ngIf="task.status === 'uploading'"
-                      [nzColor]="'blue'">
-                      <span class="fixed-width-speed">{{ formatSpeed(task.uploadSpeed) }}</span> -
-                      <span class="fixed-width-time">{{ formatTime(task.totalTime ?? 0) }}</span> elapsed,
-                      <span class="fixed-width-time">{{ formatTime(task.estimatedTimeRemaining ?? 0) }} left</span>
-                    </nz-tag>
+                      <div
+                        class="upload-stats"
+                        *ngIf="task.status !== 'initializing'">
+                        <nz-progress
+                          [nzPercent]="task.percentage"
+                          [nzStatus]="getUploadStatus(task.status)"></nz-progress>
+                        <nz-tag
+                          *ngIf="task.status === 'uploading'"
+                          [nzColor]="'blue'">
+                          <span class="fixed-width-speed">{{ formatSpeed(task.uploadSpeed) }}</span> -
+                          <span class="fixed-width-time">{{ formatTime(task.totalTime ?? 0) }}</span> elapsed,
+                          <span class="fixed-width-time">{{ formatTime(task.estimatedTimeRemaining ?? 0) }} left</span>
+                        </nz-tag>
 
-                    <nz-tag *ngIf="(task.status === 'finished' || task.status === 'aborted')">
-                      Upload time: {{ formatTime(task.totalTime ?? 0) }}
-                    </nz-tag>
+                        <nz-tag *ngIf="(task.status === 'finished' || task.status === 'aborted')">
+                          Upload time: {{ formatTime(task.totalTime ?? 0) }}
+                        </nz-tag>
+                      </div>
+                    </div>
                   </div>
-                </div>
-              </div>
-            </nz-collapse-panel>
+                </nz-collapse-panel>
 
-            <nz-divider
-              class="section-divider"
-              *ngIf="activeCount > 0"></nz-divider>
+                <nz-divider
+                  class="section-divider"
+                  *ngIf="activeCount > 0"></nz-divider>
+
+                <nz-collapse-panel
+                  *ngIf="hasAnyActivity"
+                  [nzHeader]="'Finished: ' + pendingChangesCount + ' file(s)'"
+                  (nzActiveChange)="$event && stagedObjectsList.remeasureViewport()">
+                  <texera-dataset-staged-objects-list
+                    #stagedObjectsList
+                    [uploadTimeMap]="uploadTimeMap"
+                    [did]="did"
+                    [userMakeChangesEvent]="userMakeChanges"
+                    (stagedObjectsChanged)="onStagedObjectsUpdated($event)">
+                  </texera-dataset-staged-objects-list>
+                </nz-collapse-panel>
+              </nz-collapse>
 
-            <nz-collapse-panel
-              *ngIf="hasAnyActivity"
-              [nzHeader]="'Finished: ' + pendingChangesCount + ' file(s)'"
-              (nzActiveChange)="$event && stagedObjectsList.remeasureViewport()">
               <texera-dataset-staged-objects-list
-                #stagedObjectsList
+                *ngIf="!hasAnyActivity"
                 [uploadTimeMap]="uploadTimeMap"
                 [did]="did"
                 [userMakeChangesEvent]="userMakeChanges"
                 (stagedObjectsChanged)="onStagedObjectsUpdated($event)">
               </texera-dataset-staged-objects-list>
+
+              <div
+                *ngIf="userHasWriteAccess() && userHasPendingChanges"
+                class="version-creator">
+                <div class="version-input-container">
+                  <label>Version:</label>
+                  <input
+                    nz-input
+                    [(ngModel)]="versionName"
+                    placeholder="Describe the new version (Optional)"
+                    [disabled]="isCreatingVersion"
+                    (keydown.enter)="onClickOpenVersionCreator()"
+                    class="version-input" />
+                </div>
+                <div>
+                  <button
+                    nz-button
+                    nzType="primary"
+                    [nzLoading]="isCreatingVersion"
+                    (click)="onClickOpenVersionCreator()"
+                    class="create-dataset-version-button">
+                    Submit
+                  </button>
+                </div>
+              </div>
             </nz-collapse-panel>
           </nz-collapse>
+        </div>
+      </nz-sider>
+    </nz-layout>
+  </nz-tab>
+  <nz-tab
+    nzTitle="Settings"
+    *ngIf="userHasWriteAccess()">
+    <div class="settings-tab-content">
+      <nz-card class="settings-general-card">
+        <h3 class="settings-card-title">General</h3>
 
-          <texera-dataset-staged-objects-list
-            *ngIf="!hasAnyActivity"
-            [uploadTimeMap]="uploadTimeMap"
-            [did]="did"
-            [userMakeChangesEvent]="userMakeChanges"
-            (stagedObjectsChanged)="onStagedObjectsUpdated($event)">
-          </texera-dataset-staged-objects-list>
+        <div class="settings-name-row">
+          <div class="settings-name-label">
+            <label>Dataset name</label>
+            <p class="settings-hint">Lowercase letters, numbers and hyphens.</p>
+          </div>
+          <div class="settings-name-controls">
+            <input
+              nz-input
+              [(ngModel)]="editedDatasetName" />
+            <button
+              nz-button
+              nzType="primary"
+              (click)="onSaveDatasetName()">
+              Save
+            </button>
+          </div>
+        </div>
 
-          <div
-            *ngIf="userHasWriteAccess() && userHasPendingChanges"
-            class="version-creator">
-            <div class="version-input-container">
-              <label>Version:</label>
-              <input
-                nz-input
-                [(ngModel)]="versionName"
-                placeholder="Describe the new version (Optional)"
-                [disabled]="isCreatingVersion"
-                (keydown.enter)="onClickOpenVersionCreator()"
-                class="version-input" />
-            </div>
-            <div>
-              <button
-                nz-button
-                nzType="primary"
-                [nzLoading]="isCreatingVersion"
-                (click)="onClickOpenVersionCreator()"
-                class="create-dataset-version-button">
-                Submit
-              </button>
-            </div>
+        <nz-divider></nz-divider>
+
+        <div class="settings-field">
+          <label class="settings-field-label">Description</label>
+          <div class="settings-field-hint">Shown on cards and the Metadata tab.</div>
+          <texera-markdown-description
+            [description]="datasetDescription"
+            [editable]="userDatasetAccessLevel === 'WRITE'"
+            [enableViewMore]="true"
+            (descriptionChange)="onDatasetDescriptionChange($event)">
+          </texera-markdown-description>
+        </div>
+      </nz-card>
+
+      <nz-card class="settings-general-card">
+        <h3 class="settings-card-title">Access &amp; visibility</h3>
+
+        <div class="settings-name-row">
+          <div class="settings-name-label">
+            <label>Visibility</label>
+            <p class="settings-hint">
+              {{ datasetIsPublic ? "Public — anyone can view this dataset." : "Private — only you and invited
+              collaborators can see this dataset." }}
+            </p>
+          </div>
+          <div class="settings-name-controls">
+            <nz-switch
+              [ngModel]="datasetIsPublic"
+              (ngModelChange)="onPublicStatusChange($event)"
+              [nzDisabled]="userDatasetAccessLevel !== 'WRITE'"
+              nzCheckedChildren="public"
+              nzUnCheckedChildren="private"></nz-switch>
+          </div>
+        </div>
+
+        <nz-divider></nz-divider>
+
+        <div class="settings-name-row">
+          <div class="settings-name-label">
+            <label>Downloadable</label>
+            <p class="settings-hint">
+              {{ datasetIsDownloadable ? "Viewers can download this dataset." : "Viewers can browse files but cannot
+              download them." }}
+            </p>
+          </div>
+          <div class="settings-name-controls">
+            <nz-switch
+              [ngModel]="datasetIsDownloadable"
+              (ngModelChange)="onDownloadableStatusChange($event)"
+              [nzDisabled]="!isOwner"
+              nzCheckedChildren="allowed"
+              nzUnCheckedChildren="blocked"></nz-switch>
           </div>
-        </nz-collapse-panel>
-      </nz-collapse>
+        </div>
+      </nz-card>
+
+      <nz-card class="settings-general-card">
+        <h3 class="settings-card-title">Delete</h3>
+
+        <div class="settings-name-row">
+          <div class="settings-name-label">
+            <label>Delete dataset</label>
+            <p class="settings-hint">This permanently deletes the dataset and all of its versions.</p>
+          </div>
+          <div class="settings-name-controls">
+            <button
+              nz-button
+              nzType="text"
+              title="Delete"
+              [disabled]="!isOwner"
+              (nzOnConfirm)="onDeleteDataset()"
+              nz-popconfirm
+              nzPopconfirmTitle="Confirm to delete this dataset.">
+              <i
+                nz-icon
+                nzType="delete"></i>
+            </button>
+          </div>
+        </div>
+      </nz-card>
     </div>
-  </nz-sider>
-</nz-layout>
+  </nz-tab>
+</nz-tabs>
diff --git a/frontend/src/app/dashboard/component/user/user-dataset/user-dataset-explorer/dataset-detail.component.scss b/frontend/src/app/dashboard/component/user/user-dataset/user-dataset-explorer/dataset-detail.component.scss
index d5ef708f88..b5bbf7dfce 100644
--- a/frontend/src/app/dashboard/component/user/user-dataset/user-dataset-explorer/dataset-detail.component.scss
+++ b/frontend/src/app/dashboard/component/user/user-dataset/user-dataset-explorer/dataset-detail.component.scss
@@ -347,3 +347,80 @@ nz-select {
   border-radius: 8px;
   margin-right: 80px;
 }
+
+nz-tabs {
+  margin-top: 6px;
+}
+
+::ng-deep .ant-tabs-nav {
+  padding-left: 16px;
+}
+
+// The Settings tab shares the tab area's bounded height with the Data Card
+// tab. Give its content its own scroll region (mirroring the height:100% +
+// overflow-y:auto pattern used by other dashboard pages) so both cards can
+// be scrolled fully into view, with bottom padding for breathing room below
+// the last card.
+.settings-tab-content {
+  height: 100%;
+  overflow-y: auto;
+  padding-bottom: 24px;
+}
+
+.settings-general-card {
+  max-width: 700px;
+  margin: 24px auto 0;
+  border-radius: 16px;
+  border: 1px solid #d9d9d9;
+
+  .settings-card-title {
+    font-weight: 600;
+    margin-bottom: 20px;
+  }
+
+  .settings-field-label {
+    display: block;
+    font-weight: 600;
+  }
+
+  .settings-field-hint {
+    color: rgba(0, 0, 0, 0.45);
+    font-size: 12px;
+    margin-bottom: 8px;
+  }
+
+  .settings-name-row {
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+    gap: 16px;
+
+    .settings-name-label label {
+      font-weight: 600;
+    }
+
+    .settings-hint {
+      color: rgba(0, 0, 0, 0.45);
+      font-size: 12px;
+      margin: 4px 0 0;
+    }
+
+    .settings-name-controls {
+      display: flex;
+      gap: 8px;
+      flex-shrink: 0;
+
+      input {
+        border-radius: 8px;
+      }
+
+      button {
+        border-radius: 8px;
+      }
+    }
+  }
+}
+
+::ng-deep .settings-general-card button {
+  border-radius: 8px;
+}
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 91d8acce94..3b40c12d09 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
@@ -18,7 +18,7 @@
  */
 
 import { ComponentFixture, TestBed } from "@angular/core/testing";
-import { ActivatedRoute } from "@angular/router";
+import { ActivatedRoute, Router } from "@angular/router";
 import { of, Subject, throwError } from "rxjs";
 import { NzModalService } from "ng-zorro-antd/modal";
 import { MarkdownService } from "ngx-markdown";
@@ -38,6 +38,7 @@ import { Dataset, DatasetVersion } from "../../../../../common/type/dataset";
 import { DashboardDataset } from "../../../../type/dashboard-dataset.interface";
 import { HttpErrorResponse } from "@angular/common/http";
 import { format } from "date-fns";
+import { USER_DATASET } from "../../../../../app-routing.constant";
 
 describe("DatasetDetailComponent upload queue", () => {
   let fixture: ComponentFixture<DatasetDetailComponent>;
@@ -429,6 +430,8 @@ describe("DatasetDetailComponent behavior", () => {
       updateDatasetDownloadable: vi.fn(() => of({})),
       updateDatasetCoverImage: vi.fn(() => of({})),
       updateDatasetDescription: vi.fn(() => of({})),
+      updateDatasetName: vi.fn(() => of({})),
+      deleteDatasets: vi.fn(() => of({})),
       deleteDatasetFile: vi.fn(() => of({})),
       getDatasetDiff: vi.fn(() => of([])),
       multipartUpload: vi.fn(() => of()),
@@ -1036,4 +1039,144 @@ describe("DatasetDetailComponent behavior", () => {
       expect(component.trackByTask(0, task)).toBe("owner/data/file.csv");
     });
   });
+
+  describe("onSaveDatasetName", () => {
+    it("seeds editedDatasetName from the loaded dataset name", () => {
+      datasetServiceStub.getDataset.mockReturnValue(
+        of(makeDashboardDataset({ dataset: makeDataset({ name: "seed-name" }) }))
+      );
+      createComponent();
+      component.did = 5;
+      component.retrieveDatasetInfo();
+
+      expect(component.editedDatasetName).toBe("seed-name");
+    });
+
+    it("persists a valid name unchanged and toasts success", () => {
+      datasetServiceStub.updateDatasetName.mockReturnValue(of({}));
+      createComponent();
+      component.did = 5;
+      // Mixed case, hyphen and underscore are all valid: the name must be saved
+      // verbatim, not rewritten.
+      component.editedDatasetName = "My-Cool_Dataset";
+
+      component.onSaveDatasetName();
+
+      expect(datasetServiceStub.updateDatasetName).toHaveBeenCalledWith(5, "My-Cool_Dataset");
+      expect(component.datasetName).toBe("My-Cool_Dataset");
+      expect(component.editedDatasetName).toBe("My-Cool_Dataset");
+      expect(notificationServiceStub.success).toHaveBeenCalledWith("Dataset name updated to 'My-Cool_Dataset'");
+    });
+
+    it("rejects an invalid name with a validation error and does not call the rename API", () => {
+      createComponent();
+      component.did = 5;
+      component.datasetName = "original";
+      component.editedDatasetName = "My Cool Dataset"; // spaces are not allowed
+
+      component.onSaveDatasetName();
+
+      expect(datasetServiceStub.updateDatasetName).not.toHaveBeenCalled();
+      expect(component.datasetName).toBe("original");
+      expect(notificationServiceStub.error).toHaveBeenCalledWith(
+        "Invalid dataset name: only letters, numbers, underscores, and hyphens are allowed (max 128 characters)"
+      );
+    });
+
+    it("toasts an error and leaves the name unchanged when the rename fails", () => {
+      datasetServiceStub.updateDatasetName.mockReturnValue(throwError(() => new Error("boom")));
+      createComponent();
+      component.did = 5;
+      component.datasetName = "original";
+      component.editedDatasetName = "new-name";
+
+      component.onSaveDatasetName();
+
+      expect(component.datasetName).toBe("original");
+      expect(notificationServiceStub.error).toHaveBeenCalledWith("boom");
+    });
+
+    it("does nothing when there is no did", () => {
+      createComponent();
+      component.did = undefined;
+      component.editedDatasetName = "whatever";
+
+      component.onSaveDatasetName();
+
+      expect(datasetServiceStub.updateDatasetName).not.toHaveBeenCalled();
+    });
+  });
+
+  describe("onDeleteDataset", () => {
+    it("deletes the dataset, toasts success and navigates back to the dataset list", () => {
+      datasetServiceStub.deleteDatasets.mockReturnValue(of({}));
+      createComponent();
+      const navigateSpy = vi.spyOn(TestBed.inject(Router), "navigate").mockResolvedValue(true);
+      component.did = 5;
+      component.datasetName = "DS";
+
+      component.onDeleteDataset();
+
+      expect(datasetServiceStub.deleteDatasets).toHaveBeenCalledWith(5);
+      expect(notificationServiceStub.success).toHaveBeenCalledWith("Dataset DS was deleted");
+      expect(navigateSpy).toHaveBeenCalledWith([USER_DATASET]);
+    });
+
+    it("toasts an error and does not navigate when the deletion fails", () => {
+      datasetServiceStub.deleteDatasets.mockReturnValue(throwError(() => new Error("boom")));
+      createComponent();
+      const navigateSpy = vi.spyOn(TestBed.inject(Router), "navigate").mockResolvedValue(true);
+      component.did = 5;
+
+      component.onDeleteDataset();
+
+      expect(notificationServiceStub.error).toHaveBeenCalledWith("boom");
+      expect(navigateSpy).not.toHaveBeenCalled();
+    });
+
+    it("does nothing when there is no did", () => {
+      createComponent();
+      const navigateSpy = vi.spyOn(TestBed.inject(Router), "navigate").mockResolvedValue(true);
+      component.did = undefined;
+
+      component.onDeleteDataset();
+
+      expect(datasetServiceStub.deleteDatasets).not.toHaveBeenCalled();
+      expect(navigateSpy).not.toHaveBeenCalled();
+    });
+  });
+
+  describe("delete button disabled state", () => {
+    // The Settings tab (and its Delete card) only render for WRITE access; the
+    // delete button itself is owner-only, mirroring the Downloadable switch's
+    // [nzDisabled]="!isOwner". Renders WRITE access with the given ownership,
+    // activates the (inactive) Settings tab so its pane is in the DOM, then
+    // returns the delete button element.
+    const renderDeleteButton = (isOwner: boolean): HTMLButtonElement => {
+      datasetServiceStub.getDataset.mockReturnValue(of(makeDashboardDataset({ accessPrivilege: "WRITE", isOwner })));
+      createComponent();
+      fixture.detectChanges();
+
+      const tabButtons: NodeListOf<HTMLElement> = fixture.nativeElement.querySelectorAll(".ant-tabs-tab-btn");
+      const settingsTab = Array.from(tabButtons).find(tab => tab.textContent?.includes("Settings"));
+      settingsTab?.click();
+      fixture.detectChanges();
+
+      return fixture.nativeElement.querySelector('button[title="Delete"]') as HTMLButtonElement;
+    };
+
+    it("disables the delete button for a non-owner with write access", () => {
+      const button = renderDeleteButton(false);
+
+      expect(button).toBeTruthy();
+      expect(button.disabled).toBe(true);
+    });
+
+    it("enables the delete button for the owner", () => {
+      const button = renderDeleteButton(true);
+
+      expect(button).toBeTruthy();
+      expect(button.disabled).toBe(false);
+    });
+  });
 });
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 bdef5e0168..3581459670 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
@@ -18,9 +18,15 @@
  */
 
 import { Component, EventEmitter, OnInit, Output, ViewChild } from "@angular/core";
-import { ActivatedRoute } from "@angular/router";
+import { ActivatedRoute, Router } from "@angular/router";
+import { USER_DATASET } from "../../../../../app-routing.constant";
+import { extractErrorMessage } from "../../../../../common/util/error";
 import { UntilDestroy, untilDestroyed } from "@ngneat/until-destroy";
-import { DatasetService, MultipartUploadProgress } from "../../../../service/user/dataset/dataset.service";
+import {
+  DatasetService,
+  MultipartUploadProgress,
+  validateDatasetName,
+} from "../../../../service/user/dataset/dataset.service";
 import { NzResizeEvent, NzResizableDirective, NzResizeHandleComponent } from "ng-zorro-antd/resizable";
 import {
   DatasetFileNode,
@@ -51,7 +57,7 @@ import { ɵNzTransitionPatchDirective } from "ng-zorro-antd/core/transition-patc
 import { NzIconDirective } from "ng-zorro-antd/icon";
 import { NzSpaceCompactItemDirective } from "ng-zorro-antd/space";
 import { NzButtonComponent } from "ng-zorro-antd/button";
-import { NzPopoverDirective } from "ng-zorro-antd/popover";
+import { NzPopconfirmDirective } from "ng-zorro-antd/popconfirm";
 import { NzSwitchComponent } from "ng-zorro-antd/switch";
 import { FormsModule } from "@angular/forms";
 import { MarkdownDescriptionComponent } from "../../markdown-description/markdown-description.component";
@@ -68,6 +74,7 @@ import { NzProgressComponent } from "ng-zorro-antd/progress";
 import { UserDatasetStagedObjectsListComponent } from "./user-dataset-staged-objects-list/user-dataset-staged-objects-list.component";
 import { NzInputDirective } from "ng-zorro-antd/input";
 import { CdkFixedSizeVirtualScroll, CdkVirtualForOf, CdkVirtualScrollViewport } from "@angular/cdk/scrolling";
+import { NzTabsComponent, NzTabComponent } from "ng-zorro-antd/tabs";
 
 export const THROTTLE_TIME_MS = 1000;
 export const ABORT_RETRY_MAX_ATTEMPTS = 10;
@@ -88,7 +95,7 @@ export const ABORT_RETRY_BACKOFF_BASE_MS = 100;
     NzIconDirective,
     NzSpaceCompactItemDirective,
     NzButtonComponent,
-    NzPopoverDirective,
+    NzPopconfirmDirective,
     NzSwitchComponent,
     FormsModule,
     MarkdownDescriptionComponent,
@@ -114,11 +121,14 @@ export const ABORT_RETRY_BACKOFF_BASE_MS = 100;
     CdkVirtualScrollViewport,
     CdkFixedSizeVirtualScroll,
     CdkVirtualForOf,
+    NzTabsComponent,
+    NzTabComponent,
   ],
 })
 export class DatasetDetailComponent implements OnInit {
   public did: number | undefined;
   public datasetName: string = "";
+  public editedDatasetName: string = "";
   public datasetDescription: string = "";
   public datasetCreationTime: string = "";
   public datasetCreationTimeTooltip: string = "";
@@ -194,6 +204,7 @@ export class DatasetDetailComponent implements OnInit {
 
   constructor(
     private route: ActivatedRoute,
+    private router: Router,
     private modalService: NzModalService,
     private datasetService: DatasetService,
     private notificationService: NotificationService,
@@ -359,6 +370,7 @@ export class DatasetDetailComponent implements OnInit {
         .subscribe(dashboardDataset => {
           const dataset = dashboardDataset.dataset;
           this.datasetName = dataset.name;
+          this.editedDatasetName = dataset.name;
           this.datasetDescription = dataset.description;
           this.userDatasetAccessLevel = dashboardDataset.accessPrivilege;
           this.datasetIsPublic = dataset.isPublic;
@@ -917,6 +929,52 @@ export class DatasetDetailComponent implements OnInit {
       });
   }
 
+  onSaveDatasetName(): void {
+    if (!this.did) {
+      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;
+    const nameError = validateDatasetName(name);
+    if (nameError) {
+      this.notificationService.error(nameError);
+      return;
+    }
+
+    this.datasetService
+      .updateDatasetName(this.did, name)
+      .pipe(untilDestroyed(this))
+      .subscribe({
+        next: () => {
+          this.datasetName = name;
+          this.editedDatasetName = name;
+          this.notificationService.success(`Dataset name updated to '${name}'`);
+        },
+        error: (err: unknown) => {
+          this.notificationService.error(extractErrorMessage(err));
+        },
+      });
+  }
+
+  onDeleteDataset(): void {
+    if (!this.did) {
+      return;
+    }
+    this.datasetService
+      .deleteDatasets(this.did)
+      .pipe(untilDestroyed(this))
+      .subscribe({
+        next: () => {
+          this.notificationService.success(`Dataset ${this.datasetName} was deleted`);
+          this.router.navigate([USER_DATASET]);
+        },
+        error: (err: unknown) => {
+          this.notificationService.error(extractErrorMessage(err));
+        },
+      });
+  }
+
   async copyCurrentFilePath(): Promise<void> {
     if (!this.currentDisplayedFileName) {
       return;