mirror of
https://github.com/GNS3/gns3-web-ui.git
synced 2025-03-23 20:15:16 +00:00
Limit experimental features
This commit is contained in:
parent
e6c1851b16
commit
d929cd4187
@ -17,6 +17,9 @@ import { SelectionManager } from "../../cartography/shared/managers/selection-ma
|
||||
import { Server } from "../../shared/models/server";
|
||||
import { Node } from "../../cartography/shared/models/node";
|
||||
import { Project } from "../../shared/models/project";
|
||||
import { ProjectService } from "../../shared/services/project.service";
|
||||
import { MockedProjectService } from "../../shared/services/project.service.spec";
|
||||
import { SettingsService } from "../../shared/services/settings.service";
|
||||
|
||||
|
||||
describe('ProjectMapShortcutsComponent', () => {
|
||||
@ -37,9 +40,11 @@ describe('ProjectMapShortcutsComponent', () => {
|
||||
],
|
||||
providers: [
|
||||
HttpServer,
|
||||
{ provide: NodeService, useFactory: () => instance(nodeServiceMock)},
|
||||
{ provide: HotkeysService, useFactory: () => hotkeyServiceInstanceMock},
|
||||
{ provide: ToasterService, useClass: MockedToasterService},
|
||||
{ provide: NodeService, useFactory: () => instance(nodeServiceMock) },
|
||||
{ provide: HotkeysService, useFactory: () => hotkeyServiceInstanceMock },
|
||||
{ provide: ToasterService, useClass: MockedToasterService },
|
||||
{ provide: ProjectService, useClass: MockedProjectService },
|
||||
{ provide: SettingsService, useClass: SettingsService }
|
||||
],
|
||||
declarations: [ ProjectMapShortcutsComponent ]
|
||||
})
|
||||
|
@ -6,6 +6,7 @@ import { NodeService } from '../../shared/services/node.service';
|
||||
import { Server } from '../../shared/models/server';
|
||||
import { ToasterService } from '../../shared/services/toaster.service';
|
||||
import { Project } from "../../shared/models/project";
|
||||
import { ProjectService } from "../../shared/services/project.service";
|
||||
|
||||
|
||||
@Component({
|
||||
@ -23,6 +24,7 @@ export class ProjectMapShortcutsComponent implements OnInit, OnDestroy {
|
||||
private hotkeysService: HotkeysService,
|
||||
private toaster: ToasterService,
|
||||
private nodesService: NodeService,
|
||||
private projectService: ProjectService
|
||||
) { }
|
||||
|
||||
ngOnInit() {
|
||||
@ -30,8 +32,8 @@ export class ProjectMapShortcutsComponent implements OnInit, OnDestroy {
|
||||
this.hotkeysService.add(this.deleteHotkey);
|
||||
}
|
||||
|
||||
onDeleteHandler(event: KeyboardEvent):boolean {
|
||||
if (!this.project.readonly) {
|
||||
onDeleteHandler(event: KeyboardEvent): boolean {
|
||||
if (!this.projectService.isReadOnly(this.project)) {
|
||||
const selectedNodes = this.selectionManager.getSelectedNodes();
|
||||
if (selectedNodes) {
|
||||
selectedNodes.forEach((node) => {
|
||||
|
@ -33,7 +33,7 @@
|
||||
</div>
|
||||
</mat-menu>
|
||||
|
||||
<mat-toolbar-row *ngIf="!project.readonly">
|
||||
<mat-toolbar-row *ngIf="!readonly">
|
||||
<button mat-icon-button [color]="drawLineMode ? 'primary': 'basic'" (click)="toggleDrawLineMode()">
|
||||
<mat-icon>timeline</mat-icon>
|
||||
</button>
|
||||
@ -45,13 +45,13 @@
|
||||
</button>
|
||||
</mat-toolbar-row>
|
||||
|
||||
<mat-toolbar-row *ngIf="!project.readonly" >
|
||||
<mat-toolbar-row *ngIf="!readonly" >
|
||||
<button mat-icon-button (click)="createSnapshotModal()">
|
||||
<mat-icon>snooze</mat-icon>
|
||||
</button>
|
||||
</mat-toolbar-row>
|
||||
|
||||
<mat-toolbar-row *ngIf="!project.readonly" >
|
||||
<mat-toolbar-row *ngIf="!readonly" >
|
||||
<app-appliance [server]="server" (onNodeCreation)="onNodeCreation($event)"></app-appliance>
|
||||
</mat-toolbar-row>
|
||||
|
||||
|
@ -40,7 +40,7 @@ import { SelectionManager } from "../cartography/shared/managers/selection-manag
|
||||
import { InRectangleHelper } from "../cartography/map/helpers/in-rectangle-helper";
|
||||
import { DrawingsDataSource } from "../cartography/shared/datasources/drawings-datasource";
|
||||
import { Subscription } from "rxjs/Subscription";
|
||||
|
||||
import { SettingsService } from "../shared/services/settings.service";
|
||||
|
||||
|
||||
@Component({
|
||||
@ -61,6 +61,7 @@ export class ProjectMapComponent implements OnInit, OnDestroy {
|
||||
private ws: Subject<any>;
|
||||
private drawLineMode = false;
|
||||
private movingMode = false;
|
||||
private readonly = false;
|
||||
|
||||
protected selectionManager: SelectionManager;
|
||||
|
||||
@ -85,6 +86,7 @@ export class ProjectMapComponent implements OnInit, OnDestroy {
|
||||
private progressDialogService: ProgressDialogService,
|
||||
private toaster: ToasterService,
|
||||
private projectWebServiceHandler: ProjectWebServiceHandler,
|
||||
private settingsService: SettingsService,
|
||||
protected nodesDataSource: NodesDataSource,
|
||||
protected linksDataSource: LinksDataSource,
|
||||
protected drawingsDataSource: DrawingsDataSource,
|
||||
@ -104,7 +106,6 @@ export class ProjectMapComponent implements OnInit, OnDestroy {
|
||||
.flatMap((server: Server) => {
|
||||
this.server = server;
|
||||
return this.projectService.get(server, paramMap.get('project_id')).map((project) => {
|
||||
project.readonly = true;
|
||||
return project;
|
||||
});
|
||||
})
|
||||
@ -162,6 +163,8 @@ export class ProjectMapComponent implements OnInit, OnDestroy {
|
||||
}
|
||||
|
||||
onProjectLoad(project: Project) {
|
||||
this.readonly = this.projectService.isReadOnly(project);
|
||||
|
||||
const subscription = this.symbolService
|
||||
.load(this.server)
|
||||
.flatMap(() => {
|
||||
@ -195,10 +198,11 @@ export class ProjectMapComponent implements OnInit, OnDestroy {
|
||||
}
|
||||
|
||||
setUpMapCallbacks(project: Project) {
|
||||
if (this.project.readonly) {
|
||||
if (this.readonly) {
|
||||
this.mapChild.graphLayout.getSelectionTool().deactivate();
|
||||
}
|
||||
this.mapChild.graphLayout.getNodesWidget().setDraggingEnabled(!this.project.readonly);
|
||||
|
||||
this.mapChild.graphLayout.getNodesWidget().setDraggingEnabled(!this.readonly);
|
||||
|
||||
this.mapChild.graphLayout.getNodesWidget().setOnContextMenuCallback((event: any, node: Node) => {
|
||||
this.nodeContextMenu.open(node, event.clientY, event.clientX);
|
||||
@ -280,18 +284,19 @@ export class ProjectMapComponent implements OnInit, OnDestroy {
|
||||
public toggleMovingMode() {
|
||||
this.movingMode = !this.movingMode;
|
||||
if (this.movingMode) {
|
||||
if (!this.project.readonly) {
|
||||
if (!this.readonly) {
|
||||
this.mapChild.graphLayout.getSelectionTool().deactivate();
|
||||
}
|
||||
this.mapChild.graphLayout.getMovingTool().activate();
|
||||
} else {
|
||||
this.mapChild.graphLayout.getMovingTool().deactivate();
|
||||
if (!this.project.readonly) {
|
||||
if (!this.readonly) {
|
||||
this.mapChild.graphLayout.getSelectionTool().activate();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public onChooseInterface(event) {
|
||||
const node: Node = event.node;
|
||||
const port: Port = event.port;
|
||||
|
@ -6,6 +6,7 @@ import { FormsModule } from "@angular/forms";
|
||||
import { SettingsService } from "../shared/services/settings.service";
|
||||
import { PersistenceModule } from "angular-persistence";
|
||||
import { BrowserAnimationsModule } from "@angular/platform-browser/animations";
|
||||
import { MockedToasterService, ToasterService } from "../shared/services/toaster.service";
|
||||
|
||||
describe('SettingsComponent', () => {
|
||||
let component: SettingsComponent;
|
||||
@ -17,7 +18,10 @@ describe('SettingsComponent', () => {
|
||||
imports: [
|
||||
MatExpansionModule, MatCheckboxModule, FormsModule,
|
||||
PersistenceModule, BrowserAnimationsModule ],
|
||||
providers: [ SettingsService ],
|
||||
providers: [
|
||||
SettingsService,
|
||||
{ provide: ToasterService, useClass: MockedToasterService }
|
||||
],
|
||||
declarations: [ SettingsComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
@ -37,7 +41,8 @@ describe('SettingsComponent', () => {
|
||||
|
||||
it('should get and save new settings', () => {
|
||||
const settings = {
|
||||
'crash_reports': true
|
||||
'crash_reports': true,
|
||||
'experimental_features': true
|
||||
};
|
||||
const getAll = spyOn(settingsService, 'getAll').and.returnValue(settings);
|
||||
const setAll = spyOn(settingsService, 'setAll');
|
||||
|
@ -3,7 +3,7 @@
|
||||
<mat-menu #contextMenu="matMenu">
|
||||
<app-start-node-action [server]="server" [node]="node"></app-start-node-action>
|
||||
<app-stop-node-action [server]="server" [node]="node"></app-stop-node-action>
|
||||
<app-move-layer-up-action *ngIf="!project.readonly" [server]="server" [node]="node"></app-move-layer-up-action>
|
||||
<app-move-layer-down-action *ngIf="!project.readonly" [server]="server" [node]="node"></app-move-layer-down-action>
|
||||
<app-move-layer-up-action *ngIf="!projectService.isReadOnly(project)" [server]="server" [node]="node"></app-move-layer-up-action>
|
||||
<app-move-layer-down-action *ngIf="!projectService.isReadOnly(project)" [server]="server" [node]="node"></app-move-layer-down-action>
|
||||
</mat-menu>
|
||||
</div>
|
||||
|
@ -4,6 +4,7 @@ import { DomSanitizer } from "@angular/platform-browser";
|
||||
import { Node } from "../../cartography/shared/models/node";
|
||||
import { Server } from "../models/server";
|
||||
import { Project } from "../models/project";
|
||||
import { ProjectService } from "../services/project.service";
|
||||
|
||||
|
||||
@Component({
|
||||
@ -23,7 +24,8 @@ export class NodeContextMenuComponent implements OnInit {
|
||||
|
||||
constructor(
|
||||
private sanitizer: DomSanitizer,
|
||||
private changeDetector: ChangeDetectorRef) {}
|
||||
private changeDetector: ChangeDetectorRef,
|
||||
protected projectService: ProjectService) {}
|
||||
|
||||
ngOnInit() {
|
||||
this.setPosition(0, 0);
|
||||
|
@ -4,12 +4,21 @@ import { HttpClient } from '@angular/common/http';
|
||||
import { HttpTestingController, HttpClientTestingModule } from '@angular/common/http/testing';
|
||||
import { HttpServer } from './http-server.service';
|
||||
import { Server } from '../models/server';
|
||||
import { Node } from '../../cartography/shared/models/node';
|
||||
import { Port } from '../models/port';
|
||||
import { getTestServer } from './testing';
|
||||
import { Appliance } from '../models/appliance';
|
||||
import { Project } from '../models/project';
|
||||
import { ProjectService } from './project.service';
|
||||
import { SettingsService } from "./settings.service";
|
||||
import { MockedSettingsService } from "./settings.service.spec";
|
||||
|
||||
|
||||
/**
|
||||
* Mocks ProjectsService so it's not based on settings
|
||||
*/
|
||||
export class MockedProjectService {
|
||||
isReadOnly(project) {
|
||||
return project.readonly;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
describe('ProjectService', () => {
|
||||
let httpClient: HttpClient;
|
||||
@ -25,7 +34,8 @@ describe('ProjectService', () => {
|
||||
],
|
||||
providers: [
|
||||
HttpServer,
|
||||
ProjectService
|
||||
ProjectService,
|
||||
{ provide: SettingsService, useClass: MockedSettingsService }
|
||||
]
|
||||
});
|
||||
|
||||
|
@ -8,11 +8,13 @@ import { Link } from "../../cartography/shared/models/link";
|
||||
import { Server } from "../models/server";
|
||||
import { HttpServer } from "./http-server.service";
|
||||
import {Drawing} from "../../cartography/shared/models/drawing";
|
||||
import { SettingsService } from "./settings.service";
|
||||
|
||||
@Injectable()
|
||||
export class ProjectService {
|
||||
|
||||
constructor(private httpServer: HttpServer) { }
|
||||
constructor(private httpServer: HttpServer,
|
||||
private settingsService: SettingsService) { }
|
||||
|
||||
get(server: Server, project_id: string) {
|
||||
return this.httpServer
|
||||
@ -52,4 +54,11 @@ export class ProjectService {
|
||||
notificationsPath(server: Server, project_id: string): string {
|
||||
return `ws://${server.ip}:${server.port}/v2/projects/${project_id}/notifications/ws`;
|
||||
}
|
||||
|
||||
isReadOnly(project: Project) {
|
||||
if (project.readonly) {
|
||||
return project.readonly;
|
||||
}
|
||||
return !this.settingsService.isExperimentalEnabled();
|
||||
}
|
||||
}
|
||||
|
@ -5,6 +5,13 @@ import { Settings, SettingsService } from './settings.service';
|
||||
import createSpyObj = jasmine.createSpyObj;
|
||||
|
||||
|
||||
export class MockedSettingsService {
|
||||
isExperimentalEnabled() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
describe('SettingsService', () => {
|
||||
let persistenceService: PersistenceService;
|
||||
|
||||
@ -45,7 +52,8 @@ describe('SettingsService', () => {
|
||||
|
||||
it('should get all values', inject([SettingsService], (service: SettingsService) => {
|
||||
expect(service.getAll()).toEqual({
|
||||
'crash_reports': true
|
||||
'crash_reports': true,
|
||||
'experimental_features': false
|
||||
});
|
||||
}));
|
||||
|
||||
@ -53,10 +61,11 @@ describe('SettingsService', () => {
|
||||
const settings = {
|
||||
'crash_reports': false
|
||||
};
|
||||
service.setAll(settings)
|
||||
service.setAll(settings);
|
||||
|
||||
expect(service.getAll()).toEqual({
|
||||
'crash_reports': false
|
||||
'crash_reports': false,
|
||||
'experimental_features': false
|
||||
});
|
||||
}));
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user