Merge pull request #688 from GNS3/angular-resolvers

Introducing the Angular 8 Resolvers to Web UI to fetch data before navigating to the route
This commit is contained in:
piotrpekala7 2020-02-28 14:30:13 +01:00 committed by GitHub
commit 04a2cd543a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 50 additions and 38 deletions

View File

@ -61,6 +61,7 @@ import { PageNotFoundComponent } from './components/page-not-found/page-not-foun
import { Gns3vmComponent } from './components/preferences/gns3vm/gns3vm.component'; import { Gns3vmComponent } from './components/preferences/gns3vm/gns3vm.component';
import { DirectLinkComponent } from './components/direct-link/direct-link.component'; import { DirectLinkComponent } from './components/direct-link/direct-link.component';
import { SystemStatusComponent } from './components/system-status/system-status.component'; import { SystemStatusComponent } from './components/system-status/system-status.component';
import { ServerResolve } from './resolvers/server-resolve';
import { ProjectMapGuard } from './guards/project-map-guard'; import { ProjectMapGuard } from './guards/project-map-guard';
const routes: Routes = [ const routes: Routes = [
@ -71,7 +72,11 @@ const routes: Routes = [
{ path: '', redirectTo: 'servers', pathMatch: 'full' }, { path: '', redirectTo: 'servers', pathMatch: 'full' },
{ path: 'servers', component: ServersComponent }, { path: 'servers', component: ServersComponent },
{ path: 'bundled', component: BundledServerFinderComponent }, { path: 'bundled', component: BundledServerFinderComponent },
{ path: 'server/:server_id/projects', component: ProjectsComponent }, {
path: 'server/:server_id/projects',
component: ProjectsComponent,
resolve: { server : ServerResolve }
},
{ path: 'help', component: HelpComponent }, { path: 'help', component: HelpComponent },
{ path: 'settings', component: SettingsComponent }, { path: 'settings', component: SettingsComponent },
{ path: 'settings/console', component: ConsoleComponent }, { path: 'settings/console', component: ConsoleComponent },
@ -79,7 +84,11 @@ const routes: Routes = [
{ path: 'server/:server_id/systemstatus', component: SystemStatusComponent }, { path: 'server/:server_id/systemstatus', component: SystemStatusComponent },
{ path: 'server/:server_ip/:server_port/project/:project_id', component: DirectLinkComponent}, { path: 'server/:server_ip/:server_port/project/:project_id', component: DirectLinkComponent},
{ path: 'server/:server_id/project/:project_id/snapshots', component: ListOfSnapshotsComponent }, {
path: 'server/:server_id/project/:project_id/snapshots',
component: ListOfSnapshotsComponent,
resolve: { server : ServerResolve }
},
{ path: 'server/:server_id/preferences', component: PreferencesComponent }, { path: 'server/:server_id/preferences', component: PreferencesComponent },
{ path: 'server/:server_id/preferences/gns3vm', component: Gns3vmComponent }, { path: 'server/:server_id/preferences/gns3vm', component: Gns3vmComponent },
// { path: 'server/:server_id/preferences/general', component: GeneralPreferencesComponent }, // { path: 'server/:server_id/preferences/general', component: GeneralPreferencesComponent },

View File

@ -266,6 +266,7 @@ import { StatusChartComponent } from './components/system-status/status-chart/st
import { NgCircleProgressModule } from 'ng-circle-progress'; import { NgCircleProgressModule } from 'ng-circle-progress';
import { OpenFileExplorerActionComponent } from './components/project-map/context-menu/actions/open-file-explorer/open-file-explorer-action.component'; import { OpenFileExplorerActionComponent } from './components/project-map/context-menu/actions/open-file-explorer/open-file-explorer-action.component';
import { NgxChildProcessModule } from 'ngx-childprocess'; import { NgxChildProcessModule } from 'ngx-childprocess';
import { ServerResolve } from './resolvers/server-resolve';
import { ProjectMapGuard } from './guards/project-map-guard'; import { ProjectMapGuard } from './guards/project-map-guard';
if (environment.production) { if (environment.production) {
@ -540,6 +541,7 @@ if (environment.production) {
Gns3vmService, Gns3vmService,
ThemeService, ThemeService,
GoogleAnalyticsService, GoogleAnalyticsService,
ServerResolve,
ProjectMapGuard, ProjectMapGuard,
Title Title
], ],

View File

@ -41,7 +41,6 @@ export class ProjectsComponent implements OnInit {
constructor( constructor(
private route: ActivatedRoute, private route: ActivatedRoute,
private serverService: ServerService,
private projectService: ProjectService, private projectService: ProjectService,
private settingsService: SettingsService, private settingsService: SettingsService,
private progressService: ProgressService, private progressService: ProgressService,
@ -53,24 +52,13 @@ export class ProjectsComponent implements OnInit {
) {} ) {}
ngOnInit() { ngOnInit() {
this.server = this.route.snapshot.data['server'];
this.refresh();
this.sort.sort(<MatSortable>{ this.sort.sort(<MatSortable>{
id: 'name', id: 'name',
start: 'asc' start: 'asc'
}); });
this.dataSource = new ProjectDataSource(this.projectDatabase, this.sort); this.dataSource = new ProjectDataSource(this.projectDatabase, this.sort);
this.route.paramMap
.pipe(
switchMap((params: ParamMap) => {
const server_id = params.get('server_id');
return this.serverService.get(parseInt(server_id, 10));
})
)
.subscribe((server: Server) => {
this.server = server;
this.refresh();
});
this.settings = this.settingsService.getAll(); this.settings = this.settingsService.getAll();
this.projectService.projectListSubject.subscribe(() => this.refresh()); this.projectService.projectListSubject.subscribe(() => this.refresh());

View File

@ -17,6 +17,7 @@ import { Server } from '../../../models/server';
import { Snapshot } from '../../../models/snapshot'; import { Snapshot } from '../../../models/snapshot';
import { MockedToasterService } from '../../../services/toaster.service.spec'; import { MockedToasterService } from '../../../services/toaster.service.spec';
import { NameFilter } from '../../../filters/nameFilter.pipe'; import { NameFilter } from '../../../filters/nameFilter.pipe';
import { ServerResolve } from '../../../resolvers/server-resolve';
export class MockedActivatedRoute { export class MockedActivatedRoute {
get() { get() {
@ -32,6 +33,9 @@ export class MockedActivatedRoute {
get(name: string): string { get(name: string): string {
return '1'; return '1';
} }
},
data: {
'server': new Server()
} }
}, },
}; };
@ -56,17 +60,25 @@ describe('ListOfSnapshotsComponent', () => {
let component: ListOfSnapshotsComponent; let component: ListOfSnapshotsComponent;
let fixture: ComponentFixture<ListOfSnapshotsComponent>; let fixture: ComponentFixture<ListOfSnapshotsComponent>;
let activatedRoute = new MockedActivatedRoute().get(); let activatedRoute = new MockedActivatedRoute().get();
let mockedServerService = new MockedServerService();
let mockedSnapshotService = new MockedSnapshotService(); let mockedSnapshotService = new MockedSnapshotService();
let mockedToasterService = new MockedToasterService(); let mockedToasterService = new MockedToasterService();
beforeEach(async(() => { beforeEach(async(() => {
TestBed.configureTestingModule({ TestBed.configureTestingModule({
imports: [MatDialogModule, MatTableModule, MatIconModule, MatToolbarModule, MatMenuModule, MatCheckboxModule, CommonModule, NoopAnimationsModule, RouterTestingModule.withRoutes([])], imports: [MatDialogModule,
MatTableModule,
MatIconModule,
MatToolbarModule,
MatMenuModule,
MatCheckboxModule,
CommonModule,
NoopAnimationsModule,
RouterTestingModule.withRoutes([
{ path: 'server/:server_id/project/:project_id/snapshots', component: ListOfSnapshotsComponent, resolve: {server: ServerResolve} }
])],
providers: [ providers: [
{ provide: SnapshotService, useValue: mockedSnapshotService }, { provide: SnapshotService, useValue: mockedSnapshotService },
{ provide: ActivatedRoute, useValue: activatedRoute }, { provide: ActivatedRoute, useValue: activatedRoute },
{ provide: ServerService, useValue: mockedServerService },
{ provide: ProgressDialogService, useClass: ProgressDialogService }, { provide: ProgressDialogService, useClass: ProgressDialogService },
{ provide: ToasterService, useValue: mockedToasterService } { provide: ToasterService, useValue: mockedToasterService }
], ],

View File

@ -23,20 +23,16 @@ export class ListOfSnapshotsComponent implements OnInit {
searchText: string; searchText: string;
constructor( constructor(
private snapshotService: SnapshotService,
private serverService: ServerService,
private route: ActivatedRoute, private route: ActivatedRoute,
private snapshotService: SnapshotService,
private progressDialogService: ProgressDialogService, private progressDialogService: ProgressDialogService,
private toaster: ToasterService private toaster: ToasterService
) {} ) {}
ngOnInit() { ngOnInit() {
let serverId = this.route.snapshot.paramMap.get("server_id");
this.projectId = this.route.snapshot.paramMap.get("project_id"); this.projectId = this.route.snapshot.paramMap.get("project_id");
this.serverService.get(parseInt(serverId, 10)).then((server: Server) => { this.server = this.route.snapshot.data['server'];
this.server = server;
this.getSnapshots(); this.getSnapshots();
});
} }
getSnapshots() { getSnapshots() {

View File

@ -0,0 +1,15 @@
import { Injectable } from "@angular/core";
import { Resolve, ActivatedRouteSnapshot } from '@angular/router';
import { ServerService } from '../services/server.service';
import { Server } from '../models/server';
@Injectable()
export class ServerResolve implements Resolve<Server> {
constructor(
private serverService: ServerService
) {}
resolve(route: ActivatedRouteSnapshot) {
return this.serverService.get(parseInt(route.params['server_id']));
}
}

View File

@ -97,16 +97,6 @@ describe('ServerService', () => {
record.name = 'test'; record.name = 'test';
}); });
it('should get an object', done => {
spyOn(db, 'getByKey').and.returnValue(Promise.resolve([record]));
service.get(1).then(result => {
expect(db.getByKey).toHaveBeenCalledWith('servers', 1);
expect(result).toEqual([record]);
done();
});
});
it('should create an object', done => { it('should create an object', done => {
const created = new Server(); const created = new Server();
created.id = 22; created.id = 22;

View File

@ -18,8 +18,8 @@ export class ServerService {
}); });
} }
public get(id: number) { public get(id: number): Promise<Server> {
return this.onReady(() => this.indexedDbService.get().getByKey(this.tablename, id)); return this.onReady(() => this.indexedDbService.get().getByKey(this.tablename, id)) as Promise<Server>;
} }
public create(server: Server) { public create(server: Server) {