From bba0f6cc2f806c23c0e4f4b49ca77a863f1894cf Mon Sep 17 00:00:00 2001 From: Xinyuan Lin Date: Thu, 11 Jul 2024 15:23:13 -0700 Subject: [PATCH 01/33] init --- core/gui/src/app/hub/hub.component.html | 52 +++++++++++++++++++++++++ core/gui/src/app/hub/hub.component.scss | 33 ++++++++++++++++ core/gui/src/app/hub/hub.component.ts | 42 ++++++++++++++++++++ 3 files changed, 127 insertions(+) create mode 100644 core/gui/src/app/hub/hub.component.html create mode 100644 core/gui/src/app/hub/hub.component.scss create mode 100644 core/gui/src/app/hub/hub.component.ts diff --git a/core/gui/src/app/hub/hub.component.html b/core/gui/src/app/hub/hub.component.html new file mode 100644 index 00000000000..a8d882d2dfe --- /dev/null +++ b/core/gui/src/app/hub/hub.component.html @@ -0,0 +1,52 @@ + +
+
+

Collaborative Data Analytics Using Workflows

+

+
+ Texera supports scalable computation and enables advanced AI/ML techniques. +
+ "Collaboration" is a key focus, and we enable an experience similar to Google Docs, but for data analytics. +
+

+ +
+ +
diff --git a/core/gui/src/app/hub/hub.component.scss b/core/gui/src/app/hub/hub.component.scss new file mode 100644 index 00000000000..1c14c791c9d --- /dev/null +++ b/core/gui/src/app/hub/hub.component.scss @@ -0,0 +1,33 @@ +.content { + text-align: center; +} + +ul { + list-style-type: none; + height: 70px; + padding: 10px; + overflow: hidden; + background-color: #f8f9fa; + vertical-align: baseline; +} + +li { + float: left; + padding: 14px; +} + +li a { + color: black; + font-weight: bold; +} + +#logo { + height: 70px; + padding: 0; + margin-right: 14px; +} + +#googleButton { + float: right; + padding: 5px 0; +} diff --git a/core/gui/src/app/hub/hub.component.ts b/core/gui/src/app/hub/hub.component.ts new file mode 100644 index 00000000000..d0b2ceea642 --- /dev/null +++ b/core/gui/src/app/hub/hub.component.ts @@ -0,0 +1,42 @@ +import { Component, OnInit } from "@angular/core"; +import { environment } from "../../../environments/environment"; +import { UserService } from "../../common/service/user/user.service"; +import { ActivatedRoute, Router } from "@angular/router"; +import { catchError, mergeMap } from "rxjs/operators"; +import { throwError } from "rxjs"; +import { NotificationService } from "../../common/service/notification/notification.service"; +import { UntilDestroy, untilDestroyed } from "@ngneat/until-destroy"; +import { GoogleAuthService } from "../../common/service/user/google-auth.service"; + +@UntilDestroy() +@Component({ + selector: "texera-hub", + templateUrl: "./hub.component.html", + styleUrls: ["./hub.component.scss"], +}) +export class HubComponent implements OnInit { + localLogin = environment.localLogin; + constructor( + private userService: UserService, + private route: ActivatedRoute, + private googleAuthService: GoogleAuthService, + private notificationService: NotificationService, + private router: Router + ) {} + + ngOnInit(): void { + this.googleAuthService.googleAuthInit(document.getElementById("googleButton")); + this.googleAuthService.googleCredentialResponse + .pipe(mergeMap(res => this.userService.googleLogin(res.credential))) + .pipe( + catchError((e: unknown) => { + this.notificationService.error((e as Error).message, { nzDuration: 10 }); + return throwError(() => e); + }), + untilDestroyed(this) + ) + .subscribe(() => + this.router.navigateByUrl(this.route.snapshot.queryParams["returnUrl"] || "/dashboard/workflow") + ); + } +} From 038bb13e0e250d2131e7879804d0dd95cef2f256 Mon Sep 17 00:00:00 2001 From: Xinyuan Lin Date: Thu, 11 Jul 2024 16:24:25 -0700 Subject: [PATCH 02/33] expand dashboard menu --- .../src/app/dashboard/user/component/dashboard.component.html | 1 - 1 file changed, 1 deletion(-) diff --git a/core/gui/src/app/dashboard/user/component/dashboard.component.html b/core/gui/src/app/dashboard/user/component/dashboard.component.html index f1f6256afb0..cb7aaaebd9a 100644 --- a/core/gui/src/app/dashboard/user/component/dashboard.component.html +++ b/core/gui/src/app/dashboard/user/component/dashboard.component.html @@ -9,7 +9,6 @@
    Date: Fri, 12 Jul 2024 13:48:44 -0700 Subject: [PATCH 03/33] update --- core/gui/src/app/app.module.ts | 2 + core/gui/src/app/hub/hub.component.html | 131 ++++++++++++++---------- core/gui/src/app/hub/hub.component.scss | 37 ++----- core/gui/src/app/hub/hub.component.ts | 41 +------- 4 files changed, 94 insertions(+), 117 deletions(-) diff --git a/core/gui/src/app/app.module.ts b/core/gui/src/app/app.module.ts index 0a53a47d533..ee8a2ab2987 100644 --- a/core/gui/src/app/app.module.ts +++ b/core/gui/src/app/app.module.ts @@ -133,6 +133,7 @@ import { TreeModule } from "@ali-hm/angular-tree-component"; import { EnvironmentComponent } from "./workspace/component/left-panel/environment/environment.component"; import { FileSelectionComponent } from "./workspace/component/file-selection/file-selection.component"; import { ResultExportationComponent } from "./workspace/component/result-exportation/result-exportation.component"; +import { HubComponent } from "./hub/hub.component"; registerLocaleData(en); @@ -215,6 +216,7 @@ registerLocaleData(en); WorkflowRuntimeStatisticsComponent, FlarumComponent, HighlightSearchTermsPipe, + HubComponent ], imports: [ BrowserModule, diff --git a/core/gui/src/app/hub/hub.component.html b/core/gui/src/app/hub/hub.component.html index a8d882d2dfe..bc5f2292630 100644 --- a/core/gui/src/app/hub/hub.component.html +++ b/core/gui/src/app/hub/hub.component.html @@ -1,52 +1,79 @@ - -
    -
    -

    Collaborative Data Analytics Using Workflows

    -

    -
    - Texera supports scalable computation and enables advanced AI/ML techniques. -
    - "Collaboration" is a key focus, and we enable an experience similar to Google Docs, but for data analytics. -
    -

    - -
    - -
    + +
      +
    • + + Projects +
    • + +
    • + + Workflows +
    • + +
    • + + Results +
    • + +
    • + + Datasets +
    • + +
    • + + Search +
    • +
    • + + Quota +
    • +
    +
    \ No newline at end of file diff --git a/core/gui/src/app/hub/hub.component.scss b/core/gui/src/app/hub/hub.component.scss index 1c14c791c9d..2a3fac10e89 100644 --- a/core/gui/src/app/hub/hub.component.scss +++ b/core/gui/src/app/hub/hub.component.scss @@ -1,33 +1,14 @@ -.content { - text-align: center; +button { + border: none; } -ul { - list-style-type: none; - height: 70px; - padding: 10px; - overflow: hidden; - background-color: #f8f9fa; - vertical-align: baseline; +.ant-layout-content { + background-color: white; + border: 1px solid #f0f0f0; } -li { - float: left; - padding: 14px; -} - -li a { - color: black; - font-weight: bold; -} - -#logo { - height: 70px; - padding: 0; - margin-right: 14px; -} - -#googleButton { - float: right; - padding: 5px 0; +.ant-menu { + overflow-x: hidden; + overflow-y: auto; + height: calc(100vh - 70px - 48px); } diff --git a/core/gui/src/app/hub/hub.component.ts b/core/gui/src/app/hub/hub.component.ts index d0b2ceea642..765a8dc346f 100644 --- a/core/gui/src/app/hub/hub.component.ts +++ b/core/gui/src/app/hub/hub.component.ts @@ -1,42 +1,9 @@ -import { Component, OnInit } from "@angular/core"; -import { environment } from "../../../environments/environment"; -import { UserService } from "../../common/service/user/user.service"; -import { ActivatedRoute, Router } from "@angular/router"; -import { catchError, mergeMap } from "rxjs/operators"; -import { throwError } from "rxjs"; -import { NotificationService } from "../../common/service/notification/notification.service"; -import { UntilDestroy, untilDestroyed } from "@ngneat/until-destroy"; -import { GoogleAuthService } from "../../common/service/user/google-auth.service"; +import { Component } from "@angular/core"; -@UntilDestroy() @Component({ selector: "texera-hub", - templateUrl: "./hub.component.html", - styleUrls: ["./hub.component.scss"], + templateUrl: "hub.component.html", + styleUrls: ["hub.component.scss"], }) -export class HubComponent implements OnInit { - localLogin = environment.localLogin; - constructor( - private userService: UserService, - private route: ActivatedRoute, - private googleAuthService: GoogleAuthService, - private notificationService: NotificationService, - private router: Router - ) {} - ngOnInit(): void { - this.googleAuthService.googleAuthInit(document.getElementById("googleButton")); - this.googleAuthService.googleCredentialResponse - .pipe(mergeMap(res => this.userService.googleLogin(res.credential))) - .pipe( - catchError((e: unknown) => { - this.notificationService.error((e as Error).message, { nzDuration: 10 }); - return throwError(() => e); - }), - untilDestroyed(this) - ) - .subscribe(() => - this.router.navigateByUrl(this.route.snapshot.queryParams["returnUrl"] || "/dashboard/workflow") - ); - } -} +export class HubComponent {} \ No newline at end of file From c750f022b4c3eefa64749bfb49a33ba84987c710 Mon Sep 17 00:00:00 2001 From: Xinyuan Lin Date: Fri, 12 Jul 2024 15:41:08 -0700 Subject: [PATCH 04/33] test (#2728) --- core/gui/src/app/hub/hub.component.html | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/core/gui/src/app/hub/hub.component.html b/core/gui/src/app/hub/hub.component.html index bc5f2292630..73bf2dd3c48 100644 --- a/core/gui/src/app/hub/hub.component.html +++ b/core/gui/src/app/hub/hub.component.html @@ -76,4 +76,6 @@ Quota
-
\ No newline at end of file + + +new line \ No newline at end of file From 44df0614ecb6291e4ae0a91556866799c0f044fa Mon Sep 17 00:00:00 2001 From: linxinyuan Date: Fri, 12 Jul 2024 22:23:15 -0700 Subject: [PATCH 05/33] update --- core/gui/src/app/app-routing.module.ts | 156 ++++++++------- core/gui/src/app/app.module.ts | 8 +- .../common/service/user/auth-guard.service.ts | 2 +- .../user/component/dashboard.component.html | 184 ++++++++++-------- .../user/component/dashboard.component.scss | 25 ++- .../user/component/dashboard.component.ts | 14 +- 6 files changed, 217 insertions(+), 172 deletions(-) diff --git a/core/gui/src/app/app-routing.module.ts b/core/gui/src/app/app-routing.module.ts index 297d7fcd601..4ddb1b7b7e0 100644 --- a/core/gui/src/app/app-routing.module.ts +++ b/core/gui/src/app/app-routing.module.ts @@ -18,10 +18,7 @@ import { FlarumComponent } from "./dashboard/user/component/flarum/flarum.compon import { GmailComponent } from "./dashboard/admin/component/gmail/gmail.component"; import { UserDatasetExplorerComponent } from "./dashboard/user/component/user-dataset/user-dataset-explorer/user-dataset-explorer.component"; import { UserDatasetComponent } from "./dashboard/user/component/user-dataset/user-dataset.component"; -/* - * This file defines the url path - * The workflow workspace is set as default path - */ + const routes: Routes = [ { path: "", @@ -35,82 +32,83 @@ const routes: Routes = [ }, ]; if (environment.userSystemEnabled) { - /* - * The user dashboard is under path '/dashboard' - * The saved workflow is under path '/dashboard/workflow' - * The user file is under path '/dashboard/user-file' - * The user dictionary is under path '/dashboard/user-dictionary' - * The user project list is under path '/dashboard/project' - * The single user project is under path 'dashboard/project/{pid}' - */ - routes.push({ - path: "dashboard", - component: DashboardComponent, - canActivate: [AuthGuardService], - children: [ - { - path: "user-project", - component: UserProjectComponent, - }, - { - path: "user-project/:pid", - component: UserProjectSectionComponent, - }, - { - path: "workflow", - component: UserWorkflowComponent, - }, - { - path: "user-file", - component: UserFileComponent, - }, - { - path: "dataset", - component: UserDatasetComponent, - }, - // the below two URLs route to the same Component. The component will render the page accordingly - { - path: "dataset/:did", - component: UserDatasetExplorerComponent, - }, - { - path: "dataset/create", - component: UserDatasetExplorerComponent, - }, - { - path: "user-quota", - component: UserQuotaComponent, - }, - { - path: "search", - component: SearchComponent, - }, - { - path: "discussion", - component: FlarumComponent, - }, - { - path: "admin/user", - component: AdminUserComponent, - canActivate: [AdminGuardService], - }, - { - path: "admin/gmail", - component: GmailComponent, - canActivate: [AdminGuardService], - }, - { - path: "admin/execution", - component: AdminExecutionComponent, - canActivate: [AdminGuardService], - }, - ], - }); + routes.push( + { + path: "dashboard", + component: DashboardComponent, + children: [ + { + path: "home", + component: HomeComponent, + }, + { + path: "user", + canActivate: [AuthGuardService], + children: [ + { + path: "project", + component: UserProjectComponent, + }, + { + path: "project/:pid", + component: UserProjectSectionComponent, + }, + { + path: "workflow", + component: UserWorkflowComponent, + }, + { + path: "file", + component: UserFileComponent, + }, + { + path: "dataset", + component: UserDatasetComponent, + }, + // the below two URLs route to the same Component. The component will render the page accordingly + { + path: "dataset/:did", + component: UserDatasetExplorerComponent, + }, + { + path: "dataset/create", + component: UserDatasetExplorerComponent, + }, + { + path: "quota", + component: UserQuotaComponent, + }, + { + path: "search", + component: SearchComponent, + }, + { + path: "discussion", + component: FlarumComponent, + }, + ] + }, + { + path: "admin", + canActivate: [AdminGuardService], + children: [ + { + path: "user", + component: AdminUserComponent, + }, + { + path: "gmail", + component: GmailComponent, + }, + { + path: "execution", + component: AdminExecutionComponent, + }, + ] + }, - routes.push({ - path: "home", - component: HomeComponent, - }); + ], + }); } // redirect all other paths to index. routes.push({ diff --git a/core/gui/src/app/app.module.ts b/core/gui/src/app/app.module.ts index e939abe7fba..4298eb26fe2 100644 --- a/core/gui/src/app/app.module.ts +++ b/core/gui/src/app/app.module.ts @@ -89,7 +89,7 @@ import { NzSwitchModule } from "ng-zorro-antd/switch"; import { HomeComponent } from "./home/component/home.component"; import { NzLayoutModule } from "ng-zorro-antd/layout"; import { AuthGuardService } from "./common/service/user/auth-guard.service"; -import { LocalLoginComponent } from "./home/component/login/local-login/local-login.component"; +import { LocalLoginComponent } from "./home/component/local-login/local-login.component"; import { MarkdownModule } from "ngx-markdown"; import { FileSaverService } from "./dashboard/user/service/user-file/file-saver.service"; import { DragDropModule } from "@angular/cdk/drag-drop"; @@ -133,7 +133,8 @@ import { TreeModule } from "@ali-hm/angular-tree-component"; import { EnvironmentComponent } from "./workspace/component/left-panel/environment/environment.component"; import { FileSelectionComponent } from "./workspace/component/file-selection/file-selection.component"; import { ResultExportationComponent } from "./workspace/component/result-exportation/result-exportation.component"; -import { HubComponent } from "./hub/hub.component"; +import { HubComponent } from "./hub/component/hub.component"; +import { HubWorkflowSearchComponent } from "./hub/component/workflow/search/hub-workflow-search.component"; registerLocaleData(en); @@ -216,7 +217,8 @@ registerLocaleData(en); WorkflowRuntimeStatisticsComponent, FlarumComponent, HighlightSearchTermsPipe, - HubComponent + HubComponent, + HubWorkflowSearchComponent ], imports: [ BrowserModule, diff --git a/core/gui/src/app/common/service/user/auth-guard.service.ts b/core/gui/src/app/common/service/user/auth-guard.service.ts index a78d350fe17..6976dfe2316 100644 --- a/core/gui/src/app/common/service/user/auth-guard.service.ts +++ b/core/gui/src/app/common/service/user/auth-guard.service.ts @@ -17,7 +17,7 @@ export class AuthGuardService implements CanActivate { if (this.userService.isLogin() || !environment.userSystemEnabled) { return true; } else { - this.router.navigate(["home"], { queryParams: { returnUrl: state.url === "/" ? null : state.url } }); + this.router.navigate(["dashboard/home"], { queryParams: { returnUrl: state.url === "/" ? null : state.url } }); return false; } } diff --git a/core/gui/src/app/dashboard/user/component/dashboard.component.html b/core/gui/src/app/dashboard/user/component/dashboard.component.html index cb7aaaebd9a..bf175760eb6 100644 --- a/core/gui/src/app/dashboard/user/component/dashboard.component.html +++ b/core/gui/src/app/dashboard/user/component/dashboard.component.html @@ -1,11 +1,28 @@ + +
  • - - Projects -
  • + *ngIf="isLogin" + nz-submenu + nzTitle="Your Work" + nzIcon="user" + nzOpen="true"> +
      +
    • + + Projects +
    • -
    • - - Workflows -
    • +
    • + + Workflows +
    • -
    • - - Results -
    • +
    • + + Results +
    • -
    • - - Datasets -
    • +
    • + + Datasets +
    • -
    • - - Search -
    • -
    • - - Quota -
    • -
    • - - Forum +
    • + + Search +
    • +
    • + + Quota +
    • +
    • + + Forum +
    • +
    +
  • this.isLogin = this.userService.isLogin()) + } ngOnInit(): void { if (!document.cookie.includes("flarum_remember")) { From b4ed1a24e60e088668b7d23625eaa498511193b6 Mon Sep 17 00:00:00 2001 From: linxinyuan Date: Fri, 12 Jul 2024 22:23:27 -0700 Subject: [PATCH 06/33] update --- .../user/component/user-icon/user-icon.component.ts | 2 +- .../{login => }/local-login/local-login.component.html | 0 .../{login => }/local-login/local-login.component.scss | 0 .../{login => }/local-login/local-login.component.ts | 8 ++++---- .../src/app/workspace/component/menu/menu.component.html | 4 ++-- 5 files changed, 7 insertions(+), 7 deletions(-) rename core/gui/src/app/home/component/{login => }/local-login/local-login.component.html (100%) rename core/gui/src/app/home/component/{login => }/local-login/local-login.component.scss (100%) rename core/gui/src/app/home/component/{login => }/local-login/local-login.component.ts (94%) diff --git a/core/gui/src/app/dashboard/user/component/user-icon/user-icon.component.ts b/core/gui/src/app/dashboard/user/component/user-icon/user-icon.component.ts index a5f013803e1..4a90cbac08a 100644 --- a/core/gui/src/app/dashboard/user/component/user-icon/user-icon.component.ts +++ b/core/gui/src/app/dashboard/user/component/user-icon/user-icon.component.ts @@ -27,6 +27,6 @@ export class UserIconComponent { public onClickLogout(): void { this.userService.logout(); document.cookie = "flarum_remember=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;"; - window.location.href = "home"; + window.location.reload(); } } diff --git a/core/gui/src/app/home/component/login/local-login/local-login.component.html b/core/gui/src/app/home/component/local-login/local-login.component.html similarity index 100% rename from core/gui/src/app/home/component/login/local-login/local-login.component.html rename to core/gui/src/app/home/component/local-login/local-login.component.html diff --git a/core/gui/src/app/home/component/login/local-login/local-login.component.scss b/core/gui/src/app/home/component/local-login/local-login.component.scss similarity index 100% rename from core/gui/src/app/home/component/login/local-login/local-login.component.scss rename to core/gui/src/app/home/component/local-login/local-login.component.scss diff --git a/core/gui/src/app/home/component/login/local-login/local-login.component.ts b/core/gui/src/app/home/component/local-login/local-login.component.ts similarity index 94% rename from core/gui/src/app/home/component/login/local-login/local-login.component.ts rename to core/gui/src/app/home/component/local-login/local-login.component.ts index a0d3e633661..6723a8b5dfd 100644 --- a/core/gui/src/app/home/component/login/local-login/local-login.component.ts +++ b/core/gui/src/app/home/component/local-login/local-login.component.ts @@ -1,9 +1,9 @@ import { Component } from "@angular/core"; -import { UserService } from "../../../../common/service/user/user.service"; +import { UserService } from "../../../common/service/user/user.service"; import { FormBuilder, FormControl, FormGroup, Validators } from "@angular/forms"; import { UntilDestroy, untilDestroyed } from "@ngneat/until-destroy"; import { ActivatedRoute, Router } from "@angular/router"; -import { NotificationService } from "../../../../common/service/notification/notification.service"; +import { NotificationService } from "../../../common/service/notification/notification.service"; import { catchError } from "rxjs/operators"; import { throwError } from "rxjs"; @UntilDestroy() @@ -72,7 +72,7 @@ export class LocalLoginComponent { untilDestroyed(this) ) .subscribe(() => - this.router.navigateByUrl(this.route.snapshot.queryParams["returnUrl"] || "/dashboard/workflow") + this.router.navigateByUrl(this.route.snapshot.queryParams["returnUrl"] || "/dashboard/user/workflow") ); } @@ -110,7 +110,7 @@ export class LocalLoginComponent { untilDestroyed(this) ) .subscribe(() => - this.router.navigateByUrl(this.route.snapshot.queryParams["returnUrl"] || "/dashboard/workflow") + this.router.navigateByUrl(this.route.snapshot.queryParams["returnUrl"] || "/dashboard/user/workflow") ); } } diff --git a/core/gui/src/app/workspace/component/menu/menu.component.html b/core/gui/src/app/workspace/component/menu/menu.component.html index 32dacb63a1a..05b7ea2077a 100644 --- a/core/gui/src/app/workspace/component/menu/menu.component.html +++ b/core/gui/src/app/workspace/component/menu/menu.component.html @@ -1,6 +1,6 @@
  • +
      +
    • + + Home +
    • +
    • + + Workflows +
    • +
    +
  • \ No newline at end of file diff --git a/core/gui/src/app/hub/component/hub.component.scss b/core/gui/src/app/hub/component/hub.component.scss new file mode 100644 index 00000000000..e69de29bb2d diff --git a/core/gui/src/app/hub/hub.component.ts b/core/gui/src/app/hub/component/hub.component.ts similarity index 100% rename from core/gui/src/app/hub/hub.component.ts rename to core/gui/src/app/hub/component/hub.component.ts diff --git a/core/gui/src/app/hub/component/workflow/result/hub.component.html b/core/gui/src/app/hub/component/workflow/result/hub.component.html new file mode 100644 index 00000000000..b857338278f --- /dev/null +++ b/core/gui/src/app/hub/component/workflow/result/hub.component.html @@ -0,0 +1,19 @@ +
  • +
      +
    • + + Public Workflows +
    • +
    +
  • \ No newline at end of file diff --git a/core/gui/src/app/hub/component/workflow/result/hub.component.scss b/core/gui/src/app/hub/component/workflow/result/hub.component.scss new file mode 100644 index 00000000000..e69de29bb2d diff --git a/core/gui/src/app/hub/component/workflow/result/hub.component.ts b/core/gui/src/app/hub/component/workflow/result/hub.component.ts new file mode 100644 index 00000000000..765a8dc346f --- /dev/null +++ b/core/gui/src/app/hub/component/workflow/result/hub.component.ts @@ -0,0 +1,9 @@ +import { Component } from "@angular/core"; + +@Component({ + selector: "texera-hub", + templateUrl: "hub.component.html", + styleUrls: ["hub.component.scss"], +}) + +export class HubComponent {} \ No newline at end of file diff --git a/core/gui/src/app/hub/component/workflow/search/hub-workflow-search.component.html b/core/gui/src/app/hub/component/workflow/search/hub-workflow-search.component.html new file mode 100644 index 00000000000..c0ee72e604b --- /dev/null +++ b/core/gui/src/app/hub/component/workflow/search/hub-workflow-search.component.html @@ -0,0 +1,17 @@ +
    + + +
    +

    Welcome to KNIME Community Hub

    +
    +
    + Access 1000 workflows + provided by Texera and our community. +
    +
    \ No newline at end of file diff --git a/core/gui/src/app/hub/component/workflow/search/hub-workflow-search.component.scss b/core/gui/src/app/hub/component/workflow/search/hub-workflow-search.component.scss new file mode 100644 index 00000000000..e69de29bb2d diff --git a/core/gui/src/app/hub/component/workflow/search/hub-workflow-search.component.ts b/core/gui/src/app/hub/component/workflow/search/hub-workflow-search.component.ts new file mode 100644 index 00000000000..2733c085779 --- /dev/null +++ b/core/gui/src/app/hub/component/workflow/search/hub-workflow-search.component.ts @@ -0,0 +1,17 @@ +import { Component } from "@angular/core"; + +@Component({ + selector: "texera-hub-workflow-search", + templateUrl: "hub-workflow-search.component.html", + styleUrls: ["hub-workflow-search.component.scss"], +}) + +export class HubWorkflowSearchComponent { + inputValue?: string; + options: string[] = []; + + onInput(event: Event): void { + const value = (event.target as HTMLInputElement).value; + this.options = value ? [value, value + value, value + value + value] : []; + } +} \ No newline at end of file diff --git a/core/gui/src/app/hub/hub.component.html b/core/gui/src/app/hub/hub.component.html deleted file mode 100644 index 73bf2dd3c48..00000000000 --- a/core/gui/src/app/hub/hub.component.html +++ /dev/null @@ -1,81 +0,0 @@ - -
      -
    • - - Projects -
    • - -
    • - - Workflows -
    • - -
    • - - Results -
    • - -
    • - - Datasets -
    • - -
    • - - Search -
    • -
    • - - Quota -
    • -
    -
    - -new line \ No newline at end of file diff --git a/core/gui/src/app/hub/hub.component.scss b/core/gui/src/app/hub/hub.component.scss deleted file mode 100644 index 2a3fac10e89..00000000000 --- a/core/gui/src/app/hub/hub.component.scss +++ /dev/null @@ -1,14 +0,0 @@ -button { - border: none; -} - -.ant-layout-content { - background-color: white; - border: 1px solid #f0f0f0; -} - -.ant-menu { - overflow-x: hidden; - overflow-y: auto; - height: calc(100vh - 70px - 48px); -} From 7c97e16f9aab9fdac6010d0e2bfc62c17e3988bd Mon Sep 17 00:00:00 2001 From: linxinyuan Date: Sat, 13 Jul 2024 16:53:43 -0700 Subject: [PATCH 08/33] update --- .../ics/texera/web/TexeraWebApplication.scala | 32 +++++++++++++++---- .../hub/workflow/HubWorkflowResource.scala | 15 ++++----- core/gui/src/app/app-routing.module.ts | 14 +++++++- core/gui/src/app/app.module.ts | 10 ++++++ .../src/app/hub/component/hub.component.html | 2 +- .../component/type/hub-workflow.interface.ts | 8 +++++ .../detail/hub-workflow-detail.component.html | 9 ++++++ .../hub-workflow-detail.component.scss} | 0 .../detail/hub-workflow-detail.component.ts | 20 ++++++++++++ .../workflow/hub-workflow.component.html | 1 + .../workflow/hub-workflow.component.scss | 0 .../workflow/hub-workflow.component.ts | 9 ++++++ .../result/hub-workflow-result.component.html | 9 ++++++ .../result/hub-workflow-result.component.scss | 0 .../result/hub-workflow-result.component.ts | 20 ++++++++++++ .../workflow/result/hub.component.html | 19 ----------- .../workflow/result/hub.component.ts | 9 ------ .../search/hub-workflow-search.component.html | 13 ++------ .../search/hub-workflow-search.component.ts | 10 +----- .../hub-workflow-search-bar.component.html | 10 ++++++ .../hub-workflow-search-bar.component.scss | 0 .../hub-workflow-search-bar.component.ts | 17 ++++++++++ .../service/workflow/hub-workflow.service.ts | 19 +++++++++++ 23 files changed, 182 insertions(+), 64 deletions(-) create mode 100644 core/gui/src/app/hub/component/type/hub-workflow.interface.ts create mode 100644 core/gui/src/app/hub/component/workflow/detail/hub-workflow-detail.component.html rename core/gui/src/app/hub/component/workflow/{result/hub.component.scss => detail/hub-workflow-detail.component.scss} (100%) create mode 100644 core/gui/src/app/hub/component/workflow/detail/hub-workflow-detail.component.ts create mode 100644 core/gui/src/app/hub/component/workflow/hub-workflow.component.html create mode 100644 core/gui/src/app/hub/component/workflow/hub-workflow.component.scss create mode 100644 core/gui/src/app/hub/component/workflow/hub-workflow.component.ts create mode 100644 core/gui/src/app/hub/component/workflow/result/hub-workflow-result.component.html create mode 100644 core/gui/src/app/hub/component/workflow/result/hub-workflow-result.component.scss create mode 100644 core/gui/src/app/hub/component/workflow/result/hub-workflow-result.component.ts delete mode 100644 core/gui/src/app/hub/component/workflow/result/hub.component.html delete mode 100644 core/gui/src/app/hub/component/workflow/result/hub.component.ts create mode 100644 core/gui/src/app/hub/component/workflow/search/search-bar/hub-workflow-search-bar.component.html create mode 100644 core/gui/src/app/hub/component/workflow/search/search-bar/hub-workflow-search-bar.component.scss create mode 100644 core/gui/src/app/hub/component/workflow/search/search-bar/hub-workflow-search-bar.component.ts create mode 100644 core/gui/src/app/hub/service/workflow/hub-workflow.service.ts diff --git a/core/amber/src/main/scala/edu/uci/ics/texera/web/TexeraWebApplication.scala b/core/amber/src/main/scala/edu/uci/ics/texera/web/TexeraWebApplication.scala index 1e6655c61a6..8bb5c0b4cc4 100644 --- a/core/amber/src/main/scala/edu/uci/ics/texera/web/TexeraWebApplication.scala +++ b/core/amber/src/main/scala/edu/uci/ics/texera/web/TexeraWebApplication.scala @@ -14,24 +14,44 @@ import edu.uci.ics.amber.engine.common.virtualidentity.ExecutionIdentity import edu.uci.ics.texera.Utils import edu.uci.ics.texera.Utils.{maptoStatusCode, objectMapper} import edu.uci.ics.texera.web.auth.JwtAuth.jwtConsumer -import edu.uci.ics.texera.web.auth.{GuestAuthFilter, SessionUser, UserAuthenticator, UserRoleAuthorizer} +import edu.uci.ics.texera.web.auth.{ + GuestAuthFilter, + SessionUser, + UserAuthenticator, + UserRoleAuthorizer +} import edu.uci.ics.texera.web.model.jooq.generated.tables.pojos.WorkflowExecutions import edu.uci.ics.texera.web.resource.auth.{AuthResource, GoogleAuthResource} import edu.uci.ics.texera.web.resource._ import edu.uci.ics.texera.web.resource.dashboard.DashboardResource import edu.uci.ics.texera.web.resource.dashboard.admin.execution.AdminExecutionResource import edu.uci.ics.texera.web.resource.dashboard.admin.user.AdminUserResource -import edu.uci.ics.texera.web.resource.dashboard.hub.HubWorkflowResource -import edu.uci.ics.texera.web.resource.dashboard.user.dataset.{DatasetAccessResource, DatasetResource} +import edu.uci.ics.texera.web.resource.dashboard.hub.workflow.HubWorkflowResource +import edu.uci.ics.texera.web.resource.dashboard.user.dataset.{ + DatasetAccessResource, + DatasetResource +} import edu.uci.ics.texera.web.resource.dashboard.user.dataset.`type`.{FileNode, FileNodeSerializer} import edu.uci.ics.texera.web.resource.dashboard.user.dataset.service.GitVersionControlLocalFileStorage import edu.uci.ics.texera.web.resource.dashboard.user.dataset.utils.PathUtils.getAllDatasetDirectories -import edu.uci.ics.texera.web.resource.dashboard.user.file.{UserFileAccessResource, UserFileResource} -import edu.uci.ics.texera.web.resource.dashboard.user.project.{ProjectAccessResource, ProjectResource, PublicProjectResource} +import edu.uci.ics.texera.web.resource.dashboard.user.file.{ + UserFileAccessResource, + UserFileResource +} +import edu.uci.ics.texera.web.resource.dashboard.user.project.{ + ProjectAccessResource, + ProjectResource, + PublicProjectResource +} import edu.uci.ics.texera.web.resource.dashboard.user.quota.UserQuotaResource import edu.uci.ics.texera.web.resource.dashboard.user.discussion.UserDiscussionResource import edu.uci.ics.texera.web.resource.dashboard.user.environment.EnvironmentResource -import edu.uci.ics.texera.web.resource.dashboard.user.workflow.{WorkflowAccessResource, WorkflowExecutionsResource, WorkflowResource, WorkflowVersionResource} +import edu.uci.ics.texera.web.resource.dashboard.user.workflow.{ + WorkflowAccessResource, + WorkflowExecutionsResource, + WorkflowResource, + WorkflowVersionResource +} import edu.uci.ics.texera.web.service.ExecutionsMetadataPersistService import edu.uci.ics.texera.web.storage.MongoDatabaseManager import edu.uci.ics.texera.web.workflowruntimestate.WorkflowAggregatedState.{COMPLETED, FAILED} diff --git a/core/amber/src/main/scala/edu/uci/ics/texera/web/resource/dashboard/hub/workflow/HubWorkflowResource.scala b/core/amber/src/main/scala/edu/uci/ics/texera/web/resource/dashboard/hub/workflow/HubWorkflowResource.scala index 82006519200..e1191537192 100644 --- a/core/amber/src/main/scala/edu/uci/ics/texera/web/resource/dashboard/hub/workflow/HubWorkflowResource.scala +++ b/core/amber/src/main/scala/edu/uci/ics/texera/web/resource/dashboard/hub/workflow/HubWorkflowResource.scala @@ -1,25 +1,24 @@ -package edu.uci.ics.texera.web.resource.dashboard.hub +package edu.uci.ics.texera.web.resource.dashboard.hub.workflow import edu.uci.ics.texera.web.SqlServer import edu.uci.ics.texera.web.model.jooq.generated.Tables._ -import org.jooq.{Record, Result} +import edu.uci.ics.texera.web.model.jooq.generated.tables.pojos.Workflow -import javax.annotation.security.RolesAllowed +import java.util import javax.ws.rs._ import javax.ws.rs.core.MediaType @Produces(Array(MediaType.APPLICATION_JSON)) -@RolesAllowed(Array("REGULAR", "ADMIN")) -@Path("/workflow") +@Path("/hub") class HubWorkflowResource { final private lazy val context = SqlServer.createDSLContext() @GET - @Path("/user-workflow-ids") - def retrieveWorkflows(): Result[Record] = { + @Path("/workflows") + def retrieveWorkflows(): util.List[Workflow] = { context .select() .from(WORKFLOW) - .fetch() + .fetchInto(classOf[Workflow]) } } diff --git a/core/gui/src/app/app-routing.module.ts b/core/gui/src/app/app-routing.module.ts index b36b2e11b48..2ef9046db50 100644 --- a/core/gui/src/app/app-routing.module.ts +++ b/core/gui/src/app/app-routing.module.ts @@ -19,6 +19,8 @@ import { GmailComponent } from "./dashboard/admin/component/gmail/gmail.componen import { UserDatasetExplorerComponent } from "./dashboard/user/component/user-dataset/user-dataset-explorer/user-dataset-explorer.component"; import { UserDatasetComponent } from "./dashboard/user/component/user-dataset/user-dataset.component"; import { HubWorkflowSearchComponent } from "./hub/component/workflow/search/hub-workflow-search.component"; +import { HubWorkflowResultComponent } from "./hub/component/workflow/result/hub-workflow-result.component"; +import { HubWorkflowComponent } from "./hub/component/workflow/hub-workflow.component"; const routes: Routes = [ { @@ -47,7 +49,17 @@ if (environment.userSystemEnabled) { children: [ { path: "workflow", - component: HubWorkflowSearchComponent, + component: HubWorkflowComponent, + children: [ + { + path: "search", + component: HubWorkflowSearchComponent, + }, + { + path: "result", + component: HubWorkflowResultComponent, + } + ] }, ] }, diff --git a/core/gui/src/app/app.module.ts b/core/gui/src/app/app.module.ts index b8d926c011b..d833e9a452d 100644 --- a/core/gui/src/app/app.module.ts +++ b/core/gui/src/app/app.module.ts @@ -136,6 +136,12 @@ import { ResultExportationComponent } from "./workspace/component/result-exporta import { HubComponent } from "./hub/component/hub.component"; import { HubWorkflowSearchComponent } from "./hub/component/workflow/search/hub-workflow-search.component"; import { GoogleLoginComponent } from "./dashboard/user/component/google-login/google-login.component"; +import { HubWorkflowResultComponent } from "./hub/component/workflow/result/hub-workflow-result.component"; +import { HubWorkflowComponent } from "./hub/component/workflow/hub-workflow.component"; +import { + HubWorkflowSearchBarComponent +} from "./hub/component/workflow/search/search-bar/hub-workflow-search-bar.component"; +import { HubWorkflowDetailComponent } from "./hub/component/workflow/detail/hub-workflow-detail.component"; registerLocaleData(en); @@ -219,7 +225,11 @@ registerLocaleData(en); FlarumComponent, HighlightSearchTermsPipe, HubComponent, + HubWorkflowComponent, HubWorkflowSearchComponent, + HubWorkflowSearchBarComponent, + HubWorkflowDetailComponent, + HubWorkflowResultComponent, GoogleLoginComponent ], imports: [ diff --git a/core/gui/src/app/hub/component/hub.component.html b/core/gui/src/app/hub/component/hub.component.html index 0e093394d2d..a302db04984 100644 --- a/core/gui/src/app/hub/component/hub.component.html +++ b/core/gui/src/app/hub/component/hub.component.html @@ -20,7 +20,7 @@ nz-tooltip="Search public workflows" nzMatchRouter="true" nzTooltipPlacement="right" - routerLink="/dashboard/hub/workflow"> + routerLink="/dashboard/hub/workflow/search"> diff --git a/core/gui/src/app/hub/component/type/hub-workflow.interface.ts b/core/gui/src/app/hub/component/type/hub-workflow.interface.ts new file mode 100644 index 00000000000..8763c1acb82 --- /dev/null +++ b/core/gui/src/app/hub/component/type/hub-workflow.interface.ts @@ -0,0 +1,8 @@ +export interface HubWorkflow { + name: string; + description: string; + wid: number; + content: string; + creation_time: number; + last_modified_time: number; +} diff --git a/core/gui/src/app/hub/component/workflow/detail/hub-workflow-detail.component.html b/core/gui/src/app/hub/component/workflow/detail/hub-workflow-detail.component.html new file mode 100644 index 00000000000..9067c7c5b0a --- /dev/null +++ b/core/gui/src/app/hub/component/workflow/detail/hub-workflow-detail.component.html @@ -0,0 +1,9 @@ + + + + + + {{ workflow.name }} + + + \ No newline at end of file diff --git a/core/gui/src/app/hub/component/workflow/result/hub.component.scss b/core/gui/src/app/hub/component/workflow/detail/hub-workflow-detail.component.scss similarity index 100% rename from core/gui/src/app/hub/component/workflow/result/hub.component.scss rename to core/gui/src/app/hub/component/workflow/detail/hub-workflow-detail.component.scss diff --git a/core/gui/src/app/hub/component/workflow/detail/hub-workflow-detail.component.ts b/core/gui/src/app/hub/component/workflow/detail/hub-workflow-detail.component.ts new file mode 100644 index 00000000000..79a0877f75f --- /dev/null +++ b/core/gui/src/app/hub/component/workflow/detail/hub-workflow-detail.component.ts @@ -0,0 +1,20 @@ +import { Component } from "@angular/core"; +import { HubWorkflowService } from "../../../service/workflow/hub-workflow.service"; +import { HubWorkflow } from "../../type/hub-workflow.interface"; +import { UntilDestroy, untilDestroyed } from "@ngneat/until-destroy"; + +@UntilDestroy() +@Component({ + selector: "texera-hub-workflow-result", + templateUrl: "hub-workflow-detail.component.html", + styleUrls: ["hub-workflow-detail.component.scss"], +}) + +export class HubWorkflowDetailComponent { + listOfWorkflows: HubWorkflow[] = []; + constructor(private hubWorkflowService: HubWorkflowService) { + hubWorkflowService.getHubWorkflows().pipe(untilDestroyed(this)).subscribe(workflows => { + this.listOfWorkflows = workflows; + }); + } +} \ No newline at end of file diff --git a/core/gui/src/app/hub/component/workflow/hub-workflow.component.html b/core/gui/src/app/hub/component/workflow/hub-workflow.component.html new file mode 100644 index 00000000000..90c6b646328 --- /dev/null +++ b/core/gui/src/app/hub/component/workflow/hub-workflow.component.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/core/gui/src/app/hub/component/workflow/hub-workflow.component.scss b/core/gui/src/app/hub/component/workflow/hub-workflow.component.scss new file mode 100644 index 00000000000..e69de29bb2d diff --git a/core/gui/src/app/hub/component/workflow/hub-workflow.component.ts b/core/gui/src/app/hub/component/workflow/hub-workflow.component.ts new file mode 100644 index 00000000000..4d912f566e4 --- /dev/null +++ b/core/gui/src/app/hub/component/workflow/hub-workflow.component.ts @@ -0,0 +1,9 @@ +import { Component } from "@angular/core"; + +@Component({ + selector: "texera-hub-workflow", + templateUrl: "hub-workflow.component.html", + styleUrls: ["hub-workflow.component.scss"], +}) + +export class HubWorkflowComponent {} \ No newline at end of file diff --git a/core/gui/src/app/hub/component/workflow/result/hub-workflow-result.component.html b/core/gui/src/app/hub/component/workflow/result/hub-workflow-result.component.html new file mode 100644 index 00000000000..9067c7c5b0a --- /dev/null +++ b/core/gui/src/app/hub/component/workflow/result/hub-workflow-result.component.html @@ -0,0 +1,9 @@ + + + + + + {{ workflow.name }} + + + \ No newline at end of file diff --git a/core/gui/src/app/hub/component/workflow/result/hub-workflow-result.component.scss b/core/gui/src/app/hub/component/workflow/result/hub-workflow-result.component.scss new file mode 100644 index 00000000000..e69de29bb2d diff --git a/core/gui/src/app/hub/component/workflow/result/hub-workflow-result.component.ts b/core/gui/src/app/hub/component/workflow/result/hub-workflow-result.component.ts new file mode 100644 index 00000000000..5142bcbb7b4 --- /dev/null +++ b/core/gui/src/app/hub/component/workflow/result/hub-workflow-result.component.ts @@ -0,0 +1,20 @@ +import { Component } from "@angular/core"; +import { HubWorkflowService } from "../../../service/workflow/hub-workflow.service"; +import { HubWorkflow } from "../../type/hub-workflow.interface"; +import { UntilDestroy, untilDestroyed } from "@ngneat/until-destroy"; + +@UntilDestroy() +@Component({ + selector: "texera-hub-workflow-result", + templateUrl: "hub-workflow-result.component.html", + styleUrls: ["hub-workflow-result.component.scss"], +}) + +export class HubWorkflowResultComponent { + listOfWorkflows: HubWorkflow[] = []; + constructor(private hubWorkflowService: HubWorkflowService) { + hubWorkflowService.getHubWorkflows().pipe(untilDestroyed(this)).subscribe(workflows => { + this.listOfWorkflows = workflows; + }); + } +} \ No newline at end of file diff --git a/core/gui/src/app/hub/component/workflow/result/hub.component.html b/core/gui/src/app/hub/component/workflow/result/hub.component.html deleted file mode 100644 index b857338278f..00000000000 --- a/core/gui/src/app/hub/component/workflow/result/hub.component.html +++ /dev/null @@ -1,19 +0,0 @@ -
  • -
      -
    • - - Public Workflows -
    • -
    -
  • \ No newline at end of file diff --git a/core/gui/src/app/hub/component/workflow/result/hub.component.ts b/core/gui/src/app/hub/component/workflow/result/hub.component.ts deleted file mode 100644 index 765a8dc346f..00000000000 --- a/core/gui/src/app/hub/component/workflow/result/hub.component.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { Component } from "@angular/core"; - -@Component({ - selector: "texera-hub", - templateUrl: "hub.component.html", - styleUrls: ["hub.component.scss"], -}) - -export class HubComponent {} \ No newline at end of file diff --git a/core/gui/src/app/hub/component/workflow/search/hub-workflow-search.component.html b/core/gui/src/app/hub/component/workflow/search/hub-workflow-search.component.html index c0ee72e604b..d6b2eb3f8ac 100644 --- a/core/gui/src/app/hub/component/workflow/search/hub-workflow-search.component.html +++ b/core/gui/src/app/hub/component/workflow/search/hub-workflow-search.component.html @@ -1,17 +1,8 @@ -
    - - -
    +

    Welcome to KNIME Community Hub

    - Access 1000 workflows + Access 1000 workflows provided by Texera and our community.
    \ No newline at end of file diff --git a/core/gui/src/app/hub/component/workflow/search/hub-workflow-search.component.ts b/core/gui/src/app/hub/component/workflow/search/hub-workflow-search.component.ts index 2733c085779..45b8d543086 100644 --- a/core/gui/src/app/hub/component/workflow/search/hub-workflow-search.component.ts +++ b/core/gui/src/app/hub/component/workflow/search/hub-workflow-search.component.ts @@ -6,12 +6,4 @@ import { Component } from "@angular/core"; styleUrls: ["hub-workflow-search.component.scss"], }) -export class HubWorkflowSearchComponent { - inputValue?: string; - options: string[] = []; - - onInput(event: Event): void { - const value = (event.target as HTMLInputElement).value; - this.options = value ? [value, value + value, value + value + value] : []; - } -} \ No newline at end of file +export class HubWorkflowSearchComponent {} \ No newline at end of file diff --git a/core/gui/src/app/hub/component/workflow/search/search-bar/hub-workflow-search-bar.component.html b/core/gui/src/app/hub/component/workflow/search/search-bar/hub-workflow-search-bar.component.html new file mode 100644 index 00000000000..a596635016b --- /dev/null +++ b/core/gui/src/app/hub/component/workflow/search/search-bar/hub-workflow-search-bar.component.html @@ -0,0 +1,10 @@ +
    + + +
    \ No newline at end of file diff --git a/core/gui/src/app/hub/component/workflow/search/search-bar/hub-workflow-search-bar.component.scss b/core/gui/src/app/hub/component/workflow/search/search-bar/hub-workflow-search-bar.component.scss new file mode 100644 index 00000000000..e69de29bb2d diff --git a/core/gui/src/app/hub/component/workflow/search/search-bar/hub-workflow-search-bar.component.ts b/core/gui/src/app/hub/component/workflow/search/search-bar/hub-workflow-search-bar.component.ts new file mode 100644 index 00000000000..920b95f7eda --- /dev/null +++ b/core/gui/src/app/hub/component/workflow/search/search-bar/hub-workflow-search-bar.component.ts @@ -0,0 +1,17 @@ +import { Component } from "@angular/core"; + +@Component({ + selector: "texera-hub-workflow-search-bar", + templateUrl: "hub-workflow-search-bar.component.html", + styleUrls: ["hub-workflow-search-bar.component.scss"], +}) + +export class HubWorkflowSearchBarComponent { + inputValue?: string; + options: string[] = []; + + onInput(event: Event): void { + const value = (event.target as HTMLInputElement).value; + this.options = value ? [value, value + value, value + value + value] : []; + } +} \ No newline at end of file diff --git a/core/gui/src/app/hub/service/workflow/hub-workflow.service.ts b/core/gui/src/app/hub/service/workflow/hub-workflow.service.ts new file mode 100644 index 00000000000..420d38e7439 --- /dev/null +++ b/core/gui/src/app/hub/service/workflow/hub-workflow.service.ts @@ -0,0 +1,19 @@ +import { HttpClient } from "@angular/common/http"; +import { Injectable } from "@angular/core"; +import { Observable } from "rxjs"; +import { AppSettings } from "../../../common/app-setting"; +import { HubWorkflow } from "../../component/type/hub-workflow.interface"; + +export const BASE_URL = `${AppSettings.getApiEndpoint()}/hub/`; + +@Injectable({ + providedIn: "root", +}) +export class HubWorkflowService { + constructor(private http: HttpClient) {} + + public getHubWorkflows(): Observable { + return this.http.get(`${BASE_URL}/workflows/`); + } + +} From c1c42d1b2be8d0a8d7ce6055b61687b24c0206d7 Mon Sep 17 00:00:00 2001 From: linxinyuan Date: Sat, 13 Jul 2024 23:28:29 -0700 Subject: [PATCH 09/33] update --- core/gui/src/app/app-routing.module.ts | 2 +- core/gui/src/app/app.component.html | 1 - core/gui/src/app/app.component.ts | 2 +- core/gui/src/app/app.module.ts | 4 ++-- .../user/component/dashboard.component.html | 2 +- .../user/component/dashboard.component.ts | 2 ++ .../user-icon/user-icon.component.spec.ts | 2 +- .../app/home/component/home.component.scss | 3 --- .../component/home}/home.component.html | 2 +- .../component/home}/home.component.ts | 3 +-- .../local-login/local-login.component.html | 0 .../local-login/local-login.component.scss | 0 .../local-login/local-login.component.ts | 4 ++-- .../workflow/hub-workflow.component.html | 1 - .../workflow/hub-workflow.component.scss | 0 .../workflow/hub-workflow.component.ts | 3 +-- .../search/hub-workflow-search.component.html | 16 +++++++++------ .../search/hub-workflow-search.component.scss | 20 +++++++++++++++++++ .../hub-workflow-search-bar.component.html | 16 ++++++++------- .../hub-workflow-search-bar.component.scss | 0 .../hub-workflow-search-bar.component.ts | 3 +-- 21 files changed, 53 insertions(+), 33 deletions(-) delete mode 100644 core/gui/src/app/app.component.html delete mode 100644 core/gui/src/app/home/component/home.component.scss rename core/gui/src/app/{home/component => hub/component/home}/home.component.html (96%) rename core/gui/src/app/{home/component => hub/component/home}/home.component.ts (65%) rename core/gui/src/app/{home/component => hub/component/home}/local-login/local-login.component.html (100%) rename core/gui/src/app/{home/component => hub/component/home}/local-login/local-login.component.scss (100%) rename core/gui/src/app/{home/component => hub/component/home}/local-login/local-login.component.ts (96%) delete mode 100644 core/gui/src/app/hub/component/workflow/hub-workflow.component.html delete mode 100644 core/gui/src/app/hub/component/workflow/hub-workflow.component.scss delete mode 100644 core/gui/src/app/hub/component/workflow/search/search-bar/hub-workflow-search-bar.component.scss diff --git a/core/gui/src/app/app-routing.module.ts b/core/gui/src/app/app-routing.module.ts index 2ef9046db50..5423701baa8 100644 --- a/core/gui/src/app/app-routing.module.ts +++ b/core/gui/src/app/app-routing.module.ts @@ -8,7 +8,7 @@ import { UserQuotaComponent } from "./dashboard/user/component/user-quota/user-q import { UserProjectSectionComponent } from "./dashboard/user/component/user-project/user-project-section/user-project-section.component"; import { UserProjectComponent } from "./dashboard/user/component/user-project/user-project.component"; import { WorkspaceComponent } from "./workspace/component/workspace.component"; -import { HomeComponent } from "./home/component/home.component"; +import { HomeComponent } from "./hub/component/home/home.component"; import { AuthGuardService } from "./common/service/user/auth-guard.service"; import { AdminUserComponent } from "./dashboard/admin/component/user/admin-user.component"; import { AdminExecutionComponent } from "./dashboard/admin/component/execution/admin-execution.component"; diff --git a/core/gui/src/app/app.component.html b/core/gui/src/app/app.component.html deleted file mode 100644 index 0680b43f9c6..00000000000 --- a/core/gui/src/app/app.component.html +++ /dev/null @@ -1 +0,0 @@ - diff --git a/core/gui/src/app/app.component.ts b/core/gui/src/app/app.component.ts index 0a7db8501cf..509c9cadc99 100644 --- a/core/gui/src/app/app.component.ts +++ b/core/gui/src/app/app.component.ts @@ -2,6 +2,6 @@ import { Component } from "@angular/core"; @Component({ selector: "texera-root", - templateUrl: "./app.component.html", + template: "", }) export class AppComponent {} diff --git a/core/gui/src/app/app.module.ts b/core/gui/src/app/app.module.ts index d833e9a452d..78b91e09736 100644 --- a/core/gui/src/app/app.module.ts +++ b/core/gui/src/app/app.module.ts @@ -86,10 +86,10 @@ import { CoeditorUserIconComponent } from "./workspace/component/menu/coeditor-u import { InputAutoCompleteComponent } from "./workspace/component/input-autocomplete/input-autocomplete.component"; import { CollabWrapperComponent } from "./common/formly/collab-wrapper/collab-wrapper/collab-wrapper.component"; import { NzSwitchModule } from "ng-zorro-antd/switch"; -import { HomeComponent } from "./home/component/home.component"; +import { HomeComponent } from "./hub/component/home/home.component"; import { NzLayoutModule } from "ng-zorro-antd/layout"; import { AuthGuardService } from "./common/service/user/auth-guard.service"; -import { LocalLoginComponent } from "./home/component/local-login/local-login.component"; +import { LocalLoginComponent } from "./hub/component/home/local-login/local-login.component"; import { MarkdownModule } from "ngx-markdown"; import { FileSaverService } from "./dashboard/user/service/user-file/file-saver.service"; import { DragDropModule } from "@angular/cdk/drag-drop"; diff --git a/core/gui/src/app/dashboard/user/component/dashboard.component.html b/core/gui/src/app/dashboard/user/component/dashboard.component.html index 26015492f8b..82e393665dd 100644 --- a/core/gui/src/app/dashboard/user/component/dashboard.component.html +++ b/core/gui/src/app/dashboard/user/component/dashboard.component.html @@ -29,7 +29,7 @@
      - +
    • { let component: UserIconComponent; diff --git a/core/gui/src/app/home/component/home.component.scss b/core/gui/src/app/home/component/home.component.scss deleted file mode 100644 index 96e913d842f..00000000000 --- a/core/gui/src/app/home/component/home.component.scss +++ /dev/null @@ -1,3 +0,0 @@ -.content { - text-align: center; -} \ No newline at end of file diff --git a/core/gui/src/app/home/component/home.component.html b/core/gui/src/app/hub/component/home/home.component.html similarity index 96% rename from core/gui/src/app/home/component/home.component.html rename to core/gui/src/app/hub/component/home/home.component.html index 8b8c5a650d9..700aca7b31c 100644 --- a/core/gui/src/app/home/component/home.component.html +++ b/core/gui/src/app/hub/component/home/home.component.html @@ -6,7 +6,7 @@
      + style="text-align: center;">

      Collaborative Data Analytics Using Workflows


      diff --git a/core/gui/src/app/home/component/home.component.ts b/core/gui/src/app/hub/component/home/home.component.ts similarity index 65% rename from core/gui/src/app/home/component/home.component.ts rename to core/gui/src/app/hub/component/home/home.component.ts index e1ba4557afd..fefcc32199f 100644 --- a/core/gui/src/app/home/component/home.component.ts +++ b/core/gui/src/app/hub/component/home/home.component.ts @@ -1,10 +1,9 @@ import { Component } from "@angular/core"; -import { environment } from "../../../environments/environment"; +import { environment } from "../../../../environments/environment"; @Component({ selector: "texera-login", templateUrl: "home.component.html", - styleUrls: ["home.component.scss"], }) export class HomeComponent{ localLogin = environment.localLogin; diff --git a/core/gui/src/app/home/component/local-login/local-login.component.html b/core/gui/src/app/hub/component/home/local-login/local-login.component.html similarity index 100% rename from core/gui/src/app/home/component/local-login/local-login.component.html rename to core/gui/src/app/hub/component/home/local-login/local-login.component.html diff --git a/core/gui/src/app/home/component/local-login/local-login.component.scss b/core/gui/src/app/hub/component/home/local-login/local-login.component.scss similarity index 100% rename from core/gui/src/app/home/component/local-login/local-login.component.scss rename to core/gui/src/app/hub/component/home/local-login/local-login.component.scss diff --git a/core/gui/src/app/home/component/local-login/local-login.component.ts b/core/gui/src/app/hub/component/home/local-login/local-login.component.ts similarity index 96% rename from core/gui/src/app/home/component/local-login/local-login.component.ts rename to core/gui/src/app/hub/component/home/local-login/local-login.component.ts index 6723a8b5dfd..c3d8afd86ee 100644 --- a/core/gui/src/app/home/component/local-login/local-login.component.ts +++ b/core/gui/src/app/hub/component/home/local-login/local-login.component.ts @@ -1,9 +1,9 @@ import { Component } from "@angular/core"; -import { UserService } from "../../../common/service/user/user.service"; +import { UserService } from "../../../../common/service/user/user.service"; import { FormBuilder, FormControl, FormGroup, Validators } from "@angular/forms"; import { UntilDestroy, untilDestroyed } from "@ngneat/until-destroy"; import { ActivatedRoute, Router } from "@angular/router"; -import { NotificationService } from "../../../common/service/notification/notification.service"; +import { NotificationService } from "../../../../common/service/notification/notification.service"; import { catchError } from "rxjs/operators"; import { throwError } from "rxjs"; @UntilDestroy() diff --git a/core/gui/src/app/hub/component/workflow/hub-workflow.component.html b/core/gui/src/app/hub/component/workflow/hub-workflow.component.html deleted file mode 100644 index 90c6b646328..00000000000 --- a/core/gui/src/app/hub/component/workflow/hub-workflow.component.html +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/core/gui/src/app/hub/component/workflow/hub-workflow.component.scss b/core/gui/src/app/hub/component/workflow/hub-workflow.component.scss deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/core/gui/src/app/hub/component/workflow/hub-workflow.component.ts b/core/gui/src/app/hub/component/workflow/hub-workflow.component.ts index 4d912f566e4..c7275a1bd3d 100644 --- a/core/gui/src/app/hub/component/workflow/hub-workflow.component.ts +++ b/core/gui/src/app/hub/component/workflow/hub-workflow.component.ts @@ -2,8 +2,7 @@ import { Component } from "@angular/core"; @Component({ selector: "texera-hub-workflow", - templateUrl: "hub-workflow.component.html", - styleUrls: ["hub-workflow.component.scss"], + template: "", }) export class HubWorkflowComponent {} \ No newline at end of file diff --git a/core/gui/src/app/hub/component/workflow/search/hub-workflow-search.component.html b/core/gui/src/app/hub/component/workflow/search/hub-workflow-search.component.html index d6b2eb3f8ac..fd70f133569 100644 --- a/core/gui/src/app/hub/component/workflow/search/hub-workflow-search.component.html +++ b/core/gui/src/app/hub/component/workflow/search/hub-workflow-search.component.html @@ -1,8 +1,12 @@ - -

      Welcome to KNIME Community Hub

      -
      -
      - Access 1000 workflows - provided by Texera and our community. +
      +
      +

      Welcome to Texera Community Hub

      +
      + Access 1000 workflows +
      + provided by Texera and our community. +
      +
      +
      \ No newline at end of file diff --git a/core/gui/src/app/hub/component/workflow/search/hub-workflow-search.component.scss b/core/gui/src/app/hub/component/workflow/search/hub-workflow-search.component.scss index e69de29bb2d..71fa09a02d7 100644 --- a/core/gui/src/app/hub/component/workflow/search/hub-workflow-search.component.scss +++ b/core/gui/src/app/hub/component/workflow/search/hub-workflow-search.component.scss @@ -0,0 +1,20 @@ +.container { + background-color: #f4f4f4; + display: flex; + justify-content: center; + align-items: center; + height: 100%; +} + +.box { + background: #fff; + padding: 40px 60px; + border-radius: 10px; + box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); + text-align: center; +} + +i { + color: #666; + font-style: normal; +} \ No newline at end of file diff --git a/core/gui/src/app/hub/component/workflow/search/search-bar/hub-workflow-search-bar.component.html b/core/gui/src/app/hub/component/workflow/search/search-bar/hub-workflow-search-bar.component.html index a596635016b..c91fc5bdf9a 100644 --- a/core/gui/src/app/hub/component/workflow/search/search-bar/hub-workflow-search-bar.component.html +++ b/core/gui/src/app/hub/component/workflow/search/search-bar/hub-workflow-search-bar.component.html @@ -1,10 +1,12 @@
      - + + +
      \ No newline at end of file diff --git a/core/gui/src/app/hub/component/workflow/search/search-bar/hub-workflow-search-bar.component.scss b/core/gui/src/app/hub/component/workflow/search/search-bar/hub-workflow-search-bar.component.scss deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/core/gui/src/app/hub/component/workflow/search/search-bar/hub-workflow-search-bar.component.ts b/core/gui/src/app/hub/component/workflow/search/search-bar/hub-workflow-search-bar.component.ts index 920b95f7eda..830f44c4c97 100644 --- a/core/gui/src/app/hub/component/workflow/search/search-bar/hub-workflow-search-bar.component.ts +++ b/core/gui/src/app/hub/component/workflow/search/search-bar/hub-workflow-search-bar.component.ts @@ -2,8 +2,7 @@ import { Component } from "@angular/core"; @Component({ selector: "texera-hub-workflow-search-bar", - templateUrl: "hub-workflow-search-bar.component.html", - styleUrls: ["hub-workflow-search-bar.component.scss"], + templateUrl: "hub-workflow-search-bar.component.html" }) export class HubWorkflowSearchBarComponent { From 4d636cd20642b45015e12ad39b6d303122800be0 Mon Sep 17 00:00:00 2001 From: linxinyuan Date: Sat, 13 Jul 2024 23:33:57 -0700 Subject: [PATCH 10/33] update --- core/gui/src/app/app-routing.module.ts | 10 ++-- core/gui/src/app/app.module.ts | 10 ++-- .../admin/component/gmail/gmail.component.ts | 47 ------------------- .../execution/admin-execution.component.html | 0 .../admin-execution.component.spec.ts | 0 .../execution/admin-execution.component.ts | 0 .../admin/gmail/admin-gmail.component.html} | 0 .../admin/gmail/admin-gmail.component.scss} | 0 .../admin}/user/admin-user.component.html | 0 .../admin}/user/admin-user.component.scss | 0 .../admin}/user/admin-user.component.spec.ts | 0 .../admin}/user/admin-user.component.ts | 2 +- 12 files changed, 11 insertions(+), 58 deletions(-) delete mode 100644 core/gui/src/app/dashboard/admin/component/gmail/gmail.component.ts rename core/gui/src/app/dashboard/{admin/component => component/admin}/execution/admin-execution.component.html (100%) rename core/gui/src/app/dashboard/{admin/component => component/admin}/execution/admin-execution.component.spec.ts (100%) rename core/gui/src/app/dashboard/{admin/component => component/admin}/execution/admin-execution.component.ts (100%) rename core/gui/src/app/dashboard/{admin/component/gmail/gmail.component.html => component/admin/gmail/admin-gmail.component.html} (100%) rename core/gui/src/app/dashboard/{admin/component/gmail/gmail.component.scss => component/admin/gmail/admin-gmail.component.scss} (100%) rename core/gui/src/app/dashboard/{admin/component => component/admin}/user/admin-user.component.html (100%) rename core/gui/src/app/dashboard/{admin/component => component/admin}/user/admin-user.component.scss (100%) rename core/gui/src/app/dashboard/{admin/component => component/admin}/user/admin-user.component.spec.ts (100%) rename core/gui/src/app/dashboard/{admin/component => component/admin}/user/admin-user.component.ts (97%) diff --git a/core/gui/src/app/app-routing.module.ts b/core/gui/src/app/app-routing.module.ts index 5423701baa8..820cc88b40c 100644 --- a/core/gui/src/app/app-routing.module.ts +++ b/core/gui/src/app/app-routing.module.ts @@ -1,7 +1,7 @@ import { NgModule } from "@angular/core"; import { RouterModule, Routes } from "@angular/router"; import { environment } from "../environments/environment"; -import { DashboardComponent } from "./dashboard/user/component/dashboard.component"; +import { DashboardComponent } from "./dashboard/component/dashboard.component"; import { UserWorkflowComponent } from "./dashboard/user/component/user-workflow/user-workflow.component"; import { UserFileComponent } from "./dashboard/user/component/user-file/user-file.component"; import { UserQuotaComponent } from "./dashboard/user/component/user-quota/user-quota.component"; @@ -10,12 +10,12 @@ import { UserProjectComponent } from "./dashboard/user/component/user-project/us import { WorkspaceComponent } from "./workspace/component/workspace.component"; import { HomeComponent } from "./hub/component/home/home.component"; import { AuthGuardService } from "./common/service/user/auth-guard.service"; -import { AdminUserComponent } from "./dashboard/admin/component/user/admin-user.component"; -import { AdminExecutionComponent } from "./dashboard/admin/component/execution/admin-execution.component"; +import { AdminUserComponent } from "./dashboard/component/admin/user/admin-user.component"; +import { AdminExecutionComponent } from "./dashboard/component/admin/execution/admin-execution.component"; import { AdminGuardService } from "./dashboard/user/service/admin/guard/admin-guard.service"; import { SearchComponent } from "./dashboard/user/component/search/search.component"; import { FlarumComponent } from "./dashboard/user/component/flarum/flarum.component"; -import { GmailComponent } from "./dashboard/admin/component/gmail/gmail.component"; +import { AdminGmailComponent } from "./dashboard/component/admin/gmail/admin-gmail.component"; import { UserDatasetExplorerComponent } from "./dashboard/user/component/user-dataset/user-dataset-explorer/user-dataset-explorer.component"; import { UserDatasetComponent } from "./dashboard/user/component/user-dataset/user-dataset.component"; import { HubWorkflowSearchComponent } from "./hub/component/workflow/search/hub-workflow-search.component"; @@ -120,7 +120,7 @@ if (environment.userSystemEnabled) { }, { path: "gmail", - component: GmailComponent, + component: AdminGmailComponent, }, { path: "execution", diff --git a/core/gui/src/app/app.module.ts b/core/gui/src/app/app.module.ts index 78b91e09736..b2242b02d87 100644 --- a/core/gui/src/app/app.module.ts +++ b/core/gui/src/app/app.module.ts @@ -35,7 +35,7 @@ import { ObjectTypeComponent } from "./common/formly/object.type"; import { UserFileUploadService } from "./dashboard/user/service/user-file/user-file-upload.service"; import { UserFileService } from "./dashboard/user/service/user-file/user-file.service"; import { UserService } from "./common/service/user/user.service"; -import { DashboardComponent } from "./dashboard/user/component/dashboard.component"; +import { DashboardComponent } from "./dashboard/component/dashboard.component"; import { UserWorkflowComponent } from "./dashboard/user/component/user-workflow/user-workflow.component"; import { ShareAccessComponent } from "./dashboard/user/component/share-access/share-access.component"; import { WorkflowExecutionHistoryComponent } from "./dashboard/user/component/user-workflow/ngbd-modal-workflow-executions/workflow-execution-history.component"; @@ -77,8 +77,8 @@ import { NgbdModalRemoveProjectFileComponent } from "./dashboard/user/component/ import { PresetWrapperComponent } from "./common/formly/preset-wrapper/preset-wrapper.component"; import { NzModalCommentBoxComponent } from "./workspace/component/workflow-editor/comment-box-modal/nz-modal-comment-box.component"; import { NzCommentModule } from "ng-zorro-antd/comment"; -import { AdminUserComponent } from "./dashboard/admin/component/user/admin-user.component"; -import { AdminExecutionComponent } from "./dashboard/admin/component/execution/admin-execution.component"; +import { AdminUserComponent } from "./dashboard/component/admin/user/admin-user.component"; +import { AdminExecutionComponent } from "./dashboard/component/admin/execution/admin-execution.component"; import { NzPopconfirmModule } from "ng-zorro-antd/popconfirm"; import { AdminGuardService } from "./dashboard/user/service/admin/guard/admin-guard.service"; import { ContextMenuComponent } from "./workspace/component/workflow-editor/context-menu/context-menu/context-menu.component"; @@ -102,7 +102,7 @@ import { UserFileListItemComponent } from "./dashboard/user/component/user-file/ import { SearchComponent } from "./dashboard/user/component/search/search.component"; import { SearchResultsComponent } from "./dashboard/user/component/search-results/search-results.component"; import { PortPropertyEditFrameComponent } from "./workspace/component/property-editor/port-property-edit-frame/port-property-edit-frame.component"; -import { GmailComponent } from "./dashboard/admin/component/gmail/gmail.component"; +import { AdminGmailComponent } from "./dashboard/component/admin/gmail/admin-gmail.component"; import { PublicProjectComponent } from "./dashboard/user/component/user-project/public-project/public-project.component"; import { FormlyNgZorroAntdModule } from "@ngx-formly/ng-zorro-antd"; import { FlarumComponent } from "./dashboard/user/component/flarum/flarum.component"; @@ -147,7 +147,7 @@ registerLocaleData(en); @NgModule({ declarations: [ - GmailComponent, + AdminGmailComponent, PublicProjectComponent, AppComponent, WorkspaceComponent, diff --git a/core/gui/src/app/dashboard/admin/component/gmail/gmail.component.ts b/core/gui/src/app/dashboard/admin/component/gmail/gmail.component.ts deleted file mode 100644 index d0cbc2da6a6..00000000000 --- a/core/gui/src/app/dashboard/admin/component/gmail/gmail.component.ts +++ /dev/null @@ -1,47 +0,0 @@ -import { Component, OnInit } from "@angular/core"; -import { GmailService } from "../../../../common/service/gmail/gmail.service"; -import { FormBuilder, FormGroup, Validators } from "@angular/forms"; -import { UntilDestroy, untilDestroyed } from "@ngneat/until-destroy"; -@UntilDestroy() -@Component({ - selector: "texera-gmail", - templateUrl: "./gmail.component.html", - styleUrls: ["./gmail.component.scss"], -}) -export class GmailComponent implements OnInit { - public validateForm!: FormGroup; - public email: String | undefined; - constructor( - private gmailAuthService: GmailService, - private formBuilder: FormBuilder - ) {} - - ngOnInit(): void { - this.validateForm = this.formBuilder.group({ - email: [null, [Validators.email, Validators.required]], - subject: [null, [Validators.required]], - content: [null, [Validators.required]], - }); - this.getSenderEmail(); - } - - getSenderEmail() { - this.gmailAuthService - .getSenderEmail() - .pipe(untilDestroyed(this)) - .subscribe({ - next: email => (this.email = email), - error: (err: unknown) => { - this.email = undefined; - console.log(err); - }, - }); - } - sendTestEmail(): void { - this.gmailAuthService.sendEmail( - this.validateForm.value.subject, - this.validateForm.value.content, - this.validateForm.value.email - ); - } -} diff --git a/core/gui/src/app/dashboard/admin/component/execution/admin-execution.component.html b/core/gui/src/app/dashboard/component/admin/execution/admin-execution.component.html similarity index 100% rename from core/gui/src/app/dashboard/admin/component/execution/admin-execution.component.html rename to core/gui/src/app/dashboard/component/admin/execution/admin-execution.component.html diff --git a/core/gui/src/app/dashboard/admin/component/execution/admin-execution.component.spec.ts b/core/gui/src/app/dashboard/component/admin/execution/admin-execution.component.spec.ts similarity index 100% rename from core/gui/src/app/dashboard/admin/component/execution/admin-execution.component.spec.ts rename to core/gui/src/app/dashboard/component/admin/execution/admin-execution.component.spec.ts diff --git a/core/gui/src/app/dashboard/admin/component/execution/admin-execution.component.ts b/core/gui/src/app/dashboard/component/admin/execution/admin-execution.component.ts similarity index 100% rename from core/gui/src/app/dashboard/admin/component/execution/admin-execution.component.ts rename to core/gui/src/app/dashboard/component/admin/execution/admin-execution.component.ts diff --git a/core/gui/src/app/dashboard/admin/component/gmail/gmail.component.html b/core/gui/src/app/dashboard/component/admin/gmail/admin-gmail.component.html similarity index 100% rename from core/gui/src/app/dashboard/admin/component/gmail/gmail.component.html rename to core/gui/src/app/dashboard/component/admin/gmail/admin-gmail.component.html diff --git a/core/gui/src/app/dashboard/admin/component/gmail/gmail.component.scss b/core/gui/src/app/dashboard/component/admin/gmail/admin-gmail.component.scss similarity index 100% rename from core/gui/src/app/dashboard/admin/component/gmail/gmail.component.scss rename to core/gui/src/app/dashboard/component/admin/gmail/admin-gmail.component.scss diff --git a/core/gui/src/app/dashboard/admin/component/user/admin-user.component.html b/core/gui/src/app/dashboard/component/admin/user/admin-user.component.html similarity index 100% rename from core/gui/src/app/dashboard/admin/component/user/admin-user.component.html rename to core/gui/src/app/dashboard/component/admin/user/admin-user.component.html diff --git a/core/gui/src/app/dashboard/admin/component/user/admin-user.component.scss b/core/gui/src/app/dashboard/component/admin/user/admin-user.component.scss similarity index 100% rename from core/gui/src/app/dashboard/admin/component/user/admin-user.component.scss rename to core/gui/src/app/dashboard/component/admin/user/admin-user.component.scss diff --git a/core/gui/src/app/dashboard/admin/component/user/admin-user.component.spec.ts b/core/gui/src/app/dashboard/component/admin/user/admin-user.component.spec.ts similarity index 100% rename from core/gui/src/app/dashboard/admin/component/user/admin-user.component.spec.ts rename to core/gui/src/app/dashboard/component/admin/user/admin-user.component.spec.ts diff --git a/core/gui/src/app/dashboard/admin/component/user/admin-user.component.ts b/core/gui/src/app/dashboard/component/admin/user/admin-user.component.ts similarity index 97% rename from core/gui/src/app/dashboard/admin/component/user/admin-user.component.ts rename to core/gui/src/app/dashboard/component/admin/user/admin-user.component.ts index cb69d7febc5..a64f9cd18c4 100644 --- a/core/gui/src/app/dashboard/admin/component/user/admin-user.component.ts +++ b/core/gui/src/app/dashboard/component/admin/user/admin-user.component.ts @@ -5,7 +5,7 @@ import { NzModalService } from "ng-zorro-antd/modal"; import { AdminUserService } from "../../../user/service/admin/user/admin-user.service"; import { Role, User } from "../../../../common/type/user"; import { UserService } from "../../../../common/service/user/user.service"; -import { UserQuotaComponent } from "src/app/dashboard/user/component/user-quota/user-quota.component"; +import { UserQuotaComponent } from "../../../user/component/user-quota/user-quota.component"; @UntilDestroy() @Component({ From 62de61ac359f5cdea0774010c5ba5a4ce8671f7d Mon Sep 17 00:00:00 2001 From: linxinyuan Date: Sat, 13 Jul 2024 23:37:21 -0700 Subject: [PATCH 11/33] update --- core/gui/src/app/app-routing.module.ts | 2 +- core/gui/src/app/app.module.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/core/gui/src/app/app-routing.module.ts b/core/gui/src/app/app-routing.module.ts index 820cc88b40c..5c2c4ea1b20 100644 --- a/core/gui/src/app/app-routing.module.ts +++ b/core/gui/src/app/app-routing.module.ts @@ -1,7 +1,7 @@ import { NgModule } from "@angular/core"; import { RouterModule, Routes } from "@angular/router"; import { environment } from "../environments/environment"; -import { DashboardComponent } from "./dashboard/component/dashboard.component"; +import { DashboardComponent } from "./dashboard/user/component/dashboard.component"; import { UserWorkflowComponent } from "./dashboard/user/component/user-workflow/user-workflow.component"; import { UserFileComponent } from "./dashboard/user/component/user-file/user-file.component"; import { UserQuotaComponent } from "./dashboard/user/component/user-quota/user-quota.component"; diff --git a/core/gui/src/app/app.module.ts b/core/gui/src/app/app.module.ts index b2242b02d87..d324794a978 100644 --- a/core/gui/src/app/app.module.ts +++ b/core/gui/src/app/app.module.ts @@ -35,7 +35,7 @@ import { ObjectTypeComponent } from "./common/formly/object.type"; import { UserFileUploadService } from "./dashboard/user/service/user-file/user-file-upload.service"; import { UserFileService } from "./dashboard/user/service/user-file/user-file.service"; import { UserService } from "./common/service/user/user.service"; -import { DashboardComponent } from "./dashboard/component/dashboard.component"; +import { DashboardComponent } from "./dashboard/user/component/dashboard.component"; import { UserWorkflowComponent } from "./dashboard/user/component/user-workflow/user-workflow.component"; import { ShareAccessComponent } from "./dashboard/user/component/share-access/share-access.component"; import { WorkflowExecutionHistoryComponent } from "./dashboard/user/component/user-workflow/ngbd-modal-workflow-executions/workflow-execution-history.component"; From 6323c59b3f121100548da3f1e4e8fe5f41e581d1 Mon Sep 17 00:00:00 2001 From: linxinyuan Date: Sun, 14 Jul 2024 00:38:07 -0700 Subject: [PATCH 12/33] update --- .../hub/workflow/HubWorkflowResource.scala | 14 +++++++++++--- .../user-project-list-item.component.ts | 2 +- .../user-project-section.component.ts | 4 +--- .../user-workflow-list-item.component.ts | 2 +- .../detail/hub-workflow-detail.component.ts | 2 +- .../result/hub-workflow-result.component.ts | 4 ++-- .../hub-workflow-search-bar.component.html | 4 ++-- .../hub-workflow-search-bar.component.ts | 18 ++++++++++++++---- .../service/workflow/hub-workflow.service.ts | 6 +++--- .../workspace/component/menu/menu.component.ts | 3 +-- 10 files changed, 37 insertions(+), 22 deletions(-) diff --git a/core/amber/src/main/scala/edu/uci/ics/texera/web/resource/dashboard/hub/workflow/HubWorkflowResource.scala b/core/amber/src/main/scala/edu/uci/ics/texera/web/resource/dashboard/hub/workflow/HubWorkflowResource.scala index e1191537192..d0237fcc68a 100644 --- a/core/amber/src/main/scala/edu/uci/ics/texera/web/resource/dashboard/hub/workflow/HubWorkflowResource.scala +++ b/core/amber/src/main/scala/edu/uci/ics/texera/web/resource/dashboard/hub/workflow/HubWorkflowResource.scala @@ -9,16 +9,24 @@ import javax.ws.rs._ import javax.ws.rs.core.MediaType @Produces(Array(MediaType.APPLICATION_JSON)) -@Path("/hub") +@Path("/hub/workflow") class HubWorkflowResource { final private lazy val context = SqlServer.createDSLContext() @GET - @Path("/workflows") - def retrieveWorkflows(): util.List[Workflow] = { + @Path("/list") + def getWorkflowList: util.List[Workflow] = { context .select() .from(WORKFLOW) .fetchInto(classOf[Workflow]) } + + @GET + @Path("/count") + def getWorkflowCount: Integer = { + context.selectCount + .from(WORKFLOW) + .fetchOne(0, classOf[Integer]) + } } diff --git a/core/gui/src/app/dashboard/user/component/user-project/user-project-list-item/user-project-list-item.component.ts b/core/gui/src/app/dashboard/user/component/user-project/user-project-list-item/user-project-list-item.component.ts index 2d8b9451fa7..ce6a802398b 100644 --- a/core/gui/src/app/dashboard/user/component/user-project/user-project-list-item/user-project-list-item.component.ts +++ b/core/gui/src/app/dashboard/user/component/user-project/user-project-list-item/user-project-list-item.component.ts @@ -15,7 +15,7 @@ import { UserService } from "../../../../../common/service/user/user.service"; styleUrls: ["./user-project-list-item.component.scss"], }) export class UserProjectListItemComponent implements OnInit { - public readonly ROUTER_USER_PROJECT_BASE_URL = "/dashboard/user-project"; + public readonly ROUTER_USER_PROJECT_BASE_URL = "/dashboard/user/project"; public readonly MAX_PROJECT_DESCRIPTION_CHAR_COUNT = 10000; private _entry?: DashboardProject; @Input() public keywords: string[] = []; diff --git a/core/gui/src/app/dashboard/user/component/user-project/user-project-section/user-project-section.component.ts b/core/gui/src/app/dashboard/user/component/user-project/user-project-section/user-project-section.component.ts index 033bed6ad83..d8bf4346fb0 100644 --- a/core/gui/src/app/dashboard/user/component/user-project/user-project-section/user-project-section.component.ts +++ b/core/gui/src/app/dashboard/user/component/user-project/user-project-section/user-project-section.component.ts @@ -11,8 +11,6 @@ import { UntilDestroy, untilDestroyed } from "@ngneat/until-destroy"; import { DashboardProject } from "../../../type/dashboard-project.interface"; import { isDefined } from "../../../../../common/util/predicate"; -export const ROUTER_USER_PROJECT_BASE_URL = "/dashboard/user-project"; - @UntilDestroy() @Component({ selector: "texera-user-project-section", @@ -98,7 +96,7 @@ export class UserProjectSectionComponent implements OnInit { * navigate to another project page */ public jumpToProject({ pid }: DashboardProject): void { - this.router.navigate([`${ROUTER_USER_PROJECT_BASE_URL}/${pid}`]).then(null); + this.router.navigate([`/dashboard/user/project/${pid}`]).then(null); } public updateProjectColor(color: string) { color = color.substring(1); diff --git a/core/gui/src/app/dashboard/user/component/user-workflow/user-workflow-list-item/user-workflow-list-item.component.ts b/core/gui/src/app/dashboard/user/component/user-workflow/user-workflow-list-item/user-workflow-list-item.component.ts index ef6b206dd1a..65572925c84 100644 --- a/core/gui/src/app/dashboard/user/component/user-workflow/user-workflow-list-item/user-workflow-list-item.component.ts +++ b/core/gui/src/app/dashboard/user/component/user-workflow/user-workflow-list-item/user-workflow-list-item.component.ts @@ -23,7 +23,7 @@ import { firstValueFrom } from "rxjs"; }) export class UserWorkflowListItemComponent { ROUTER_WORKFLOW_BASE_URL = "/workflow"; - ROUTER_USER_PROJECT_BASE_URL = "/dashboard/user-project"; + ROUTER_USER_PROJECT_BASE_URL = "/dashboard/user/project"; private _entry?: DashboardEntry; @Input() public keywords: string[] = []; diff --git a/core/gui/src/app/hub/component/workflow/detail/hub-workflow-detail.component.ts b/core/gui/src/app/hub/component/workflow/detail/hub-workflow-detail.component.ts index 79a0877f75f..3de3e7cbbd6 100644 --- a/core/gui/src/app/hub/component/workflow/detail/hub-workflow-detail.component.ts +++ b/core/gui/src/app/hub/component/workflow/detail/hub-workflow-detail.component.ts @@ -13,7 +13,7 @@ import { UntilDestroy, untilDestroyed } from "@ngneat/until-destroy"; export class HubWorkflowDetailComponent { listOfWorkflows: HubWorkflow[] = []; constructor(private hubWorkflowService: HubWorkflowService) { - hubWorkflowService.getHubWorkflows().pipe(untilDestroyed(this)).subscribe(workflows => { + hubWorkflowService.getWorkflowList().pipe(untilDestroyed(this)).subscribe(workflows => { this.listOfWorkflows = workflows; }); } diff --git a/core/gui/src/app/hub/component/workflow/result/hub-workflow-result.component.ts b/core/gui/src/app/hub/component/workflow/result/hub-workflow-result.component.ts index 5142bcbb7b4..440126939ed 100644 --- a/core/gui/src/app/hub/component/workflow/result/hub-workflow-result.component.ts +++ b/core/gui/src/app/hub/component/workflow/result/hub-workflow-result.component.ts @@ -12,8 +12,8 @@ import { UntilDestroy, untilDestroyed } from "@ngneat/until-destroy"; export class HubWorkflowResultComponent { listOfWorkflows: HubWorkflow[] = []; - constructor(private hubWorkflowService: HubWorkflowService) { - hubWorkflowService.getHubWorkflows().pipe(untilDestroyed(this)).subscribe(workflows => { + constructor(hubWorkflowService: HubWorkflowService) { + hubWorkflowService.getWorkflowList().pipe(untilDestroyed(this)).subscribe(workflows => { this.listOfWorkflows = workflows; }); } diff --git a/core/gui/src/app/hub/component/workflow/search/search-bar/hub-workflow-search-bar.component.html b/core/gui/src/app/hub/component/workflow/search/search-bar/hub-workflow-search-bar.component.html index c91fc5bdf9a..aa72e54cf7d 100644 --- a/core/gui/src/app/hub/component/workflow/search/search-bar/hub-workflow-search-bar.component.html +++ b/core/gui/src/app/hub/component/workflow/search/search-bar/hub-workflow-search-bar.component.html @@ -4,9 +4,9 @@ placeholder="Search" nz-input [(ngModel)]="inputValue" - (input)="onInput($event)" + (ngModelChange)="onChange($event)" [nzAutocomplete]="auto" /> - +
      \ No newline at end of file diff --git a/core/gui/src/app/hub/component/workflow/search/search-bar/hub-workflow-search-bar.component.ts b/core/gui/src/app/hub/component/workflow/search/search-bar/hub-workflow-search-bar.component.ts index 830f44c4c97..960ec1e71f2 100644 --- a/core/gui/src/app/hub/component/workflow/search/search-bar/hub-workflow-search-bar.component.ts +++ b/core/gui/src/app/hub/component/workflow/search/search-bar/hub-workflow-search-bar.component.ts @@ -1,5 +1,8 @@ import { Component } from "@angular/core"; +import { HubWorkflowService } from "../../../../service/workflow/hub-workflow.service"; +import { UntilDestroy, untilDestroyed } from "@ngneat/until-destroy"; +@UntilDestroy() @Component({ selector: "texera-hub-workflow-search-bar", templateUrl: "hub-workflow-search-bar.component.html" @@ -7,10 +10,17 @@ import { Component } from "@angular/core"; export class HubWorkflowSearchBarComponent { inputValue?: string; - options: string[] = []; + workflowNames: string[] = []; + filteredOptions: string[] = []; - onInput(event: Event): void { - const value = (event.target as HTMLInputElement).value; - this.options = value ? [value, value + value, value + value + value] : []; + constructor(hubWorkflowService: HubWorkflowService) { + this.filteredOptions = this.workflowNames; + hubWorkflowService.getWorkflowList().pipe(untilDestroyed(this)).subscribe(workflows => { + this.workflowNames = workflows.map(obj => obj.name); + }); + } + + onChange(value: string): void { + this.filteredOptions = this.workflowNames.filter(option => option.toLowerCase().indexOf(value.toLowerCase()) !== -1); } } \ No newline at end of file diff --git a/core/gui/src/app/hub/service/workflow/hub-workflow.service.ts b/core/gui/src/app/hub/service/workflow/hub-workflow.service.ts index 420d38e7439..c5a52b6c8ef 100644 --- a/core/gui/src/app/hub/service/workflow/hub-workflow.service.ts +++ b/core/gui/src/app/hub/service/workflow/hub-workflow.service.ts @@ -4,7 +4,7 @@ import { Observable } from "rxjs"; import { AppSettings } from "../../../common/app-setting"; import { HubWorkflow } from "../../component/type/hub-workflow.interface"; -export const BASE_URL = `${AppSettings.getApiEndpoint()}/hub/`; +export const BASE_URL = `${AppSettings.getApiEndpoint()}/hub/workflow`; @Injectable({ providedIn: "root", @@ -12,8 +12,8 @@ export const BASE_URL = `${AppSettings.getApiEndpoint()}/hub/`; export class HubWorkflowService { constructor(private http: HttpClient) {} - public getHubWorkflows(): Observable { - return this.http.get(`${BASE_URL}/workflows/`); + public getWorkflowList(): Observable { + return this.http.get(`${BASE_URL}/list`); } } diff --git a/core/gui/src/app/workspace/component/menu/menu.component.ts b/core/gui/src/app/workspace/component/menu/menu.component.ts index 7a8198690c8..141899e3c9a 100644 --- a/core/gui/src/app/workspace/component/menu/menu.component.ts +++ b/core/gui/src/app/workspace/component/menu/menu.component.ts @@ -27,7 +27,6 @@ import { OperatorMenuService } from "../../service/operator-menu/operator-menu.s import { CoeditorPresenceService } from "../../service/workflow-graph/model/coeditor-presence.service"; import { Subscription, timer } from "rxjs"; import { isDefined } from "../../../common/util/predicate"; -import { FileSelectionComponent } from "../file-selection/file-selection.component"; import { NzModalService } from "ng-zorro-antd/modal"; import { ResultExportationComponent } from "../result-exportation/result-exportation.component"; @@ -330,7 +329,7 @@ export class MenuComponent implements OnInit { * */ public onClickExportExecutionResult(exportType: string): void { - const modal = this.modalService.create({ + this.modalService.create({ nzTitle: "Export Result and Save to a Dataset", nzContent: ResultExportationComponent, nzData: { From ab3283e2c3d2a09c6ed757d6546fd406ee4ef214 Mon Sep 17 00:00:00 2001 From: linxinyuan Date: Sun, 14 Jul 2024 00:50:37 -0700 Subject: [PATCH 13/33] fix fmt --- core/gui/src/app/app-routing.module.ts | 195 +++++++++--------- core/gui/src/app/app.module.ts | 6 +- .../user/component/dashboard.component.ts | 5 +- .../google-login/google-login.component.ts | 6 +- .../user-icon/user-icon.component.ts | 5 +- .../hub/component/home/home.component.html | 2 +- .../app/hub/component/home/home.component.ts | 4 +- .../src/app/hub/component/hub.component.html | 14 +- .../src/app/hub/component/hub.component.ts | 3 +- .../detail/hub-workflow-detail.component.html | 11 +- .../detail/hub-workflow-detail.component.ts | 12 +- .../workflow/hub-workflow.component.ts | 3 +- .../result/hub-workflow-result.component.html | 11 +- .../result/hub-workflow-result.component.ts | 13 +- .../hub-workflow-search-bar.component.html | 15 ++ .../hub-workflow-search-bar.component.ts | 28 +++ .../search/hub-workflow-search.component.html | 11 +- .../search/hub-workflow-search.component.scss | 2 +- .../search/hub-workflow-search.component.ts | 15 +- .../hub-workflow-search-bar.component.html | 12 -- .../hub-workflow-search-bar.component.ts | 26 --- .../service/workflow/hub-workflow.service.ts | 11 +- 22 files changed, 229 insertions(+), 181 deletions(-) create mode 100644 core/gui/src/app/hub/component/workflow/search-bar/hub-workflow-search-bar.component.html create mode 100644 core/gui/src/app/hub/component/workflow/search-bar/hub-workflow-search-bar.component.ts delete mode 100644 core/gui/src/app/hub/component/workflow/search/search-bar/hub-workflow-search-bar.component.html delete mode 100644 core/gui/src/app/hub/component/workflow/search/search-bar/hub-workflow-search-bar.component.ts diff --git a/core/gui/src/app/app-routing.module.ts b/core/gui/src/app/app-routing.module.ts index 5c2c4ea1b20..96ae42f4251 100644 --- a/core/gui/src/app/app-routing.module.ts +++ b/core/gui/src/app/app-routing.module.ts @@ -21,6 +21,7 @@ import { UserDatasetComponent } from "./dashboard/user/component/user-dataset/us import { HubWorkflowSearchComponent } from "./hub/component/workflow/search/hub-workflow-search.component"; import { HubWorkflowResultComponent } from "./hub/component/workflow/result/hub-workflow-result.component"; import { HubWorkflowComponent } from "./hub/component/workflow/hub-workflow.component"; +import { HubWorkflowDetailComponent } from "./hub/component/workflow/detail/hub-workflow-detail.component"; const routes: Routes = [ { @@ -35,102 +36,104 @@ const routes: Routes = [ }, ]; if (environment.userSystemEnabled) { - routes.push( - { - path: "dashboard", - component: DashboardComponent, - children: [ - { - path: "home", - component: HomeComponent, - }, - { - path: "hub", - children: [ - { - path: "workflow", - component: HubWorkflowComponent, - children: [ - { - path: "search", - component: HubWorkflowSearchComponent, - }, - { - path: "result", - component: HubWorkflowResultComponent, - } - ] - }, - ] - }, - { - path: "user", - canActivate: [AuthGuardService], - children: [ - { - path: "project", - component: UserProjectComponent, - }, - { - path: "project/:pid", - component: UserProjectSectionComponent, - }, - { - path: "workflow", - component: UserWorkflowComponent, - }, - { - path: "file", - component: UserFileComponent, - }, - { - path: "dataset", - component: UserDatasetComponent, - }, - // the below two URLs route to the same Component. The component will render the page accordingly - { - path: "dataset/:did", - component: UserDatasetExplorerComponent, - }, - { - path: "dataset/create", - component: UserDatasetExplorerComponent, - }, - { - path: "quota", - component: UserQuotaComponent, - }, - { - path: "search", - component: SearchComponent, - }, - { - path: "discussion", - component: FlarumComponent, - }, - ] - }, - { - path: "admin", - canActivate: [AdminGuardService], - children: [ - { - path: "user", - component: AdminUserComponent, - }, - { - path: "gmail", - component: AdminGmailComponent, - }, - { - path: "execution", - component: AdminExecutionComponent, - }, - ] - }, - - ], - }); + routes.push({ + path: "dashboard", + component: DashboardComponent, + children: [ + { + path: "home", + component: HomeComponent, + }, + { + path: "hub", + children: [ + { + path: "workflow", + component: HubWorkflowComponent, + children: [ + { + path: "search", + component: HubWorkflowSearchComponent, + }, + { + path: "search/result", + component: HubWorkflowResultComponent, + }, + { + path: "search/result/detail", + component: HubWorkflowDetailComponent, + }, + ], + }, + ], + }, + { + path: "user", + canActivate: [AuthGuardService], + children: [ + { + path: "project", + component: UserProjectComponent, + }, + { + path: "project/:pid", + component: UserProjectSectionComponent, + }, + { + path: "workflow", + component: UserWorkflowComponent, + }, + { + path: "file", + component: UserFileComponent, + }, + { + path: "dataset", + component: UserDatasetComponent, + }, + // the below two URLs route to the same Component. The component will render the page accordingly + { + path: "dataset/:did", + component: UserDatasetExplorerComponent, + }, + { + path: "dataset/create", + component: UserDatasetExplorerComponent, + }, + { + path: "quota", + component: UserQuotaComponent, + }, + { + path: "search", + component: SearchComponent, + }, + { + path: "discussion", + component: FlarumComponent, + }, + ], + }, + { + path: "admin", + canActivate: [AdminGuardService], + children: [ + { + path: "user", + component: AdminUserComponent, + }, + { + path: "gmail", + component: AdminGmailComponent, + }, + { + path: "execution", + component: AdminExecutionComponent, + }, + ], + }, + ], + }); } // redirect all other paths to index. routes.push({ diff --git a/core/gui/src/app/app.module.ts b/core/gui/src/app/app.module.ts index d324794a978..0d5ff32b9f1 100644 --- a/core/gui/src/app/app.module.ts +++ b/core/gui/src/app/app.module.ts @@ -138,9 +138,7 @@ import { HubWorkflowSearchComponent } from "./hub/component/workflow/search/hub- import { GoogleLoginComponent } from "./dashboard/user/component/google-login/google-login.component"; import { HubWorkflowResultComponent } from "./hub/component/workflow/result/hub-workflow-result.component"; import { HubWorkflowComponent } from "./hub/component/workflow/hub-workflow.component"; -import { - HubWorkflowSearchBarComponent -} from "./hub/component/workflow/search/search-bar/hub-workflow-search-bar.component"; +import { HubWorkflowSearchBarComponent } from "./hub/component/workflow/search-bar/hub-workflow-search-bar.component"; import { HubWorkflowDetailComponent } from "./hub/component/workflow/detail/hub-workflow-detail.component"; registerLocaleData(en); @@ -230,7 +228,7 @@ registerLocaleData(en); HubWorkflowSearchBarComponent, HubWorkflowDetailComponent, HubWorkflowResultComponent, - GoogleLoginComponent + GoogleLoginComponent, ], imports: [ BrowserModule, diff --git a/core/gui/src/app/dashboard/user/component/dashboard.component.ts b/core/gui/src/app/dashboard/user/component/dashboard.component.ts index dab87f215ed..972a29f3d42 100644 --- a/core/gui/src/app/dashboard/user/component/dashboard.component.ts +++ b/core/gui/src/app/dashboard/user/component/dashboard.component.ts @@ -23,9 +23,10 @@ export class DashboardComponent implements OnInit { private userService: UserService, private flarumService: FlarumService ) { - this.userService.userChanged() + this.userService + .userChanged() .pipe(untilDestroyed(this)) - .subscribe(() => this.isLogin = this.userService.isLogin()) + .subscribe(() => (this.isLogin = this.userService.isLogin())); } ngOnInit(): void { diff --git a/core/gui/src/app/dashboard/user/component/google-login/google-login.component.ts b/core/gui/src/app/dashboard/user/component/google-login/google-login.component.ts index 9ead57526dc..54901557f45 100644 --- a/core/gui/src/app/dashboard/user/component/google-login/google-login.component.ts +++ b/core/gui/src/app/dashboard/user/component/google-login/google-login.component.ts @@ -8,7 +8,7 @@ import { GoogleAuthService } from "../../../../common/service/user/google-auth.s @UntilDestroy() @Component({ selector: "texera-google-login", - template: "" + template: "", }) export class GoogleLoginComponent implements AfterViewInit { @ViewChild("googleButton") googleButton!: ElementRef; @@ -27,6 +27,8 @@ export class GoogleLoginComponent implements AfterViewInit { mergeMap(res => this.userService.googleLogin(res.credential)), untilDestroyed(this) ) - .subscribe(() => this.router.navigate([this.route.snapshot.queryParams["returnUrl"] || "/dashboard/user/workflow"])); + .subscribe(() => + this.router.navigate([this.route.snapshot.queryParams["returnUrl"] || "/dashboard/user/workflow"]) + ); } } diff --git a/core/gui/src/app/dashboard/user/component/user-icon/user-icon.component.ts b/core/gui/src/app/dashboard/user/component/user-icon/user-icon.component.ts index 69691f16682..6b83c0888eb 100644 --- a/core/gui/src/app/dashboard/user/component/user-icon/user-icon.component.ts +++ b/core/gui/src/app/dashboard/user/component/user-icon/user-icon.component.ts @@ -18,7 +18,10 @@ import { Router } from "@angular/router"; export class UserIconComponent { public user: User | undefined; - constructor(private userService: UserService, private router: Router) { + constructor( + private userService: UserService, + private router: Router + ) { this.user = this.userService.getCurrentUser(); } diff --git a/core/gui/src/app/hub/component/home/home.component.html b/core/gui/src/app/hub/component/home/home.component.html index 700aca7b31c..7fc71b3d3e7 100644 --- a/core/gui/src/app/hub/component/home/home.component.html +++ b/core/gui/src/app/hub/component/home/home.component.html @@ -6,7 +6,7 @@
      + style="text-align: center">

      Collaborative Data Analytics Using Workflows


      diff --git a/core/gui/src/app/hub/component/home/home.component.ts b/core/gui/src/app/hub/component/home/home.component.ts index fefcc32199f..cf766f4bf33 100644 --- a/core/gui/src/app/hub/component/home/home.component.ts +++ b/core/gui/src/app/hub/component/home/home.component.ts @@ -5,6 +5,6 @@ import { environment } from "../../../../environments/environment"; selector: "texera-login", templateUrl: "home.component.html", }) -export class HomeComponent{ +export class HomeComponent { localLogin = environment.localLogin; -} \ No newline at end of file +} diff --git a/core/gui/src/app/hub/component/hub.component.html b/core/gui/src/app/hub/component/hub.component.html index a302db04984..a38d2b53ade 100644 --- a/core/gui/src/app/hub/component/hub.component.html +++ b/core/gui/src/app/hub/component/hub.component.html @@ -10,9 +10,9 @@ nzMatchRouter="true" nzTooltipPlacement="right" routerLink="/dashboard/home"> - + Home

    • - + Workflows
    - \ No newline at end of file + diff --git a/core/gui/src/app/hub/component/hub.component.ts b/core/gui/src/app/hub/component/hub.component.ts index 765a8dc346f..130dcd8cfb9 100644 --- a/core/gui/src/app/hub/component/hub.component.ts +++ b/core/gui/src/app/hub/component/hub.component.ts @@ -5,5 +5,4 @@ import { Component } from "@angular/core"; templateUrl: "hub.component.html", styleUrls: ["hub.component.scss"], }) - -export class HubComponent {} \ No newline at end of file +export class HubComponent {} diff --git a/core/gui/src/app/hub/component/workflow/detail/hub-workflow-detail.component.html b/core/gui/src/app/hub/component/workflow/detail/hub-workflow-detail.component.html index 9067c7c5b0a..bc9d5448f61 100644 --- a/core/gui/src/app/hub/component/workflow/detail/hub-workflow-detail.component.html +++ b/core/gui/src/app/hub/component/workflow/detail/hub-workflow-detail.component.html @@ -1,9 +1,14 @@ - + - + {{ workflow.name }} - \ No newline at end of file + diff --git a/core/gui/src/app/hub/component/workflow/detail/hub-workflow-detail.component.ts b/core/gui/src/app/hub/component/workflow/detail/hub-workflow-detail.component.ts index 3de3e7cbbd6..19a757bcf87 100644 --- a/core/gui/src/app/hub/component/workflow/detail/hub-workflow-detail.component.ts +++ b/core/gui/src/app/hub/component/workflow/detail/hub-workflow-detail.component.ts @@ -9,12 +9,14 @@ import { UntilDestroy, untilDestroyed } from "@ngneat/until-destroy"; templateUrl: "hub-workflow-detail.component.html", styleUrls: ["hub-workflow-detail.component.scss"], }) - export class HubWorkflowDetailComponent { listOfWorkflows: HubWorkflow[] = []; constructor(private hubWorkflowService: HubWorkflowService) { - hubWorkflowService.getWorkflowList().pipe(untilDestroyed(this)).subscribe(workflows => { - this.listOfWorkflows = workflows; - }); + hubWorkflowService + .getWorkflowList() + .pipe(untilDestroyed(this)) + .subscribe(workflows => { + this.listOfWorkflows = workflows; + }); } -} \ No newline at end of file +} diff --git a/core/gui/src/app/hub/component/workflow/hub-workflow.component.ts b/core/gui/src/app/hub/component/workflow/hub-workflow.component.ts index c7275a1bd3d..2bc51a1cf03 100644 --- a/core/gui/src/app/hub/component/workflow/hub-workflow.component.ts +++ b/core/gui/src/app/hub/component/workflow/hub-workflow.component.ts @@ -4,5 +4,4 @@ import { Component } from "@angular/core"; selector: "texera-hub-workflow", template: "", }) - -export class HubWorkflowComponent {} \ No newline at end of file +export class HubWorkflowComponent {} diff --git a/core/gui/src/app/hub/component/workflow/result/hub-workflow-result.component.html b/core/gui/src/app/hub/component/workflow/result/hub-workflow-result.component.html index 9067c7c5b0a..bc9d5448f61 100644 --- a/core/gui/src/app/hub/component/workflow/result/hub-workflow-result.component.html +++ b/core/gui/src/app/hub/component/workflow/result/hub-workflow-result.component.html @@ -1,9 +1,14 @@ - + - + {{ workflow.name }} - \ No newline at end of file + diff --git a/core/gui/src/app/hub/component/workflow/result/hub-workflow-result.component.ts b/core/gui/src/app/hub/component/workflow/result/hub-workflow-result.component.ts index 440126939ed..84e309120d7 100644 --- a/core/gui/src/app/hub/component/workflow/result/hub-workflow-result.component.ts +++ b/core/gui/src/app/hub/component/workflow/result/hub-workflow-result.component.ts @@ -9,12 +9,15 @@ import { UntilDestroy, untilDestroyed } from "@ngneat/until-destroy"; templateUrl: "hub-workflow-result.component.html", styleUrls: ["hub-workflow-result.component.scss"], }) - export class HubWorkflowResultComponent { listOfWorkflows: HubWorkflow[] = []; + constructor(hubWorkflowService: HubWorkflowService) { - hubWorkflowService.getWorkflowList().pipe(untilDestroyed(this)).subscribe(workflows => { - this.listOfWorkflows = workflows; - }); + hubWorkflowService + .getWorkflowList() + .pipe(untilDestroyed(this)) + .subscribe(workflows => { + this.listOfWorkflows = workflows; + }); } -} \ No newline at end of file +} diff --git a/core/gui/src/app/hub/component/workflow/search-bar/hub-workflow-search-bar.component.html b/core/gui/src/app/hub/component/workflow/search-bar/hub-workflow-search-bar.component.html new file mode 100644 index 00000000000..76058f596c1 --- /dev/null +++ b/core/gui/src/app/hub/component/workflow/search-bar/hub-workflow-search-bar.component.html @@ -0,0 +1,15 @@ +
    + + + + +
    diff --git a/core/gui/src/app/hub/component/workflow/search-bar/hub-workflow-search-bar.component.ts b/core/gui/src/app/hub/component/workflow/search-bar/hub-workflow-search-bar.component.ts new file mode 100644 index 00000000000..2edf5d26fe4 --- /dev/null +++ b/core/gui/src/app/hub/component/workflow/search-bar/hub-workflow-search-bar.component.ts @@ -0,0 +1,28 @@ +import { Component } from "@angular/core"; +import { HubWorkflowService } from "../../../service/workflow/hub-workflow.service"; +import { UntilDestroy, untilDestroyed } from "@ngneat/until-destroy"; + +@UntilDestroy() +@Component({ + selector: "texera-hub-workflow-search-bar", + templateUrl: "hub-workflow-search-bar.component.html", +}) +export class HubWorkflowSearchBarComponent { + inputValue?: string; + workflowNames: string[] = []; + filteredOptions: string[] = []; + + constructor(hubWorkflowService: HubWorkflowService) { + this.filteredOptions = this.workflowNames; + hubWorkflowService + .getWorkflowList() + .pipe(untilDestroyed(this)) + .subscribe(workflows => (this.workflowNames = workflows.map(obj => obj.name))); + } + + onChange(value: string) { + this.filteredOptions = this.workflowNames.filter( + option => option.toLowerCase().indexOf(value.toLowerCase()) !== -1 + ); + } +} diff --git a/core/gui/src/app/hub/component/workflow/search/hub-workflow-search.component.html b/core/gui/src/app/hub/component/workflow/search/hub-workflow-search.component.html index fd70f133569..38a94560bf1 100644 --- a/core/gui/src/app/hub/component/workflow/search/hub-workflow-search.component.html +++ b/core/gui/src/app/hub/component/workflow/search/hub-workflow-search.component.html @@ -2,11 +2,18 @@

    Welcome to Texera Community Hub


    - Access 1000 workflows + Access + {{workflowCount}} workflows
    provided by Texera and our community.

    - \ No newline at end of file + diff --git a/core/gui/src/app/hub/component/workflow/search/hub-workflow-search.component.scss b/core/gui/src/app/hub/component/workflow/search/hub-workflow-search.component.scss index 71fa09a02d7..97e981a2648 100644 --- a/core/gui/src/app/hub/component/workflow/search/hub-workflow-search.component.scss +++ b/core/gui/src/app/hub/component/workflow/search/hub-workflow-search.component.scss @@ -17,4 +17,4 @@ i { color: #666; font-style: normal; -} \ No newline at end of file +} diff --git a/core/gui/src/app/hub/component/workflow/search/hub-workflow-search.component.ts b/core/gui/src/app/hub/component/workflow/search/hub-workflow-search.component.ts index 45b8d543086..820d738f7e1 100644 --- a/core/gui/src/app/hub/component/workflow/search/hub-workflow-search.component.ts +++ b/core/gui/src/app/hub/component/workflow/search/hub-workflow-search.component.ts @@ -1,9 +1,22 @@ import { Component } from "@angular/core"; +import { HubWorkflowService } from "../../../service/workflow/hub-workflow.service"; +import { UntilDestroy, untilDestroyed } from "@ngneat/until-destroy"; +@UntilDestroy() @Component({ selector: "texera-hub-workflow-search", templateUrl: "hub-workflow-search.component.html", styleUrls: ["hub-workflow-search.component.scss"], }) +export class HubWorkflowSearchComponent { + workflowCount: number | undefined; -export class HubWorkflowSearchComponent {} \ No newline at end of file + constructor(hubWorkflowService: HubWorkflowService) { + hubWorkflowService + .getWorkflowCount() + .pipe(untilDestroyed(this)) + .subscribe(count => { + this.workflowCount = count; + }); + } +} diff --git a/core/gui/src/app/hub/component/workflow/search/search-bar/hub-workflow-search-bar.component.html b/core/gui/src/app/hub/component/workflow/search/search-bar/hub-workflow-search-bar.component.html deleted file mode 100644 index aa72e54cf7d..00000000000 --- a/core/gui/src/app/hub/component/workflow/search/search-bar/hub-workflow-search-bar.component.html +++ /dev/null @@ -1,12 +0,0 @@ -
    - - - - -
    \ No newline at end of file diff --git a/core/gui/src/app/hub/component/workflow/search/search-bar/hub-workflow-search-bar.component.ts b/core/gui/src/app/hub/component/workflow/search/search-bar/hub-workflow-search-bar.component.ts deleted file mode 100644 index 960ec1e71f2..00000000000 --- a/core/gui/src/app/hub/component/workflow/search/search-bar/hub-workflow-search-bar.component.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { Component } from "@angular/core"; -import { HubWorkflowService } from "../../../../service/workflow/hub-workflow.service"; -import { UntilDestroy, untilDestroyed } from "@ngneat/until-destroy"; - -@UntilDestroy() -@Component({ - selector: "texera-hub-workflow-search-bar", - templateUrl: "hub-workflow-search-bar.component.html" -}) - -export class HubWorkflowSearchBarComponent { - inputValue?: string; - workflowNames: string[] = []; - filteredOptions: string[] = []; - - constructor(hubWorkflowService: HubWorkflowService) { - this.filteredOptions = this.workflowNames; - hubWorkflowService.getWorkflowList().pipe(untilDestroyed(this)).subscribe(workflows => { - this.workflowNames = workflows.map(obj => obj.name); - }); - } - - onChange(value: string): void { - this.filteredOptions = this.workflowNames.filter(option => option.toLowerCase().indexOf(value.toLowerCase()) !== -1); - } -} \ No newline at end of file diff --git a/core/gui/src/app/hub/service/workflow/hub-workflow.service.ts b/core/gui/src/app/hub/service/workflow/hub-workflow.service.ts index c5a52b6c8ef..35586e58e97 100644 --- a/core/gui/src/app/hub/service/workflow/hub-workflow.service.ts +++ b/core/gui/src/app/hub/service/workflow/hub-workflow.service.ts @@ -4,16 +4,19 @@ import { Observable } from "rxjs"; import { AppSettings } from "../../../common/app-setting"; import { HubWorkflow } from "../../component/type/hub-workflow.interface"; -export const BASE_URL = `${AppSettings.getApiEndpoint()}/hub/workflow`; - @Injectable({ providedIn: "root", }) export class HubWorkflowService { + readonly BASE_URL: string = `${AppSettings.getApiEndpoint()}/hub/workflow`; + constructor(private http: HttpClient) {} - public getWorkflowList(): Observable { - return this.http.get(`${BASE_URL}/list`); + public getWorkflowCount(): Observable { + return this.http.get(`${this.BASE_URL}/count`); } + public getWorkflowList(): Observable { + return this.http.get(`${this.BASE_URL}/list`); + } } From a1846eba943e4e313033b1a16b854c59acf4bc90 Mon Sep 17 00:00:00 2001 From: linxinyuan Date: Sun, 14 Jul 2024 01:00:34 -0700 Subject: [PATCH 14/33] update --- .../search-bar/hub-workflow-search-bar.component.html | 8 +++++--- .../search-bar/hub-workflow-search-bar.component.ts | 7 ++++++- .../workflow/search/hub-workflow-search.component.html | 3 +-- 3 files changed, 12 insertions(+), 6 deletions(-) diff --git a/core/gui/src/app/hub/component/workflow/search-bar/hub-workflow-search-bar.component.html b/core/gui/src/app/hub/component/workflow/search-bar/hub-workflow-search-bar.component.html index 76058f596c1..e40fb1f8aeb 100644 --- a/core/gui/src/app/hub/component/workflow/search-bar/hub-workflow-search-bar.component.html +++ b/core/gui/src/app/hub/component/workflow/search-bar/hub-workflow-search-bar.component.html @@ -1,4 +1,4 @@ -
    +
    @@ -7,9 +7,11 @@ nz-input [(ngModel)]="inputValue" (ngModelChange)="onChange($event)" - [nzAutocomplete]="auto" /> + [nzAutocomplete]="auto" + name="searchInput" /> + -
    + diff --git a/core/gui/src/app/hub/component/workflow/search-bar/hub-workflow-search-bar.component.ts b/core/gui/src/app/hub/component/workflow/search-bar/hub-workflow-search-bar.component.ts index 2edf5d26fe4..ead4cd8e0ce 100644 --- a/core/gui/src/app/hub/component/workflow/search-bar/hub-workflow-search-bar.component.ts +++ b/core/gui/src/app/hub/component/workflow/search-bar/hub-workflow-search-bar.component.ts @@ -1,6 +1,7 @@ import { Component } from "@angular/core"; import { HubWorkflowService } from "../../../service/workflow/hub-workflow.service"; import { UntilDestroy, untilDestroyed } from "@ngneat/until-destroy"; +import { Router } from "@angular/router"; @UntilDestroy() @Component({ @@ -12,7 +13,7 @@ export class HubWorkflowSearchBarComponent { workflowNames: string[] = []; filteredOptions: string[] = []; - constructor(hubWorkflowService: HubWorkflowService) { + constructor(hubWorkflowService: HubWorkflowService, private router: Router) { this.filteredOptions = this.workflowNames; hubWorkflowService .getWorkflowList() @@ -25,4 +26,8 @@ export class HubWorkflowSearchBarComponent { option => option.toLowerCase().indexOf(value.toLowerCase()) !== -1 ); } + + onSubmit() { + this.router.navigate(["/dashboard/hub/workflow/search/result"]); + } } diff --git a/core/gui/src/app/hub/component/workflow/search/hub-workflow-search.component.html b/core/gui/src/app/hub/component/workflow/search/hub-workflow-search.component.html index 38a94560bf1..3bf42736565 100644 --- a/core/gui/src/app/hub/component/workflow/search/hub-workflow-search.component.html +++ b/core/gui/src/app/hub/component/workflow/search/hub-workflow-search.component.html @@ -5,8 +5,7 @@

    Welcome to Texera Community Hub

    Access {{workflowCount}} workflows From 663b8ea0f09463a5d6b2da66352f3f7cb6bdfa30 Mon Sep 17 00:00:00 2001 From: linxinyuan Date: Sun, 14 Jul 2024 01:36:16 -0700 Subject: [PATCH 15/33] update --- .../dashboard/user/component/dashboard.component.ts | 11 ++++++++--- .../component/google-login/google-login.component.ts | 6 ++++-- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/core/gui/src/app/dashboard/user/component/dashboard.component.ts b/core/gui/src/app/dashboard/user/component/dashboard.component.ts index 972a29f3d42..967344de48e 100644 --- a/core/gui/src/app/dashboard/user/component/dashboard.component.ts +++ b/core/gui/src/app/dashboard/user/component/dashboard.component.ts @@ -1,4 +1,4 @@ -import { Component, OnInit } from "@angular/core"; +import { ChangeDetectorRef, Component, OnInit } from "@angular/core"; import { WorkflowPersistService } from "../../../common/service/workflow-persist/workflow-persist.service"; import { UserService } from "../../../common/service/user/user.service"; import { UntilDestroy, untilDestroyed } from "@ngneat/until-destroy"; @@ -21,12 +21,17 @@ export class DashboardComponent implements OnInit { constructor( private userService: UserService, - private flarumService: FlarumService + private flarumService: FlarumService, + private cdr: ChangeDetectorRef ) { this.userService .userChanged() .pipe(untilDestroyed(this)) - .subscribe(() => (this.isLogin = this.userService.isLogin())); + .subscribe(() => { + this.isLogin = this.userService.isLogin(); + this.isAdmin = this.userService.isAdmin(); + this.cdr.detectChanges(); + }); } ngOnInit(): void { diff --git a/core/gui/src/app/dashboard/user/component/google-login/google-login.component.ts b/core/gui/src/app/dashboard/user/component/google-login/google-login.component.ts index 54901557f45..76ce118090a 100644 --- a/core/gui/src/app/dashboard/user/component/google-login/google-login.component.ts +++ b/core/gui/src/app/dashboard/user/component/google-login/google-login.component.ts @@ -27,8 +27,10 @@ export class GoogleLoginComponent implements AfterViewInit { mergeMap(res => this.userService.googleLogin(res.credential)), untilDestroyed(this) ) - .subscribe(() => - this.router.navigate([this.route.snapshot.queryParams["returnUrl"] || "/dashboard/user/workflow"]) + .subscribe(() => { + const returnUrl = this.route.snapshot.queryParams["returnUrl"]; + if (returnUrl) this.router.navigate([returnUrl]); + } ); } } From 3c49e8cb57768c3d9e55ac5ae22f4faddeb3ee81 Mon Sep 17 00:00:00 2001 From: linxinyuan Date: Sun, 14 Jul 2024 02:44:17 -0700 Subject: [PATCH 16/33] update --- .../google-login/google-login.component.ts | 7 ++- .../component/type/hub-workflow.interface.ts | 4 +- .../detail/hub-workflow-detail.component.html | 41 +++++++++++------ .../detail/hub-workflow-detail.component.scss | 46 +++++++++++++++++++ .../detail/hub-workflow-detail.component.ts | 44 +++++++++++++----- .../result/hub-workflow-result.component.html | 30 ++++++++---- .../result/hub-workflow-result.component.scss | 29 ++++++++++++ .../hub-workflow-search-bar.component.html | 4 +- .../hub-workflow-search-bar.component.ts | 5 +- .../search/hub-workflow-search.component.html | 8 +--- 10 files changed, 170 insertions(+), 48 deletions(-) diff --git a/core/gui/src/app/dashboard/user/component/google-login/google-login.component.ts b/core/gui/src/app/dashboard/user/component/google-login/google-login.component.ts index 76ce118090a..713701150e3 100644 --- a/core/gui/src/app/dashboard/user/component/google-login/google-login.component.ts +++ b/core/gui/src/app/dashboard/user/component/google-login/google-login.component.ts @@ -28,9 +28,8 @@ export class GoogleLoginComponent implements AfterViewInit { untilDestroyed(this) ) .subscribe(() => { - const returnUrl = this.route.snapshot.queryParams["returnUrl"]; - if (returnUrl) this.router.navigate([returnUrl]); - } - ); + const returnUrl = this.route.snapshot.queryParams["returnUrl"]; + if (returnUrl) this.router.navigate([returnUrl]); + }); } } diff --git a/core/gui/src/app/hub/component/type/hub-workflow.interface.ts b/core/gui/src/app/hub/component/type/hub-workflow.interface.ts index 8763c1acb82..5e8c3c06458 100644 --- a/core/gui/src/app/hub/component/type/hub-workflow.interface.ts +++ b/core/gui/src/app/hub/component/type/hub-workflow.interface.ts @@ -3,6 +3,6 @@ export interface HubWorkflow { description: string; wid: number; content: string; - creation_time: number; - last_modified_time: number; + creationTime: number; + lastModifiedTime: number; } diff --git a/core/gui/src/app/hub/component/workflow/detail/hub-workflow-detail.component.html b/core/gui/src/app/hub/component/workflow/detail/hub-workflow-detail.component.html index bc9d5448f61..fa750613a0c 100644 --- a/core/gui/src/app/hub/component/workflow/detail/hub-workflow-detail.component.html +++ b/core/gui/src/app/hub/component/workflow/detail/hub-workflow-detail.component.html @@ -1,14 +1,29 @@ - +
    +

    Workflow Detail Page

    +
    +
    +

    ID

    +

    {{ wid }}

    +
    +
    +

    Workflow Name

    +

    {{ workflow.name }}

    +
    +
    +

    Created By

    +

    {{ workflow.createdBy }}

    +
    +
    - - - - {{ workflow.name }} - - - +
    +

    Steps

    + +
    +

    {{ step.name }}

    +

    {{ step.description }}

    +

    Status: {{ step.status }}

    +
    +
    +
    diff --git a/core/gui/src/app/hub/component/workflow/detail/hub-workflow-detail.component.scss b/core/gui/src/app/hub/component/workflow/detail/hub-workflow-detail.component.scss index e69de29bb2d..c6034ac63b1 100644 --- a/core/gui/src/app/hub/component/workflow/detail/hub-workflow-detail.component.scss +++ b/core/gui/src/app/hub/component/workflow/detail/hub-workflow-detail.component.scss @@ -0,0 +1,46 @@ +body { + font-family: Arial, sans-serif; + margin: 0; + padding: 0; + background-color: #f4f4f4; +} +.container { + width: 80%; + margin: 30px auto 0; + padding: 20px; + background-color: #fff; + box-shadow: 0 0 10px rgba(0, 0, 0, 0.1); +} +h1 { + color: #333; +} +.workflow-info { + display: flex; + justify-content: space-between; + margin-bottom: 20px; +} +.workflow-info div { + flex: 1; + padding: 10px; + background-color: #e9e9e9; + margin-right: 10px; +} +.workflow-info div:last-child { + margin-right: 0; +} +.workflow-steps { + margin-top: 20px; +} +.workflow-step { + background-color: #f9f9f9; + padding: 15px; + margin-bottom: 10px; + border-left: 5px solid #007bff; +} +.workflow-step h3 { + margin: 0; + color: #007bff; +} +.workflow-step p { + margin: 5px 0; +} diff --git a/core/gui/src/app/hub/component/workflow/detail/hub-workflow-detail.component.ts b/core/gui/src/app/hub/component/workflow/detail/hub-workflow-detail.component.ts index 19a757bcf87..c0e3c52d068 100644 --- a/core/gui/src/app/hub/component/workflow/detail/hub-workflow-detail.component.ts +++ b/core/gui/src/app/hub/component/workflow/detail/hub-workflow-detail.component.ts @@ -1,7 +1,6 @@ import { Component } from "@angular/core"; -import { HubWorkflowService } from "../../../service/workflow/hub-workflow.service"; -import { HubWorkflow } from "../../type/hub-workflow.interface"; -import { UntilDestroy, untilDestroyed } from "@ngneat/until-destroy"; +import { UntilDestroy } from "@ngneat/until-destroy"; +import { ActivatedRoute } from "@angular/router"; @UntilDestroy() @Component({ @@ -10,13 +9,36 @@ import { UntilDestroy, untilDestroyed } from "@ngneat/until-destroy"; styleUrls: ["hub-workflow-detail.component.scss"], }) export class HubWorkflowDetailComponent { - listOfWorkflows: HubWorkflow[] = []; - constructor(private hubWorkflowService: HubWorkflowService) { - hubWorkflowService - .getWorkflowList() - .pipe(untilDestroyed(this)) - .subscribe(workflows => { - this.listOfWorkflows = workflows; - }); + wid: string | null; + + workflow = { + name: "Example Workflow", + createdBy: "John Doe", + steps: [ + { + name: "Step 1: Data Collection", + description: "Collect necessary data from various sources.", + status: "Completed", + }, + { + name: "Step 2: Data Analysis", + description: "Analyze the collected data for insights.", + status: "In Progress", + }, + { + name: "Step 3: Report Generation", + description: "Generate reports based on the analysis.", + status: "Not Started", + }, + { + name: "Step 4: Presentation", + description: "Present the findings to stakeholders.", + status: "Not Started", + }, + ], + }; + + constructor(private route: ActivatedRoute) { + this.wid = this.route.snapshot.queryParamMap.get("wid"); } } diff --git a/core/gui/src/app/hub/component/workflow/result/hub-workflow-result.component.html b/core/gui/src/app/hub/component/workflow/result/hub-workflow-result.component.html index bc9d5448f61..3a302831f5e 100644 --- a/core/gui/src/app/hub/component/workflow/result/hub-workflow-result.component.html +++ b/core/gui/src/app/hub/component/workflow/result/hub-workflow-result.component.html @@ -2,13 +2,25 @@ - - - {{ workflow.name }} - - + nzHeader="Results" + nzFooter="Total Workflows: {{listOfWorkflows.length}}"> +
    + + +

    ID: {{ workflow.wid }}

    +

    Description: {{ workflow.description }}

    +

    Created On: {{ workflow.creationTime | date }}

    +

    Modified On: {{ workflow.lastModifiedTime | date }}

    + +
    +
    +
    diff --git a/core/gui/src/app/hub/component/workflow/result/hub-workflow-result.component.scss b/core/gui/src/app/hub/component/workflow/result/hub-workflow-result.component.scss index e69de29bb2d..4985d3c4279 100644 --- a/core/gui/src/app/hub/component/workflow/result/hub-workflow-result.component.scss +++ b/core/gui/src/app/hub/component/workflow/result/hub-workflow-result.component.scss @@ -0,0 +1,29 @@ +.workflow-list { + display: flex; + flex-wrap: wrap; + justify-content: space-around; + padding: 20px; + background-color: #f9f9f9; +} + +.workflow-card { + width: 300px; + transition: + transform 0.3s, + box-shadow 0.3s; +} + +.workflow-card:hover { + transform: scale(1.05); + box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2); +} + +.workflow-card p { + margin: 0; + color: #666; +} + +.workflow-card button { + margin-top: 10px; + width: 100%; +} diff --git a/core/gui/src/app/hub/component/workflow/search-bar/hub-workflow-search-bar.component.html b/core/gui/src/app/hub/component/workflow/search-bar/hub-workflow-search-bar.component.html index e40fb1f8aeb..24e603e5fa8 100644 --- a/core/gui/src/app/hub/component/workflow/search-bar/hub-workflow-search-bar.component.html +++ b/core/gui/src/app/hub/component/workflow/search-bar/hub-workflow-search-bar.component.html @@ -10,7 +10,9 @@ [nzAutocomplete]="auto" name="searchInput" /> - + diff --git a/core/gui/src/app/hub/component/workflow/search-bar/hub-workflow-search-bar.component.ts b/core/gui/src/app/hub/component/workflow/search-bar/hub-workflow-search-bar.component.ts index ead4cd8e0ce..7fdbfb50e68 100644 --- a/core/gui/src/app/hub/component/workflow/search-bar/hub-workflow-search-bar.component.ts +++ b/core/gui/src/app/hub/component/workflow/search-bar/hub-workflow-search-bar.component.ts @@ -13,7 +13,10 @@ export class HubWorkflowSearchBarComponent { workflowNames: string[] = []; filteredOptions: string[] = []; - constructor(hubWorkflowService: HubWorkflowService, private router: Router) { + constructor( + hubWorkflowService: HubWorkflowService, + private router: Router + ) { this.filteredOptions = this.workflowNames; hubWorkflowService .getWorkflowList() diff --git a/core/gui/src/app/hub/component/workflow/search/hub-workflow-search.component.html b/core/gui/src/app/hub/component/workflow/search/hub-workflow-search.component.html index 3bf42736565..caf693d2c83 100644 --- a/core/gui/src/app/hub/component/workflow/search/hub-workflow-search.component.html +++ b/core/gui/src/app/hub/component/workflow/search/hub-workflow-search.component.html @@ -2,13 +2,7 @@

    Welcome to Texera Community Hub


    - Access - {{workflowCount}} workflows + Access {{workflowCount}} workflows
    provided by Texera and our community.
    From aa050ac090566b8a0c1590a8ddee0b766c79fe4c Mon Sep 17 00:00:00 2001 From: linxinyuan Date: Sun, 14 Jul 2024 16:13:47 -0700 Subject: [PATCH 17/33] update --- .../admin/gmail/admin-gmail.component.ts | 47 +++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 core/gui/src/app/dashboard/component/admin/gmail/admin-gmail.component.ts diff --git a/core/gui/src/app/dashboard/component/admin/gmail/admin-gmail.component.ts b/core/gui/src/app/dashboard/component/admin/gmail/admin-gmail.component.ts new file mode 100644 index 00000000000..835baa2180c --- /dev/null +++ b/core/gui/src/app/dashboard/component/admin/gmail/admin-gmail.component.ts @@ -0,0 +1,47 @@ +import { Component, OnInit } from "@angular/core"; +import { GmailService } from "../../../../common/service/gmail/gmail.service"; +import { FormBuilder, FormGroup, Validators } from "@angular/forms"; +import { UntilDestroy, untilDestroyed } from "@ngneat/until-destroy"; +@UntilDestroy() +@Component({ + selector: "texera-gmail", + templateUrl: "./admin-gmail.component.html", + styleUrls: ["./admin-gmail.component.scss"], +}) +export class AdminGmailComponent implements OnInit { + public validateForm!: FormGroup; + public email: String | undefined; + constructor( + private gmailAuthService: GmailService, + private formBuilder: FormBuilder + ) {} + + ngOnInit(): void { + this.validateForm = this.formBuilder.group({ + email: [null, [Validators.email, Validators.required]], + subject: [null, [Validators.required]], + content: [null, [Validators.required]], + }); + this.getSenderEmail(); + } + + getSenderEmail() { + this.gmailAuthService + .getSenderEmail() + .pipe(untilDestroyed(this)) + .subscribe({ + next: email => (this.email = email), + error: (err: unknown) => { + this.email = undefined; + console.log(err); + }, + }); + } + sendTestEmail(): void { + this.gmailAuthService.sendEmail( + this.validateForm.value.subject, + this.validateForm.value.content, + this.validateForm.value.email + ); + } +} From 81ecfbe0f0b71b1708dfb79800c71039c74a9a0a Mon Sep 17 00:00:00 2001 From: linxinyuan Date: Mon, 15 Jul 2024 23:01:14 -0700 Subject: [PATCH 18/33] resolve conflict --- core/gui/src/app/app-routing.module.ts | 28 +++++++++---------- core/gui/src/app/app.module.ts | 2 +- .../admin-execution.component.spec.ts | 2 +- .../execution/admin-execution.component.ts | 4 +-- .../admin/user/admin-user.component.spec.ts | 2 +- .../admin/user/admin-user.component.ts | 4 +-- .../component/dashboard.component.ts | 8 +++--- .../google-login/google-login.component.ts | 0 8 files changed, 25 insertions(+), 25 deletions(-) rename core/gui/src/app/dashboard/{user/component => component/user}/google-login/google-login.component.ts (100%) diff --git a/core/gui/src/app/app-routing.module.ts b/core/gui/src/app/app-routing.module.ts index 172b9cd249f..d77ad02a399 100644 --- a/core/gui/src/app/app-routing.module.ts +++ b/core/gui/src/app/app-routing.module.ts @@ -1,23 +1,23 @@ import { NgModule } from "@angular/core"; import { RouterModule, Routes } from "@angular/router"; import { environment } from "../environments/environment"; -import { DashboardComponent } from "./dashboard/user/component/dashboard.component"; -import { UserWorkflowComponent } from "./dashboard/user/component/user-workflow/user-workflow.component"; -import { UserFileComponent } from "./dashboard/user/component/user-file/user-file.component"; -import { UserQuotaComponent } from "./dashboard/user/component/user-quota/user-quota.component"; -import { UserProjectSectionComponent } from "./dashboard/user/component/user-project/user-project-section/user-project-section.component"; -import { UserProjectComponent } from "./dashboard/user/component/user-project/user-project.component"; +import { DashboardComponent } from "./dashboard/component/dashboard.component"; +import { UserWorkflowComponent } from "./dashboard/component/user/user-workflow/user-workflow.component"; +import { UserFileComponent } from "./dashboard/component/user/user-file/user-file.component"; +import { UserQuotaComponent } from "./dashboard/component/user/user-quota/user-quota.component"; +import { UserProjectSectionComponent } from "./dashboard/component/user/user-project/user-project-section/user-project-section.component"; +import { UserProjectComponent } from "./dashboard/component/user/user-project/user-project.component"; import { WorkspaceComponent } from "./workspace/component/workspace.component"; import { HomeComponent } from "./hub/component/home/home.component"; import { AuthGuardService } from "./common/service/user/auth-guard.service"; -import { AdminUserComponent } from "./dashboard/user/component/admin/user/admin-user.component"; -import { AdminExecutionComponent } from "./dashboard/user/component/admin/execution/admin-execution.component"; -import { AdminGuardService } from "./dashboard/user/service/admin/guard/admin-guard.service"; -import { SearchComponent } from "./dashboard/user/component/search/search.component"; -import { FlarumComponent } from "./dashboard/user/component/flarum/flarum.component"; -import { AdminGmailComponent } from "./dashboard/user/component/admin/gmail/admin-gmail.component"; -import { UserDatasetExplorerComponent } from "./dashboard/user/component/user-dataset/user-dataset-explorer/user-dataset-explorer.component"; -import { UserDatasetComponent } from "./dashboard/user/component/user-dataset/user-dataset.component"; +import { AdminUserComponent } from "./dashboard/component/admin/user/admin-user.component"; +import { AdminExecutionComponent } from "./dashboard/component/admin/execution/admin-execution.component"; +import { AdminGuardService } from "./dashboard/service/admin/guard/admin-guard.service"; +import { SearchComponent } from "./dashboard/component/user/search/search.component"; +import { FlarumComponent } from "./dashboard/component/user/flarum/flarum.component"; +import { AdminGmailComponent } from "./dashboard/component/admin/gmail/admin-gmail.component"; +import { UserDatasetExplorerComponent } from "./dashboard/component/user/user-dataset/user-dataset-explorer/user-dataset-explorer.component"; +import { UserDatasetComponent } from "./dashboard/component/user/user-dataset/user-dataset.component"; import { HubWorkflowSearchComponent } from "./hub/component/workflow/search/hub-workflow-search.component"; import { HubWorkflowResultComponent } from "./hub/component/workflow/result/hub-workflow-result.component"; import { HubWorkflowComponent } from "./hub/component/workflow/hub-workflow.component"; diff --git a/core/gui/src/app/app.module.ts b/core/gui/src/app/app.module.ts index 1fefa46edcb..52752c5b94d 100644 --- a/core/gui/src/app/app.module.ts +++ b/core/gui/src/app/app.module.ts @@ -135,7 +135,7 @@ import { FileSelectionComponent } from "./workspace/component/file-selection/fil import { ResultExportationComponent } from "./workspace/component/result-exportation/result-exportation.component"; import { HubComponent } from "./hub/component/hub.component"; import { HubWorkflowSearchComponent } from "./hub/component/workflow/search/hub-workflow-search.component"; -import { GoogleLoginComponent } from "./dashboard/user/component/google-login/google-login.component"; +import { GoogleLoginComponent } from "./dashboard/component/user/google-login/google-login.component"; import { HubWorkflowResultComponent } from "./hub/component/workflow/result/hub-workflow-result.component"; import { HubWorkflowComponent } from "./hub/component/workflow/hub-workflow.component"; import { HubWorkflowSearchBarComponent } from "./hub/component/workflow/search-bar/hub-workflow-search-bar.component"; diff --git a/core/gui/src/app/dashboard/component/admin/execution/admin-execution.component.spec.ts b/core/gui/src/app/dashboard/component/admin/execution/admin-execution.component.spec.ts index 1693a1d0ed7..8534ea2cb4e 100644 --- a/core/gui/src/app/dashboard/component/admin/execution/admin-execution.component.spec.ts +++ b/core/gui/src/app/dashboard/component/admin/execution/admin-execution.component.spec.ts @@ -1,6 +1,6 @@ import { ComponentFixture, inject, TestBed, waitForAsync } from "@angular/core/testing"; import { AdminExecutionComponent } from "./admin-execution.component"; -import { AdminExecutionService } from "../../../user/service/admin/execution/admin-execution.service"; +import { AdminExecutionService } from "../../../service/admin/execution/admin-execution.service"; import { HttpClientTestingModule, HttpTestingController } from "@angular/common/http/testing"; import { NzDropDownModule } from "ng-zorro-antd/dropdown"; import { NzModalModule } from "ng-zorro-antd/modal"; diff --git a/core/gui/src/app/dashboard/component/admin/execution/admin-execution.component.ts b/core/gui/src/app/dashboard/component/admin/execution/admin-execution.component.ts index 35d1800772c..c22cb793e29 100644 --- a/core/gui/src/app/dashboard/component/admin/execution/admin-execution.component.ts +++ b/core/gui/src/app/dashboard/component/admin/execution/admin-execution.component.ts @@ -1,10 +1,10 @@ import { Component, OnDestroy, OnInit } from "@angular/core"; import { UntilDestroy, untilDestroyed } from "@ngneat/until-destroy"; -import { AdminExecutionService } from "../../../user/service/admin/execution/admin-execution.service"; +import { AdminExecutionService } from "../../../service/admin/execution/admin-execution.service"; import { Execution } from "../../../../common/type/execution"; import { NzTableFilterFn, NzTableSortFn } from "ng-zorro-antd/table"; import { NzModalService } from "ng-zorro-antd/modal"; -import { WorkflowExecutionHistoryComponent } from "../../../user/component/user-workflow/ngbd-modal-workflow-executions/workflow-execution-history.component"; +import { WorkflowExecutionHistoryComponent } from "../../user/user-workflow/ngbd-modal-workflow-executions/workflow-execution-history.component"; import { Workflow } from "../../../../common/type/workflow"; import { WorkflowWebsocketService } from "../../../../workspace/service/workflow-websocket/workflow-websocket.service"; diff --git a/core/gui/src/app/dashboard/component/admin/user/admin-user.component.spec.ts b/core/gui/src/app/dashboard/component/admin/user/admin-user.component.spec.ts index df3c62b4d1a..592e9f5c7f6 100644 --- a/core/gui/src/app/dashboard/component/admin/user/admin-user.component.spec.ts +++ b/core/gui/src/app/dashboard/component/admin/user/admin-user.component.spec.ts @@ -2,7 +2,7 @@ import { ComponentFixture, inject, TestBed, waitForAsync } from "@angular/core/t import { AdminUserComponent } from "./admin-user.component"; import { UserService } from "../../../../common/service/user/user.service"; import { StubUserService } from "../../../../common/service/user/stub-user.service"; -import { AdminUserService } from "../../../user/service/admin/user/admin-user.service"; +import { AdminUserService } from "../../../service/admin/user/admin-user.service"; import { HttpClientTestingModule, HttpTestingController } from "@angular/common/http/testing"; import { NzDropDownModule } from "ng-zorro-antd/dropdown"; import { NzModalModule } from "ng-zorro-antd/modal"; diff --git a/core/gui/src/app/dashboard/component/admin/user/admin-user.component.ts b/core/gui/src/app/dashboard/component/admin/user/admin-user.component.ts index a64f9cd18c4..a7427dd0c0d 100644 --- a/core/gui/src/app/dashboard/component/admin/user/admin-user.component.ts +++ b/core/gui/src/app/dashboard/component/admin/user/admin-user.component.ts @@ -2,10 +2,10 @@ import { Component, OnInit } from "@angular/core"; import { UntilDestroy, untilDestroyed } from "@ngneat/until-destroy"; import { NzTableFilterFn, NzTableSortFn } from "ng-zorro-antd/table"; import { NzModalService } from "ng-zorro-antd/modal"; -import { AdminUserService } from "../../../user/service/admin/user/admin-user.service"; +import { AdminUserService } from "../../../service/admin/user/admin-user.service"; import { Role, User } from "../../../../common/type/user"; import { UserService } from "../../../../common/service/user/user.service"; -import { UserQuotaComponent } from "../../../user/component/user-quota/user-quota.component"; +import { UserQuotaComponent } from "../../user/user-quota/user-quota.component"; @UntilDestroy() @Component({ diff --git a/core/gui/src/app/dashboard/component/dashboard.component.ts b/core/gui/src/app/dashboard/component/dashboard.component.ts index 967344de48e..9479d702818 100644 --- a/core/gui/src/app/dashboard/component/dashboard.component.ts +++ b/core/gui/src/app/dashboard/component/dashboard.component.ts @@ -1,10 +1,10 @@ import { ChangeDetectorRef, Component, OnInit } from "@angular/core"; -import { WorkflowPersistService } from "../../../common/service/workflow-persist/workflow-persist.service"; -import { UserService } from "../../../common/service/user/user.service"; +import { WorkflowPersistService } from "../../common/service/workflow-persist/workflow-persist.service"; +import { UserService } from "../../common/service/user/user.service"; import { UntilDestroy, untilDestroyed } from "@ngneat/until-destroy"; -import { FlarumService } from "../service/flarum/flarum.service"; +import { FlarumService } from "../service/user/flarum/flarum.service"; import { HttpErrorResponse } from "@angular/common/http"; -import { HubComponent } from "../../../hub/component/hub.component"; +import { HubComponent } from "../../hub/component/hub.component"; @Component({ selector: "texera-dashboard", diff --git a/core/gui/src/app/dashboard/user/component/google-login/google-login.component.ts b/core/gui/src/app/dashboard/component/user/google-login/google-login.component.ts similarity index 100% rename from core/gui/src/app/dashboard/user/component/google-login/google-login.component.ts rename to core/gui/src/app/dashboard/component/user/google-login/google-login.component.ts From a3a4456b4f68e0b2f21fcb029de04fface642985 Mon Sep 17 00:00:00 2001 From: gspikehalo <2318002579@qq.com> Date: Sat, 24 Aug 2024 23:11:16 -0700 Subject: [PATCH 19/33] quick fix. Some urls have changed, but Intellij's automatic merge has not modified them. --- core/gui/src/app/app-routing.module.ts | 27 +++++++++---------- .../user-dataset-explorer.component.ts | 4 +-- .../user-dataset/user-dataset.component.ts | 2 +- .../admin/guard/admin-guard.service.ts | 2 +- .../component/menu/menu.component.html | 2 +- 5 files changed, 17 insertions(+), 20 deletions(-) diff --git a/core/gui/src/app/app-routing.module.ts b/core/gui/src/app/app-routing.module.ts index bf9a0d7f1cf..fefa6fb813a 100644 --- a/core/gui/src/app/app-routing.module.ts +++ b/core/gui/src/app/app-routing.module.ts @@ -116,22 +116,19 @@ if (environment.userSystemEnabled) { canActivate: [AdminGuardService], }, { - path: "admin", + path: "admin/user", + component: AdminUserComponent, + canActivate: [AdminGuardService], + }, + { + path: "admin/gmail", + component: AdminGmailComponent, + canActivate: [AdminGuardService], + }, + { + path: "admin/execution", + component: AdminExecutionComponent, canActivate: [AdminGuardService], - children: [ - { - path: "user", - component: AdminUserComponent, - }, - { - path: "gmail", - component: AdminGmailComponent, - }, - { - path: "execution", - component: AdminExecutionComponent, - }, - ], }, ], }); diff --git a/core/gui/src/app/dashboard/component/user/user-dataset/user-dataset-explorer/user-dataset-explorer.component.ts b/core/gui/src/app/dashboard/component/user/user-dataset/user-dataset-explorer/user-dataset-explorer.component.ts index 1994277d349..7e34fb501d1 100644 --- a/core/gui/src/app/dashboard/component/user/user-dataset/user-dataset-explorer/user-dataset-explorer.component.ts +++ b/core/gui/src/app/dashboard/component/user/user-dataset/user-dataset-explorer/user-dataset-explorer.component.ts @@ -104,7 +104,7 @@ export class UserDatasetExplorerComponent implements OnInit { this.retrieveDatasetVersionList(); this.renderDatasetViewSider(); } else { - this.router.navigate([`/dashboard/user/dataset/${creationID}`]); + this.router.navigate([`/dashboard/dataset/${creationID}`]); } } else { // creation failed @@ -113,7 +113,7 @@ export class UserDatasetExplorerComponent implements OnInit { this.isCreatingDataset = false; this.retrieveDatasetVersionList(); } else { - this.router.navigate(["/dashboard/user/dataset"]); + this.router.navigate(["/dashboard/dataset"]); } } } diff --git a/core/gui/src/app/dashboard/component/user/user-dataset/user-dataset.component.ts b/core/gui/src/app/dashboard/component/user/user-dataset/user-dataset.component.ts index 01f4e6641e0..271dde11986 100644 --- a/core/gui/src/app/dashboard/component/user/user-dataset/user-dataset.component.ts +++ b/core/gui/src/app/dashboard/component/user/user-dataset/user-dataset.component.ts @@ -101,7 +101,7 @@ export class UserDatasetComponent implements AfterViewInit { } public onClickOpenDatasetAddComponent(): void { - this.router.navigate(["/dashboard/user/dataset/create"]); + this.router.navigate(["/dashboard/dataset/create"]); } public deleteDataset(entry: DashboardEntry): void { diff --git a/core/gui/src/app/dashboard/service/admin/guard/admin-guard.service.ts b/core/gui/src/app/dashboard/service/admin/guard/admin-guard.service.ts index 9eb473fe8e3..0e87e9ef903 100644 --- a/core/gui/src/app/dashboard/service/admin/guard/admin-guard.service.ts +++ b/core/gui/src/app/dashboard/service/admin/guard/admin-guard.service.ts @@ -17,7 +17,7 @@ export class AdminGuardService implements CanActivate { if (this.userService.isAdmin()) { return true; } else { - this.router.navigate(["/dashboard/user/workflow"]); + this.router.navigate(["/dashboard/workflow"]); return false; } } diff --git a/core/gui/src/app/workspace/component/menu/menu.component.html b/core/gui/src/app/workspace/component/menu/menu.component.html index 6359004c274..861f3c909f5 100644 --- a/core/gui/src/app/workspace/component/menu/menu.component.html +++ b/core/gui/src/app/workspace/component/menu/menu.component.html @@ -59,7 +59,7 @@ - +
    diff --git a/core/gui/src/app/dashboard/component/dashboard.component.ts b/core/gui/src/app/dashboard/component/dashboard.component.ts index 71077d6d1bb..4fb864e2d6b 100644 --- a/core/gui/src/app/dashboard/component/dashboard.component.ts +++ b/core/gui/src/app/dashboard/component/dashboard.component.ts @@ -20,7 +20,7 @@ export class DashboardComponent implements OnInit { displayForum: boolean = true; displayNavbar: boolean = true; isCollpased: boolean = false; - routesWithoutNavbar: string[] = ["/workspace"]; + routesWithoutNavbar: string[] = ["/workspace", "/home"]; currentComponent = HubComponent; constructor( @@ -41,7 +41,7 @@ export class DashboardComponent implements OnInit { ngOnInit(): void { this.isCollpased = false; - if (!document.cookie.includes("flarum_remember")) { + if (!document.cookie.includes("flarum_remember") && this.isLogin) { this.flarumService .auth() .pipe(untilDestroyed(this)) diff --git a/core/gui/src/app/hub/component/home/home.component.html b/core/gui/src/app/hub/component/home/home.component.html index 7fc71b3d3e7..30e9212a6f0 100644 --- a/core/gui/src/app/hub/component/home/home.component.html +++ b/core/gui/src/app/hub/component/home/home.component.html @@ -1,3 +1,18 @@ +
    + class="content">

    Collaborative Data Analytics Using Workflows


    diff --git a/core/gui/src/app/hub/component/home/home.component.scss b/core/gui/src/app/hub/component/home/home.component.scss new file mode 100644 index 00000000000..1c14c791c9d --- /dev/null +++ b/core/gui/src/app/hub/component/home/home.component.scss @@ -0,0 +1,33 @@ +.content { + text-align: center; +} + +ul { + list-style-type: none; + height: 70px; + padding: 10px; + overflow: hidden; + background-color: #f8f9fa; + vertical-align: baseline; +} + +li { + float: left; + padding: 14px; +} + +li a { + color: black; + font-weight: bold; +} + +#logo { + height: 70px; + padding: 0; + margin-right: 14px; +} + +#googleButton { + float: right; + padding: 5px 0; +} diff --git a/core/gui/src/app/hub/component/home/home.component.ts b/core/gui/src/app/hub/component/home/home.component.ts index cf766f4bf33..55c5a2d8cbe 100644 --- a/core/gui/src/app/hub/component/home/home.component.ts +++ b/core/gui/src/app/hub/component/home/home.component.ts @@ -1,10 +1,50 @@ -import { Component } from "@angular/core"; +import { UntilDestroy } from "@ngneat/until-destroy"; +import { Component, OnInit } from "@angular/core"; import { environment } from "../../../../environments/environment"; +import { UserService } from "../../../common/service/user/user.service"; +import { ActivatedRoute, Router } from "@angular/router"; +import { GoogleAuthService } from "../../../common/service/user/google-auth.service"; +import { NotificationService } from "../../../common/service/notification/notification.service"; +import { catchError, mergeMap } from "rxjs/operators"; +import { throwError } from "rxjs"; +@UntilDestroy() @Component({ selector: "texera-login", - templateUrl: "home.component.html", + templateUrl: "./home.component.html", + styleUrls: ["./home.component.scss"], }) -export class HomeComponent { +export class HomeComponent implements OnInit { localLogin = environment.localLogin; + + constructor( + private userService: UserService, + private route: ActivatedRoute, + private googleAuthService: GoogleAuthService, + private notificationService: NotificationService, + private router: Router, + ) {} + + ngOnInit(): void { + if (!sessionStorage.getItem("homePageReloaded")) { + sessionStorage.setItem("homePageReloaded", "true"); + window.location.reload(); + } else { + sessionStorage.removeItem("homePageReloaded"); + + this.googleAuthService.googleAuthInit(document.getElementById("googleButton")); + this.googleAuthService.googleCredentialResponse + .pipe(mergeMap(res => this.userService.googleLogin(res.credential))) + .pipe( + catchError((e: unknown) => { + this.notificationService.error((e as Error).message, { nzDuration: 10 }); + return throwError(() => e); + }) + ) + // eslint-disable-next-line rxjs-angular/prefer-takeuntil + .subscribe(() => + this.router.navigateByUrl(this.route.snapshot.queryParams["returnUrl"] || "/dashboard/user/workflow") + ); + } + } } diff --git a/core/gui/src/app/hub/component/home/local-login/local-login.component.ts b/core/gui/src/app/hub/component/home/local-login/local-login.component.ts index eb7fc3fb275..c3d8afd86ee 100644 --- a/core/gui/src/app/hub/component/home/local-login/local-login.component.ts +++ b/core/gui/src/app/hub/component/home/local-login/local-login.component.ts @@ -72,7 +72,7 @@ export class LocalLoginComponent { untilDestroyed(this) ) .subscribe(() => - this.router.navigateByUrl(this.route.snapshot.queryParams["returnUrl"] || "/dashboard/workflow") + this.router.navigateByUrl(this.route.snapshot.queryParams["returnUrl"] || "/dashboard/user/workflow") ); } From 1e54248c297c70454e92f1cf083830bf4dc22e48 Mon Sep 17 00:00:00 2001 From: gspikehalo <2318002579@qq.com> Date: Fri, 13 Sep 2024 13:05:46 -0700 Subject: [PATCH 26/33] fmt fix --- core/gui/src/app/hub/component/home/home.component.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/gui/src/app/hub/component/home/home.component.ts b/core/gui/src/app/hub/component/home/home.component.ts index 55c5a2d8cbe..accf6784901 100644 --- a/core/gui/src/app/hub/component/home/home.component.ts +++ b/core/gui/src/app/hub/component/home/home.component.ts @@ -22,7 +22,7 @@ export class HomeComponent implements OnInit { private route: ActivatedRoute, private googleAuthService: GoogleAuthService, private notificationService: NotificationService, - private router: Router, + private router: Router ) {} ngOnInit(): void { From 427b41b342e4fc9ce0cd8d012f64a6d6da074a82 Mon Sep 17 00:00:00 2001 From: gspikehalo <2318002579@qq.com> Date: Fri, 13 Sep 2024 14:04:04 -0700 Subject: [PATCH 27/33] fix workflow create url --- .../component/user/user-workflow/user-workflow.component.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/gui/src/app/dashboard/component/user/user-workflow/user-workflow.component.ts b/core/gui/src/app/dashboard/component/user/user-workflow/user-workflow.component.ts index 0d6259eb1b1..7bd7f33e653 100644 --- a/core/gui/src/app/dashboard/component/user/user-workflow/user-workflow.component.ts +++ b/core/gui/src/app/dashboard/component/user/user-workflow/user-workflow.component.ts @@ -58,7 +58,7 @@ import { DashboardWorkflow } from "../../../type/dashboard-workflow.interface"; styleUrls: ["user-workflow.component.scss"], }) export class UserWorkflowComponent implements AfterViewInit { - public ROUTER_WORKFLOW_BASE_URL = "/dashboard/workspace"; + public ROUTER_WORKFLOW_BASE_URL = "/dashboard/user/workspace"; private _searchResultsComponent?: SearchResultsComponent; @ViewChild(SearchResultsComponent) get searchResultsComponent(): SearchResultsComponent { if (this._searchResultsComponent) { From 38e9dc3d5bf59d4f7c03fea3261fe1d1dbcc0eea Mon Sep 17 00:00:00 2001 From: gspikehalo <2318002579@qq.com> Date: Fri, 13 Sep 2024 14:57:07 -0700 Subject: [PATCH 28/33] Modified: The home screen will be displayed when user are not logged in, but the user's avatar will not be displayed. --- .../component/dashboard.component.html | 10 +++- .../component/dashboard.component.scss | 6 +-- .../component/dashboard.component.ts | 5 +- .../src/app/hub/component/hub.component.html | 51 ++++++++----------- .../src/app/hub/component/hub.component.ts | 6 ++- 5 files changed, 38 insertions(+), 40 deletions(-) diff --git a/core/gui/src/app/dashboard/component/dashboard.component.html b/core/gui/src/app/dashboard/component/dashboard.component.html index 39eef08216e..b7ef88eaa19 100644 --- a/core/gui/src/app/dashboard/component/dashboard.component.html +++ b/core/gui/src/app/dashboard/component/dashboard.component.html @@ -18,7 +18,15 @@ height="50" src="../../../../assets/logos/logo.png" /> - + +

  • + +
  • +
  • -
      -
    • - - Home -
    • -
    • - - Workflows -
    • -
    -
  • +
      +
    • + + Home +
    • +
    • + + Workflows +
    • +
    diff --git a/core/gui/src/app/hub/component/hub.component.ts b/core/gui/src/app/hub/component/hub.component.ts index 130dcd8cfb9..ae887fb283b 100644 --- a/core/gui/src/app/hub/component/hub.component.ts +++ b/core/gui/src/app/hub/component/hub.component.ts @@ -1,8 +1,10 @@ -import { Component } from "@angular/core"; +import { Component, Input } from "@angular/core"; @Component({ selector: "texera-hub", templateUrl: "hub.component.html", styleUrls: ["hub.component.scss"], }) -export class HubComponent {} +export class HubComponent{ + @Input() isLogin: boolean = false; +} From b2ca9cbbef2d7a233475b6bfb4e04d62cc8a929b Mon Sep 17 00:00:00 2001 From: gspikehalo <2318002579@qq.com> Date: Fri, 13 Sep 2024 14:57:56 -0700 Subject: [PATCH 29/33] fmt fix --- core/gui/src/app/hub/component/hub.component.html | 8 ++++++-- core/gui/src/app/hub/component/hub.component.ts | 2 +- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/core/gui/src/app/hub/component/hub.component.html b/core/gui/src/app/hub/component/hub.component.html index e72fd704b6e..8570c329259 100644 --- a/core/gui/src/app/hub/component/hub.component.html +++ b/core/gui/src/app/hub/component/hub.component.html @@ -6,7 +6,9 @@ nzMatchRouter="true" nzTooltipPlacement="right" routerLink="/dashboard/home"> - + Home
  • - + Workflows
  • diff --git a/core/gui/src/app/hub/component/hub.component.ts b/core/gui/src/app/hub/component/hub.component.ts index ae887fb283b..da565963799 100644 --- a/core/gui/src/app/hub/component/hub.component.ts +++ b/core/gui/src/app/hub/component/hub.component.ts @@ -5,6 +5,6 @@ import { Component, Input } from "@angular/core"; templateUrl: "hub.component.html", styleUrls: ["hub.component.scss"], }) -export class HubComponent{ +export class HubComponent { @Input() isLogin: boolean = false; } From 2f1242d3901329b9b6f259aaebad46f19668fccd Mon Sep 17 00:00:00 2001 From: gspikehalo <2318002579@qq.com> Date: Fri, 13 Sep 2024 16:31:10 -0700 Subject: [PATCH 30/33] update Jooq and backend workflow schema --- .../model/jooq/generated/tables/Workflow.java | 15 +++-- .../generated/tables/daos/WorkflowDao.java | 14 +++++ .../tables/interfaces/IWorkflow.java | 10 +++ .../jooq/generated/tables/pojos/Workflow.java | 20 +++++- .../tables/records/WorkflowRecord.java | 62 +++++++++++++++---- .../user/workflow/WorkflowResource.scala | 6 +- core/scripts/sql/texera_ddl.sql | 5 +- core/scripts/sql/update/15.sql | 4 ++ 8 files changed, 116 insertions(+), 20 deletions(-) create mode 100644 core/scripts/sql/update/15.sql diff --git a/core/amber/src/main/scala/edu/uci/ics/texera/web/model/jooq/generated/tables/Workflow.java b/core/amber/src/main/scala/edu/uci/ics/texera/web/model/jooq/generated/tables/Workflow.java index bec6659b827..fb8037b41a3 100644 --- a/core/amber/src/main/scala/edu/uci/ics/texera/web/model/jooq/generated/tables/Workflow.java +++ b/core/amber/src/main/scala/edu/uci/ics/texera/web/model/jooq/generated/tables/Workflow.java @@ -19,7 +19,7 @@ import org.jooq.Index; import org.jooq.Name; import org.jooq.Record; -import org.jooq.Row6; +import org.jooq.Row7; import org.jooq.Schema; import org.jooq.Table; import org.jooq.TableField; @@ -35,7 +35,7 @@ @SuppressWarnings({ "all", "unchecked", "rawtypes" }) public class Workflow extends TableImpl { - private static final long serialVersionUID = -908784271; + private static final long serialVersionUID = -1770381178; /** * The reference instance of texera_db.workflow @@ -80,6 +80,11 @@ public Class getRecordType() { */ public final TableField LAST_MODIFIED_TIME = createField(DSL.name("last_modified_time"), org.jooq.impl.SQLDataType.TIMESTAMP.nullable(false).defaultValue(org.jooq.impl.DSL.field("CURRENT_TIMESTAMP", org.jooq.impl.SQLDataType.TIMESTAMP)), this, ""); + /** + * The column texera_db.workflow.is_published. + */ + public final TableField IS_PUBLISHED = createField(DSL.name("is_published"), org.jooq.impl.SQLDataType.TINYINT.nullable(false).defaultValue(org.jooq.impl.DSL.inline("0", org.jooq.impl.SQLDataType.TINYINT)), this, ""); + /** * Create a texera_db.workflow table reference */ @@ -165,11 +170,11 @@ public Workflow rename(Name name) { } // ------------------------------------------------------------------------- - // Row6 type methods + // Row7 type methods // ------------------------------------------------------------------------- @Override - public Row6 fieldsRow() { - return (Row6) super.fieldsRow(); + public Row7 fieldsRow() { + return (Row7) super.fieldsRow(); } } diff --git a/core/amber/src/main/scala/edu/uci/ics/texera/web/model/jooq/generated/tables/daos/WorkflowDao.java b/core/amber/src/main/scala/edu/uci/ics/texera/web/model/jooq/generated/tables/daos/WorkflowDao.java index f5fb65ba286..6ba5b23af30 100644 --- a/core/amber/src/main/scala/edu/uci/ics/texera/web/model/jooq/generated/tables/daos/WorkflowDao.java +++ b/core/amber/src/main/scala/edu/uci/ics/texera/web/model/jooq/generated/tables/daos/WorkflowDao.java @@ -130,4 +130,18 @@ public List f public List fetchByLastModifiedTime(Timestamp... values) { return fetch(Workflow.WORKFLOW.LAST_MODIFIED_TIME, values); } + + /** + * Fetch records that have is_published BETWEEN lowerInclusive AND upperInclusive + */ + public List fetchRangeOfIsPublished(Byte lowerInclusive, Byte upperInclusive) { + return fetchRange(Workflow.WORKFLOW.IS_PUBLISHED, lowerInclusive, upperInclusive); + } + + /** + * Fetch records that have is_published IN (values) + */ + public List fetchByIsPublished(Byte... values) { + return fetch(Workflow.WORKFLOW.IS_PUBLISHED, values); + } } diff --git a/core/amber/src/main/scala/edu/uci/ics/texera/web/model/jooq/generated/tables/interfaces/IWorkflow.java b/core/amber/src/main/scala/edu/uci/ics/texera/web/model/jooq/generated/tables/interfaces/IWorkflow.java index fcd188fe700..003210d08e0 100644 --- a/core/amber/src/main/scala/edu/uci/ics/texera/web/model/jooq/generated/tables/interfaces/IWorkflow.java +++ b/core/amber/src/main/scala/edu/uci/ics/texera/web/model/jooq/generated/tables/interfaces/IWorkflow.java @@ -76,6 +76,16 @@ public interface IWorkflow extends Serializable { */ public Timestamp getLastModifiedTime(); + /** + * Setter for texera_db.workflow.is_published. + */ + public void setIsPublished(Byte value); + + /** + * Getter for texera_db.workflow.is_published. + */ + public Byte getIsPublished(); + // ------------------------------------------------------------------------- // FROM and INTO // ------------------------------------------------------------------------- diff --git a/core/amber/src/main/scala/edu/uci/ics/texera/web/model/jooq/generated/tables/pojos/Workflow.java b/core/amber/src/main/scala/edu/uci/ics/texera/web/model/jooq/generated/tables/pojos/Workflow.java index 98aa423b443..b23054885b2 100644 --- a/core/amber/src/main/scala/edu/uci/ics/texera/web/model/jooq/generated/tables/pojos/Workflow.java +++ b/core/amber/src/main/scala/edu/uci/ics/texera/web/model/jooq/generated/tables/pojos/Workflow.java @@ -17,7 +17,7 @@ @SuppressWarnings({ "all", "unchecked", "rawtypes" }) public class Workflow implements IWorkflow { - private static final long serialVersionUID = -380738907; + private static final long serialVersionUID = 171585219; private String name; private String description; @@ -25,6 +25,7 @@ public class Workflow implements IWorkflow { private String content; private Timestamp creationTime; private Timestamp lastModifiedTime; + private Byte isPublished; public Workflow() {} @@ -35,6 +36,7 @@ public Workflow(IWorkflow value) { this.content = value.getContent(); this.creationTime = value.getCreationTime(); this.lastModifiedTime = value.getLastModifiedTime(); + this.isPublished = value.getIsPublished(); } public Workflow( @@ -43,7 +45,8 @@ public Workflow( UInteger wid, String content, Timestamp creationTime, - Timestamp lastModifiedTime + Timestamp lastModifiedTime, + Byte isPublished ) { this.name = name; this.description = description; @@ -51,6 +54,7 @@ public Workflow( this.content = content; this.creationTime = creationTime; this.lastModifiedTime = lastModifiedTime; + this.isPublished = isPublished; } @Override @@ -113,6 +117,16 @@ public void setLastModifiedTime(Timestamp lastModifiedTime) { this.lastModifiedTime = lastModifiedTime; } + @Override + public Byte getIsPublished() { + return this.isPublished; + } + + @Override + public void setIsPublished(Byte isPublished) { + this.isPublished = isPublished; + } + @Override public String toString() { StringBuilder sb = new StringBuilder("Workflow ("); @@ -123,6 +137,7 @@ public String toString() { sb.append(", ").append(content); sb.append(", ").append(creationTime); sb.append(", ").append(lastModifiedTime); + sb.append(", ").append(isPublished); sb.append(")"); return sb.toString(); @@ -140,6 +155,7 @@ public void from(IWorkflow from) { setContent(from.getContent()); setCreationTime(from.getCreationTime()); setLastModifiedTime(from.getLastModifiedTime()); + setIsPublished(from.getIsPublished()); } @Override diff --git a/core/amber/src/main/scala/edu/uci/ics/texera/web/model/jooq/generated/tables/records/WorkflowRecord.java b/core/amber/src/main/scala/edu/uci/ics/texera/web/model/jooq/generated/tables/records/WorkflowRecord.java index 1f16bfd5ef3..403bd5e6090 100644 --- a/core/amber/src/main/scala/edu/uci/ics/texera/web/model/jooq/generated/tables/records/WorkflowRecord.java +++ b/core/amber/src/main/scala/edu/uci/ics/texera/web/model/jooq/generated/tables/records/WorkflowRecord.java @@ -11,8 +11,8 @@ import org.jooq.Field; import org.jooq.Record1; -import org.jooq.Record6; -import org.jooq.Row6; +import org.jooq.Record7; +import org.jooq.Row7; import org.jooq.impl.UpdatableRecordImpl; import org.jooq.types.UInteger; @@ -21,9 +21,9 @@ * This class is generated by jOOQ. */ @SuppressWarnings({ "all", "unchecked", "rawtypes" }) -public class WorkflowRecord extends UpdatableRecordImpl implements Record6, IWorkflow { +public class WorkflowRecord extends UpdatableRecordImpl implements Record7, IWorkflow { - private static final long serialVersionUID = 948369234; + private static final long serialVersionUID = 702670612; /** * Setter for texera_db.workflow.name. @@ -121,6 +121,22 @@ public Timestamp getLastModifiedTime() { return (Timestamp) get(5); } + /** + * Setter for texera_db.workflow.is_published. + */ + @Override + public void setIsPublished(Byte value) { + set(6, value); + } + + /** + * Getter for texera_db.workflow.is_published. + */ + @Override + public Byte getIsPublished() { + return (Byte) get(6); + } + // ------------------------------------------------------------------------- // Primary key information // ------------------------------------------------------------------------- @@ -131,17 +147,17 @@ public Record1 key() { } // ------------------------------------------------------------------------- - // Record6 type implementation + // Record7 type implementation // ------------------------------------------------------------------------- @Override - public Row6 fieldsRow() { - return (Row6) super.fieldsRow(); + public Row7 fieldsRow() { + return (Row7) super.fieldsRow(); } @Override - public Row6 valuesRow() { - return (Row6) super.valuesRow(); + public Row7 valuesRow() { + return (Row7) super.valuesRow(); } @Override @@ -174,6 +190,11 @@ public Field field6() { return Workflow.WORKFLOW.LAST_MODIFIED_TIME; } + @Override + public Field field7() { + return Workflow.WORKFLOW.IS_PUBLISHED; + } + @Override public String component1() { return getName(); @@ -204,6 +225,11 @@ public Timestamp component6() { return getLastModifiedTime(); } + @Override + public Byte component7() { + return getIsPublished(); + } + @Override public String value1() { return getName(); @@ -234,6 +260,11 @@ public Timestamp value6() { return getLastModifiedTime(); } + @Override + public Byte value7() { + return getIsPublished(); + } + @Override public WorkflowRecord value1(String value) { setName(value); @@ -271,13 +302,20 @@ public WorkflowRecord value6(Timestamp value) { } @Override - public WorkflowRecord values(String value1, String value2, UInteger value3, String value4, Timestamp value5, Timestamp value6) { + public WorkflowRecord value7(Byte value) { + setIsPublished(value); + return this; + } + + @Override + public WorkflowRecord values(String value1, String value2, UInteger value3, String value4, Timestamp value5, Timestamp value6, Byte value7) { value1(value1); value2(value2); value3(value3); value4(value4); value5(value5); value6(value6); + value7(value7); return this; } @@ -293,6 +331,7 @@ public void from(IWorkflow from) { setContent(from.getContent()); setCreationTime(from.getCreationTime()); setLastModifiedTime(from.getLastModifiedTime()); + setIsPublished(from.getIsPublished()); } @Override @@ -315,7 +354,7 @@ public WorkflowRecord() { /** * Create a detached, initialised WorkflowRecord */ - public WorkflowRecord(String name, String description, UInteger wid, String content, Timestamp creationTime, Timestamp lastModifiedTime) { + public WorkflowRecord(String name, String description, UInteger wid, String content, Timestamp creationTime, Timestamp lastModifiedTime, Byte isPublished) { super(Workflow.WORKFLOW); set(0, name); @@ -324,5 +363,6 @@ public WorkflowRecord(String name, String description, UInteger wid, String cont set(3, content); set(4, creationTime); set(5, lastModifiedTime); + set(6, isPublished); } } diff --git a/core/amber/src/main/scala/edu/uci/ics/texera/web/resource/dashboard/user/workflow/WorkflowResource.scala b/core/amber/src/main/scala/edu/uci/ics/texera/web/resource/dashboard/user/workflow/WorkflowResource.scala index 0c63ce39c28..0989fbe96f3 100644 --- a/core/amber/src/main/scala/edu/uci/ics/texera/web/resource/dashboard/user/workflow/WorkflowResource.scala +++ b/core/amber/src/main/scala/edu/uci/ics/texera/web/resource/dashboard/user/workflow/WorkflowResource.scala @@ -89,6 +89,7 @@ object WorkflowResource { content: String, creationTime: Timestamp, lastModifiedTime: Timestamp, + isPublished: Byte, readonly: Boolean ) @@ -265,6 +266,7 @@ class WorkflowResource extends LazyLogging { workflow.getContent, workflow.getCreationTime, workflow.getLastModifiedTime, + workflow.getIsPublished, !WorkflowAccessResource.hasWriteAccess(wid, user.getUid) ) } else { @@ -349,7 +351,8 @@ class WorkflowResource extends LazyLogging { null, workflow.getContent, null, - null + null, + 0.toByte ), sessionUser ) @@ -389,6 +392,7 @@ class WorkflowResource extends LazyLogging { @Path("/create") def createWorkflow(workflow: Workflow, @Auth sessionUser: SessionUser): DashboardWorkflow = { val user = sessionUser.getUser + // Todo: may change here if (workflow.getWid != null) { throw new BadRequestException("Cannot create a new workflow with a provided id.") } else { diff --git a/core/scripts/sql/texera_ddl.sql b/core/scripts/sql/texera_ddl.sql index 82da21d0537..4785301269d 100644 --- a/core/scripts/sql/texera_ddl.sql +++ b/core/scripts/sql/texera_ddl.sql @@ -206,4 +206,7 @@ CREATE FULLTEXT INDEX `idx_user_project_name_description` ON `texera_db`.`projec CREATE FULLTEXT INDEX `idx_dataset_name_description` ON `texera_db`.`dataset` (name, description); -CREATE FULLTEXT INDEX `idx_dataset_version_name` ON `texera_db`.`dataset_version` (name); \ No newline at end of file +CREATE FULLTEXT INDEX `idx_dataset_version_name` ON `texera_db`.`dataset_version` (name); + +ALTER TABLE workflow +ADD is_published BOOLEAN NOT NULL DEFAULT false; \ No newline at end of file diff --git a/core/scripts/sql/update/15.sql b/core/scripts/sql/update/15.sql new file mode 100644 index 00000000000..83108ef9ec7 --- /dev/null +++ b/core/scripts/sql/update/15.sql @@ -0,0 +1,4 @@ +USE `texera_db`; + +ALTER TABLE workflow +ADD is_published BOOLEAN NOT NULL DEFAULT false; \ No newline at end of file From 2ea585a2f22f8f7f7e74b72d83c141469bb96acb Mon Sep 17 00:00:00 2001 From: gspikehalo <2318002579@qq.com> Date: Fri, 13 Sep 2024 17:38:14 -0700 Subject: [PATCH 31/33] Add publish buttons to the dataset and workflow. --- .../user/workflow/WorkflowResource.scala | 53 +++++- .../workflow-persist.service.ts | 14 ++ .../execution/admin-execution.component.ts | 1 + .../user/list-item/list-item.component.ts | 3 + .../share-access/share-access.component.html | 38 +++++ .../share-access/share-access.component.scss | 39 ++++- .../share-access/share-access.component.ts | 153 +++++++++++++++++- .../user-project-list-item.component.html | 11 -- .../user-project-list-item.component.ts | 24 +-- .../type/workflow-metadata.interface.ts | 1 + .../component/menu/menu.component.html | 10 ++ .../component/menu/menu.component.scss | 8 + .../component/menu/menu.component.ts | 26 ++- .../component/workspace.component.html | 5 +- .../component/workspace.component.ts | 11 +- .../model/workflow-action.service.ts | 5 + 16 files changed, 353 insertions(+), 49 deletions(-) diff --git a/core/amber/src/main/scala/edu/uci/ics/texera/web/resource/dashboard/user/workflow/WorkflowResource.scala b/core/amber/src/main/scala/edu/uci/ics/texera/web/resource/dashboard/user/workflow/WorkflowResource.scala index 0989fbe96f3..386b3968410 100644 --- a/core/amber/src/main/scala/edu/uci/ics/texera/web/resource/dashboard/user/workflow/WorkflowResource.scala +++ b/core/amber/src/main/scala/edu/uci/ics/texera/web/resource/dashboard/user/workflow/WorkflowResource.scala @@ -380,6 +380,28 @@ class WorkflowResource extends LazyLogging { resultWorkflows.toList } + @POST + @Consumes(Array(MediaType.APPLICATION_JSON)) + @Produces(Array(MediaType.APPLICATION_JSON)) + @Path("/clone/{wid}") + def cloneWorkflow(@PathParam("wid") wid: UInteger, @Auth sessionUser: SessionUser): UInteger = { + val workflow: Workflow = workflowDao.fetchOneByWid(wid) + val newWorkflow: DashboardWorkflow = createWorkflow( + new Workflow( + workflow.getName + "_clone", + workflow.getDescription, + null, + workflow.getContent, + null, + null, + 0.toByte + ), + sessionUser + ) + //TODO: copy the environment as well + newWorkflow.workflow.getWid + } + /** * This method creates and insert a new workflow to database * @@ -392,7 +414,6 @@ class WorkflowResource extends LazyLogging { @Path("/create") def createWorkflow(workflow: Workflow, @Auth sessionUser: SessionUser): DashboardWorkflow = { val user = sessionUser.getUser - // Todo: may change here if (workflow.getWid != null) { throw new BadRequestException("Cannot create a new workflow with a provided id.") } else { @@ -485,4 +506,34 @@ class WorkflowResource extends LazyLogging { workflowDao.update(userWorkflow) } } + + @PUT + @RolesAllowed(Array("REGULAR", "ADMIN")) + @Path("/public/{wid}") + def makePublic(@PathParam("wid") wid: UInteger, @Auth user: SessionUser): Unit = { + println(wid + " is public now") + val workflow: Workflow = workflowDao.fetchOneByWid(wid) + workflow.setIsPublished(1.toByte) + workflowDao.update(workflow) + } + + @PUT + @RolesAllowed(Array("REGULAR", "ADMIN")) + @Path("/private/{wid}") + def makePrivate(@PathParam("wid") wid: UInteger): Unit = { + println(wid + " is private now") + val workflow: Workflow = workflowDao.fetchOneByWid(wid) + workflow.setIsPublished(0.toByte) + workflowDao.update(workflow) + } + + @GET + @Path("/type/{wid}") + def getWorkflowType(@PathParam("wid") wid: UInteger): String = { + val workflow: Workflow = workflowDao.fetchOneByWid(wid) + if (workflow.getIsPublished() == 1.toByte) + "Public" + else + "Private" + } } diff --git a/core/gui/src/app/common/service/workflow-persist/workflow-persist.service.ts b/core/gui/src/app/common/service/workflow-persist/workflow-persist.service.ts index cfc499b67e2..156ddbf3a85 100644 --- a/core/gui/src/app/common/service/workflow-persist/workflow-persist.service.ts +++ b/core/gui/src/app/common/service/workflow-persist/workflow-persist.service.ts @@ -46,6 +46,7 @@ export class WorkflowPersistService { name: workflow.name, description: workflow.description, content: JSON.stringify(workflow.content), + isPublished: workflow.isPublished, }) .pipe( filter((updatedWorkflow: Workflow) => updatedWorkflow != null), @@ -169,6 +170,19 @@ export class WorkflowPersistService { ); } + public getWorkflowIsPublished(wid: number): Observable { + return this.http.get(`${AppSettings.getApiEndpoint()}/${WORKFLOW_BASE_URL}/type/${wid}`, { responseType: "text" }); + } + + public updateWorkflowIsPublished(wid: number, isPublished: boolean): Observable { + if (isPublished) { + return this.http.put(`${AppSettings.getApiEndpoint()}/${WORKFLOW_BASE_URL}/public/${wid}`, null); + } else { + return this.http.put(`${AppSettings.getApiEndpoint()}/${WORKFLOW_BASE_URL}/private/${wid}`, null); + } + } + + public setWorkflowPersistFlag(flag: boolean): void { this.workflowPersistFlag = flag; } diff --git a/core/gui/src/app/dashboard/component/admin/execution/admin-execution.component.ts b/core/gui/src/app/dashboard/component/admin/execution/admin-execution.component.ts index e6c7f5d1199..f85b380a666 100644 --- a/core/gui/src/app/dashboard/component/admin/execution/admin-execution.component.ts +++ b/core/gui/src/app/dashboard/component/admin/execution/admin-execution.component.ts @@ -122,6 +122,7 @@ export class AdminExecutionComponent implements OnInit, OnDestroy { description: "", creationTime: 0, lastModifiedTime: 0, + isPublished:0, readonly: false, }; 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 8c79f7896c2..35779bf0671 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 @@ -101,10 +101,12 @@ export class ListItemComponent implements OnInit, OnChanges { type: this.entry.type, id: this.entry.id, allOwners: await firstValueFrom(this.workflowPersistService.retrieveOwners()), + inWorkspace: false, }, nzFooter: null, nzTitle: "Share this workflow with others", nzCentered: true, + nzWidth: "700px", }); } else if (this.entry.type === "dataset") { this.modalService.create({ @@ -117,6 +119,7 @@ export class ListItemComponent implements OnInit, OnChanges { nzFooter: null, nzTitle: "Share this dataset with others", nzCentered: true, + nzWidth: "700px", }); } } diff --git a/core/gui/src/app/dashboard/component/user/share-access/share-access.component.html b/core/gui/src/app/dashboard/component/user/share-access/share-access.component.html index 851464b6dff..5a520a50857 100644 --- a/core/gui/src/app/dashboard/component/user/share-access/share-access.component.html +++ b/core/gui/src/app/dashboard/component/user/share-access/share-access.component.html @@ -1,3 +1,41 @@ +
    + + + +
    +
    diff --git a/core/gui/src/app/dashboard/component/user/share-access/share-access.component.scss b/core/gui/src/app/dashboard/component/user/share-access/share-access.component.scss index e25f9ce23c7..6beaacc500f 100644 --- a/core/gui/src/app/dashboard/component/user/share-access/share-access.component.scss +++ b/core/gui/src/app/dashboard/component/user/share-access/share-access.component.scss @@ -11,8 +11,45 @@ .add-button { margin-left: 8px; white-space: nowrap; - padding: 8 18px; + padding: 8px 18px; height: 25px; font-size: 14px; line-height: 1; } + +.access-button-group { + display: flex; + flex-direction: row; + justify-content: space-evenly; + align-items: center; +} + +.access-button { + display: flex; + flex-direction: column; + align-items: center; + justify-content: space-evenly; + height: 150px; + width: 300px; + padding: 20px; + margin-bottom: 24px; + border-radius: 10px; +} + +.button-icon { + font-size: 40px; +} + +.button-text > p { + font-size: 12px; + font-weight: lighter; + display: flex; + flex-direction: column; + align-items: center; + justify-content: space-between; +} + +.button-text-header { + font-size: 25px; + font-weight: bold; +} diff --git a/core/gui/src/app/dashboard/component/user/share-access/share-access.component.ts b/core/gui/src/app/dashboard/component/user/share-access/share-access.component.ts index 5bf4a6e7583..44e27996906 100644 --- a/core/gui/src/app/dashboard/component/user/share-access/share-access.component.ts +++ b/core/gui/src/app/dashboard/component/user/share-access/share-access.component.ts @@ -1,19 +1,22 @@ -import { Component, inject, OnInit } from "@angular/core"; +import { Component, inject, Input, OnInit } from "@angular/core"; import { FormBuilder, FormGroup, Validators, FormControl } from "@angular/forms"; import { ShareAccessService } from "../../../service/user/share-access/share-access.service"; import { ShareAccess } from "../../../type/share-access.interface"; import { UntilDestroy, untilDestroyed } from "@ngneat/until-destroy"; import { UserService } from "../../../../common/service/user/user.service"; import { GmailService } from "../../../../common/service/gmail/gmail.service"; -import { NZ_MODAL_DATA } from "ng-zorro-antd/modal"; +import { NZ_MODAL_DATA, NzModalRef, NzModalService } from "ng-zorro-antd/modal"; import { NotificationService } from "../../../../common/service/notification/notification.service"; import { HttpErrorResponse } from "@angular/common/http"; import { NzMessageService } from "ng-zorro-antd/message"; +import { DatasetService } from "../../../service/user/dataset/dataset.service"; +import { WorkflowPersistService } from "src/app/common/service/workflow-persist/workflow-persist.service"; +import { WorkflowActionService } from "src/app/workspace/service/workflow-graph/model/workflow-action.service"; @UntilDestroy() @Component({ - templateUrl: "share-access.component.html", selector: "texera-share-access", + templateUrl: "share-access.component.html", styleUrls: ["./share-access.component.scss"], }) export class ShareAccessComponent implements OnInit { @@ -23,6 +26,7 @@ export class ShareAccessComponent implements OnInit { readonly id: number = this.nzModalData.id; readonly allOwners: string[] = this.nzModalData.allOwners; + readonly inWorkspace: boolean = this.nzModalData.inWorkspace; public validateForm: FormGroup; public accessList: ReadonlyArray = []; public owner: string = ""; @@ -30,6 +34,7 @@ export class ShareAccessComponent implements OnInit { public ownerSearchValue?: string; public emailTags: string[] = []; currentEmail: string | undefined = ""; + isPublic: boolean | null = null; constructor( private accessService: ShareAccessService, @@ -37,8 +42,11 @@ export class ShareAccessComponent implements OnInit { private userService: UserService, private gmailService: GmailService, private notificationService: NotificationService, - private message: NzMessageService - ) { + private message: NzMessageService, + private modalService: NzModalService, + private workflowPersistService: WorkflowPersistService, + private datasetService: DatasetService, + private workflowActionService: WorkflowActionService ) { this.validateForm = this.formBuilder.group({ email: [null, Validators.email], accessLevel: ["READ"], @@ -57,6 +65,21 @@ export class ShareAccessComponent implements OnInit { .subscribe(name => { this.owner = name; }); + if (this.type === "workflow") { + this.workflowPersistService + .getWorkflowIsPublished(this.id) + .pipe(untilDestroyed(this)) + .subscribe(dashboardWorkflow => { + this.isPublic = dashboardWorkflow === "Public"; + }); + } else if (this.type === "dataset") { + this.datasetService + .getDataset(this.id) + .pipe(untilDestroyed(this)) + .subscribe(dashboardDataset => { + this.isPublic = dashboardDataset.dataset.isPublic === 1; + }); + } } public handleInputConfirm(event?: Event): void { @@ -148,4 +171,124 @@ export class ShareAccessComponent implements OnInit { .pipe(untilDestroyed(this)) .subscribe(() => this.ngOnInit()); } + verifyPublish(): void { + if (!this.isPublic) { + const modal: NzModalRef = this.modalService.create({ + nzTitle: "Notice", + nzContent: `Publishing your ${this.type} would grant all Texera users read access to your ${this.type} along with the right to clone your work.`, + nzFooter: [ + { + label: "Cancel", + onClick: () => modal.close(), + }, + { + label: "Publish", + type: "primary", + onClick: () => { + if (this.type === "workflow") { + this.publishWorkflow(); + + if (this.inWorkspace) { + this.workflowActionService.setWorkflowIsPublished(1); + } + } else if (this.type === "dataset") { + this.publishDataset(); + } + modal.close(); + }, + }, + ], + }); + } + } + + verifyUnpublish(): void { + if (this.isPublic) { + const modal: NzModalRef = this.modalService.create({ + nzTitle: "Notice", + nzContent: `All other users would lose access to your ${this.type} if you unpublish it.`, + nzFooter: [ + { + label: "Cancel", + onClick: () => modal.close(), + }, + { + label: "Unpublish", + type: "primary", + onClick: () => { + if (this.type === "workflow") { + this.unpublishWorkflow(); + if (this.inWorkspace) { + this.workflowActionService.setWorkflowIsPublished(0); + } + } else if (this.type === "dataset") { + this.unpublishDataset(); + } + modal.close(); + }, + }, + ], + }); + } + } + + public publishWorkflow(): void { + if (!this.isPublic) { + console.log("Workflow " + this.id + " is published"); + this.workflowPersistService + .updateWorkflowIsPublished(this.id, true) + .pipe(untilDestroyed(this)) + .subscribe(() => (this.isPublic = true)); + } else { + console.log("Workflow " + this.id + " is already published"); + } + } + + public unpublishWorkflow(): void { + if (this.isPublic) { + console.log("Workflow " + this.id + " is unpublished"); + this.workflowPersistService + .updateWorkflowIsPublished(this.id, false) + .pipe(untilDestroyed(this)) + .subscribe(() => (this.isPublic = false)); + } else { + console.log("Workflow " + this.id + " is already private"); + } + } + + public publishDataset(): void { + if (!this.isPublic) { + this.datasetService + .updateDatasetPublicity(this.id) + .pipe(untilDestroyed(this)) + .subscribe({ + next: (res: Response) => { + this.isPublic = true; + }, + error: (err: unknown) => { + this.notificationService.error("Failed to publish the dataset"); + }, + }); + } else { + console.log("Dataset " + this.id + " is already private"); + } + } + + public unpublishDataset(): void { + if (this.isPublic) { + this.datasetService + .updateDatasetPublicity(this.id) + .pipe(untilDestroyed(this)) + .subscribe({ + next: (res: Response) => { + this.isPublic = false; + }, + error: (err: unknown) => { + this.notificationService.error("Failed to unpublish the dataset"); + }, + }); + } else { + console.log("Dataset " + this.id + " is already private"); + } + } } diff --git a/core/gui/src/app/dashboard/component/user/user-project/user-project-list-item/user-project-list-item.component.html b/core/gui/src/app/dashboard/component/user/user-project/user-project-list-item/user-project-list-item.component.html index 7e9beb55dc9..4800805f523 100644 --- a/core/gui/src/app/dashboard/component/user/user-project/user-project-list-item/user-project-list-item.component.html +++ b/core/gui/src/app/dashboard/component/user/user-project/user-project-list-item/user-project-list-item.component.html @@ -153,17 +153,6 @@
      - -
      - -
      -
      +
    - -Git hash: {{ gitCommitHash }} +Git hash: {{ gitCommitHash }} diff --git a/core/gui/src/app/workspace/component/workspace.component.ts b/core/gui/src/app/workspace/component/workspace.component.ts index 655aa0e3f51..9280b1abbcc 100644 --- a/core/gui/src/app/workspace/component/workspace.component.ts +++ b/core/gui/src/app/workspace/component/workspace.component.ts @@ -21,6 +21,7 @@ import { SchemaPropagationService } from "../service/dynamic-schema/schema-propa import { WorkflowConsoleService } from "../service/workflow-console/workflow-console.service"; import { OperatorReuseCacheStatusService } from "../service/workflow-status/operator-reuse-cache-status.service"; import { CodeEditorService } from "../service/code-editor/code-editor.service"; +import { WorkflowMetadata } from "src/app/dashboard/type/workflow-metadata.interface"; export const SAVE_DEBOUNCE_TIME_IN_MS = 5000; @@ -38,6 +39,7 @@ export class WorkspaceComponent implements AfterViewInit, OnInit, OnDestroy { public pid?: number = undefined; public gitCommitHash: string = Version.raw; public showResultPanel: boolean = false; + public writeAccess: boolean = false; userSystemEnabled = environment.userSystemEnabled; @ViewChild("codeEditor", { read: ViewContainerRef }) codeEditorViewRef!: ViewContainerRef; constructor( @@ -262,13 +264,14 @@ export class WorkspaceComponent implements AfterViewInit, OnInit, OnDestroy { this.workflowActionService .workflowMetaDataChanged() .pipe( - switchMap(() => of(this.workflowActionService.getWorkflowMetadata().wid)), - filter(isDefined), + switchMap(() => of(this.workflowActionService.getWorkflowMetadata())), + filter((metadata: WorkflowMetadata) => isDefined(metadata.wid)), distinctUntilChanged() ) .pipe(untilDestroyed(this)) - .subscribe(wid => { - this.workflowWebsocketService.reopenWebsocket(wid); + .subscribe((metadata: WorkflowMetadata) => { + this.writeAccess = !metadata.readonly; + this.workflowWebsocketService.reopenWebsocket(metadata.wid as number); }); } } diff --git a/core/gui/src/app/workspace/service/workflow-graph/model/workflow-action.service.ts b/core/gui/src/app/workspace/service/workflow-graph/model/workflow-action.service.ts index a4a61b9bbe6..72e73857879 100644 --- a/core/gui/src/app/workspace/service/workflow-graph/model/workflow-action.service.ts +++ b/core/gui/src/app/workspace/service/workflow-graph/model/workflow-action.service.ts @@ -36,6 +36,7 @@ export const DEFAULT_WORKFLOW = { wid: 0, creationTime: undefined, lastModifiedTime: undefined, + isPublished: 0, readonly: false, }; export const DEFAULT_SETTINGS = { @@ -822,6 +823,10 @@ export class WorkflowActionService { this.reloadWorkflow(undefined); } + public setWorkflowIsPublished(newPublishState: number): void { + this.setWorkflowMetadata({ ...this.workflowMetadata, isPublished: newPublishState }); + } + /** * Need to quit shared-editing room at first. */ From 03bf2c72aaf9b3a5b052197a008a645858ff7f5a Mon Sep 17 00:00:00 2001 From: gspikehalo <2318002579@qq.com> Date: Fri, 13 Sep 2024 18:12:59 -0700 Subject: [PATCH 32/33] fmt fix --- .../service/workflow-persist/workflow-persist.service.ts | 1 - .../component/admin/execution/admin-execution.component.ts | 2 +- .../component/user/share-access/share-access.component.ts | 3 ++- core/gui/src/app/workspace/component/workspace.component.html | 3 ++- 4 files changed, 5 insertions(+), 4 deletions(-) diff --git a/core/gui/src/app/common/service/workflow-persist/workflow-persist.service.ts b/core/gui/src/app/common/service/workflow-persist/workflow-persist.service.ts index 156ddbf3a85..57ef6512745 100644 --- a/core/gui/src/app/common/service/workflow-persist/workflow-persist.service.ts +++ b/core/gui/src/app/common/service/workflow-persist/workflow-persist.service.ts @@ -182,7 +182,6 @@ export class WorkflowPersistService { } } - public setWorkflowPersistFlag(flag: boolean): void { this.workflowPersistFlag = flag; } diff --git a/core/gui/src/app/dashboard/component/admin/execution/admin-execution.component.ts b/core/gui/src/app/dashboard/component/admin/execution/admin-execution.component.ts index f85b380a666..fb68550f651 100644 --- a/core/gui/src/app/dashboard/component/admin/execution/admin-execution.component.ts +++ b/core/gui/src/app/dashboard/component/admin/execution/admin-execution.component.ts @@ -122,7 +122,7 @@ export class AdminExecutionComponent implements OnInit, OnDestroy { description: "", creationTime: 0, lastModifiedTime: 0, - isPublished:0, + isPublished: 0, readonly: false, }; diff --git a/core/gui/src/app/dashboard/component/user/share-access/share-access.component.ts b/core/gui/src/app/dashboard/component/user/share-access/share-access.component.ts index 44e27996906..8d8f21b2ef0 100644 --- a/core/gui/src/app/dashboard/component/user/share-access/share-access.component.ts +++ b/core/gui/src/app/dashboard/component/user/share-access/share-access.component.ts @@ -46,7 +46,8 @@ export class ShareAccessComponent implements OnInit { private modalService: NzModalService, private workflowPersistService: WorkflowPersistService, private datasetService: DatasetService, - private workflowActionService: WorkflowActionService ) { + private workflowActionService: WorkflowActionService + ) { this.validateForm = this.formBuilder.group({ email: [null, Validators.email], accessLevel: ["READ"], diff --git a/core/gui/src/app/workspace/component/workspace.component.html b/core/gui/src/app/workspace/component/workspace.component.html index bdca96ccc18..57a64a6fc1b 100644 --- a/core/gui/src/app/workspace/component/workspace.component.html +++ b/core/gui/src/app/workspace/component/workspace.component.html @@ -4,7 +4,8 @@ Git hash: {{ gitCommitHash }} + [pid]="pid">Git hash: {{ gitCommitHash }} From d50890c3788ee8bdb63f5786d361a2fb94402c36 Mon Sep 17 00:00:00 2001 From: gspikehalo <2318002579@qq.com> Date: Fri, 13 Sep 2024 18:19:48 -0700 Subject: [PATCH 33/33] fix unit test --- .../dashboard/component/user-dashboard-test-fixtures.ts | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/core/gui/src/app/dashboard/component/user-dashboard-test-fixtures.ts b/core/gui/src/app/dashboard/component/user-dashboard-test-fixtures.ts index bb7e88344a5..b91e0c3b3d8 100644 --- a/core/gui/src/app/dashboard/component/user-dashboard-test-fixtures.ts +++ b/core/gui/src/app/dashboard/component/user-dashboard-test-fixtures.ts @@ -32,6 +32,7 @@ export const testWorkflow1: Workflow = { content: testWorkflowContent(["Aggregation", "NlpSentiment", "SimpleSink"]), creationTime: januaryFirst1970, lastModifiedTime: januaryFirst1970 + 2, + isPublished: 0, readonly: false, }; @@ -42,6 +43,7 @@ export const testWorkflow2: Workflow = { content: testWorkflowContent(["Aggregation", "NlpSentiment", "SimpleSink"]), creationTime: januaryFirst1970 + (oneDay + 3), lastModifiedTime: januaryFirst1970 + (oneDay + 3), + isPublished: 0, readonly: false, }; @@ -52,6 +54,7 @@ export const testWorkflow3: Workflow = { content: testWorkflowContent(["Aggregation", "NlpSentiment"]), creationTime: januaryFirst1970 + oneDay, lastModifiedTime: januaryFirst1970 + (oneDay + 4), + isPublished: 0, readonly: false, }; @@ -62,6 +65,7 @@ export const testWorkflow4: Workflow = { content: testWorkflowContent([]), creationTime: januaryFirst1970 + (oneDay + 3) * 2, lastModifiedTime: januaryFirst1970 + oneDay * 2 + 6, + isPublished: 0, readonly: false, }; @@ -72,6 +76,7 @@ export const testWorkflow5: Workflow = { content: testWorkflowContent([]), creationTime: januaryFirst1970 + oneDay * 2, lastModifiedTime: januaryFirst1970 + oneDay * 2 + 8, + isPublished: 0, readonly: false, }; @@ -82,6 +87,7 @@ export const testDownloadWorkflow1: Workflow = { content: testWorkflowContent([]), creationTime: januaryFirst1970, //januaryFirst1970 is 1970-01-01 in PST lastModifiedTime: januaryFirst1970 + 2, + isPublished: 0, readonly: false, }; @@ -92,6 +98,7 @@ export const testDownloadWorkflow2: Workflow = { content: testWorkflowContent([]), creationTime: januaryFirst1970 + (oneDay + 3), // oneDay is the number of milliseconds in a day lastModifiedTime: januaryFirst1970 + (oneDay + 3), + isPublished: 0, readonly: false, }; @@ -102,6 +109,7 @@ export const testDownloadWorkflow3: Workflow = { content: testWorkflowContent([]), creationTime: januaryFirst1970 + oneDay, lastModifiedTime: januaryFirst1970 + (oneDay + 4), + isPublished: 0, readonly: false, };