From 763c573954f246744774e60698f3ffa3a77eef04 Mon Sep 17 00:00:00 2001 From: omergronich Date: Thu, 23 Feb 2023 23:31:42 +0200 Subject: [PATCH 1/7] =?UTF-8?q?feat:=20=F0=9F=8E=B8=20Temporary=20workspac?= =?UTF-8?q?e=20connection=20screen?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/cli-gui/src/app/app.component.html | 2 +- apps/cli-gui/src/app/app.routes.ts | 22 ++++++++++--- .../src/app/guards/current-workspace.guard.ts | 18 +++++++++++ apps/cli-gui/src/main.ts | 26 ++++------------ .../data-access/connect-workspace.service.ts | 18 +++++++++++ .../connect-workspace.component.html | 13 +++++++- .../connect-workspace.component.scss | 9 ++++++ .../connect-workspace.component.ts | 31 +++++++++++++++++-- .../workspace-manager.component.html | 1 - 9 files changed, 110 insertions(+), 30 deletions(-) create mode 100644 apps/cli-gui/src/app/guards/current-workspace.guard.ts create mode 100644 libs/workspace-manager/src/lib/workspace-manager/data-access/connect-workspace.service.ts diff --git a/apps/cli-gui/src/app/app.component.html b/apps/cli-gui/src/app/app.component.html index ed39c6a..0e6160e 100644 --- a/apps/cli-gui/src/app/app.component.html +++ b/apps/cli-gui/src/app/app.component.html @@ -1,6 +1,6 @@
-
+
import('@angular-cli-gui/generators').then(m => m.GeneratorsComponent), + loadComponent: () => + import('@angular-cli-gui/generators').then( + (m) => m.GeneratorsComponent + ), }, { path: 'configuration', - loadComponent: () => import('@angular-cli-gui/configuration').then(m => m.ConfigurationComponent), + loadComponent: () => + import('@angular-cli-gui/configuration').then( + (m) => m.ConfigurationComponent + ), }, { path: 'executors', - loadComponent: () => import('@angular-cli-gui/executors').then(m => m.ExecutorsComponent), + loadComponent: () => + import('@angular-cli-gui/executors').then( + (m) => m.ExecutorsComponent + ), }, ], }, { path: 'workspace-manager', - loadChildren: () => import('@angular-cli-gui/workspace-manager').then(m => m.WORKSPACE_MANAGER_ROUTES), + loadChildren: () => + import('@angular-cli-gui/workspace-manager').then( + (m) => m.WORKSPACE_MANAGER_ROUTES + ), }, ]; diff --git a/apps/cli-gui/src/app/guards/current-workspace.guard.ts b/apps/cli-gui/src/app/guards/current-workspace.guard.ts new file mode 100644 index 0000000..c7ee0cc --- /dev/null +++ b/apps/cli-gui/src/app/guards/current-workspace.guard.ts @@ -0,0 +1,18 @@ +import { HttpClient } from '@angular/common/http'; +import { inject } from '@angular/core'; +import { Router } from '@angular/router'; +import { catchError, map, Observable, of } from 'rxjs'; + +export const currentWorkspaceGuard = (): Observable => { + const router = inject(Router); + const http = inject(HttpClient); + const workspace$ = http.get('/api/workspace'); + + return workspace$.pipe( + map(() => true), + catchError(() => { + router.navigate(['workspace-manager', 'connect-workspace']); + return of(false); + }) + ); +}; diff --git a/apps/cli-gui/src/main.ts b/apps/cli-gui/src/main.ts index 77824e4..1eab944 100644 --- a/apps/cli-gui/src/main.ts +++ b/apps/cli-gui/src/main.ts @@ -1,32 +1,18 @@ -import { HttpClient, provideHttpClient } from '@angular/common/http'; -import { APP_INITIALIZER } from '@angular/core'; +import { provideHttpClient } from '@angular/common/http'; import { bootstrapApplication } from '@angular/platform-browser'; import { provideAnimations } from '@angular/platform-browser/animations'; -import { provideRouter, withEnabledBlockingInitialNavigation } from '@angular/router'; -import { map } from 'rxjs'; +import { + provideRouter, + withEnabledBlockingInitialNavigation, +} from '@angular/router'; import { AppComponent } from './app/app.component'; import { APP_ROUTES } from './app/app.routes'; -import { CoreService } from './app/core/core.service'; bootstrapApplication(AppComponent, { providers: [ provideRouter(APP_ROUTES, withEnabledBlockingInitialNavigation()), provideHttpClient(), provideAnimations(), - { - provide: APP_INITIALIZER, - useFactory: (http: HttpClient, core: CoreService) => () => - http.get(`/api/workspace`).pipe( - map((projectNames) => - core.update({ - projectNames, - currentProjectName: projectNames?.[0], - }) - ) - ), - deps: [HttpClient, CoreService], - multi: true, - }, ], -}).catch(err => console.error(err)); +}).catch((err) => console.error(err)); diff --git a/libs/workspace-manager/src/lib/workspace-manager/data-access/connect-workspace.service.ts b/libs/workspace-manager/src/lib/workspace-manager/data-access/connect-workspace.service.ts new file mode 100644 index 0000000..a8a3ec2 --- /dev/null +++ b/libs/workspace-manager/src/lib/workspace-manager/data-access/connect-workspace.service.ts @@ -0,0 +1,18 @@ +import { HttpClient } from '@angular/common/http'; +import { inject, Injectable } from '@angular/core'; +import { Router } from '@angular/router'; +import { Observable, tap } from 'rxjs'; + +@Injectable({ providedIn: 'root' }) +export class ConnectWorkspaceService { + http = inject(HttpClient); + router = inject(Router); + + connectWorkspace(path: string): Observable { + return this.http.post('/api/workspace/connect', { path }).pipe( + tap(() => { + this.router.navigate(['']); + }) + ); + } +} diff --git a/libs/workspace-manager/src/lib/workspace-manager/features/connect-workspace/connect-workspace.component.html b/libs/workspace-manager/src/lib/workspace-manager/features/connect-workspace/connect-workspace.component.html index 5067e62..ea9f16e 100644 --- a/libs/workspace-manager/src/lib/workspace-manager/features/connect-workspace/connect-workspace.component.html +++ b/libs/workspace-manager/src/lib/workspace-manager/features/connect-workspace/connect-workspace.component.html @@ -1 +1,12 @@ -

connect-workspace works!

+
+

Connect your Angular workspace

+ + The absolute path to your workspace + + + +
diff --git a/libs/workspace-manager/src/lib/workspace-manager/features/connect-workspace/connect-workspace.component.scss b/libs/workspace-manager/src/lib/workspace-manager/features/connect-workspace/connect-workspace.component.scss index e69de29..8a4e9d0 100644 --- a/libs/workspace-manager/src/lib/workspace-manager/features/connect-workspace/connect-workspace.component.scss +++ b/libs/workspace-manager/src/lib/workspace-manager/features/connect-workspace/connect-workspace.component.scss @@ -0,0 +1,9 @@ +.connect-workspace-form { + display: grid; + place-content: center; + height: 100%; + + .workspace-path-field { + min-width: 350px; + } +} diff --git a/libs/workspace-manager/src/lib/workspace-manager/features/connect-workspace/connect-workspace.component.ts b/libs/workspace-manager/src/lib/workspace-manager/features/connect-workspace/connect-workspace.component.ts index a9318bf..d9cfec0 100644 --- a/libs/workspace-manager/src/lib/workspace-manager/features/connect-workspace/connect-workspace.component.ts +++ b/libs/workspace-manager/src/lib/workspace-manager/features/connect-workspace/connect-workspace.component.ts @@ -1,12 +1,37 @@ import { CommonModule } from '@angular/common'; -import { ChangeDetectionStrategy, Component } from '@angular/core'; +import { ChangeDetectionStrategy, Component, inject } from '@angular/core'; +import { + FormControl, + FormGroup, + ReactiveFormsModule, + Validators, +} from '@angular/forms'; +import { MatButtonModule } from '@angular/material/button'; +import { MatInputModule } from '@angular/material/input'; + +import { ConnectWorkspaceService } from '../../data-access/connect-workspace.service'; @Component({ selector: 'cli-connect-workspace', standalone: true, - imports: [CommonModule], + imports: [CommonModule, MatInputModule, MatButtonModule, ReactiveFormsModule], templateUrl: './connect-workspace.component.html', styleUrls: ['./connect-workspace.component.scss'], changeDetection: ChangeDetectionStrategy.OnPush, }) -export class ConnectWorkspaceComponent {} +export class ConnectWorkspaceComponent { + connectService = inject(ConnectWorkspaceService); + form = new FormGroup( + { + path: new FormControl('', [Validators.required]), + }, + { updateOn: 'submit' } + ); + + connectWorkspace($event: SubmitEvent): void { + $event.preventDefault(); + if (!this.form.valid) return; + const path = this.form.controls.path.value ?? ''; + this.connectService.connectWorkspace(path).subscribe(); + } +} diff --git a/libs/workspace-manager/src/lib/workspace-manager/workspace-manager.component.html b/libs/workspace-manager/src/lib/workspace-manager/workspace-manager.component.html index f8d14d1..0680b43 100644 --- a/libs/workspace-manager/src/lib/workspace-manager/workspace-manager.component.html +++ b/libs/workspace-manager/src/lib/workspace-manager/workspace-manager.component.html @@ -1,2 +1 @@ -

workspace-manager works!

From 9bda3d6eb4878ed28dce056c40a59e0d49ba1297 Mon Sep 17 00:00:00 2001 From: omergronich Date: Thu, 23 Feb 2023 23:47:12 +0200 Subject: [PATCH 2/7] =?UTF-8?q?fix:=20=F0=9F=90=9B=20infinite=20loop=20bec?= =?UTF-8?q?ause=20of=20route=20change=20/=20guard=20redirect?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/cli-gui/src/app/app.component.html | 2 +- apps/cli-gui/src/app/app.component.ts | 4 ++-- apps/cli-gui/src/app/app.routes.ts | 9 +++++---- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/apps/cli-gui/src/app/app.component.html b/apps/cli-gui/src/app/app.component.html index 0e6160e..ed39c6a 100644 --- a/apps/cli-gui/src/app/app.component.html +++ b/apps/cli-gui/src/app/app.component.html @@ -1,6 +1,6 @@
-
+
@@ -28,10 +33,6 @@ export const APP_ROUTES: Routes = [ (m) => m.ExecutorsComponent ), }, - { - path: '**', - redirectTo: 'generators', - }, ], }, { From 91d7bdc67c58b9d6d3ff32e5c776ce80f1322e3d Mon Sep 17 00:00:00 2001 From: omergronich Date: Thu, 23 Feb 2023 23:55:59 +0200 Subject: [PATCH 3/7] =?UTF-8?q?fix:=20=F0=9F=90=9B=20added=20required=20mo?= =?UTF-8?q?cks?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../connect-workspace.component.spec.ts | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/libs/workspace-manager/src/lib/workspace-manager/features/connect-workspace/connect-workspace.component.spec.ts b/libs/workspace-manager/src/lib/workspace-manager/features/connect-workspace/connect-workspace.component.spec.ts index 6e94ac2..fc5d12b 100644 --- a/libs/workspace-manager/src/lib/workspace-manager/features/connect-workspace/connect-workspace.component.spec.ts +++ b/libs/workspace-manager/src/lib/workspace-manager/features/connect-workspace/connect-workspace.component.spec.ts @@ -1,4 +1,7 @@ +import { HttpClientTestingModule } from '@angular/common/http/testing'; import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { NoopAnimationsModule } from '@angular/platform-browser/animations'; +import { RouterTestingModule } from '@angular/router/testing'; import { ConnectWorkspaceComponent } from './connect-workspace.component'; @@ -8,7 +11,12 @@ describe('ConnectWorkspaceComponent', () => { beforeEach(async () => { await TestBed.configureTestingModule({ - imports: [ConnectWorkspaceComponent], + imports: [ + ConnectWorkspaceComponent, + HttpClientTestingModule, + RouterTestingModule, + NoopAnimationsModule, + ], }).compileComponents(); fixture = TestBed.createComponent(ConnectWorkspaceComponent); From a212839a7931ab22bc3d736643ebdd9b06cb28ae Mon Sep 17 00:00:00 2001 From: omergronich Date: Fri, 24 Feb 2023 23:45:58 +0200 Subject: [PATCH 4/7] =?UTF-8?q?fix:=20=F0=9F=90=9B=20using=20ngSubmit=20in?= =?UTF-8?q?stead=20of=20html=20submit?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../connect-workspace/connect-workspace.component.html | 2 +- .../features/connect-workspace/connect-workspace.component.ts | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/libs/workspace-manager/src/lib/workspace-manager/features/connect-workspace/connect-workspace.component.html b/libs/workspace-manager/src/lib/workspace-manager/features/connect-workspace/connect-workspace.component.html index ea9f16e..04265ae 100644 --- a/libs/workspace-manager/src/lib/workspace-manager/features/connect-workspace/connect-workspace.component.html +++ b/libs/workspace-manager/src/lib/workspace-manager/features/connect-workspace/connect-workspace.component.html @@ -1,7 +1,7 @@

Connect your Angular workspace

diff --git a/libs/workspace-manager/src/lib/workspace-manager/features/connect-workspace/connect-workspace.component.ts b/libs/workspace-manager/src/lib/workspace-manager/features/connect-workspace/connect-workspace.component.ts index d9cfec0..6cbe049 100644 --- a/libs/workspace-manager/src/lib/workspace-manager/features/connect-workspace/connect-workspace.component.ts +++ b/libs/workspace-manager/src/lib/workspace-manager/features/connect-workspace/connect-workspace.component.ts @@ -28,8 +28,7 @@ export class ConnectWorkspaceComponent { { updateOn: 'submit' } ); - connectWorkspace($event: SubmitEvent): void { - $event.preventDefault(); + connectWorkspace(): void { if (!this.form.valid) return; const path = this.form.controls.path.value ?? ''; this.connectService.connectWorkspace(path).subscribe(); From c5ac4501128cb03a5cfdc8f16437c055a7ecd1d0 Mon Sep 17 00:00:00 2001 From: omergronich Date: Sat, 25 Feb 2023 00:39:44 +0200 Subject: [PATCH 5/7] =?UTF-8?q?refactor:=20=F0=9F=92=A1=20keeping=20curren?= =?UTF-8?q?t=20path=20in=20local=20storage?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/cli-gui/src/app/app.component.html | 2 +- .../src/app/guards/current-workspace.guard.ts | 45 ++++++++++++++++--- libs/shared/data/src/index.ts | 1 + .../data/src/lib/local-storage-keys.consts.ts | 1 + libs/workspace-manager/src/index.ts | 1 + .../data-access/connect-workspace.service.ts | 2 + 6 files changed, 45 insertions(+), 7 deletions(-) create mode 100644 libs/shared/data/src/lib/local-storage-keys.consts.ts diff --git a/apps/cli-gui/src/app/app.component.html b/apps/cli-gui/src/app/app.component.html index ed39c6a..b4e2389 100644 --- a/apps/cli-gui/src/app/app.component.html +++ b/apps/cli-gui/src/app/app.component.html @@ -1,5 +1,5 @@ -
+
=> { const router = inject(Router); const http = inject(HttpClient); - const workspace$ = http.get('/api/workspace'); + const connectWorkspaceService = inject(ConnectWorkspaceService); + const core = inject(CoreService); + const retrySubject = new Subject(); + const projectNames$ = http.get('/api/workspace'); + const currentWorkspacePath = localStorage.getItem(CURRENT_WORKSPACE_PATH); - return workspace$.pipe( + return projectNames$.pipe( + // Save projects to state + tap((projectNames) => { + core.update({ + projectNames, + currentProjectName: projectNames?.[0], + }); + }), + // Map to true to allow navigation map(() => true), catchError(() => { - router.navigate(['workspace-manager', 'connect-workspace']); - return of(false); - }) + if (!currentWorkspacePath) { + router.navigate(['workspace-manager', 'connect-workspace']); + return of(false); + } + + // if path saved in local storage is invalid somehow (maybe deleted workspace) + // remove it from local storage so on 2nd retry cycle user will be navigated to workspace connection screen + localStorage.removeItem(CURRENT_WORKSPACE_PATH); + + // Connect to workspace using local storage path and retry to get projectNames + return connectWorkspaceService + .connectWorkspace(currentWorkspacePath) + .pipe( + map(() => { + retrySubject.next(); + return false; + }) + ); + }), + retry({ delay: () => retrySubject }) ); }; diff --git a/libs/shared/data/src/index.ts b/libs/shared/data/src/index.ts index 2c7ff31..5c8f84d 100644 --- a/libs/shared/data/src/index.ts +++ b/libs/shared/data/src/index.ts @@ -1,2 +1,3 @@ export * from './lib/exec-result.interface'; export * from './lib/generate-component-args.interface'; +export * from './lib/local-storage-keys.consts'; diff --git a/libs/shared/data/src/lib/local-storage-keys.consts.ts b/libs/shared/data/src/lib/local-storage-keys.consts.ts new file mode 100644 index 0000000..7a7dd2d --- /dev/null +++ b/libs/shared/data/src/lib/local-storage-keys.consts.ts @@ -0,0 +1 @@ +export const CURRENT_WORKSPACE_PATH = 'currentWorkspacePath'; diff --git a/libs/workspace-manager/src/index.ts b/libs/workspace-manager/src/index.ts index 88b3d6a..84e30aa 100644 --- a/libs/workspace-manager/src/index.ts +++ b/libs/workspace-manager/src/index.ts @@ -1,2 +1,3 @@ export * from './lib/workspace-manager/workspace-manager.component'; export * from './lib/workspace-manager/workspace-manager.routes'; +export * from './lib/workspace-manager/data-access/connect-workspace.service'; diff --git a/libs/workspace-manager/src/lib/workspace-manager/data-access/connect-workspace.service.ts b/libs/workspace-manager/src/lib/workspace-manager/data-access/connect-workspace.service.ts index a8a3ec2..647cad9 100644 --- a/libs/workspace-manager/src/lib/workspace-manager/data-access/connect-workspace.service.ts +++ b/libs/workspace-manager/src/lib/workspace-manager/data-access/connect-workspace.service.ts @@ -1,6 +1,7 @@ import { HttpClient } from '@angular/common/http'; import { inject, Injectable } from '@angular/core'; import { Router } from '@angular/router'; +import { CURRENT_WORKSPACE_PATH } from '@angular-cli-gui/shared/data'; import { Observable, tap } from 'rxjs'; @Injectable({ providedIn: 'root' }) @@ -11,6 +12,7 @@ export class ConnectWorkspaceService { connectWorkspace(path: string): Observable { return this.http.post('/api/workspace/connect', { path }).pipe( tap(() => { + localStorage.setItem(CURRENT_WORKSPACE_PATH, path); this.router.navigate(['']); }) ); From 0618a41db068f487424517870b5066868a465718 Mon Sep 17 00:00:00 2001 From: omergronich Date: Sun, 26 Feb 2023 21:36:05 +0200 Subject: [PATCH 6/7] =?UTF-8?q?fix:=20=F0=9F=90=9B=20removed=20NgFor?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/cli-gui/src/app/app.component.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/cli-gui/src/app/app.component.ts b/apps/cli-gui/src/app/app.component.ts index 71dbd8a..c514536 100644 --- a/apps/cli-gui/src/app/app.component.ts +++ b/apps/cli-gui/src/app/app.component.ts @@ -1,4 +1,4 @@ -import { AsyncPipe, NgFor, NgForOf, NgIf } from '@angular/common'; +import { AsyncPipe, NgForOf, NgIf } from '@angular/common'; import { Component } from '@angular/core'; import { MatSelectModule } from '@angular/material/select'; import { RouterOutlet } from '@angular/router'; @@ -7,7 +7,7 @@ import { CoreService } from './core/core.service'; @Component({ standalone: true, - imports: [NgFor, NgIf, AsyncPipe, RouterOutlet, MatSelectModule, NgForOf], + imports: [NgIf, AsyncPipe, RouterOutlet, MatSelectModule, NgForOf], selector: 'cli-root', templateUrl: './app.component.html', styleUrls: ['./app.component.scss'], From fe64ce0e392c85f355d77f5b5cb6a6e38ffca3c8 Mon Sep 17 00:00:00 2001 From: omergronich Date: Sun, 26 Feb 2023 21:39:27 +0200 Subject: [PATCH 7/7] =?UTF-8?q?refactor:=20=F0=9F=92=A1=20replaced=20local?= =?UTF-8?q?Storage=20with=20sessionStorage?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/cli-gui/src/app/guards/current-workspace.guard.ts | 4 ++-- .../data-access/connect-workspace.service.ts | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/apps/cli-gui/src/app/guards/current-workspace.guard.ts b/apps/cli-gui/src/app/guards/current-workspace.guard.ts index 6a3752c..7828add 100644 --- a/apps/cli-gui/src/app/guards/current-workspace.guard.ts +++ b/apps/cli-gui/src/app/guards/current-workspace.guard.ts @@ -14,7 +14,7 @@ export const currentWorkspaceGuard = (): Observable => { const core = inject(CoreService); const retrySubject = new Subject(); const projectNames$ = http.get('/api/workspace'); - const currentWorkspacePath = localStorage.getItem(CURRENT_WORKSPACE_PATH); + const currentWorkspacePath = sessionStorage.getItem(CURRENT_WORKSPACE_PATH); return projectNames$.pipe( // Save projects to state @@ -34,7 +34,7 @@ export const currentWorkspaceGuard = (): Observable => { // if path saved in local storage is invalid somehow (maybe deleted workspace) // remove it from local storage so on 2nd retry cycle user will be navigated to workspace connection screen - localStorage.removeItem(CURRENT_WORKSPACE_PATH); + sessionStorage.removeItem(CURRENT_WORKSPACE_PATH); // Connect to workspace using local storage path and retry to get projectNames return connectWorkspaceService diff --git a/libs/workspace-manager/src/lib/workspace-manager/data-access/connect-workspace.service.ts b/libs/workspace-manager/src/lib/workspace-manager/data-access/connect-workspace.service.ts index 647cad9..2f074f6 100644 --- a/libs/workspace-manager/src/lib/workspace-manager/data-access/connect-workspace.service.ts +++ b/libs/workspace-manager/src/lib/workspace-manager/data-access/connect-workspace.service.ts @@ -12,7 +12,7 @@ export class ConnectWorkspaceService { connectWorkspace(path: string): Observable { return this.http.post('/api/workspace/connect', { path }).pipe( tap(() => { - localStorage.setItem(CURRENT_WORKSPACE_PATH, path); + sessionStorage.setItem(CURRENT_WORKSPACE_PATH, path); this.router.navigate(['']); }) );