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

yiconghuang pushed a commit to branch feat/add-model
in repository https://gitbox.apache.org/repos/asf/texera.git

commit 900f4d182f03782985ddfb5683ac5a00f5140fae
Author: Yicong Huang <[email protected]>
AuthorDate: Wed Aug 27 02:37:55 2025 -0700

    feat: add share and icons
---
 core/gui/src/app/app.module.ts                     |  4 ++
 .../user/list-item/list-item.component.ts          | 18 +++++-
 ...nt.html => user-model-list-item.component.html} | 32 +++++------
 ...nt.scss => user-model-list-item.component.scss} |  0
 ...ponent.ts => user-model-list-item.component.ts} | 65 +++++++++++-----------
 .../dashboard/service/user/model/model.service.ts  | 54 +++++++++---------
 6 files changed, 97 insertions(+), 76 deletions(-)

diff --git a/core/gui/src/app/app.module.ts b/core/gui/src/app/app.module.ts
index acf9803b9c..b353e529e3 100644
--- a/core/gui/src/app/app.module.ts
+++ b/core/gui/src/app/app.module.ts
@@ -186,6 +186,9 @@ import {
   InputAutoCompleteModelComponent
 } from 
"./workspace/component/input-autocomplete-model/input-auto-complete-model.component";
 import { ModelSelectionComponent } from 
"./workspace/component/model-selection/model-selection.component";
+import {
+  UserModelListItemComponent
+} from 
"./dashboard/component/user/user-model/user-dataset-list-item/user-model-list-item.component";
 
 registerLocaleData(en);
 
@@ -213,6 +216,7 @@ registerLocaleData(en);
     UserAvatarComponent,
     LocalLoginComponent,
     UserWorkflowComponent,
+    UserModelListItemComponent,
     UserQuotaComponent,
     RowModalComponent,
     OperatorLabelComponent,
diff --git 
a/core/gui/src/app/dashboard/component/user/list-item/list-item.component.ts 
b/core/gui/src/app/dashboard/component/user/list-item/list-item.component.ts
index c6aa7574a7..f4b298a660 100644
--- a/core/gui/src/app/dashboard/component/user/list-item/list-item.component.ts
+++ b/core/gui/src/app/dashboard/component/user/list-item/list-item.component.ts
@@ -51,6 +51,7 @@ import {
   DASHBOARD_USER_WORKSPACE,
 } from "../../../../app-routing.constant";
 import { isDefined } from "../../../../common/util/predicate";
+import { ModelService } from "../../../service/user/model/model.service";
 
 @UntilDestroy()
 @Component({
@@ -100,6 +101,7 @@ export class ListItemComponent implements OnChanges {
     private modalService: NzModalService,
     private workflowPersistService: WorkflowPersistService,
     private datasetService: DatasetService,
+    private modelService: ModelService,
     private modal: NzModalService,
     private hubService: HubService,
     private downloadService: DownloadService,
@@ -144,7 +146,7 @@ export class ListItemComponent implements OnChanges {
         } else {
           this.entryLink = [DASHBOARD_HUB_MODEL_RESULT_DETAIL, 
String(this.entry.id)];
         }
-        this.iconType = "database";
+        this.iconType = "code-sandbox";
         this.size = this.entry.size;
       }
     } else if (this.entry.type === "file") {
@@ -202,6 +204,20 @@ export class ListItemComponent implements OnChanges {
         nzCentered: true,
         nzWidth: "700px",
       });
+    }else if (this.entry.type === "model") {
+      modal = this.modalService.create({
+        nzContent: ShareAccessComponent,
+        nzData: {
+          writeAccess: this.entry.accessLevel === "WRITE",
+          type: "model",
+          id: this.entry.id,
+          allOwners: await firstValueFrom(this.modelService.retrieveOwners()),
+        },
+        nzFooter: null,
+        nzTitle: "Share this model with others",
+        nzCentered: true,
+        nzWidth: "700px",
+      });
     }
     if (modal) {
       modal.componentInstance?.refresh.pipe(untilDestroyed(this)).subscribe(() 
=> {
diff --git 
a/core/gui/src/app/dashboard/component/user/user-model/user-dataset-list-item/user-dataset-list-item.component.html
 
b/core/gui/src/app/dashboard/component/user/user-model/user-dataset-list-item/user-model-list-item.component.html
similarity index 86%
rename from 
core/gui/src/app/dashboard/component/user/user-model/user-dataset-list-item/user-dataset-list-item.component.html
rename to 
core/gui/src/app/dashboard/component/user/user-model/user-dataset-list-item/user-model-list-item.component.html
index 4f7d5e0195..d1ff4c9255 100644
--- 
a/core/gui/src/app/dashboard/component/user/user-model/user-dataset-list-item/user-dataset-list-item.component.html
+++ 
b/core/gui/src/app/dashboard/component/user/user-model/user-dataset-list-item/user-model-list-item.component.html
@@ -24,33 +24,33 @@
       <nz-avatar
         [ngStyle]="{ 'background-color': 'grey', 'vertical-align': 'middle' }"
         [nzGap]="4"
-        [nzText]="'' + dataset.did"
+        [nzText]="'' + model.mid"
         nzSize="default"></nz-avatar>
     </nz-list-item-meta-avatar>
 
-    <!-- editable name of saved dataset -->
+    <!-- editable name of saved model -->
     <nz-list-item-meta-title class="meta-title-container">
       <div class="dataset-item-meta-title">
         <a
           *ngIf="!editingName; else customDatasetTitle "
-          [routerLink]="DASHBOARD_USER_DATASET + '/' + dataset.did"
+          [routerLink]="DASHBOARD_USER_DATASET + '/' + model.mid"
           class="dataset-name"
-          >{{ dataset.name }}</a
+        >{{ model.name }}</a
         >
         <ng-template #customDatasetTitle>
           <input
             #customName
             (focusout)="confirmUpdateDatasetCustomName(customName.value)"
             (keyup.enter)="confirmUpdateDatasetCustomName(customName.value)"
-            placeholder="{{ dataset.name }}"
-            value="{{ dataset.name }}" />
+            placeholder="{{ model.name }}"
+            value="{{ model.name }}" />
         </ng-template>
         <button
           *ngIf="editable && entry.accessPrivilege === 'WRITE'"
           (click)="editingName = true"
           nz-button
-          mat-card-title="Customize Dataset Name"
-          nz-tooltip="Customize Dataset Name"
+          mat-card-title="Customize Model Name"
+          nz-tooltip="Customize Model Name"
           nzSize="small"
           nzTooltipPlacement="bottom"
           nzType="text">
@@ -93,14 +93,14 @@
       </div>
     </nz-list-item-meta-title>
 
-    <!-- editable description of saved dataset -->
+    <!-- editable description of saved model -->
     <nz-list-item-meta-description>
       <div class="dataset-item-meta-description">
         <label
           *ngIf="!editingDescription; else customDatasetDescription "
           (click)="editingDescription = editable && entry.accessPrivilege == 
'WRITE'"
           class="dataset-description-label">
-          {{ dataset.description }}
+          {{ model.description }}
         </label>
         <ng-template #customDatasetDescription>
           <input
@@ -109,7 +109,7 @@
             
(focusout)="confirmUpdateDatasetCustomDescription(customDescription.value)"
             
(keyup.enter)="confirmUpdateDatasetCustomDescription(customDescription.value)"
             class="dataset-editable-description-input"
-            value="{{ dataset.description }}"
+            value="{{ model.description }}"
             maxlength="500" />
         </ng-template>
       </div>
@@ -121,8 +121,8 @@
       <button
         (click)="onClickOpenShareAccess()"
         nz-button
-        nz-tooltip="Share the dataset {{
-                      dataset.name
+        nz-tooltip="Share the Model {{
+                      model.name
                   }} to others"
         nzTooltipPlacement="bottom"
         type="button">
@@ -136,12 +136,12 @@
       <button
         (nzOnConfirm)="deleted.emit()"
         nz-popconfirm
-        nzPopconfirmTitle="Confirm to delete this dataset."
+        nzPopconfirmTitle="Confirm to delete this Model."
         [disabled]="!entry.isOwner"
         class="delete-dataset-btn"
         nz-button
-        nz-tooltip="Delete the dataset {{
-                      dataset.name
+        nz-tooltip="Delete the model {{
+                      model.name
                   }}"
         nzTooltipPlacement="bottom">
         <i
diff --git 
a/core/gui/src/app/dashboard/component/user/user-model/user-dataset-list-item/user-dataset-list-item.component.scss
 
b/core/gui/src/app/dashboard/component/user/user-model/user-dataset-list-item/user-model-list-item.component.scss
similarity index 100%
rename from 
core/gui/src/app/dashboard/component/user/user-model/user-dataset-list-item/user-dataset-list-item.component.scss
rename to 
core/gui/src/app/dashboard/component/user/user-model/user-dataset-list-item/user-model-list-item.component.scss
diff --git 
a/core/gui/src/app/dashboard/component/user/user-model/user-dataset-list-item/user-dataset-list-item.component.ts
 
b/core/gui/src/app/dashboard/component/user/user-model/user-dataset-list-item/user-model-list-item.component.ts
similarity index 64%
rename from 
core/gui/src/app/dashboard/component/user/user-model/user-dataset-list-item/user-dataset-list-item.component.ts
rename to 
core/gui/src/app/dashboard/component/user/user-model/user-dataset-list-item/user-model-list-item.component.ts
index c18d37ee0c..7b9a050a75 100644
--- 
a/core/gui/src/app/dashboard/component/user/user-model/user-dataset-list-item/user-dataset-list-item.component.ts
+++ 
b/core/gui/src/app/dashboard/component/user/user-model/user-dataset-list-item/user-model-list-item.component.ts
@@ -19,47 +19,47 @@
 
 import { UntilDestroy, untilDestroyed } from "@ngneat/until-destroy";
 import { Component, EventEmitter, Input, Output } from "@angular/core";
-import { Dataset } from "../../../../../common/type/dataset";
-import { DatasetService } from 
"../../../../service/user/dataset/dataset.service";
 import { ShareAccessComponent } from 
"../../share-access/share-access.component";
 import { NotificationService } from 
"../../../../../common/service/notification/notification.service";
 import { NzModalService } from "ng-zorro-antd/modal";
-import { DashboardDataset } from 
"../../../../type/dashboard-dataset.interface";
 import { DASHBOARD_USER_DATASET } from "../../../../../app-routing.constant";
+import { DashboardModel } from "../../../../type/dashboard-model.interface";
+import { Model } from "../../../../../common/type/model";
+import { ModelService } from "../../../../service/user/model/model.service";
 
 @UntilDestroy()
 @Component({
-  selector: "texera-user-dataset-list-item",
-  templateUrl: "./user-dataset-list-item.component.html",
-  styleUrls: ["./user-dataset-list-item.component.scss"],
+  selector: "texera-user-model-list-item",
+  templateUrl: "./user-model-list-item.component.html",
+  styleUrls: ["./user-model-list-item.component.scss"],
 })
-export class UserDatasetListItemComponent {
+export class UserModelListItemComponent {
   protected readonly DASHBOARD_USER_DATASET = DASHBOARD_USER_DATASET;
 
-  private _entry?: DashboardDataset;
+  private _entry?: DashboardModel;
 
   @Output()
   refresh = new EventEmitter<void>();
 
   @Input()
-  get entry(): DashboardDataset {
+  get entry(): DashboardModel {
     if (!this._entry) {
       throw new Error("entry property must be provided to 
UserDatasetListItemComponent.");
     }
     return this._entry;
   }
 
-  set entry(value: DashboardDataset) {
+  set entry(value: DashboardModel) {
     this._entry = value;
   }
 
-  get dataset(): Dataset {
-    if (!this.entry.dataset) {
+  get model(): Model {
+    if (!this.entry.model) {
       throw new Error(
-        "Incorrect type of DashboardEntry provided to 
UserDatasetListItemComponent. Entry must be dataset."
+        "Incorrect type of DashboardEntry provided to 
UserModelListItemComponent. Entry must be model.",
       );
     }
-    return this.entry.dataset;
+    return this.entry.model;
   }
 
   @Input() editable = false;
@@ -71,47 +71,48 @@ export class UserDatasetListItemComponent {
 
   constructor(
     private modalService: NzModalService,
-    private datasetService: DatasetService,
-    private notificationService: NotificationService
-  ) {}
+    private modelService: ModelService,
+    private notificationService: NotificationService,
+  ) {
+  }
 
   public confirmUpdateDatasetCustomName(name: string) {
-    if (this.entry.dataset.name === name) {
+    if (this.entry.model.name === name) {
       return;
     }
 
-    if (this.entry.dataset.did)
-      this.datasetService
-        .updateDatasetName(this.entry.dataset.did, name)
+    if (this.entry.model.mid)
+      this.modelService
+        .updateModelName(this.entry.model.mid, name)
         .pipe(untilDestroyed(this))
         .subscribe({
           next: () => {
-            this.entry.dataset.name = name;
+            this.entry.model.name = name;
             this.editingName = false;
           },
           error: () => {
-            this.notificationService.error("Update dataset name failed");
+            this.notificationService.error("Update model name failed");
             this.editingName = false;
           },
         });
   }
 
   public confirmUpdateDatasetCustomDescription(description: string) {
-    if (this.entry.dataset.description === description) {
+    if (this.entry.model.description === description) {
       return;
     }
 
-    if (this.entry.dataset.did)
-      this.datasetService
-        .updateDatasetDescription(this.entry.dataset.did, description)
+    if (this.entry.model.mid)
+      this.modelService
+        .updateModelDescription(this.entry.model.mid, description)
         .pipe(untilDestroyed(this))
         .subscribe({
           next: () => {
-            this.entry.dataset.description = description;
+            this.entry.model.description = description;
             this.editingDescription = false;
           },
           error: () => {
-            this.notificationService.error("Update dataset description 
failed");
+            this.notificationService.error("Update model description failed");
             this.editingDescription = false;
           },
         });
@@ -122,11 +123,11 @@ export class UserDatasetListItemComponent {
       nzContent: ShareAccessComponent,
       nzData: {
         writeAccess: this.entry.accessPrivilege === "WRITE",
-        type: "dataset",
-        id: this.dataset.did,
+        type: "model",
+        id: this.model.mid,
       },
       nzFooter: null,
-      nzTitle: "Share this dataset with others",
+      nzTitle: "Share this model with others",
       nzCentered: true,
     });
   }
diff --git a/core/gui/src/app/dashboard/service/user/model/model.service.ts 
b/core/gui/src/app/dashboard/service/user/model/model.service.ts
index 06042ab036..0670803583 100644
--- a/core/gui/src/app/dashboard/service/user/model/model.service.ts
+++ b/core/gui/src/app/dashboard/service/user/model/model.service.ts
@@ -30,22 +30,22 @@ import { GuiConfigService } from 
"../../../../common/service/gui-config.service"
 
 export const MODEL_BASE_URL = "model";
 export const MODEL_CREATE_URL = MODEL_BASE_URL + "/create";
-export const DATASET_UPDATE_BASE_URL = MODEL_BASE_URL + "/update";
-export const DATASET_UPDATE_NAME_URL = DATASET_UPDATE_BASE_URL + "/name";
-export const DATASET_UPDATE_DESCRIPTION_URL = DATASET_UPDATE_BASE_URL + 
"/description";
-export const DATASET_UPDATE_PUBLICITY_URL = "update/publicity";
-export const DATASET_UPDATE_DOWNLOADABLE_URL = "update/downloadable";
-export const DATASET_LIST_URL = MODEL_BASE_URL + "/list";
-export const DATASET_SEARCH_URL = MODEL_BASE_URL + "/search";
-export const DATASET_DELETE_URL = MODEL_BASE_URL + "/delete";
-
-export const DATASET_VERSION_BASE_URL = "version";
-export const DATASET_VERSION_RETRIEVE_LIST_URL = DATASET_VERSION_BASE_URL + 
"/list";
-export const DATASET_VERSION_LATEST_URL = DATASET_VERSION_BASE_URL + "/latest";
-export const DEFAULT_DATASET_NAME = "Untitled model";
-export const DATASET_PUBLIC_VERSION_BASE_URL = "publicVersion";
-export const DATASET_PUBLIC_VERSION_RETRIEVE_LIST_URL = 
DATASET_PUBLIC_VERSION_BASE_URL + "/list";
-export const DATASET_GET_OWNERS_URL = MODEL_BASE_URL + "/user-model-owners";
+export const MODEL_UPDATE_BASE_URL = MODEL_BASE_URL + "/update";
+export const MODEL_UPDATE_NAME_URL = MODEL_UPDATE_BASE_URL + "/name";
+export const MODEL_UPDATE_DESCRIPTION_URL = MODEL_UPDATE_BASE_URL + 
"/description";
+export const MODEL_UPDATE_PUBLICITY_URL = "update/publicity";
+export const MODEL_UPDATE_DOWNLOADABLE_URL = "update/downloadable";
+export const MODEL_LIST_URL = MODEL_BASE_URL + "/list";
+export const MODEL_SEARCH_URL = MODEL_BASE_URL + "/search";
+export const MODEL_DELETE_URL = MODEL_BASE_URL + "/delete";
+
+export const MODEL_VERSION_BASE_URL = "version";
+export const MODEL_VERSION_RETRIEVE_LIST_URL = MODEL_VERSION_BASE_URL + 
"/list";
+export const MODEL_VERSION_LATEST_URL = MODEL_VERSION_BASE_URL + "/latest";
+export const DEFAULT_MODEL_NAME = "Untitled model";
+export const MODEL_PUBLIC_VERSION_BASE_URL = "publicVersion";
+export const MODEL_PUBLIC_VERSION_RETRIEVE_LIST_URL = 
MODEL_PUBLIC_VERSION_BASE_URL + "/list";
+export const MODEL_GET_OWNERS_URL = MODEL_BASE_URL + "/user-model-owners";
 
 export interface MultipartUploadProgress {
   filePath: string;
@@ -120,7 +120,7 @@ export class ModelService {
   }
 
   public retrieveAccessibleModels(): Observable<DashboardModel[]> {
-    return 
this.http.get<DashboardModel[]>(`${AppSettings.getApiEndpoint()}/${DATASET_LIST_URL}`);
+    return 
this.http.get<DashboardModel[]>(`${AppSettings.getApiEndpoint()}/${MODEL_LIST_URL}`);
   }
   public createModelVersion(did: number, newVersion: string): 
Observable<ModelVersion> {
     return this.http
@@ -446,8 +446,8 @@ export class ModelService {
    */
   public retrieveModelVersionList(did: number, isLogin: boolean = true): 
Observable<ModelVersion[]> {
     const apiEndPont = isLogin
-      ? 
`${AppSettings.getApiEndpoint()}/${MODEL_BASE_URL}/${did}/${DATASET_VERSION_RETRIEVE_LIST_URL}`
-      : 
`${AppSettings.getApiEndpoint()}/${MODEL_BASE_URL}/${did}/${DATASET_PUBLIC_VERSION_RETRIEVE_LIST_URL}`;
+      ? 
`${AppSettings.getApiEndpoint()}/${MODEL_BASE_URL}/${did}/${MODEL_VERSION_RETRIEVE_LIST_URL}`
+      : 
`${AppSettings.getApiEndpoint()}/${MODEL_BASE_URL}/${did}/${MODEL_PUBLIC_VERSION_RETRIEVE_LIST_URL}`;
     return this.http.get<ModelVersion[]>(apiEndPont);
   }
 
@@ -460,7 +460,7 @@ export class ModelService {
       .get<{
         modelVersion: ModelVersion;
         fileNodes: DatasetFileNode[];
-      
}>(`${AppSettings.getApiEndpoint()}/${MODEL_BASE_URL}/${did}/${DATASET_VERSION_LATEST_URL}`)
+      
}>(`${AppSettings.getApiEndpoint()}/${MODEL_BASE_URL}/${did}/${MODEL_VERSION_LATEST_URL}`)
       .pipe(
         map(response => {
           response.modelVersion.fileNodes = response.fileNodes;
@@ -481,8 +481,8 @@ export class ModelService {
     isLogin: boolean = true
   ): Observable<{ fileNodes: DatasetFileNode[]; size: number }> {
     const apiUrl = isLogin
-      ? 
`${AppSettings.getApiEndpoint()}/${MODEL_BASE_URL}/${did}/${DATASET_VERSION_BASE_URL}/${dvid}/rootFileNodes`
-      : 
`${AppSettings.getApiEndpoint()}/${MODEL_BASE_URL}/${did}/${DATASET_PUBLIC_VERSION_BASE_URL}/${dvid}/rootFileNodes`;
+      ? 
`${AppSettings.getApiEndpoint()}/${MODEL_BASE_URL}/${did}/${MODEL_VERSION_BASE_URL}/${dvid}/rootFileNodes`
+      : 
`${AppSettings.getApiEndpoint()}/${MODEL_BASE_URL}/${did}/${MODEL_PUBLIC_VERSION_BASE_URL}/${dvid}/rootFileNodes`;
     return this.http.get<{ fileNodes: DatasetFileNode[]; size: number 
}>(apiUrl);
   }
 
@@ -491,14 +491,14 @@ export class ModelService {
   }
 
   public updateModelName(did: number, name: string): Observable<Response> {
-    return 
this.http.post<Response>(`${AppSettings.getApiEndpoint()}/${DATASET_UPDATE_NAME_URL}`,
 {
+    return 
this.http.post<Response>(`${AppSettings.getApiEndpoint()}/${MODEL_UPDATE_NAME_URL}`,
 {
       did: did,
       name: name,
     });
   }
 
   public updateModelDescription(did: number, description: string): 
Observable<Response> {
-    return 
this.http.post<Response>(`${AppSettings.getApiEndpoint()}/${DATASET_UPDATE_DESCRIPTION_URL}`,
 {
+    return 
this.http.post<Response>(`${AppSettings.getApiEndpoint()}/${MODEL_UPDATE_DESCRIPTION_URL}`,
 {
       did: did,
       description: description,
     });
@@ -506,19 +506,19 @@ export class ModelService {
 
   public updateModelPublicity(did: number): Observable<Response> {
     return this.http.post<Response>(
-      
`${AppSettings.getApiEndpoint()}/${MODEL_BASE_URL}/${did}/${DATASET_UPDATE_PUBLICITY_URL}`,
+      
`${AppSettings.getApiEndpoint()}/${MODEL_BASE_URL}/${did}/${MODEL_UPDATE_PUBLICITY_URL}`,
       {}
     );
   }
 
   public updateModelDownloadable(did: number): Observable<Response> {
     return this.http.post<Response>(
-      
`${AppSettings.getApiEndpoint()}/${MODEL_BASE_URL}/${did}/${DATASET_UPDATE_DOWNLOADABLE_URL}`,
+      
`${AppSettings.getApiEndpoint()}/${MODEL_BASE_URL}/${did}/${MODEL_UPDATE_DOWNLOADABLE_URL}`,
       {}
     );
   }
 
   public retrieveOwners(): Observable<string[]> {
-    return 
this.http.get<string[]>(`${AppSettings.getApiEndpoint()}/${DATASET_GET_OWNERS_URL}`);
+    return 
this.http.get<string[]>(`${AppSettings.getApiEndpoint()}/${MODEL_GET_OWNERS_URL}`);
   }
 }

Reply via email to