xuang7 commented on code in PR #6493:
URL: https://github.com/apache/texera/pull/6493#discussion_r3608881755


##########
frontend/src/app/dashboard/component/user/user-dataset/user-dataset-explorer/dataset-detail.component.ts:
##########
@@ -908,6 +915,50 @@ export class DatasetDetailComponent implements OnInit {
       });
   }
 
+  onSaveDatasetName(): void {
+    if (!this.did) {
+      return;
+    }
+    // Sanitize using the same rules as dataset creation: trim leading 
whitespace,
+    // collapse runs of non-alphanumeric characters to a single "-", then 
lowercase.
+    const sanitizedName = this.editedDatasetName

Review Comment:
   Since #6426 was merged, all other rename flows now validate and reject 
invalid input instead of silently rewriting it. validateDatasetName is also 
exported from dataset.service.ts, so we could reuse it here to keep all four 
rename entry points consistent.



##########
frontend/src/app/dashboard/component/user/user-dataset/user-dataset-explorer/dataset-detail.component.html:
##########
@@ -127,366 +86,477 @@ <h2>Dataset: {{datasetName}}</h2>
     <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"
+              [disabled]="!userHasWriteAccess()"
+              (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"
+              (nzOnConfirm)="onDeleteDataset()"

Review Comment:
   The backend's delete is owner-only, and the Datasets list page disables its 
delete button with !entry.isOwner (the Downloadable switch above does too). 
Missing [disabled]="!isOwner" here, so a write-access collaborator gets an 
active button that always fails.



##########
frontend/src/app/dashboard/component/user/user-dataset/user-dataset-explorer/dataset-detail.component.ts:
##########
@@ -908,6 +915,50 @@ export class DatasetDetailComponent implements OnInit {
       });
   }
 
+  onSaveDatasetName(): void {
+    if (!this.did) {
+      return;
+    }
+    // Sanitize using the same rules as dataset creation: trim leading 
whitespace,
+    // collapse runs of non-alphanumeric characters to a single "-", then 
lowercase.
+    const sanitizedName = this.editedDatasetName
+      .trimStart()
+      .replace(/[^a-zA-Z0-9]+/g, "-")
+      .toLowerCase();
+
+    this.datasetService
+      .updateDatasetName(this.did, sanitizedName)
+      .pipe(untilDestroyed(this))
+      .subscribe({
+        next: () => {
+          this.datasetName = sanitizedName;
+          this.editedDatasetName = sanitizedName;
+          this.notificationService.success(`Dataset name updated to 
'${sanitizedName}'`);
+        },
+        error: (err: unknown) => {
+          this.notificationService.error("Failed to update dataset name");

Review Comment:
   The new rename backend returns the actual error reason (e.g., "Dataset with 
the same name already exists"). Could we surface it using 
`extractErrorMessage(err)` from `common/util/error`, as the other rename 
handlers do?



##########
frontend/src/app/dashboard/component/user/user-dataset/user-dataset-explorer/dataset-detail.component.ts:
##########
@@ -908,6 +915,50 @@ export class DatasetDetailComponent implements OnInit {
       });
   }
 
+  onSaveDatasetName(): void {
+    if (!this.did) {
+      return;
+    }
+    // Sanitize using the same rules as dataset creation: trim leading 
whitespace,
+    // collapse runs of non-alphanumeric characters to a single "-", then 
lowercase.
+    const sanitizedName = this.editedDatasetName
+      .trimStart()
+      .replace(/[^a-zA-Z0-9]+/g, "-")
+      .toLowerCase();
+
+    this.datasetService
+      .updateDatasetName(this.did, sanitizedName)
+      .pipe(untilDestroyed(this))
+      .subscribe({
+        next: () => {
+          this.datasetName = sanitizedName;
+          this.editedDatasetName = sanitizedName;
+          this.notificationService.success(`Dataset name updated to 
'${sanitizedName}'`);
+        },
+        error: (err: unknown) => {
+          this.notificationService.error("Failed to update dataset name");
+        },
+      });
+  }
+
+  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("Failed to delete the dataset");

Review Comment:
   Same here.



##########
frontend/src/app/dashboard/component/user/user-dataset/user-dataset-explorer/dataset-detail.component.html:
##########
@@ -127,366 +86,477 @@ <h2>Dataset: {{datasetName}}</h2>
     <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"
+              [disabled]="!userHasWriteAccess()"

Review Comment:
   The tab is already behind *ngIf="userHasWriteAccess()".



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