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 @@ -
+
import('./generators/generators.routes'), + loadComponent: () => + import('@angular-cli-gui/generators').then( + (m) => m.GeneratorsComponent + ), }, { path: 'configuration', @@ -22,10 +33,6 @@ export const APP_ROUTES: Routes = [ (m) => m.ExecutorsComponent ), }, - { - path: '**', - redirectTo: 'generators', - }, ], }, { 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..7828add --- /dev/null +++ b/apps/cli-gui/src/app/guards/current-workspace.guard.ts @@ -0,0 +1,51 @@ +import { HttpClient } from '@angular/common/http'; +import { inject } from '@angular/core'; +import { Router } from '@angular/router'; +import { CURRENT_WORKSPACE_PATH } from '@angular-cli-gui/shared/data'; +import { ConnectWorkspaceService } from '@angular-cli-gui/workspace-manager'; +import { catchError, map, Observable, of, retry, Subject, tap } from 'rxjs'; + +import { CoreService } from '../core/core.service'; + +export const currentWorkspaceGuard = (): Observable => { + const router = inject(Router); + const http = inject(HttpClient); + const connectWorkspaceService = inject(ConnectWorkspaceService); + const core = inject(CoreService); + const retrySubject = new Subject(); + const projectNames$ = http.get('/api/workspace'); + const currentWorkspacePath = sessionStorage.getItem(CURRENT_WORKSPACE_PATH); + + return projectNames$.pipe( + // Save projects to state + tap((projectNames) => { + core.update({ + projectNames, + currentProjectName: projectNames?.[0], + }); + }), + // Map to true to allow navigation + map(() => true), + catchError(() => { + 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 + sessionStorage.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/apps/cli-gui/src/main.ts b/apps/cli-gui/src/main.ts index 995cb50..1eab944 100644 --- a/apps/cli-gui/src/main.ts +++ b/apps/cli-gui/src/main.ts @@ -1,35 +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 { 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)); diff --git a/libs/shared/data/src/index.ts b/libs/shared/data/src/index.ts index 2f43d66..574bf0a 100644 --- a/libs/shared/data/src/index.ts +++ b/libs/shared/data/src/index.ts @@ -1,3 +1,4 @@ export * from './lib/exec-result.interface'; export * from './lib/generate-component-args.interface'; export * from './lib/directory.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 new file mode 100644 index 0000000..2f074f6 --- /dev/null +++ b/libs/workspace-manager/src/lib/workspace-manager/data-access/connect-workspace.service.ts @@ -0,0 +1,20 @@ +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' }) +export class ConnectWorkspaceService { + http = inject(HttpClient); + router = inject(Router); + + connectWorkspace(path: string): Observable { + return this.http.post('/api/workspace/connect', { path }).pipe( + tap(() => { + sessionStorage.setItem(CURRENT_WORKSPACE_PATH, path); + 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..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 +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.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); 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..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 @@ -1,12 +1,36 @@ 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(): void { + 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!