Merge pull request #434 from GNS3/Moving-the-menu-code-from-the-project-map-component

Moving the menu code from the project map component #356
This commit is contained in:
ziajka 2019-06-29 07:50:04 +02:00 committed by GitHub
commit cfa5d02406
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 287 additions and 171 deletions

View File

@ -188,6 +188,7 @@ import { NodeCreatedLabelStylesFixer } from './components/project-map/helpers/no
import { NonNegativeValidator } from './validators/non-negative-validator';
import { RotationValidator } from './validators/rotation-validator';
import { MapSettingService } from './services/mapsettings.service';
import { ProjectMapMenuComponent } from './components/project-map/project-map-menu/project-map-menu.component';
import { HelpComponent } from './components/help/help.component';
if (environment.production) {
@ -308,6 +309,7 @@ if (environment.production) {
ConsoleDeviceActionComponent,
ConsoleComponent,
NodesMenuComponent,
ProjectMapMenuComponent,
HelpComponent
],
imports: [

View File

@ -0,0 +1,65 @@
<button
matTooltip="Add a note"
mat-icon-button
class="menu-button"
[color]="drawTools.isTextChosen ? 'primary' : 'basic'"
(click)="addDrawing('text')">
<mat-icon>create</mat-icon>
</button>
<input
type="file"
accept=".svg, .bmp, .jpeg, .jpg, .gif, .png"
class="non-visible"
#file
(change)="uploadImageFile($event)"/>
<button
matTooltip="Insert a picture"
mat-icon-button
class="menu-button"
(click)="file.click()">
<mat-icon>image</mat-icon>
</button>
<button
matTooltip="Draw a rectangle"
mat-icon-button
class="menu-button"
[color]="drawTools.isRectangleChosen ? 'primary' : 'basic'"
(click)="addDrawing('rectangle')">
<mat-icon>crop_3_2</mat-icon>
</button>
<button
matTooltip="Draw an ellipse"
mat-icon-button
class="menu-button"
[color]="drawTools.isEllipseChosen ? 'primary' : 'basic'"
(click)="addDrawing('ellipse')">
<mat-icon>panorama_fish_eye</mat-icon>
</button>
<button
matTooltip="Draw a line"
mat-icon-button class="menu-button"
(click)="addDrawing('line')">
<svg height="40" width="40">
<line
[ngClass]="{ selected: drawTools.isLineChosen }"
x1="30"
y1="10"
x2="10"
y2="30"
style="stroke:white;stroke-width:2"/>
</svg>
</button>
<button
matTooltip="Lock or unlock all items"
mat-icon-button
class="menu-button"
[color]="isLocked ? 'primary' : 'basic'"
(click)="changeLockValue()">
<mat-icon>lock</mat-icon>
</button>
<app-drawing-added
[server]="server"
[project]="project"
[selectedDrawing]="selectedDrawing"
(drawingSaved)="onDrawingSaved()">
</app-drawing-added>

View File

@ -0,0 +1,24 @@
.menu-button {
outline: 0 !important;
transition: 0.5s;
margin-bottom: 16px;
width: 40px;
margin-right: 12px !important;
margin-left: 12px !important;
background: #263238;
padding: 0;
border: none;
background-color: transparent;
}
mat-divider.divider {
height: 40px;
margin-left: 1px;
margin-right: 7px;
width: 10px;
color: gray;
}
.non-visible {
display: none;
}

View File

@ -0,0 +1,67 @@
import { ProjectMapMenuComponent } from "./project-map-menu.component";
import { ComponentFixture, async, TestBed } from '@angular/core/testing';
import { MockedDrawingService } from '../project-map.component.spec';
import { MapSettingService } from '../../../services/mapsettings.service';
import { MatIconModule, MatToolbarModule, MatMenuModule, MatCheckboxModule } from '@angular/material';
import { CommonModule } from '@angular/common';
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
import { DrawingService } from '../../../services/drawing.service';
import { ToolsService } from '../../../services/tools.service';
import { D3MapComponent } from '../../../cartography/components/d3-map/d3-map.component';
import { ANGULAR_MAP_DECLARATIONS } from '../../../cartography/angular-map.imports';
import { NO_ERRORS_SCHEMA } from '@angular/core';
describe('ProjectMapMenuComponent', () => {
let component: ProjectMapMenuComponent;
let fixture: ComponentFixture<ProjectMapMenuComponent>;
let drawingService = new MockedDrawingService();
let mapSettingService = new MapSettingService();
beforeEach(async(() => {
TestBed.configureTestingModule({
imports: [MatIconModule, MatToolbarModule, MatMenuModule, MatCheckboxModule, CommonModule, NoopAnimationsModule],
providers: [
{ provide: DrawingService, useValue: drawingService },
{ provide: ToolsService },
{ provide: MapSettingService, useValue: mapSettingService }
],
declarations: [ProjectMapMenuComponent, D3MapComponent, ...ANGULAR_MAP_DECLARATIONS],
schemas: [NO_ERRORS_SCHEMA]
}).compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(ProjectMapMenuComponent);
component = fixture.componentInstance;
});
it('should create', () => {
expect(component).toBeTruthy();
});
it('should reset choice on draw menu after saving drawing', () => {
spyOn(component, 'resetDrawToolChoice');
component.onDrawingSaved();
expect(component.resetDrawToolChoice).toHaveBeenCalled();
});
it('should call map settings service when lock value was changed', () => {
spyOn(mapSettingService, 'changeMapLockValue');
component.changeLockValue();
expect(mapSettingService.changeMapLockValue).toHaveBeenCalled();
});
it('should call map settings service with proper value', () => {
spyOn(mapSettingService, 'changeMapLockValue');
component.changeLockValue();
expect(mapSettingService.changeMapLockValue).toHaveBeenCalledWith(true);
component.changeLockValue();
expect(mapSettingService.changeMapLockValue).toHaveBeenCalledWith(false);
});
});

View File

@ -0,0 +1,110 @@
import { Component, OnInit, OnDestroy, Input } from '@angular/core';
import { Project } from '../../../models/project';
import { Server } from '../../../models/server';
import { ToolsService } from '../../../services/tools.service';
import { MapSettingService } from '../../../services/mapsettings.service';
import { DrawingService } from '../../../services/drawing.service';
@Component({
selector: 'app-project-map-menu',
templateUrl: './project-map-menu.component.html',
styleUrls: ['./project-map-menu.component.scss']
})
export class ProjectMapMenuComponent implements OnInit, OnDestroy {
@Input() project: Project;
@Input() server: Server;
public selectedDrawing: string;
public drawTools = {
isRectangleChosen: false,
isEllipseChosen: false,
isLineChosen: false,
isTextChosen: false
};
public isLocked: boolean = false;
constructor(
private toolsService: ToolsService,
private mapSettingsService: MapSettingService,
private drawingService: DrawingService
) {}
ngOnInit() {}
public addDrawing(selectedObject: string) {
switch (selectedObject) {
case 'rectangle':
this.drawTools.isTextChosen = false;
this.drawTools.isEllipseChosen = false;
this.drawTools.isRectangleChosen = !this.drawTools.isRectangleChosen;
this.drawTools.isLineChosen = false;
break;
case 'ellipse':
this.drawTools.isTextChosen = false;
this.drawTools.isEllipseChosen = !this.drawTools.isEllipseChosen;
this.drawTools.isRectangleChosen = false;
this.drawTools.isLineChosen = false;
break;
case 'line':
this.drawTools.isTextChosen = false;
this.drawTools.isEllipseChosen = false;
this.drawTools.isRectangleChosen = false;
this.drawTools.isLineChosen = !this.drawTools.isLineChosen;
break;
case 'text':
this.drawTools.isTextChosen = !this.drawTools.isTextChosen;
this.drawTools.isEllipseChosen = false;
this.drawTools.isRectangleChosen = false;
this.drawTools.isLineChosen = false;
this.toolsService.textAddingToolActivation(this.drawTools.isTextChosen);
break;
}
this.selectedDrawing = this.selectedDrawing === selectedObject ? '' : selectedObject;
}
public onDrawingSaved() {
this.resetDrawToolChoice();
}
public resetDrawToolChoice() {
this.drawTools.isRectangleChosen = false;
this.drawTools.isEllipseChosen = false;
this.drawTools.isLineChosen = false;
this.drawTools.isTextChosen = false;
this.selectedDrawing = '';
this.toolsService.textAddingToolActivation(this.drawTools.isTextChosen);
}
public changeLockValue() {
this.isLocked = !this.isLocked;
this.mapSettingsService.changeMapLockValue(this.isLocked);
}
public uploadImageFile(event) {
this.readImageFile(event.target);
}
private readImageFile(fileInput) {
let file: File = fileInput.files[0];
let fileReader: FileReader = new FileReader();
let imageToUpload = new Image();
fileReader.onloadend = () => {
let image = fileReader.result;
let svg = this.createSvgFileForImage(image, imageToUpload);
this.drawingService.add(this.server, this.project.project_id, -(imageToUpload.width/2), -(imageToUpload.height/2), svg).subscribe(() => {});
}
imageToUpload.onload = () => { fileReader.readAsDataURL(file) };
imageToUpload.src = window.URL.createObjectURL(file);
}
private createSvgFileForImage(image: string|ArrayBuffer, imageToUpload: HTMLImageElement) {
return `<svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" height=\"${imageToUpload.height}\"
width=\"${imageToUpload.width}\">\n<image height=\"${imageToUpload.height}\" width=\"${imageToUpload.width}\" xlink:href=\"${image}\"/>\n</svg>`
}
ngOnDestroy() {}
}

View File

@ -87,77 +87,14 @@
</mat-toolbar>
</div>
<div id="show-menu-wrapper" [ngClass]="{ shadowed: !drawTools.visibility }" *ngIf="!readonly">
<div id="show-menu-wrapper" [ngClass]="{ shadowed: !isProjectMapMenuVisible }" *ngIf="!readonly">
<button class="arrow-button" mat-icon-button (click)="showMenu()"><mat-icon>keyboard_arrow_right</mat-icon></button>
</div>
<div id="menu-wrapper" [ngClass]="{ extended: drawTools.visibility }">
<div id="menu-wrapper" [ngClass]="{ extended: isProjectMapMenuVisible }">
<app-nodes-menu [server]="server" [project]="project"></app-nodes-menu>
<mat-divider class="divider" [vertical]="true"></mat-divider>
<button
matTooltip="Add a note"
mat-icon-button
class="menu-button"
[color]="drawTools.isTextChosen ? 'primary' : 'basic'"
(click)="addDrawing('text')"
>
<mat-icon>create</mat-icon>
</button>
<input
type="file"
accept=".svg, .bmp, .jpeg, .jpg, .gif, .png"
class="non-visible"
#file
(change)="uploadImageFile($event)"
/>
<button
matTooltip="Insert a picture"
mat-icon-button
class="menu-button"
(click)="file.click()"
>
<mat-icon>image</mat-icon>
</button>
<button
matTooltip="Draw a rectangle"
mat-icon-button
class="menu-button"
[color]="drawTools.isRectangleChosen ? 'primary' : 'basic'"
(click)="addDrawing('rectangle')"
>
<mat-icon>crop_3_2</mat-icon>
</button>
<button
matTooltip="Draw an ellipse"
mat-icon-button
class="menu-button"
[color]="drawTools.isEllipseChosen ? 'primary' : 'basic'"
(click)="addDrawing('ellipse')"
>
<mat-icon>panorama_fish_eye</mat-icon>
</button>
<button matTooltip="Draw a line" mat-icon-button class="menu-button" (click)="addDrawing('line')">
<svg height="40" width="40">
<line
[ngClass]="{ selected: drawTools.isLineChosen }"
x1="30"
y1="10"
x2="10"
y2="30"
style="stroke:white;stroke-width:2"
/>
</svg>
</button>
<mat-divider class="divider" [vertical]="true"></mat-divider>
<button
matTooltip="Lock or unlock all items"
mat-icon-button
class="menu-button"
[color]="isLocked ? 'primary' : 'basic'"
(click)="changeLockValue()"
>
<mat-icon>lock</mat-icon>
</button>
<app-project-map-menu [server]="server" [project]="project"></app-project-map-menu>
<button class="arrow-button" mat-icon-button (click)="hideMenu()"><mat-icon>keyboard_arrow_left</mat-icon></button>
</div>
@ -171,18 +108,9 @@
</div>
<app-progress></app-progress>
<app-project-map-shortcuts *ngIf="project" [project]="project" [server]="server"> </app-project-map-shortcuts>
<app-project-map-shortcuts *ngIf="project" [project]="project" [server]="server"></app-project-map-shortcuts>
<app-draw-link-tool [links]="links" *ngIf="tools.draw_link"></app-draw-link-tool>
<app-drawing-added
[server]="server"
[project]="project"
[selectedDrawing]="selectedDrawing"
(drawingSaved)="onDrawingSaved()"
>
</app-drawing-added>
<app-drawing-dragged [server]="server"></app-drawing-dragged>
<app-drawing-resized [server]="server"></app-drawing-resized>
<app-interface-label-dragged [server]="server"></app-interface-label-dragged>

View File

@ -46,6 +46,7 @@ import { LinkWidget } from '../../cartography/widgets/link';
import { MapScaleService } from '../../services/mapScale.service';
import { NodeCreatedLabelStylesFixer } from './helpers/node-created-label-styles-fixer';
import { MapSettingService } from '../../services/mapsettings.service';
import { ProjectMapMenuComponent } from './project-map-menu/project-map-menu.component';
export class MockedProgressService {
public activate() {}
@ -187,7 +188,6 @@ describe('ProjectMapComponent', () => {
let nodesDataSource = new MockedNodesDataSource();
let linksDataSource = new MockedLinksDataSource();
let nodeCreatedLabelStylesFixer;
let mapSettingService = new MapSettingService();
beforeEach(async(() => {
nodeCreatedLabelStylesFixer = {
@ -226,11 +226,10 @@ describe('ProjectMapComponent', () => {
useClass: RecentlyOpenedProjectService
},
{ provide: NodeCreatedLabelStylesFixer, useValue: nodeCreatedLabelStylesFixer},
{ provide: MapSettingService, useValue: mapSettingService },
{ provide: MapScaleService },
{ provide: NodeCreatedLabelStylesFixer, useValue: nodeCreatedLabelStylesFixer}
],
declarations: [ProjectMapComponent, D3MapComponent, ...ANGULAR_MAP_DECLARATIONS],
declarations: [ProjectMapComponent, ProjectMapMenuComponent, D3MapComponent, ...ANGULAR_MAP_DECLARATIONS],
schemas: [NO_ERRORS_SCHEMA]
}).compileComponents();
}));
@ -238,6 +237,9 @@ describe('ProjectMapComponent', () => {
beforeEach(() => {
fixture = TestBed.createComponent(ProjectMapComponent);
component = fixture.componentInstance;
component.projectMapMenuComponent = {
resetDrawToolChoice(){}
} as ProjectMapMenuComponent;
});
afterEach(() => {
@ -253,36 +255,10 @@ describe('ProjectMapComponent', () => {
document.getElementsByClassName = jasmine.createSpy('HTML element').and.callFake(() => {
return [dummyElement];
});
spyOn(component, 'resetDrawToolChoice');
spyOn(component.projectMapMenuComponent, 'resetDrawToolChoice').and.returnValue();
component.hideMenu();
expect(component.resetDrawToolChoice).toHaveBeenCalled();
});
it('should reset choice on draw menu after saving drawing', () => {
spyOn(component, 'resetDrawToolChoice');
component.onDrawingSaved();
expect(component.resetDrawToolChoice).toHaveBeenCalled();
});
it('should call map settings service when lock value was changed', () => {
spyOn(mapSettingService, 'changeMapLockValue');
component.changeLockValue();
expect(mapSettingService.changeMapLockValue).toHaveBeenCalled();
});
it('should call map settings service with proper value', () => {
spyOn(mapSettingService, 'changeMapLockValue');
component.changeLockValue();
expect(mapSettingService.changeMapLockValue).toHaveBeenCalledWith(true);
component.changeLockValue();
expect(mapSettingService.changeMapLockValue).toHaveBeenCalledWith(false);
expect(component.projectMapMenuComponent.resetDrawToolChoice).toHaveBeenCalled();
});
});

View File

@ -46,7 +46,7 @@ import { MovingEventSource } from '../../cartography/events/moving-event-source'
import { LinkWidget } from '../../cartography/widgets/link';
import { MapScaleService } from '../../services/mapScale.service';
import { NodeCreatedLabelStylesFixer } from './helpers/node-created-label-styles-fixer';
import { MapSettingService } from '../../services/mapsettings.service';
import { ProjectMapMenuComponent } from './project-map-menu/project-map-menu.component';
@Component({
@ -62,8 +62,8 @@ export class ProjectMapComponent implements OnInit, OnDestroy {
public symbols: Symbol[] = [];
public project: Project;
public server: Server;
public selectedDrawing: string;
private ws: Subject<any>;
public isProjectMapMenuVisible: boolean = false;
tools = {
selection: true,
@ -73,20 +73,11 @@ export class ProjectMapComponent implements OnInit, OnDestroy {
};
protected settings: Settings;
protected drawTools = {
isRectangleChosen: false,
isEllipseChosen: false,
isLineChosen: false,
isTextChosen: false,
visibility: false
};
protected isLocked: boolean = false;
private inReadOnlyMode = false;
@ViewChild(ContextMenuComponent) contextMenu: ContextMenuComponent;
@ViewChild(D3MapComponent) mapChild: D3MapComponent;
@ViewChild(ProjectMapMenuComponent) projectMapMenuComponent: ProjectMapMenuComponent;
private subscriptions: Subscription[] = [];
@ -114,7 +105,6 @@ export class ProjectMapComponent implements OnInit, OnDestroy {
private selectionManager: SelectionManager,
private selectionTool: SelectionTool,
private recentlyOpenedProjectService: RecentlyOpenedProjectService,
private mapSettingsService: MapSettingService,
private movingEventSource: MovingEventSource,
private mapScaleService: MapScaleService,
private nodeCreatedLabelStylesFixer: NodeCreatedLabelStylesFixer
@ -307,7 +297,7 @@ export class ProjectMapComponent implements OnInit, OnDestroy {
}
public onDrawingSaved() {
this.resetDrawToolChoice();
this.projectMapMenuComponent.resetDrawToolChoice();
}
public set readonly(value) {
@ -344,54 +334,13 @@ export class ProjectMapComponent implements OnInit, OnDestroy {
this.project.show_interface_labels = enabled;
}
public addDrawing(selectedObject: string) {
switch (selectedObject) {
case 'rectangle':
this.drawTools.isTextChosen = false;
this.drawTools.isEllipseChosen = false;
this.drawTools.isRectangleChosen = !this.drawTools.isRectangleChosen;
this.drawTools.isLineChosen = false;
break;
case 'ellipse':
this.drawTools.isTextChosen = false;
this.drawTools.isEllipseChosen = !this.drawTools.isEllipseChosen;
this.drawTools.isRectangleChosen = false;
this.drawTools.isLineChosen = false;
break;
case 'line':
this.drawTools.isTextChosen = false;
this.drawTools.isEllipseChosen = false;
this.drawTools.isRectangleChosen = false;
this.drawTools.isLineChosen = !this.drawTools.isLineChosen;
break;
case 'text':
this.drawTools.isTextChosen = !this.drawTools.isTextChosen;
this.drawTools.isEllipseChosen = false;
this.drawTools.isRectangleChosen = false;
this.drawTools.isLineChosen = false;
this.toolsService.textAddingToolActivation(this.drawTools.isTextChosen);
break;
}
this.selectedDrawing = this.selectedDrawing === selectedObject ? '' : selectedObject;
}
public resetDrawToolChoice() {
this.drawTools.isRectangleChosen = false;
this.drawTools.isEllipseChosen = false;
this.drawTools.isLineChosen = false;
this.drawTools.isTextChosen = false;
this.selectedDrawing = '';
this.toolsService.textAddingToolActivation(this.drawTools.isTextChosen);
}
public hideMenu() {
this.resetDrawToolChoice();
this.drawTools.visibility = false;
this.projectMapMenuComponent.resetDrawToolChoice()
this.isProjectMapMenuVisible = false;
}
public showMenu() {
this.drawTools.visibility = true;
this.isProjectMapMenuVisible = true;
}
zoomIn() {
@ -431,11 +380,6 @@ export class ProjectMapComponent implements OnInit, OnDestroy {
imageToUpload.src = window.URL.createObjectURL(file);
}
public changeLockValue() {
this.isLocked = !this.isLocked;
this.mapSettingsService.changeMapLockValue(this.isLocked);
}
public ngOnDestroy() {
this.drawingsDataSource.clear();
this.nodesDataSource.clear();