mirror of
https://github.com/GNS3/gns3-web-ui.git
synced 2025-06-06 01:01:33 +00:00
Merge pull request #1135 from GNS3/Cannot-load-symbols-after-migrating-to-v3
Cannot load symbols after migrating to v3
This commit is contained in:
commit
eb7da2f565
@ -204,6 +204,7 @@ import { TemplateComponent } from './components/template/template.component';
|
|||||||
import { TopologySummaryComponent } from './components/topology-summary/topology-summary.component';
|
import { TopologySummaryComponent } from './components/topology-summary/topology-summary.component';
|
||||||
import { WebConsoleFullWindowComponent } from './components/web-console-full-window/web-console-full-window.component';
|
import { WebConsoleFullWindowComponent } from './components/web-console-full-window/web-console-full-window.component';
|
||||||
import { DataSourceFilter } from './filters/dataSourceFilter';
|
import { DataSourceFilter } from './filters/dataSourceFilter';
|
||||||
|
import { AuthImageFilter } from './filters/authImageFilter';
|
||||||
import { DateFilter } from './filters/dateFilter.pipe';
|
import { DateFilter } from './filters/dateFilter.pipe';
|
||||||
import { NameFilter } from './filters/nameFilter.pipe';
|
import { NameFilter } from './filters/nameFilter.pipe';
|
||||||
import { ProjectsFilter } from './filters/projectsFilter.pipe';
|
import { ProjectsFilter } from './filters/projectsFilter.pipe';
|
||||||
@ -381,6 +382,7 @@ import { HttpRequestsInterceptor } from './interceptors/http.interceptor';
|
|||||||
DataSourceFilter,
|
DataSourceFilter,
|
||||||
TemplateFilter,
|
TemplateFilter,
|
||||||
ProjectsFilter,
|
ProjectsFilter,
|
||||||
|
AuthImageFilter,
|
||||||
ListOfSnapshotsComponent,
|
ListOfSnapshotsComponent,
|
||||||
CustomAdaptersComponent,
|
CustomAdaptersComponent,
|
||||||
NodesMenuComponent,
|
NodesMenuComponent,
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import { EventEmitter, Injectable } from '@angular/core';
|
import { EventEmitter, Injectable } from '@angular/core';
|
||||||
|
import { SymbolService } from '../../services/symbol.service';
|
||||||
import { event, select } from 'd3-selection';
|
import { event, select } from 'd3-selection';
|
||||||
import { MapSettingsService } from '../../services/mapsettings.service';
|
import { MapSettingsService } from '../../services/mapsettings.service';
|
||||||
import { ClickedDataEvent } from '../events/event-source';
|
import { ClickedDataEvent } from '../events/event-source';
|
||||||
@ -22,7 +23,8 @@ export class NodeWidget implements Widget {
|
|||||||
private selectionManager: SelectionManager,
|
private selectionManager: SelectionManager,
|
||||||
private labelWidget: LabelWidget,
|
private labelWidget: LabelWidget,
|
||||||
private nodesEventSource: NodesEventSource,
|
private nodesEventSource: NodesEventSource,
|
||||||
private mapSettingsService: MapSettingsService
|
private mapSettingsService: MapSettingsService,
|
||||||
|
private symbolService: SymbolService
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
public draw(view: SVGSelection) {
|
public draw(view: SVGSelection) {
|
||||||
@ -88,7 +90,13 @@ export class NodeWidget implements Widget {
|
|||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
self.onContextConsoleMenu.emit(new NodeContextMenu(event, n));
|
self.onContextConsoleMenu.emit(new NodeContextMenu(event, n));
|
||||||
})
|
})
|
||||||
.attr('xnode:href', (n: MapNode) => n.symbolUrl)
|
.attr('xnode:href', (n: MapNode) => {
|
||||||
|
let symbol = this.symbolService.get(n.symbol.split('/')[2]);
|
||||||
|
if (symbol) {
|
||||||
|
return 'data:image/svg+xml;base64,' + btoa(symbol.raw);
|
||||||
|
}
|
||||||
|
return '';
|
||||||
|
})
|
||||||
.attr('width', (n: MapNode) => {
|
.attr('width', (n: MapNode) => {
|
||||||
if (!n.width) return 60;
|
if (!n.width) return 60;
|
||||||
return n.width;
|
return n.width;
|
||||||
|
@ -32,7 +32,7 @@
|
|||||||
lazyimg
|
lazyimg
|
||||||
[ngClass]="{ imageSelected: isSelected === symbol.symbol_id }"
|
[ngClass]="{ imageSelected: isSelected === symbol.symbol_id }"
|
||||||
class="image"
|
class="image"
|
||||||
[src]="getImageSourceForTemplate(symbol.symbol_id)"
|
[src]="getImageSourceForTemplate(symbol.symbol_id)| authImage: server | async"
|
||||||
/>
|
/>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
|
import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
|
||||||
|
import { DomSanitizer } from '@angular/platform-browser';
|
||||||
import { Server } from '../../../../models/server';
|
import { Server } from '../../../../models/server';
|
||||||
import { Symbol } from '../../../../models/symbol';
|
import { Symbol } from '../../../../models/symbol';
|
||||||
import { SymbolService } from '../../../../services/symbol.service';
|
import { SymbolService } from '../../../../services/symbol.service';
|
||||||
@ -18,7 +19,7 @@ export class SymbolsComponent implements OnInit {
|
|||||||
isSelected: string = '';
|
isSelected: string = '';
|
||||||
searchText: string = '';
|
searchText: string = '';
|
||||||
|
|
||||||
constructor(private symbolService: SymbolService) {}
|
constructor(private symbolService: SymbolService, private domSanitizer: DomSanitizer) {}
|
||||||
|
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
this.isSelected = this.symbol;
|
this.isSelected = this.symbol;
|
||||||
@ -76,6 +77,11 @@ export class SymbolsComponent implements OnInit {
|
|||||||
width=\"${imageToUpload.width}\">\n<image height=\"${imageToUpload.height}\" width=\"${imageToUpload.width}\" xlink:href=\"${image}\"/>\n</svg>`;
|
width=\"${imageToUpload.width}\">\n<image height=\"${imageToUpload.height}\" width=\"${imageToUpload.width}\" xlink:href=\"${image}\"/>\n</svg>`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getImage(symbolFilename: string) {
|
||||||
|
let symbol = this.symbolService.get(symbolFilename);
|
||||||
|
return this.domSanitizer.bypassSecurityTrustUrl(`data:image/svg+xml;base64,${btoa(symbol.raw)}`);
|
||||||
|
}
|
||||||
|
|
||||||
getImageSourceForTemplate(symbol: string) {
|
getImageSourceForTemplate(symbol: string) {
|
||||||
return `${this.server.protocol}//${this.server.host}:${this.server.port}/v3/symbols/${symbol}/raw`;
|
return `${this.server.protocol}//${this.server.host}:${this.server.port}/v3/symbols/${symbol}/raw`;
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
<div *ngIf="project" [ngClass]="{ lightTheme: isLightThemeEnabled }" class="project-map">
|
<div *ngIf="project" [ngClass]="{ lightTheme: isLightThemeEnabled }" class="project-map">
|
||||||
<app-d3-map
|
<app-d3-map
|
||||||
*ngIf="!settings.angular_map"
|
*ngIf="!settings.angular_map && symbolsLoaded"
|
||||||
[server]="server"
|
[server]="server"
|
||||||
[project]="project"
|
[project]="project"
|
||||||
[symbols]="symbols"
|
[symbols]="symbols"
|
||||||
|
@ -104,6 +104,7 @@ export class ProjectMapComponent implements OnInit, OnDestroy {
|
|||||||
public gridVisibility: boolean = false;
|
public gridVisibility: boolean = false;
|
||||||
public toolbarVisibility: boolean = true;
|
public toolbarVisibility: boolean = true;
|
||||||
public symbolScaling: boolean = true;
|
public symbolScaling: boolean = true;
|
||||||
|
public symbolsLoaded: boolean = false;
|
||||||
|
|
||||||
tools = {
|
tools = {
|
||||||
selection: true,
|
selection: true,
|
||||||
@ -177,6 +178,9 @@ export class ProjectMapComponent implements OnInit, OnDestroy {
|
|||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
this.getSettings();
|
this.getSettings();
|
||||||
this.progressService.activate();
|
this.progressService.activate();
|
||||||
|
this.symbolService.symbolsLoaded.subscribe(loaded => {
|
||||||
|
this.symbolsLoaded = true;
|
||||||
|
});
|
||||||
|
|
||||||
if (this.serverService.isServiceInitialized) {
|
if (this.serverService.isServiceInitialized) {
|
||||||
this.getData();
|
this.getData();
|
||||||
@ -297,8 +301,11 @@ export class ProjectMapComponent implements OnInit, OnDestroy {
|
|||||||
.pipe(
|
.pipe(
|
||||||
mergeMap((server: Server) => {
|
mergeMap((server: Server) => {
|
||||||
if (!server) this.router.navigate(['/servers']);
|
if (!server) this.router.navigate(['/servers']);
|
||||||
|
|
||||||
this.server = server;
|
this.server = server;
|
||||||
|
|
||||||
|
// load symbols
|
||||||
|
this.symbolService.load(this.server);
|
||||||
|
|
||||||
return this.projectService.get(server, paramMap.get('project_id')).pipe(
|
return this.projectService.get(server, paramMap.get('project_id')).pipe(
|
||||||
map((project) => {
|
map((project) => {
|
||||||
return project;
|
return project;
|
||||||
|
@ -43,25 +43,25 @@
|
|||||||
<span *ngIf="i % 4 === 0" class="templateRow">
|
<span *ngIf="i % 4 === 0" class="templateRow">
|
||||||
<span class="templateIcon">
|
<span class="templateIcon">
|
||||||
<div mwlDraggable (dragStart)="dragStart($event)" (dragEnd)="dragEnd($event, filteredTemplates[i])">
|
<div mwlDraggable (dragStart)="dragStart($event)" (dragEnd)="dragEnd($event, filteredTemplates[i])">
|
||||||
<img class="image" [src]="getImageSourceForTemplate(filteredTemplates[i])" />
|
<img class="image" alt="Image" [src]="getImageSourceForTemplate(filteredTemplates[i])" />
|
||||||
</div>
|
</div>
|
||||||
<div class="templateText">{{ filteredTemplates[i].name }}</div>
|
<div class="templateText">{{ filteredTemplates[i].name }}</div>
|
||||||
</span>
|
</span>
|
||||||
<span *ngIf="filteredTemplates[i + 1]" class="templateIcon">
|
<span *ngIf="filteredTemplates[i + 1]" class="templateIcon">
|
||||||
<div mwlDraggable (dragStart)="dragStart($event)" (dragEnd)="dragEnd($event, filteredTemplates[i + 1])">
|
<div mwlDraggable (dragStart)="dragStart($event)" (dragEnd)="dragEnd($event, filteredTemplates[i + 1])">
|
||||||
<img class="image" [src]="getImageSourceForTemplate(filteredTemplates[i + 1])" />
|
<img class="image" alt="Image" [src]="getImageSourceForTemplate(filteredTemplates[i + 1])" />
|
||||||
</div>
|
</div>
|
||||||
<div class="templateText">{{ filteredTemplates[i + 1].name }}</div>
|
<div class="templateText">{{ filteredTemplates[i + 1].name }}</div>
|
||||||
</span>
|
</span>
|
||||||
<span *ngIf="filteredTemplates[i + 2]" class="templateIcon">
|
<span *ngIf="filteredTemplates[i + 2]" class="templateIcon">
|
||||||
<div mwlDraggable (dragStart)="dragStart($event)" (dragEnd)="dragEnd($event, filteredTemplates[i + 2])">
|
<div mwlDraggable (dragStart)="dragStart($event)" (dragEnd)="dragEnd($event, filteredTemplates[i + 2])">
|
||||||
<img class="image" [src]="getImageSourceForTemplate(filteredTemplates[i + 2])" />
|
<img class="image" alt="Image" [src]="getImageSourceForTemplate(filteredTemplates[i + 2])" />
|
||||||
</div>
|
</div>
|
||||||
<div class="templateText">{{ filteredTemplates[i + 2].name }}</div>
|
<div class="templateText">{{ filteredTemplates[i + 2].name }}</div>
|
||||||
</span>
|
</span>
|
||||||
<span *ngIf="filteredTemplates[i + 3]" class="templateIcon">
|
<span *ngIf="filteredTemplates[i + 3]" class="templateIcon">
|
||||||
<div mwlDraggable (dragStart)="dragStart($event)" (dragEnd)="dragEnd($event, filteredTemplates[i + 3])">
|
<div mwlDraggable (dragStart)="dragStart($event)" (dragEnd)="dragEnd($event, filteredTemplates[i + 3])">
|
||||||
<img class="image" [src]="getImageSourceForTemplate(filteredTemplates[i + 3])" />
|
<img class="image" alt="Image" [src]="getImageSourceForTemplate(filteredTemplates[i + 3])" />
|
||||||
</div>
|
</div>
|
||||||
<div class="templateText">{{ filteredTemplates[i + 3].name }}</div>
|
<div class="templateText">{{ filteredTemplates[i + 3].name }}</div>
|
||||||
</span>
|
</span>
|
||||||
|
@ -8,6 +8,7 @@ import { MapScaleService } from '../../services/mapScale.service';
|
|||||||
import { SymbolService } from '../../services/symbol.service';
|
import { SymbolService } from '../../services/symbol.service';
|
||||||
import { TemplateService } from '../../services/template.service';
|
import { TemplateService } from '../../services/template.service';
|
||||||
import { NodeAddedEvent, TemplateListDialogComponent } from './template-list-dialog/template-list-dialog.component';
|
import { NodeAddedEvent, TemplateListDialogComponent } from './template-list-dialog/template-list-dialog.component';
|
||||||
|
import { DomSanitizer } from '@angular/platform-browser';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-template',
|
selector: 'app-template',
|
||||||
@ -49,7 +50,8 @@ export class TemplateComponent implements OnInit, OnDestroy {
|
|||||||
private dialog: MatDialog,
|
private dialog: MatDialog,
|
||||||
private templateService: TemplateService,
|
private templateService: TemplateService,
|
||||||
private scaleService: MapScaleService,
|
private scaleService: MapScaleService,
|
||||||
private symbolService: SymbolService
|
private symbolService: SymbolService,
|
||||||
|
private domSanitizer: DomSanitizer
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
@ -127,7 +129,9 @@ export class TemplateComponent implements OnInit, OnDestroy {
|
|||||||
}
|
}
|
||||||
|
|
||||||
getImageSourceForTemplate(template: Template) {
|
getImageSourceForTemplate(template: Template) {
|
||||||
return this.symbolService.getSymbolFromTemplate(this.server, template);
|
let symbol = this.symbolService.getSymbolFromTemplate(template);
|
||||||
|
if (symbol) return this.domSanitizer.bypassSecurityTrustUrl(`data:image/svg+xml;base64,${btoa(symbol.raw)}`);
|
||||||
|
return this.domSanitizer.bypassSecurityTrustUrl('data:image/svg+xml;base64,');
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnDestroy() {
|
ngOnDestroy() {
|
||||||
|
26
src/app/filters/authImageFilter.ts
Normal file
26
src/app/filters/authImageFilter.ts
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
import { Pipe, PipeTransform } from '@angular/core';
|
||||||
|
import { Console } from 'console';
|
||||||
|
import { Server } from '../models/server';
|
||||||
|
import { HttpServer } from '../services/http-server.service';
|
||||||
|
import { DomSanitizer } from '@angular/platform-browser';
|
||||||
|
|
||||||
|
@Pipe({
|
||||||
|
name: 'authImage'
|
||||||
|
})
|
||||||
|
export class AuthImageFilter implements PipeTransform {
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
private httpServer: HttpServer,
|
||||||
|
private domSanitizer: DomSanitizer
|
||||||
|
) {}
|
||||||
|
|
||||||
|
async transform(src: string, server: Server) {
|
||||||
|
let url = src.split('v3')[1];
|
||||||
|
const imageBlob: Blob = await this.httpServer.getBlob(server, url).toPromise();
|
||||||
|
const reader = new FileReader();
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
reader.onloadend = () => resolve(this.domSanitizer.bypassSecurityTrustUrl(reader.result as string));
|
||||||
|
reader.readAsDataURL(imageBlob);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
@ -4,6 +4,7 @@ import { MatMenuModule } from '@angular/material/menu';
|
|||||||
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
|
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
|
||||||
import { MatToolbarModule } from '@angular/material/toolbar';
|
import { MatToolbarModule } from '@angular/material/toolbar';
|
||||||
import { RouterTestingModule } from '@angular/router/testing';
|
import { RouterTestingModule } from '@angular/router/testing';
|
||||||
|
import { ServerService } from '../../services/server.service';
|
||||||
import { ElectronService } from 'ngx-electron';
|
import { ElectronService } from 'ngx-electron';
|
||||||
import { Subject } from 'rxjs';
|
import { Subject } from 'rxjs';
|
||||||
import { ProgressComponent } from '../../common/progress/progress.component';
|
import { ProgressComponent } from '../../common/progress/progress.component';
|
||||||
@ -13,6 +14,9 @@ import { ServerManagementService, ServerStateEvent } from '../../services/server
|
|||||||
import { ToasterService } from '../../services/toaster.service';
|
import { ToasterService } from '../../services/toaster.service';
|
||||||
import { MockedToasterService } from '../../services/toaster.service.spec';
|
import { MockedToasterService } from '../../services/toaster.service.spec';
|
||||||
import { DefaultLayoutComponent } from './default-layout.component';
|
import { DefaultLayoutComponent } from './default-layout.component';
|
||||||
|
import { IndexedDbService } from '../../services/indexed-db.service';
|
||||||
|
import { HttpServer, ServerErrorHandler } from '../../services/http-server.service';
|
||||||
|
import { HttpClientModule } from '@angular/common/http';
|
||||||
|
|
||||||
class ElectronServiceMock {
|
class ElectronServiceMock {
|
||||||
public isElectronApp: boolean;
|
public isElectronApp: boolean;
|
||||||
@ -28,6 +32,10 @@ describe('DefaultLayoutComponent', () => {
|
|||||||
let fixture: ComponentFixture<DefaultLayoutComponent>;
|
let fixture: ComponentFixture<DefaultLayoutComponent>;
|
||||||
let electronServiceMock: ElectronServiceMock;
|
let electronServiceMock: ElectronServiceMock;
|
||||||
let serverManagementService = new MockedServerManagementService();
|
let serverManagementService = new MockedServerManagementService();
|
||||||
|
let serverService: ServerService;
|
||||||
|
let indexedDbService: IndexedDbService;
|
||||||
|
let httpServer: HttpServer;
|
||||||
|
let errorHandler: ServerErrorHandler;
|
||||||
|
|
||||||
beforeEach(async(() => {
|
beforeEach(async(() => {
|
||||||
electronServiceMock = new ElectronServiceMock();
|
electronServiceMock = new ElectronServiceMock();
|
||||||
@ -35,7 +43,7 @@ describe('DefaultLayoutComponent', () => {
|
|||||||
|
|
||||||
TestBed.configureTestingModule({
|
TestBed.configureTestingModule({
|
||||||
declarations: [DefaultLayoutComponent, ProgressComponent],
|
declarations: [DefaultLayoutComponent, ProgressComponent],
|
||||||
imports: [MatIconModule, MatMenuModule, MatToolbarModule, RouterTestingModule, MatProgressSpinnerModule],
|
imports: [MatIconModule, MatMenuModule, MatToolbarModule, HttpClientModule, RouterTestingModule, MatProgressSpinnerModule],
|
||||||
providers: [
|
providers: [
|
||||||
{
|
{
|
||||||
provide: ElectronService,
|
provide: ElectronService,
|
||||||
@ -53,9 +61,18 @@ describe('DefaultLayoutComponent', () => {
|
|||||||
provide: RecentlyOpenedProjectService,
|
provide: RecentlyOpenedProjectService,
|
||||||
useClass: RecentlyOpenedProjectService,
|
useClass: RecentlyOpenedProjectService,
|
||||||
},
|
},
|
||||||
|
{ provide: ServerService },
|
||||||
|
{ provide: IndexedDbService },
|
||||||
|
{ provide: HttpServer },
|
||||||
|
{ provide: ServerErrorHandler },
|
||||||
ProgressService,
|
ProgressService,
|
||||||
],
|
],
|
||||||
}).compileComponents();
|
}).compileComponents();
|
||||||
|
|
||||||
|
indexedDbService = TestBed.inject(IndexedDbService);
|
||||||
|
errorHandler = TestBed.inject(ServerErrorHandler);
|
||||||
|
httpServer = TestBed.inject(HttpServer);
|
||||||
|
serverService = TestBed.inject(ServerService);
|
||||||
}));
|
}));
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
|
@ -37,7 +37,6 @@ export class DefaultLayoutComponent implements OnInit, OnDestroy {
|
|||||||
private toasterService: ToasterService,
|
private toasterService: ToasterService,
|
||||||
private progressService: ProgressService,
|
private progressService: ProgressService,
|
||||||
private router: Router,
|
private router: Router,
|
||||||
private route: ActivatedRoute,
|
|
||||||
private serverService: ServerService
|
private serverService: ServerService
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
|
@ -39,6 +39,23 @@ export type TextOptions = {
|
|||||||
withCredentials?: boolean;
|
withCredentials?: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type BlobOptions = {
|
||||||
|
headers?:
|
||||||
|
| HttpHeaders
|
||||||
|
| {
|
||||||
|
[header: string]: string | string[];
|
||||||
|
};
|
||||||
|
observe?: 'body';
|
||||||
|
params?:
|
||||||
|
| HttpParams
|
||||||
|
| {
|
||||||
|
[param: string]: string | string[];
|
||||||
|
};
|
||||||
|
reportProgress?: boolean;
|
||||||
|
responseType: 'blob';
|
||||||
|
withCredentials?: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
export type HeadersOptions = {
|
export type HeadersOptions = {
|
||||||
headers?:
|
headers?:
|
||||||
| HttpHeaders
|
| HttpHeaders
|
||||||
@ -101,6 +118,16 @@ export class HttpServer {
|
|||||||
.pipe(catchError(this.errorHandler.handleError));
|
.pipe(catchError(this.errorHandler.handleError));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getBlob(server: Server, url: string, options?: BlobOptions): Observable<Blob> {
|
||||||
|
options = this.getBlobOptions(options);
|
||||||
|
const intercepted = this.getOptionsForServer<BlobOptions>(server, url, options);
|
||||||
|
this.requestsNotificationEmitter.emit(`GET ${intercepted.url}`);
|
||||||
|
|
||||||
|
return this.http
|
||||||
|
.get(intercepted.url, intercepted.options as BlobOptions)
|
||||||
|
.pipe(catchError(this.errorHandler.handleError));
|
||||||
|
}
|
||||||
|
|
||||||
post<T>(server: Server, url: string, body: any | null, options?: JsonOptions): Observable<T> {
|
post<T>(server: Server, url: string, body: any | null, options?: JsonOptions): Observable<T> {
|
||||||
options = this.getJsonOptions(options);
|
options = this.getJsonOptions(options);
|
||||||
const intercepted = this.getOptionsForServer(server, url, options);
|
const intercepted = this.getOptionsForServer(server, url, options);
|
||||||
@ -173,6 +200,15 @@ export class HttpServer {
|
|||||||
return options;
|
return options;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private getBlobOptions(options: BlobOptions): BlobOptions {
|
||||||
|
if (!options) {
|
||||||
|
return {
|
||||||
|
responseType: 'blob',
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return options;
|
||||||
|
}
|
||||||
|
|
||||||
private getOptionsForServer<T extends HeadersOptions>(server: Server, url: string, options: T) {
|
private getOptionsForServer<T extends HeadersOptions>(server: Server, url: string, options: T) {
|
||||||
if (server.host && server.port) {
|
if (server.host && server.port) {
|
||||||
if (!server.protocol) {
|
if (!server.protocol) {
|
||||||
|
@ -49,19 +49,11 @@ describe('SymbolService', () => {
|
|||||||
expect(req.request.method).toEqual('GET');
|
expect(req.request.method).toEqual('GET');
|
||||||
}));
|
}));
|
||||||
|
|
||||||
it('should load symbols', inject([SymbolService], (service: SymbolService) => {
|
it('should call load symbols while adding symbol', inject([SymbolService], (service: SymbolService) => {
|
||||||
spyOn(service, 'load').and.returnValue(of([]));
|
spyOn(service, 'load');
|
||||||
|
|
||||||
service.list(server).subscribe();
|
service.add(server, 'symbolName', 'symbol');
|
||||||
|
|
||||||
expect(service.load).toHaveBeenCalled();
|
expect(service.load).toHaveBeenCalled();
|
||||||
}));
|
}));
|
||||||
|
|
||||||
it('should get symbols', inject([SymbolService], (service: SymbolService) => {
|
|
||||||
const symbol = new Symbol();
|
|
||||||
symbol.symbol_id = 'myid';
|
|
||||||
service.symbols.next([symbol]);
|
|
||||||
|
|
||||||
expect(service.get('myid').symbol_id).toEqual('myid');
|
|
||||||
}));
|
|
||||||
});
|
});
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { Injectable } from '@angular/core';
|
import { Injectable } from '@angular/core';
|
||||||
import { BehaviorSubject, Observable } from 'rxjs';
|
import { BehaviorSubject, Observable, Subject } from 'rxjs';
|
||||||
import { shareReplay } from 'rxjs/operators';
|
import { shareReplay } from 'rxjs/operators';
|
||||||
import { Node } from '../cartography/models/node';
|
import { Node } from '../cartography/models/node';
|
||||||
import { Server } from '../models/server';
|
import { Server } from '../models/server';
|
||||||
@ -7,22 +7,29 @@ import { Symbol } from '../models/symbol';
|
|||||||
import { HttpServer } from './http-server.service';
|
import { HttpServer } from './http-server.service';
|
||||||
import { Template } from '../models/template';
|
import { Template } from '../models/template';
|
||||||
|
|
||||||
const CACHE_SIZE = 1;
|
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class SymbolService {
|
export class SymbolService {
|
||||||
public symbols: BehaviorSubject<Symbol[]> = new BehaviorSubject<Symbol[]>([]);
|
private symbols: Symbol[] = [];
|
||||||
private cache: Observable<Symbol[]>;
|
|
||||||
private maximumSymbolSize: number = 80;
|
private maximumSymbolSize: number = 80;
|
||||||
|
public symbolsLoaded: Subject<boolean> = new Subject<boolean>();
|
||||||
|
|
||||||
constructor(private httpServer: HttpServer) {}
|
constructor(private httpServer: HttpServer) {}
|
||||||
|
|
||||||
|
async load(server: Server) {
|
||||||
|
let symbols = await this.httpServer.get<Symbol[]>(server, '/symbols').toPromise();
|
||||||
|
await symbols.forEach(async symbol => {
|
||||||
|
symbol.raw = await this.raw(server, symbol.symbol_id).toPromise();
|
||||||
|
this.symbols.push(symbol);
|
||||||
|
});
|
||||||
|
this.symbolsLoaded.next(true);
|
||||||
|
}
|
||||||
|
|
||||||
getMaximumSymbolSize() {
|
getMaximumSymbolSize() {
|
||||||
return this.maximumSymbolSize;
|
return this.maximumSymbolSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
get(symbol_id: string): Symbol {
|
get(symbol_id: string): Symbol {
|
||||||
return this.symbols.getValue().find((symbol: Symbol) => symbol.symbol_id === symbol_id);
|
return this.symbols.find((symbol: Symbol) => symbol.filename === symbol_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
getDimensions(server: Server, symbol_id: string): Observable<SymbolDimension> {
|
getDimensions(server: Server, symbol_id: string): Observable<SymbolDimension> {
|
||||||
@ -38,25 +45,13 @@ export class SymbolService {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
getByFilename(symbol_filename: string) {
|
|
||||||
return this.symbols.getValue().find((symbol: Symbol) => symbol.filename === symbol_filename);
|
|
||||||
}
|
|
||||||
|
|
||||||
add(server: Server, symbolName: string, symbol: string) {
|
add(server: Server, symbolName: string, symbol: string) {
|
||||||
this.cache = null;
|
this.load(server);
|
||||||
return this.httpServer.post(server, `/symbols/${symbolName}/raw`, symbol);
|
return this.httpServer.post(server, `/symbols/${symbolName}/raw`, symbol);
|
||||||
}
|
}
|
||||||
|
|
||||||
load(server: Server): Observable<Symbol[]> {
|
|
||||||
return this.httpServer.get<Symbol[]>(server, '/symbols');
|
|
||||||
}
|
|
||||||
|
|
||||||
list(server: Server) {
|
list(server: Server) {
|
||||||
if (!this.cache) {
|
return this.httpServer.get<Symbol[]>(server, '/symbols');
|
||||||
this.cache = this.load(server).pipe(shareReplay(CACHE_SIZE));
|
|
||||||
}
|
|
||||||
|
|
||||||
return this.cache;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
raw(server: Server, symbol_id: string) {
|
raw(server: Server, symbol_id: string) {
|
||||||
@ -64,8 +59,8 @@ export class SymbolService {
|
|||||||
return this.httpServer.getText(server, `/symbols/${encoded_uri}/raw`);
|
return this.httpServer.getText(server, `/symbols/${encoded_uri}/raw`);
|
||||||
}
|
}
|
||||||
|
|
||||||
getSymbolFromTemplate(server: Server, template: Template) {
|
getSymbolFromTemplate(template: Template) {
|
||||||
return `${server.protocol}//${server.host}:${server.port}/v3/symbols/${template.symbol}/raw`;
|
return this.symbols.find((symbol: Symbol) => symbol.filename === template.symbol.split('/')[2]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user