Merge pull request #1157 from GNS3/master-2.2.22

Version 2.2.22
This commit is contained in:
piotrpekala7 2021-05-28 13:20:14 +02:00 committed by GitHub
commit 354b313eaa
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
22 changed files with 3513 additions and 4859 deletions

View File

@ -28,7 +28,6 @@
"classnames",
"stylenames"
],
"aot": true,
"outputPath": "dist",
"index": "src/index.html",
"main": "src/main.ts",
@ -45,7 +44,13 @@
"src/styles.scss",
"src/theme.scss"
],
"scripts": []
"scripts": [],
"vendorChunk": true,
"extractLicenses": false,
"buildOptimizer": false,
"sourceMap": true,
"optimization": false,
"namedChunks": true
},
"configurations": {
"production": {
@ -63,7 +68,6 @@
"styles": false
},
"namedChunks": false,
"aot": true,
"extractLicenses": true,
"vendorChunk": false,
"buildOptimizer": true,
@ -85,7 +89,6 @@
"outputHashing": "all",
"sourceMap": false,
"namedChunks": false,
"aot": true,
"extractLicenses": true,
"vendorChunk": false,
"buildOptimizer": true,
@ -121,7 +124,6 @@
"outputHashing": "all",
"sourceMap": false,
"namedChunks": false,
"aot": true,
"extractLicenses": true,
"vendorChunk": false,
"buildOptimizer": true,

View File

@ -41,16 +41,16 @@
},
"private": true,
"dependencies": {
"@angular/animations": "^11.2.13",
"@angular/cdk": "^11.2.12",
"@angular/common": "^11.2.13",
"@angular/compiler": "^11.2.13",
"@angular/core": "^11.2.13",
"@angular/forms": "^11.2.13",
"@angular/material": "^11.2.12",
"@angular/platform-browser": "^11.2.13",
"@angular/platform-browser-dynamic": "^11.2.13",
"@angular/router": "^11.2.13",
"@angular/animations": "^12.0.2",
"@angular/cdk": "^12.0.2",
"@angular/common": "^12.0.2",
"@angular/compiler": "^12.0.2",
"@angular/core": "^12.0.2",
"@angular/forms": "^12.0.2",
"@angular/material": "^12.0.2",
"@angular/platform-browser": "^12.0.2",
"@angular/platform-browser-dynamic": "^12.0.2",
"@angular/router": "^12.0.2",
"@sentry/browser": "^6.3.6",
"@types/jest": "^26.0.23",
"@types/mocha": "^8.2.2",
@ -58,7 +58,6 @@
"@types/react-dom": "^17.0.3",
"angular-draggable-droppable": "^4.6.0",
"angular-resizable-element": "^3.3.5",
"angular2-indexeddb": "^1.2.3",
"bootstrap": "^5.0.0",
"command-exists": "^1.2.9",
"core-js": "^3.12.1",
@ -75,8 +74,8 @@
"node-fetch": "^2.6.1",
"notosans-fontface": "1.2.2",
"prettier-plugin-organize-imports": "^2.0.0",
"rxjs": "^6.6.7",
"rxjs-compat": "^6.6.7",
"rxjs": "^6.5.3",
"rxjs-compat": "^6.5.3",
"save-svg-as-png": "^1.4.17",
"snyk": "^1.589.0",
"spark-md5": "^3.0.1",
@ -88,21 +87,21 @@
"xterm-addon-attach": "^0.6.0",
"xterm-addon-fit": "^0.5.0",
"yargs": "^17.0.1",
"zone.js": "^0.11.4"
"zone.js": "~0.11.4"
},
"devDependencies": {
"@angular-devkit/build-angular": "^0.1102.12",
"@angular/cli": "^11.2.12",
"@angular/compiler-cli": "^11.2.13",
"@angular/language-service": "^11.2.13",
"@angular-devkit/build-angular": "^12.0.2",
"@angular/cli": "^12.0.2",
"@angular/compiler-cli": "^12.0.2",
"@angular/language-service": "^12.0.2",
"@sentry/cli": "^1.64.2",
"@sentry/electron": "^2.4.1",
"@types/jasmine": "^3.7.1",
"@types/jasminewd2": "^2.0.9",
"@types/node": "15.0.2",
"@types/node": "15.6.1",
"codelyzer": "^6.0.2",
"electron": "^12.0.7",
"electron-builder": "22.11.1",
"electron": "^13.0.1",
"electron-builder": "22.10.5",
"file-loader": "^6.2.0",
"jasmine-core": "~3.7.1",
"jasmine-spec-reporter": "~7.0.0",
@ -120,11 +119,11 @@
"replace": "^1.2.1",
"rxjs-tslint": "^0.1.8",
"ts-mockito": "^2.6.1",
"ts-node": "~9.1.1",
"ts-node": "~10.0.0",
"tslint": "^6.1.3",
"tslint-config-prettier": "^1.18.0",
"typescript": "4.0.2",
"webpack": "5.36.2",
"typescript": "4.2.4",
"webpack": "5.38.0",
"yarn-upgrade-all": "^0.5.4"
},
"greenkeeper": {

View File

@ -225,7 +225,6 @@ import { ExternalSoftwareDefinitionService } from './services/external-software-
import { Gns3vmService } from './services/gns3vm.service';
import { GoogleAnalyticsService } from './services/google-analytics.service';
import { HttpServer, ServerErrorHandler } from './services/http-server.service';
import { IndexedDbService } from './services/indexed-db.service';
import { InfoService } from './services/info.service';
import { InstalledSoftwareService } from './services/installed-software.service';
import { IosConfigurationService } from './services/ios-configuration.service';
@ -488,7 +487,6 @@ import { RotationValidator } from './validators/rotation-validator';
NodeService,
LinkService,
DrawingService,
IndexedDbService,
HttpServer,
SnapshotService,
ProgressDialogService,

View File

@ -26,9 +26,7 @@ export class DrawingComponent implements OnInit {
ngOnInit() {
try {
this.drawing.element = this.svgToDrawingConverter.convert(this.drawing.svg);
} catch (error) {
console.log(`Cannot convert due to Error: '${error}'`);
}
} catch (error) {}
}
OnDragging(evt) {

View File

@ -44,9 +44,7 @@ export class DrawingsWidget implements Widget {
layer.drawings.forEach((d: MapDrawing) => {
try {
d.element = this.svgToDrawingConverter.convert(d.svg);
} catch (error) {
console.log(`Cannot convert due to Error: '${error}'`);
}
} catch (error) {}
});
return layer.drawings;
},
@ -81,9 +79,7 @@ export class DrawingsWidget implements Widget {
.on('start', (datum: MapDrawing) => {
document.body.style.cursor = 'ns-resize';
topEdge = datum.y;
console.log('started');
y = event.sourceEvent.clientY - this.context.getZeroZeroTransformationPoint().y;
// startEvent = event;
})
.on('drag', (datum: MapDrawing) => {
const evt = event;
@ -91,55 +87,10 @@ export class DrawingsWidget implements Widget {
y = event.sourceEvent.clientY - this.context.getZeroZeroTransformationPoint().y;
let height = datum.element.height - dy;
if (height < 0) {
// height = datum.y - startEvent.y;
datum.y += height;
height = topEdge - datum.y;
// console.log(topEdge - datum.y);
}
console.log('Height', height);
datum.element.height = height;
// datum.element.height -= dy;
// if(datum.element.height < 0) {
// datum.y -= datum.element.height;
// datum.element.height = Math.abs(datum.element.height);
// }
// if (!isReflectedVertical) {
// if ((datum.element.height + evt.dy) < 0) {
// isReflectedVertical = true;
// y = topEdge;
// console.log(y);
// datum.element.height = Math.abs(datum.element.height + evt.dy);
// console.log(datum.element.height);
// } else {
// datum.element.height += evt.dy;
// if (datum.element instanceof EllipseElement){
// (datum.element as EllipseElement).cy = (datum.element as EllipseElement).cy + evt.dy/2 < 0 ? 1 : (datum.element as EllipseElement).cy += evt.dy/2;
// (datum.element as EllipseElement).ry = (datum.element as EllipseElement).ry + evt.dy/2 < 0 ? 1 : (datum.element as EllipseElement).ry += evt.dy/2;
// }
// }
// } else {
// dy = y - (evt.sourceEvent.clientY - this.context.getZeroZeroTransformationPoint().y);
// y = evt.sourceEvent.clientY - this.context.getZeroZeroTransformationPoint().y;
// if ((datum.element.height + dy) < 0){
// isReflectedVertical = false;
// y = topEdge;
// console.log(y);
// datum.element.height = Math.abs(datum.element.height + evt.dy);
// console.log(datum.element.height);
// } else {
// datum.y = evt.sourceEvent.clientY - this.context.getZeroZeroTransformationPoint().y;
// datum.element.height += dy;
// if (datum.element instanceof EllipseElement) {
// (datum.element as EllipseElement).cy = (datum.element as EllipseElement).cy + dy/2 < 0 ? 1 : (datum.element as EllipseElement).cy += dy/2;
// (datum.element as EllipseElement).ry = (datum.element as EllipseElement).ry + dy/2 < 0 ? 1 : (datum.element as EllipseElement).ry += dy/2;
// }
// }
// }
this.redrawDrawing(view, datum);
})
.on('end', (datum: MapDrawing) => {

View File

@ -46,9 +46,7 @@ export class DrawingsWidget implements Widget {
layer.drawings.forEach((d: MapDrawing) => {
try {
d.element = this.svgToDrawingConverter.convert(d.svg);
} catch (error) {
console.log(`Cannot convert due to Error: '${error}'`);
}
} catch (error) {}
});
return layer.drawings;
},

View File

@ -66,7 +66,6 @@ export class DirectLinkComponent implements OnInit {
const servers = await this.serverService.findAll();
const server = servers.filter((server) => server.host === this.serverIp && server.port === this.serverPort)[0];
console.log(servers);
if (server) {
this.router.navigate(['/server', server.id, 'project', this.projectId]);
} else {

View File

@ -31,8 +31,6 @@
</mat-expansion-panel>
</mat-accordion>
</div>
<button mat-button class="full-width">
<a href="https://docs.gns3.com/docs/"> Go to documentation </a>
</button>
<button mat-button color="primary" class="full-width" (click)="goToDocumentation()">Go to documentation</button>
</div>
</div>

View File

@ -1,4 +1,4 @@
.full-width {
width: 50%;
width: 100%;
margin-top: 20px;
}

View File

@ -28,4 +28,8 @@ export class HelpComponent implements OnInit {
this.releasenotes = data.replace(new RegExp('\n', 'g'), '<br />');
});
}
goToDocumentation() {
window.location.href = "https://docs.gns3.com/docs/";
}
}

View File

@ -18,9 +18,7 @@ export class CustomAdaptersComponent {
public adapters: CustomAdapter[];
public numberOfAdapters: number;
constructor() {
console.log(this.networkTypes);
}
constructor() {}
cancelConfigureCustomAdapters() {
this.closeConfiguratorEmitter.emit(false);
@ -28,8 +26,6 @@ export class CustomAdaptersComponent {
configureCustomAdapters() {
this.adapters = [];
console.log(this.customAdapters);
this.customAdapters.adapters.forEach((n) => {
this.adapters.push({
adapter_number: n.adapter_number,

View File

@ -1,20 +0,0 @@
import { inject, TestBed } from '@angular/core/testing';
import { IndexedDbService } from './indexed-db.service';
describe('IndexedDbService', () => {
beforeEach(() => {
TestBed.configureTestingModule({
providers: [IndexedDbService],
});
});
it('should be created', inject([IndexedDbService], (service: IndexedDbService) => {
expect(service).toBeTruthy();
}));
it('should get AngularIndexedDB', inject([IndexedDbService], (service: IndexedDbService) => {
const indexeddb = service.get();
expect(indexeddb.dbWrapper.dbName).toEqual(IndexedDbService.DATABASE);
expect(indexeddb.dbWrapper.dbVersion).toEqual(IndexedDbService.VERSION);
}));
});

View File

@ -1,18 +0,0 @@
import { Injectable } from '@angular/core';
import { AngularIndexedDB } from 'angular2-indexeddb';
@Injectable()
export class IndexedDbService {
static VERSION = 1;
static DATABASE = 'gns3-web-ui';
private db: AngularIndexedDB;
constructor() {
this.db = new AngularIndexedDB(IndexedDbService.DATABASE, IndexedDbService.VERSION);
}
public get() {
return this.db;
}
}

View File

@ -1,12 +1,4 @@
import { HttpClient } from '@angular/common/http';
import { TestBed } from '@angular/core/testing';
import { AngularIndexedDB } from 'angular2-indexeddb';
import { Server } from '../models/server';
import { HttpServer, ServerErrorHandler } from '../services/http-server.service';
import { IndexedDbService } from './indexed-db.service';
import { ServerService } from './server.service';
import Spy = jasmine.Spy;
export class MockedServerService {
public servers: Server[] = [];
@ -42,138 +34,3 @@ export class MockedServerService {
return `${server.host}:${server.port}`;
}
}
describe('ServerService', () => {
let indexedDbService: IndexedDbService;
let db: AngularIndexedDB;
let service: ServerService;
let openDatabaseSpy: Spy;
let httpServer = new HttpServer({} as HttpClient, {} as ServerErrorHandler);
beforeEach(() => {
indexedDbService = new IndexedDbService();
db = indexedDbService.get();
openDatabaseSpy = spyOn(db, 'openDatabase').and.returnValue(Promise.resolve(true));
TestBed.configureTestingModule({
providers: [
ServerService,
{ provide: IndexedDbService, useValue: indexedDbService },
{ provide: HttpServer, useValue: httpServer },
],
});
service = TestBed.get(ServerService);
});
it('should be created and create database', () => {
expect(service).toBeTruthy();
expect(db.openDatabase).toHaveBeenCalled();
expect(openDatabaseSpy.calls.first().args[0]).toEqual(1);
const evnt = {
currentTarget: {
result: {
createObjectStore: function () {},
},
},
};
spyOn(evnt.currentTarget.result, 'createObjectStore');
const upgradeCallback = openDatabaseSpy.calls.first().args[1];
upgradeCallback(evnt);
expect(evnt.currentTarget.result.createObjectStore).toHaveBeenCalled();
});
describe('operations on records', () => {
let record: any;
beforeEach(() => {
record = new Server();
record.name = 'test';
});
it('should create an object', (done) => {
const created = new Server();
created.id = 22;
spyOn(db, 'add').and.returnValue(Promise.resolve(created));
service.create(record).then((result) => {
expect(db.add).toHaveBeenCalledWith('servers', record);
done();
});
});
it('should update an object', (done) => {
spyOn(db, 'update').and.returnValue(Promise.resolve(record));
service.update(record).then((result) => {
expect(db.update).toHaveBeenCalledWith('servers', record);
expect(result).toEqual(record);
done();
});
});
it('should delete an object', (done) => {
record.id = 88;
spyOn(db, 'delete').and.returnValue(Promise.resolve());
service.delete(record).then(() => {
expect(db.delete).toHaveBeenCalledWith('servers', record.id);
done();
});
});
});
it('should call findAll', (done) => {
spyOn(db, 'getAll').and.returnValue(Promise.resolve([]));
service.findAll().then((result) => {
expect(result).toEqual([]);
expect(db.getAll).toHaveBeenCalledWith('servers');
done();
});
});
it('should create local server when missing', (done) => {
spyOn(db, 'getAll').and.returnValue(Promise.resolve([]));
spyOn(service, 'create').and.returnValue(Promise.resolve(new Server()));
const expectedServer = new Server();
expectedServer.name = 'local';
expectedServer.host = 'hostname';
expectedServer.port = 9999;
expectedServer.location = 'bundled';
expectedServer.protocol = 'http:';
service.getLocalServer('hostname', 9999).then(() => {
expect(service.create).toHaveBeenCalledWith(expectedServer);
done();
});
});
it('should update local server when found', (done) => {
const server = new Server();
server.name = 'local';
server.host = 'hostname';
server.port = 9999;
server.location = 'bundled';
spyOn(db, 'getAll').and.returnValue(Promise.resolve([server]));
spyOn(service, 'update').and.returnValue(Promise.resolve(new Server()));
service.getLocalServer('hostname-2', 11111).then(() => {
server.host = 'hostname-2';
server.port = 11111;
expect(service.update).toHaveBeenCalledWith(server);
done();
});
});
});

View File

@ -2,58 +2,33 @@ import { Injectable } from '@angular/core';
import { Observable, Subject } from 'rxjs';
import { Server, ServerProtocol } from '../models/server';
import { HttpServer } from './http-server.service';
import { IndexedDbService } from './indexed-db.service';
@Injectable()
export class ServerService {
private tablename = 'servers';
private ready: Promise<any>;
private isIncognitoMode: boolean = false;
private serverIdsInIncognitoMode: string[] = [];
private serverIds: string[] = [];
public serviceInitialized: Subject<boolean> = new Subject<boolean>();
public isServiceInitialized: boolean;
constructor(private indexedDbService: IndexedDbService, private httpServer: HttpServer) {
this.ready = this.indexedDbService
.get()
.openDatabase(1, (evt) => {
evt.currentTarget.result.createObjectStore(this.tablename, { keyPath: 'id', autoIncrement: true });
})
.then(() => {
this.indexedDbService
.get()
.getAll(this.tablename)
.then(() => {})
.catch(() => {
this.isIncognitoMode = true;
});
})
.catch(() => {
this.isIncognitoMode = true;
})
.finally(() => {
constructor(private httpServer: HttpServer) {
this.serverIds = this.getServerIds();
this.isServiceInitialized = true;
this.serviceInitialized.next(true);
});
this.serviceInitialized.next(this.isServiceInitialized);
}
public tryToCreateDb() {
let promise = new Promise((resolve) => {
this.indexedDbService
.get()
.openDatabase(1, (evt) => {
evt.currentTarget.result.createObjectStore(this.tablename, { keyPath: 'id', autoIncrement: true });
})
.then(() => {})
.catch(() => {
this.isIncognitoMode = true;
});
});
return promise;
getServerIds() : string[]{
let str = localStorage.getItem("serverIds");
if (str?.length > 0) {
return str.split(",");
}
return [];
}
updateServerIds() {
localStorage.removeItem("serverIds");
localStorage.setItem("serverIds", this.serverIds.toString());
}
public get(id: number): Promise<Server> {
if (this.isIncognitoMode) {
let server: Server = JSON.parse(localStorage.getItem(`server-${id}`));
let promise = new Promise<Server>((resolve) => {
resolve(server);
@ -61,14 +36,12 @@ export class ServerService {
return promise;
}
return this.onReady(() => this.indexedDbService.get().getByKey(this.tablename, id)) as Promise<Server>;
}
public create(server: Server) {
if (this.isIncognitoMode) {
server.id = this.serverIdsInIncognitoMode.length + 1;
server.id = this.serverIds.length + 1;
localStorage.setItem(`server-${server.id}`, JSON.stringify(server));
this.serverIdsInIncognitoMode.push(`server-${server.id}`);
this.serverIds.push(`server-${server.id}`);
this.updateServerIds();
let promise = new Promise<Server>((resolve) => {
resolve(server);
@ -76,22 +49,7 @@ export class ServerService {
return promise;
}
return this.onReady(() => {
const promise = new Promise((resolve, reject) => {
this.indexedDbService
.get()
.add(this.tablename, server)
.then((added) => {
server.id = added.key;
resolve(server);
}, reject);
});
return promise;
});
}
public update(server: Server) {
if (this.isIncognitoMode) {
localStorage.removeItem(`server-${server.id}`);
localStorage.setItem(`server-${server.id}`, JSON.stringify(server));
@ -101,24 +59,10 @@ export class ServerService {
return promise;
}
return this.onReady(() => {
const promise = new Promise((resolve, reject) => {
this.indexedDbService
.get()
.update(this.tablename, server)
.then((updated) => {
resolve(server);
}, reject);
});
return promise;
});
}
public findAll() {
if (this.isIncognitoMode) {
let promise = new Promise<Server[]>((resolve) => {
let servers: Server[] = [];
this.serverIdsInIncognitoMode.forEach((n) => {
this.serverIds.forEach((n) => {
let server: Server = JSON.parse(localStorage.getItem(n));
servers.push(server);
});
@ -127,13 +71,10 @@ export class ServerService {
return promise;
}
return this.onReady(() => this.indexedDbService.get().getAll(this.tablename)) as Promise<Server[]>;
}
public delete(server: Server) {
if (this.isIncognitoMode) {
localStorage.removeItem(`server-${server.id}`);
this.serverIdsInIncognitoMode = this.serverIdsInIncognitoMode.filter((n) => n !== `server-${server.id}`);
this.serverIds = this.serverIds.filter((n) => n !== `server-${server.id}`);
this.updateServerIds();
let promise = new Promise((resolve) => {
resolve(server.id);
@ -141,9 +82,6 @@ export class ServerService {
return promise;
}
return this.onReady(() => this.indexedDbService.get().delete(this.tablename, server.id));
}
public getServerUrl(server: Server) {
return `${server.protocol}//${server.host}:${server.port}/`;
}
@ -179,25 +117,4 @@ export class ServerService {
return promise;
}
protected onReady(query) {
const promise = new Promise((resolve, reject) => {
this.ready.then(
() => {
query().then(
(result) => {
resolve(result);
},
(error) => {
reject(error);
}
);
},
(error) => {
reject(error);
}
);
});
return promise;
}
}

View File

@ -16,4 +16,4 @@ export const environment = {
* This import should be commented out in production mode because it will have a negative impact
* on performance if an error is thrown.
*/
// import 'zone.js/dist/zone-error'; // Included with Angular CLI.
// import 'zone.js/plugins/zone-error'; // Included with Angular CLI.

View File

@ -72,7 +72,7 @@
/***************************************************************************************************
* Zone JS is required by default for Angular itself.
*/
import 'zone.js/dist/zone'; // Included with Angular CLI.
import 'zone.js'; // Included with Angular CLI.
/***************************************************************************************************
* APPLICATION IMPORTS

View File

@ -1,4 +1,4 @@
import 'zone.js/dist/zone-testing';
import 'zone.js/testing';
import { getTestBed } from '@angular/core/testing';
import { BrowserDynamicTestingModule, platformBrowserDynamicTesting } from '@angular/platform-browser-dynamic/testing';

View File

@ -17,7 +17,6 @@
"polyfills.ts"
],
"include": [
// "../src/**/*",
"../node_modules/angular2-indexeddb/*"
// "../src/**/*"
]
}

View File

@ -15,7 +15,6 @@
],
"include": [
"**/*.spec.ts",
"**/*.d.ts",
"../node_modules/angular2-indexeddb/*"
"**/*.d.ts"
]
}

View File

@ -8,7 +8,6 @@
"declaration": false,
"module": "esnext",
"moduleResolution": "node",
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"importHelpers": true,
"target": "es5",

7858
yarn.lock

File diff suppressed because it is too large Load Diff