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