mirror of
https://github.com/GNS3/gns3-web-ui.git
synced 2025-01-18 02:39:50 +00:00
Merge branch 'master' into master-2.3
This commit is contained in:
commit
7bc95954ec
@ -1,6 +1,5 @@
|
|||||||
# gns3-web-ui
|
# gns3-web-ui
|
||||||
|
|
||||||
[![Known Vulnerabilities](https://snyk.io/test/github/GNS3/gns3-web-ui/badge.svg)](https://snyk.io/test/github/GNS3/gns3-web-ui)
|
|
||||||
[![Travis CI](https://api.travis-ci.org/GNS3/gns3-web-ui.svg?branch=master)](https://travis-ci.org)
|
[![Travis CI](https://api.travis-ci.org/GNS3/gns3-web-ui.svg?branch=master)](https://travis-ci.org)
|
||||||
[![AppVeyor](https://ci.appveyor.com/api/projects/status/github/GNS3/gns3-web-ui?branch=master&svg=true)](https://www.appveyor.com/)
|
[![AppVeyor](https://ci.appveyor.com/api/projects/status/github/GNS3/gns3-web-ui?branch=master&svg=true)](https://www.appveyor.com/)
|
||||||
[![CircleCI](https://circleci.com/gh/GNS3/gns3-web-ui/tree/master.png)](https://circleci.com/gh/GNS3/gns3-web-ui/tree/master.png)
|
[![CircleCI](https://circleci.com/gh/GNS3/gns3-web-ui/tree/master.png)](https://circleci.com/gh/GNS3/gns3-web-ui/tree/master.png)
|
||||||
@ -10,10 +9,6 @@
|
|||||||
[![Packages versions](https://repology.org/badge/latest-versions/gns3.svg)](https://repology.org/metapackage/gns3/versions)
|
[![Packages versions](https://repology.org/badge/latest-versions/gns3.svg)](https://repology.org/metapackage/gns3/versions)
|
||||||
[![Packages](https://repology.org/badge/tiny-repos/gns3.svg)](https://repology.org/metapackage/gns3/versions)
|
[![Packages](https://repology.org/badge/tiny-repos/gns3.svg)](https://repology.org/metapackage/gns3/versions)
|
||||||
|
|
||||||
Test WebUI implementation for GNS3.
|
|
||||||
|
|
||||||
This is not production ready version. It has been made to evaluate possibility of creation Web User Interface for GNS3 application.
|
|
||||||
|
|
||||||
|
|
||||||
## Demo
|
## Demo
|
||||||
|
|
||||||
|
501
angular.json
501
angular.json
@ -1,252 +1,253 @@
|
|||||||
{
|
{
|
||||||
"$schema": "./node_modules/@angular/cli/lib/config/schema.json",
|
"$schema": "./node_modules/@angular/cli/lib/config/schema.json",
|
||||||
"version": 1,
|
"version": 1,
|
||||||
"newProjectRoot": "projects",
|
"newProjectRoot": "projects",
|
||||||
"projects": {
|
"projects": {
|
||||||
"gns3-web-ui": {
|
"gns3-web-ui": {
|
||||||
"root": "",
|
"root": "",
|
||||||
"sourceRoot": "src",
|
"sourceRoot": "src",
|
||||||
"projectType": "application",
|
"projectType": "application",
|
||||||
"architect": {
|
"architect": {
|
||||||
"build": {
|
"build": {
|
||||||
"builder": "@angular-devkit/build-angular:browser",
|
"builder": "@angular-devkit/build-angular:browser",
|
||||||
"options": {
|
"options": {
|
||||||
"allowedCommonJsDependencies": [
|
"allowedCommonJsDependencies": [
|
||||||
"rxjs",
|
"rxjs",
|
||||||
"rxjs-compat",
|
"rxjs-compat",
|
||||||
"uuid",
|
"uuid",
|
||||||
"css-tree",
|
"css-tree",
|
||||||
"save-svg-as-png",
|
"save-svg-as-png",
|
||||||
"angular-draggable-droppable",
|
"angular-draggable-droppable",
|
||||||
"angular2-hotkeys",
|
"angular2-hotkeys",
|
||||||
"dom-set",
|
"dom-set",
|
||||||
"dom-plane",
|
"dom-plane",
|
||||||
"mousetrap",
|
"mousetrap",
|
||||||
"@mattlewis92/dom-autoscroller",
|
"@mattlewis92/dom-autoscroller",
|
||||||
"rxjs/Rx",
|
"rxjs/Rx",
|
||||||
"rxjs/add/operator/map",
|
"rxjs/add/operator/map",
|
||||||
"rxjs-compat/add/operator/map"
|
"rxjs-compat/add/operator/map"
|
||||||
],
|
],
|
||||||
"aot": true,
|
"aot": true,
|
||||||
"outputPath": "dist",
|
"outputPath": "dist",
|
||||||
"index": "src/index.html",
|
"index": "src/index.html",
|
||||||
"main": "src/main.ts",
|
"main": "src/main.ts",
|
||||||
"tsConfig": "src/tsconfig.app.json",
|
"tsConfig": "src/tsconfig.app.json",
|
||||||
"polyfills": "src/polyfills.ts",
|
"polyfills": "src/polyfills.ts",
|
||||||
"extractCss": true,
|
"assets": [
|
||||||
"assets": [
|
"src/assets",
|
||||||
"src/assets",
|
"src/favicon.ico",
|
||||||
"src/favicon.ico",
|
"src/ReleaseNotes.txt"
|
||||||
"src/ReleaseNotes.txt"
|
],
|
||||||
],
|
"styles": [
|
||||||
"styles": [
|
"node_modules/bootstrap/dist/css/bootstrap.min.css",
|
||||||
"node_modules/bootstrap/dist/css/bootstrap.min.css",
|
"node_modules/notosans-fontface/css/notosans-fontface.min.css",
|
||||||
"node_modules/notosans-fontface/css/notosans-fontface.min.css",
|
"src/styles.scss",
|
||||||
"src/styles.css",
|
{
|
||||||
{
|
"inject": true,
|
||||||
"inject": false,
|
"input": "src/theme.scss",
|
||||||
"input": "src/theme.scss",
|
"bundleName": "theme-default-dark"
|
||||||
"bundleName": "theme-default-dark"
|
},
|
||||||
},
|
{
|
||||||
{
|
"inject": true,
|
||||||
"inject": false,
|
"input": "src/theme-light.scss",
|
||||||
"input": "src/theme-light.scss",
|
"bundleName": "theme-default"
|
||||||
"bundleName": "theme-default"
|
}
|
||||||
}
|
],
|
||||||
],
|
"scripts": []
|
||||||
"scripts": []
|
},
|
||||||
},
|
"configurations": {
|
||||||
"configurations": {
|
"production": {
|
||||||
"production": {
|
"budgets": [
|
||||||
"budgets": [
|
{
|
||||||
{
|
"type": "anyComponentStyle",
|
||||||
"type": "anyComponentStyle",
|
"maximumWarning": "6kb"
|
||||||
"maximumWarning": "6kb"
|
}
|
||||||
}
|
],
|
||||||
],
|
"optimization": true,
|
||||||
"optimization": true,
|
"outputHashing": "all",
|
||||||
"outputHashing": "all",
|
"sourceMap": {
|
||||||
"sourceMap": {
|
"hidden": true,
|
||||||
"hidden": true,
|
"scripts": true,
|
||||||
"scripts": true,
|
"styles": false
|
||||||
"styles": false
|
},
|
||||||
},
|
"namedChunks": false,
|
||||||
"extractCss": true,
|
"aot": true,
|
||||||
"namedChunks": false,
|
"extractLicenses": true,
|
||||||
"aot": true,
|
"vendorChunk": false,
|
||||||
"extractLicenses": true,
|
"buildOptimizer": true,
|
||||||
"vendorChunk": false,
|
"fileReplacements": [
|
||||||
"buildOptimizer": true,
|
{
|
||||||
"fileReplacements": [
|
"replace": "src/environments/environment.ts",
|
||||||
{
|
"with": "src/environments/environment.prod.ts"
|
||||||
"replace": "src/environments/environment.ts",
|
}
|
||||||
"with": "src/environments/environment.prod.ts"
|
]
|
||||||
}
|
},
|
||||||
]
|
"electronProd": {
|
||||||
},
|
"budgets": [
|
||||||
"electronProd": {
|
{
|
||||||
"budgets": [
|
"type": "anyComponentStyle",
|
||||||
{
|
"maximumWarning": "6kb"
|
||||||
"type": "anyComponentStyle",
|
}
|
||||||
"maximumWarning": "6kb"
|
],
|
||||||
}
|
"optimization": true,
|
||||||
],
|
"outputHashing": "all",
|
||||||
"optimization": true,
|
"sourceMap": false,
|
||||||
"outputHashing": "all",
|
"namedChunks": false,
|
||||||
"sourceMap": false,
|
"aot": true,
|
||||||
"extractCss": true,
|
"extractLicenses": true,
|
||||||
"namedChunks": false,
|
"vendorChunk": false,
|
||||||
"aot": true,
|
"buildOptimizer": true,
|
||||||
"extractLicenses": true,
|
"fileReplacements": [
|
||||||
"vendorChunk": false,
|
{
|
||||||
"buildOptimizer": true,
|
"replace": "src/environments/environment.ts",
|
||||||
"fileReplacements": [
|
"with": "src/environments/environment.electron.prod.ts"
|
||||||
{
|
}
|
||||||
"replace": "src/environments/environment.ts",
|
]
|
||||||
"with": "src/environments/environment.electron.prod.ts"
|
},
|
||||||
}
|
"electronDev": {
|
||||||
]
|
"budgets": [
|
||||||
},
|
{
|
||||||
"electronDev": {
|
"type": "anyComponentStyle",
|
||||||
"budgets": [
|
"maximumWarning": "6kb"
|
||||||
{
|
}
|
||||||
"type": "anyComponentStyle",
|
],
|
||||||
"maximumWarning": "6kb"
|
"fileReplacements": [
|
||||||
}
|
{
|
||||||
],
|
"replace": "src/environments/environment.ts",
|
||||||
"fileReplacements": [
|
"with": "src/environments/environment.electron.ts"
|
||||||
{
|
}
|
||||||
"replace": "src/environments/environment.ts",
|
]
|
||||||
"with": "src/environments/environment.electron.ts"
|
},
|
||||||
}
|
"githubProd": {
|
||||||
]
|
"budgets": [
|
||||||
},
|
{
|
||||||
"githubProd": {
|
"type": "anyComponentStyle",
|
||||||
"budgets": [
|
"maximumWarning": "6kb"
|
||||||
{
|
}
|
||||||
"type": "anyComponentStyle",
|
],
|
||||||
"maximumWarning": "6kb"
|
"optimization": true,
|
||||||
}
|
"outputHashing": "all",
|
||||||
],
|
"sourceMap": false,
|
||||||
"optimization": true,
|
"namedChunks": false,
|
||||||
"outputHashing": "all",
|
"aot": true,
|
||||||
"sourceMap": false,
|
"extractLicenses": true,
|
||||||
"extractCss": true,
|
"vendorChunk": false,
|
||||||
"namedChunks": false,
|
"buildOptimizer": true,
|
||||||
"aot": true,
|
"fileReplacements": [
|
||||||
"extractLicenses": true,
|
{
|
||||||
"vendorChunk": false,
|
"replace": "src/environments/environment.ts",
|
||||||
"buildOptimizer": true,
|
"with": "src/environments/environment.github.prod.ts"
|
||||||
"fileReplacements": [
|
}
|
||||||
{
|
]
|
||||||
"replace": "src/environments/environment.ts",
|
}
|
||||||
"with": "src/environments/environment.github.prod.ts"
|
}
|
||||||
}
|
},
|
||||||
]
|
"serve": {
|
||||||
}
|
"builder": "@angular-devkit/build-angular:dev-server",
|
||||||
}
|
"options": {
|
||||||
},
|
"browserTarget": "gns3-web-ui:build"
|
||||||
"serve": {
|
},
|
||||||
"builder": "@angular-devkit/build-angular:dev-server",
|
"configurations": {
|
||||||
"options": {
|
"production": {
|
||||||
"browserTarget": "gns3-web-ui:build"
|
"browserTarget": "gns3-web-ui:build:production"
|
||||||
},
|
},
|
||||||
"configurations": {
|
"electronProd": {
|
||||||
"production": {
|
"browserTarget": "gns3-web-ui:build:electronProd"
|
||||||
"browserTarget": "gns3-web-ui:build:production"
|
},
|
||||||
},
|
"electronDev": {
|
||||||
"electronProd": {
|
"browserTarget": "gns3-web-ui:build:electronDev"
|
||||||
"browserTarget": "gns3-web-ui:build:electronProd"
|
},
|
||||||
},
|
"githubProd": {
|
||||||
"electronDev": {
|
"browserTarget": "gns3-web-ui:build:githubProd"
|
||||||
"browserTarget": "gns3-web-ui:build:electronDev"
|
}
|
||||||
},
|
}
|
||||||
"githubProd": {
|
},
|
||||||
"browserTarget": "gns3-web-ui:build:githubProd"
|
"extract-i18n": {
|
||||||
}
|
"builder": "@angular-devkit/build-angular:extract-i18n",
|
||||||
}
|
"options": {
|
||||||
},
|
"browserTarget": "gns3-web-ui:build"
|
||||||
"extract-i18n": {
|
}
|
||||||
"builder": "@angular-devkit/build-angular:extract-i18n",
|
},
|
||||||
"options": {
|
"test": {
|
||||||
"browserTarget": "gns3-web-ui:build"
|
"builder": "@angular-devkit/build-angular:karma",
|
||||||
}
|
"options": {
|
||||||
},
|
"main": "src/test.ts",
|
||||||
"test": {
|
"karmaConfig": "./karma.conf.js",
|
||||||
"builder": "@angular-devkit/build-angular:karma",
|
"polyfills": "src/polyfills.ts",
|
||||||
"options": {
|
"tsConfig": "src/tsconfig.spec.json",
|
||||||
"main": "src/test.ts",
|
"scripts": [],
|
||||||
"karmaConfig": "./karma.conf.js",
|
"styles": [
|
||||||
"polyfills": "src/polyfills.ts",
|
"node_modules/bootstrap/dist/css/bootstrap.min.css",
|
||||||
"tsConfig": "src/tsconfig.spec.json",
|
"node_modules/notosans-fontface/css/notosans-fontface.min.css",
|
||||||
"scripts": [],
|
"src/styles.scss",
|
||||||
"styles": [
|
"src/theme.scss"
|
||||||
"node_modules/bootstrap/dist/css/bootstrap.min.css",
|
],
|
||||||
"node_modules/notosans-fontface/css/notosans-fontface.min.css",
|
"assets": [
|
||||||
"src/styles.css",
|
"src/assets",
|
||||||
"src/theme.scss"
|
"src/favicon.ico"
|
||||||
],
|
],
|
||||||
"assets": [
|
"codeCoverageExclude": [
|
||||||
"src/assets",
|
"src/app/cartography/components/experimental-map/**/*"
|
||||||
"src/favicon.ico"
|
]
|
||||||
],
|
}
|
||||||
"codeCoverageExclude": [
|
},
|
||||||
"src/app/cartography/components/experimental-map/**/*"
|
"lint": {
|
||||||
]
|
"builder": "@angular-devkit/build-angular:tslint",
|
||||||
}
|
"options": {
|
||||||
},
|
"tsConfig": [
|
||||||
"lint": {
|
"src/tsconfig.app.json",
|
||||||
"builder": "@angular-devkit/build-angular:tslint",
|
"src/tsconfig.spec.json"
|
||||||
"options": {
|
],
|
||||||
"tsConfig": [
|
"exclude": [
|
||||||
"src/tsconfig.app.json",
|
"**/node_modules/**",
|
||||||
"src/tsconfig.spec.json"
|
"**/*.spec.ts"
|
||||||
],
|
]
|
||||||
"exclude": [
|
}
|
||||||
"**/node_modules/**",
|
}
|
||||||
"**/*.spec.ts"
|
},
|
||||||
]
|
"schematics": {
|
||||||
}
|
"@schematics/angular:component": {
|
||||||
}
|
"style": "scss"
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
"gns3-web-ui-e2e": {
|
},
|
||||||
"root": "e2e",
|
"gns3-web-ui-e2e": {
|
||||||
"sourceRoot": "e2e",
|
"root": "e2e",
|
||||||
"projectType": "application",
|
"sourceRoot": "e2e",
|
||||||
"architect": {
|
"projectType": "application",
|
||||||
"e2e": {
|
"architect": {
|
||||||
"builder": "@angular-devkit/build-angular:protractor",
|
"e2e": {
|
||||||
"options": {
|
"builder": "@angular-devkit/build-angular:protractor",
|
||||||
"protractorConfig": "./protractor.conf.js",
|
"options": {
|
||||||
"devServerTarget": "gns3-web-ui:serve"
|
"protractorConfig": "./protractor.conf.js",
|
||||||
}
|
"devServerTarget": "gns3-web-ui:serve"
|
||||||
},
|
}
|
||||||
"lint": {
|
},
|
||||||
"builder": "@angular-devkit/build-angular:tslint",
|
"lint": {
|
||||||
"options": {
|
"builder": "@angular-devkit/build-angular:tslint",
|
||||||
"tsConfig": [
|
"options": {
|
||||||
"e2e/tsconfig.e2e.json"
|
"tsConfig": [
|
||||||
],
|
"e2e/tsconfig.e2e.json"
|
||||||
"exclude": [
|
],
|
||||||
"**/node_modules/**"
|
"exclude": [
|
||||||
]
|
"**/node_modules/**"
|
||||||
}
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
"defaultProject": "gns3-web-ui",
|
},
|
||||||
"schematics": {
|
"defaultProject": "gns3-web-ui",
|
||||||
"@schematics/angular:component": {
|
"schematics": {
|
||||||
"prefix": "app",
|
"@schematics/angular:component": {
|
||||||
"style": "scss"
|
"prefix": "app",
|
||||||
},
|
"style": "scss"
|
||||||
"@schematics/angular:directive": {
|
},
|
||||||
"prefix": "app"
|
"@schematics/angular:directive": {
|
||||||
}
|
"prefix": "app"
|
||||||
},
|
}
|
||||||
"cli": {
|
},
|
||||||
"analytics": false
|
"cli": {
|
||||||
}
|
"analytics": false
|
||||||
|
}
|
||||||
}
|
}
|
1
debug.log
Normal file
1
debug.log
Normal file
@ -0,0 +1 @@
|
|||||||
|
[1109/003452.026:ERROR:directory_reader_win.cc(43)] FindFirstFile: The system cannot find the path specified. (0x3)
|
99
package.json
99
package.json
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "gns3-web-ui",
|
"name": "gns3-web-ui",
|
||||||
"version": "2.2.16dev1",
|
"version": "2.2.18dev",
|
||||||
"author": {
|
"author": {
|
||||||
"name": "GNS3 Technology Inc.",
|
"name": "GNS3 Technology Inc.",
|
||||||
"email": "developers@gns3.com"
|
"email": "developers@gns3.com"
|
||||||
@ -40,39 +40,38 @@
|
|||||||
},
|
},
|
||||||
"private": true,
|
"private": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@angular/animations": "^10.1.5",
|
"@angular/animations": "^11.0.8",
|
||||||
"@angular/cdk": "^10.2.4",
|
"@angular/cdk": "^11.0.3",
|
||||||
"@angular/common": "^10.1.5",
|
"@angular/common": "^11.0.8",
|
||||||
"@angular/compiler": "^10.1.5",
|
"@angular/compiler": "^11.0.8",
|
||||||
"@angular/core": "^10.1.5",
|
"@angular/core": "^11.0.8",
|
||||||
"@angular/forms": "^10.1.5",
|
"@angular/forms": "^11.0.8",
|
||||||
"@angular/http": "^7.2.16",
|
"@angular/http": "^7.2.16",
|
||||||
"@angular/material": "^10.2.4",
|
"@angular/material": "^11.0.3",
|
||||||
"@angular/platform-browser": "^10.1.5",
|
"@angular/platform-browser": "^11.0.8",
|
||||||
"@angular/platform-browser-dynamic": "^10.1.5",
|
"@angular/platform-browser-dynamic": "^11.0.8",
|
||||||
"@angular/router": "^10.1.5",
|
"@angular/router": "^11.0.8",
|
||||||
"@sentry/browser": "^5.26.0",
|
"@sentry/browser": "^5.29.2",
|
||||||
"@types/jest": "^26.0.14",
|
"@types/jest": "^26.0.20",
|
||||||
"@types/mocha": "^8.0.3",
|
"@types/mocha": "^8.2.0",
|
||||||
"angular-draggable-droppable": "^4.5.4",
|
"angular-draggable-droppable": "^4.6.0",
|
||||||
"angular-persistence": "^1.0.1",
|
"angular-persistence": "^1.0.1",
|
||||||
"angular-resizable-element": "^3.3.3",
|
"angular-resizable-element": "^3.3.4",
|
||||||
"angular2-draggable": "^2.3.2",
|
"angular2-draggable": "^2.3.2",
|
||||||
"angular2-hotkeys": "^2.2.0",
|
"angular2-hotkeys": "^2.2.0",
|
||||||
"angular2-indexeddb": "^1.2.3",
|
"angular2-indexeddb": "^1.2.3",
|
||||||
"bootstrap": "4.5.2",
|
"bootstrap": "^4.5.3",
|
||||||
"command-exists": "^1.2.9",
|
"command-exists": "^1.2.9",
|
||||||
"core-js": "^3.6.5",
|
"core-js": "^3.8.2",
|
||||||
"css-tree": "^1.0.0-alpha.36",
|
|
||||||
"d3-ng2-service": "^2.1.0",
|
"d3-ng2-service": "^2.1.0",
|
||||||
"file-saver": "^2.0.2",
|
|
||||||
"ini": "^1.3.5",
|
|
||||||
"marked": "^1.1.1",
|
"marked": "^1.1.1",
|
||||||
|
"file-saver": "^2.0.5",
|
||||||
|
"ini": "^1.3.8",
|
||||||
"material-design-icons": "^3.0.1",
|
"material-design-icons": "^3.0.1",
|
||||||
"ng-circle-progress": "^1.6.0",
|
"ng-circle-progress": "^1.6.0",
|
||||||
"ng2-file-upload": "^1.3.0",
|
"ng2-file-upload": "^1.3.0",
|
||||||
"ngx-childprocess": "^0.0.6",
|
"ngx-childprocess": "^0.0.6",
|
||||||
"ngx-device-detector": "^2.0.0",
|
"ngx-device-detector": "^2.0.5",
|
||||||
"ngx-electron": "^2.1.1",
|
"ngx-electron": "^2.1.1",
|
||||||
"node-fetch": "^2.6.1",
|
"node-fetch": "^2.6.1",
|
||||||
"notosans-fontface": "1.2.2",
|
"notosans-fontface": "1.2.2",
|
||||||
@ -80,44 +79,45 @@
|
|||||||
"rxjs-compat": "^6.6.3",
|
"rxjs-compat": "^6.6.3",
|
||||||
"save-html-as-image": "^1.3.4",
|
"save-html-as-image": "^1.3.4",
|
||||||
"save-svg-as-png": "^1.4.14",
|
"save-svg-as-png": "^1.4.14",
|
||||||
"snyk": "^1.413.3",
|
"schematics-scss-migrate": "^1.2.10",
|
||||||
"svg-crowbar": "^0.6.1",
|
"snyk": "^1.437.3",
|
||||||
|
"spark-md5": "^3.0.1",
|
||||||
|
"svg-crowbar": "^0.6.5",
|
||||||
"tree-kill": "^1.2.1",
|
"tree-kill": "^1.2.1",
|
||||||
"tslib": "^2.0.3",
|
"tslib": "^2.1.0",
|
||||||
"typeface-roboto": "^0.0.75",
|
"typeface-roboto": "^1.1.13",
|
||||||
"xterm": "^4.9.0",
|
"xterm": "^4.9.0",
|
||||||
"xterm-addon-attach": "^0.6.0",
|
"xterm-addon-attach": "^0.6.0",
|
||||||
"xterm-addon-fit": "^0.4.0",
|
"xterm-addon-fit": "^0.4.0",
|
||||||
"yargs": "^16.0.3",
|
"yargs": "^16.2.0",
|
||||||
"zone.js": "~0.11.1"
|
"zone.js": "^0.11.3"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@angular-devkit/build-angular": "^0.1001.6",
|
"@angular-devkit/build-angular": "^0.1100.6",
|
||||||
"@angular/cli": "^10.1.6",
|
"@angular/cli": "^11.0.6",
|
||||||
"@angular/compiler-cli": "^10.1.5",
|
"@angular/compiler-cli": "^11.0.8",
|
||||||
"@angular/language-service": "^10.1.5",
|
"@angular/language-service": "^11.0.8",
|
||||||
"@sentry/cli": "^1.58.0",
|
"@sentry/cli": "^1.61.0",
|
||||||
"@sentry/electron": "^2.0.1",
|
"@sentry/electron": "^2.1.0",
|
||||||
"@types/jasmine": "^3.5.14",
|
"@types/jasmine": "~3.6.0",
|
||||||
"@types/jasminewd2": "^2.0.8",
|
"@types/jasminewd2": "^2.0.8",
|
||||||
"@types/node": "14.11.2",
|
"@types/node": "14.14.10",
|
||||||
"codelyzer": "^6.0.1",
|
"codelyzer": "^6.0.0",
|
||||||
"electron": "^10.1.3",
|
"electron": "^11.2.0",
|
||||||
"electron-builder": "22.8.1",
|
"electron-builder": "22.9.1",
|
||||||
"file-loader": "^6.1.1",
|
"file-loader": "^6.2.0",
|
||||||
"jasmine-core": "^3.6.0",
|
"jasmine-core": "~3.6.0",
|
||||||
"jasmine-spec-reporter": "^6.0.0",
|
"jasmine-spec-reporter": "~5.0.0",
|
||||||
"jquery": "^3.5.1",
|
"jquery": "^3.5.1",
|
||||||
"karma": "^5.2.3",
|
"karma": "^5.2.3",
|
||||||
"karma-chrome-launcher": "^3.1.0",
|
"karma-chrome-launcher": "~3.1.0",
|
||||||
"karma-cli": "^2.0.0",
|
"karma-cli": "^2.0.0",
|
||||||
"karma-coverage-istanbul-reporter": "~3.0.2",
|
"karma-coverage-istanbul-reporter": "~3.0.2",
|
||||||
"karma-jasmine": "^4.0.1",
|
"karma-jasmine": "~4.0.0",
|
||||||
"karma-jasmine-html-reporter": "^1.5.4",
|
"karma-jasmine-html-reporter": "^1.5.0",
|
||||||
"license-checker": "^25.0.1",
|
"license-checker": "^25.0.1",
|
||||||
"node-sass": "^4.14.1",
|
|
||||||
"popper.js": "^1.16.1",
|
"popper.js": "^1.16.1",
|
||||||
"prettier": "^2.1.2",
|
"prettier": "^2.2.1",
|
||||||
"protractor": "^7.0.0",
|
"protractor": "^7.0.0",
|
||||||
"replace": "^1.2.0",
|
"replace": "^1.2.0",
|
||||||
"rxjs-tslint": "^0.1.8",
|
"rxjs-tslint": "^0.1.8",
|
||||||
@ -125,8 +125,9 @@
|
|||||||
"ts-node": "~9.0.0",
|
"ts-node": "~9.0.0",
|
||||||
"tslint": "^6.1.3",
|
"tslint": "^6.1.3",
|
||||||
"tslint-config-prettier": "^1.18.0",
|
"tslint-config-prettier": "^1.18.0",
|
||||||
"typescript": "^4.0.3",
|
"typescript": "4.0.2",
|
||||||
"webpack": "^4.44.2"
|
"webpack": "4.44.2",
|
||||||
|
"yarn-upgrade-all": "^0.5.4"
|
||||||
},
|
},
|
||||||
"greenkeeper": {
|
"greenkeeper": {
|
||||||
"ignore": [
|
"ignore": [
|
||||||
|
@ -10,7 +10,7 @@ import { ProgressService } from './common/progress/progress.service';
|
|||||||
@Component({
|
@Component({
|
||||||
selector: 'app-root',
|
selector: 'app-root',
|
||||||
templateUrl: './app.component.html',
|
templateUrl: './app.component.html',
|
||||||
styleUrls: ['./app.component.css']
|
styleUrls: ['./app.component.scss']
|
||||||
})
|
})
|
||||||
export class AppComponent implements OnInit {
|
export class AppComponent implements OnInit {
|
||||||
constructor(
|
constructor(
|
||||||
|
@ -7,7 +7,6 @@ import { HttpClientModule } from '@angular/common/http';
|
|||||||
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
|
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
|
||||||
|
|
||||||
import { D3Service } from 'd3-ng2-service';
|
import { D3Service } from 'd3-ng2-service';
|
||||||
import { HotkeyModule } from 'angular2-hotkeys';
|
|
||||||
import { PersistenceModule } from 'angular-persistence';
|
import { PersistenceModule } from 'angular-persistence';
|
||||||
import { NgxElectronModule } from 'ngx-electron';
|
import { NgxElectronModule } from 'ngx-electron';
|
||||||
import { FileUploadModule } from 'ng2-file-upload';
|
import { FileUploadModule } from 'ng2-file-upload';
|
||||||
@ -54,7 +53,6 @@ import { DrawingsDataSource } from './cartography/datasources/drawings-datasourc
|
|||||||
import { EditStyleActionComponent } from './components/project-map/context-menu/actions/edit-style-action/edit-style-action.component';
|
import { EditStyleActionComponent } from './components/project-map/context-menu/actions/edit-style-action/edit-style-action.component';
|
||||||
import { MoveLayerDownActionComponent } from './components/project-map/context-menu/actions/move-layer-down-action/move-layer-down-action.component';
|
import { MoveLayerDownActionComponent } from './components/project-map/context-menu/actions/move-layer-down-action/move-layer-down-action.component';
|
||||||
import { MoveLayerUpActionComponent } from './components/project-map/context-menu/actions/move-layer-up-action/move-layer-up-action.component';
|
import { MoveLayerUpActionComponent } from './components/project-map/context-menu/actions/move-layer-up-action/move-layer-up-action.component';
|
||||||
import { ProjectMapShortcutsComponent } from './components/project-map/project-map-shortcuts/project-map-shortcuts.component';
|
|
||||||
import { SettingsComponent } from './components/settings/settings.component';
|
import { SettingsComponent } from './components/settings/settings.component';
|
||||||
import { SettingsService } from './services/settings.service';
|
import { SettingsService } from './services/settings.service';
|
||||||
|
|
||||||
@ -321,7 +319,6 @@ import { ProjectReadmeComponent } from './components/project-map/project-readme/
|
|||||||
ResumeLinkActionComponent,
|
ResumeLinkActionComponent,
|
||||||
SuspendLinkActionComponent,
|
SuspendLinkActionComponent,
|
||||||
ResetLinkActionComponent,
|
ResetLinkActionComponent,
|
||||||
ProjectMapShortcutsComponent,
|
|
||||||
SettingsComponent,
|
SettingsComponent,
|
||||||
PreferencesComponent,
|
PreferencesComponent,
|
||||||
BundledServerFinderComponent,
|
BundledServerFinderComponent,
|
||||||
@ -489,7 +486,6 @@ import { ProjectReadmeComponent } from './components/project-map/project-readme/
|
|||||||
BrowserAnimationsModule,
|
BrowserAnimationsModule,
|
||||||
CdkTableModule,
|
CdkTableModule,
|
||||||
CartographyModule,
|
CartographyModule,
|
||||||
HotkeyModule.forRoot(),
|
|
||||||
PersistenceModule,
|
PersistenceModule,
|
||||||
NgxElectronModule,
|
NgxElectronModule,
|
||||||
FileUploadModule,
|
FileUploadModule,
|
||||||
|
@ -103,8 +103,12 @@ export class NodeWidget implements Widget {
|
|||||||
if (n.height > 64) return 64;
|
if (n.height > 64) return 64;
|
||||||
return n.height;
|
return n.height;
|
||||||
})
|
})
|
||||||
.attr('x', (n: MapNode) => 0)
|
.attr('x', (n: MapNode) => {
|
||||||
.attr('y', (n: MapNode) => 0)
|
return 0
|
||||||
|
})
|
||||||
|
.attr('y', (n: MapNode) => {
|
||||||
|
return 0
|
||||||
|
})
|
||||||
.on('mouseover', function(this, n: MapNode) {
|
.on('mouseover', function(this, n: MapNode) {
|
||||||
select(this).attr('class', 'over');
|
select(this).attr('class', 'over');
|
||||||
})
|
})
|
||||||
@ -113,6 +117,7 @@ export class NodeWidget implements Widget {
|
|||||||
});
|
});
|
||||||
|
|
||||||
node_body_merge.attr('transform', (n: MapNode) => {
|
node_body_merge.attr('transform', (n: MapNode) => {
|
||||||
|
if (!n.width) return `translate(${n.x - 30},${n.y - 30})`
|
||||||
return `translate(${n.x},${n.y})`;
|
return `translate(${n.x},${n.y})`;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -4,7 +4,7 @@ import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';
|
|||||||
@Component({
|
@Component({
|
||||||
selector: 'app-information-dialog',
|
selector: 'app-information-dialog',
|
||||||
templateUrl: 'information-dialog.component.html',
|
templateUrl: 'information-dialog.component.html',
|
||||||
styleUrls: ['information-dialog.component.css']
|
styleUrls: ['information-dialog.component.scss']
|
||||||
})
|
})
|
||||||
export class InformationDialogComponent implements OnInit {
|
export class InformationDialogComponent implements OnInit {
|
||||||
public confirmationMessage: string;
|
public confirmationMessage: string;
|
||||||
|
@ -13,7 +13,7 @@ import { AddedDataEvent } from '../../../cartography/events/event-source';
|
|||||||
@Component({
|
@Component({
|
||||||
selector: 'app-drawing-added',
|
selector: 'app-drawing-added',
|
||||||
templateUrl: './drawing-added.component.html',
|
templateUrl: './drawing-added.component.html',
|
||||||
styleUrls: ['./drawing-added.component.css']
|
styleUrls: ['./drawing-added.component.scss']
|
||||||
})
|
})
|
||||||
export class DrawingAddedComponent implements OnInit, OnDestroy {
|
export class DrawingAddedComponent implements OnInit, OnDestroy {
|
||||||
@Input() server: Server;
|
@Input() server: Server;
|
||||||
|
@ -12,7 +12,7 @@ import { Project } from '../../../models/project';
|
|||||||
@Component({
|
@Component({
|
||||||
selector: 'app-drawing-dragged',
|
selector: 'app-drawing-dragged',
|
||||||
templateUrl: './drawing-dragged.component.html',
|
templateUrl: './drawing-dragged.component.html',
|
||||||
styleUrls: ['./drawing-dragged.component.css']
|
styleUrls: ['./drawing-dragged.component.scss']
|
||||||
})
|
})
|
||||||
export class DrawingDraggedComponent implements OnInit, OnDestroy {
|
export class DrawingDraggedComponent implements OnInit, OnDestroy {
|
||||||
@Input() server: Server;
|
@Input() server: Server;
|
||||||
|
@ -12,7 +12,7 @@ import { Subscription } from 'rxjs';
|
|||||||
@Component({
|
@Component({
|
||||||
selector: 'app-drawing-resized',
|
selector: 'app-drawing-resized',
|
||||||
templateUrl: './drawing-resized.component.html',
|
templateUrl: './drawing-resized.component.html',
|
||||||
styleUrls: ['./drawing-resized.component.css']
|
styleUrls: ['./drawing-resized.component.scss']
|
||||||
})
|
})
|
||||||
export class DrawingResizedComponent implements OnInit, OnDestroy {
|
export class DrawingResizedComponent implements OnInit, OnDestroy {
|
||||||
@Input() server: Server;
|
@Input() server: Server;
|
||||||
|
@ -11,7 +11,7 @@ import { LinksEventSource } from '../../../cartography/events/links-event-source
|
|||||||
@Component({
|
@Component({
|
||||||
selector: 'app-interface-label-dragged',
|
selector: 'app-interface-label-dragged',
|
||||||
templateUrl: './interface-label-dragged.component.html',
|
templateUrl: './interface-label-dragged.component.html',
|
||||||
styleUrls: ['./interface-label-dragged.component.css']
|
styleUrls: ['./interface-label-dragged.component.scss']
|
||||||
})
|
})
|
||||||
export class InterfaceLabelDraggedComponent {
|
export class InterfaceLabelDraggedComponent {
|
||||||
@Input() server: Server;
|
@Input() server: Server;
|
||||||
|
@ -14,7 +14,7 @@ import { LinksEventSource } from '../../../cartography/events/links-event-source
|
|||||||
@Component({
|
@Component({
|
||||||
selector: 'app-link-created',
|
selector: 'app-link-created',
|
||||||
templateUrl: './link-created.component.html',
|
templateUrl: './link-created.component.html',
|
||||||
styleUrls: ['./link-created.component.css']
|
styleUrls: ['./link-created.component.scss']
|
||||||
})
|
})
|
||||||
export class LinkCreatedComponent implements OnInit, OnDestroy {
|
export class LinkCreatedComponent implements OnInit, OnDestroy {
|
||||||
@Input() server: Server;
|
@Input() server: Server;
|
||||||
|
@ -12,7 +12,7 @@ import { Project } from '../../../models/project';
|
|||||||
@Component({
|
@Component({
|
||||||
selector: 'app-node-dragged',
|
selector: 'app-node-dragged',
|
||||||
templateUrl: './node-dragged.component.html',
|
templateUrl: './node-dragged.component.html',
|
||||||
styleUrls: ['./node-dragged.component.css']
|
styleUrls: ['./node-dragged.component.scss']
|
||||||
})
|
})
|
||||||
export class NodeDraggedComponent implements OnInit, OnDestroy {
|
export class NodeDraggedComponent implements OnInit, OnDestroy {
|
||||||
@Input() server: Server;
|
@Input() server: Server;
|
||||||
|
@ -12,7 +12,7 @@ import { MapLabel } from '../../../cartography/models/map/map-label';
|
|||||||
@Component({
|
@Component({
|
||||||
selector: 'app-node-label-dragged',
|
selector: 'app-node-label-dragged',
|
||||||
templateUrl: './node-label-dragged.component.html',
|
templateUrl: './node-label-dragged.component.html',
|
||||||
styleUrls: ['./node-label-dragged.component.css']
|
styleUrls: ['./node-label-dragged.component.scss']
|
||||||
})
|
})
|
||||||
export class NodeLabelDraggedComponent implements OnInit, OnDestroy {
|
export class NodeLabelDraggedComponent implements OnInit, OnDestroy {
|
||||||
@Input() server: Server;
|
@Input() server: Server;
|
||||||
|
@ -15,7 +15,7 @@ import { Context } from '../../../cartography/models/context';
|
|||||||
@Component({
|
@Component({
|
||||||
selector: 'app-text-added',
|
selector: 'app-text-added',
|
||||||
templateUrl: './text-added.component.html',
|
templateUrl: './text-added.component.html',
|
||||||
styleUrls: ['./text-added.component.css']
|
styleUrls: ['./text-added.component.scss']
|
||||||
})
|
})
|
||||||
export class TextAddedComponent implements OnInit, OnDestroy {
|
export class TextAddedComponent implements OnInit, OnDestroy {
|
||||||
@Input() server: Server;
|
@Input() server: Server;
|
||||||
|
@ -13,7 +13,7 @@ import { MapDrawingToSvgConverter } from '../../../cartography/converters/map/ma
|
|||||||
@Component({
|
@Component({
|
||||||
selector: 'app-text-edited',
|
selector: 'app-text-edited',
|
||||||
templateUrl: './text-edited.component.html',
|
templateUrl: './text-edited.component.html',
|
||||||
styleUrls: ['./text-edited.component.css']
|
styleUrls: ['./text-edited.component.scss']
|
||||||
})
|
})
|
||||||
export class TextEditedComponent implements OnInit, OnDestroy {
|
export class TextEditedComponent implements OnInit, OnDestroy {
|
||||||
@Input() server: Server;
|
@Input() server: Server;
|
||||||
|
@ -26,7 +26,7 @@
|
|||||||
<div class="wrapper">
|
<div class="wrapper">
|
||||||
<div class="buttonWrapper" *ngFor="let symbol of filteredSymbols | filenamefilter: searchText">
|
<div class="buttonWrapper" *ngFor="let symbol of filteredSymbols | filenamefilter: searchText">
|
||||||
<button [ngClass]="{ buttonSelected: isSelected === symbol.symbol_id }" class="button" (click)="setSelected(symbol.symbol_id)">
|
<button [ngClass]="{ buttonSelected: isSelected === symbol.symbol_id }" class="button" (click)="setSelected(symbol.symbol_id)">
|
||||||
<img [ngClass]="{ imageSelected: isSelected === symbol.symbol_id }" class="image" [src]="getImageSourceForTemplate(symbol.symbol_id)"/>
|
<img lazyimg [ngClass]="{ imageSelected: isSelected === symbol.symbol_id }" class="image" [src]="getImageSourceForTemplate(symbol.symbol_id)"/>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -78,6 +78,6 @@ export class SymbolsComponent implements OnInit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
getImageSourceForTemplate(symbol: string) {
|
getImageSourceForTemplate(symbol: string) {
|
||||||
return `http://${this.server.host}:${this.server.port}/v2/symbols/${symbol}/raw`;
|
return `${this.server.protocol}//${this.server.host}:${this.server.port}/v2/symbols/${symbol}/raw`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,9 @@
|
|||||||
|
@media screen and (max-width: 700px) {
|
||||||
|
.consoleWrapper {
|
||||||
|
visibility: hidden;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.consoleWrapper {
|
.consoleWrapper {
|
||||||
box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);
|
box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);
|
||||||
position: fixed;
|
position: fixed;
|
||||||
|
@ -0,0 +1,33 @@
|
|||||||
|
import { ConsoleWrapperComponent } from "./console-wrapper.component";
|
||||||
|
import { NodeConsoleService } from '../../../services/nodeConsole.service';
|
||||||
|
import { ThemeService } from '../../../services/theme.service';
|
||||||
|
import { MapSettingsService } from '../../../services/mapsettings.service';
|
||||||
|
|
||||||
|
describe('ConsoleWrapperComponent', () => {
|
||||||
|
it('should get actual theme', () => {
|
||||||
|
const consoleService = new NodeConsoleService();
|
||||||
|
|
||||||
|
const themeService = autoSpy(ThemeService);
|
||||||
|
themeService.getActualTheme.and.returnValue('light');
|
||||||
|
|
||||||
|
const mapSettingsService = autoSpy(MapSettingsService);
|
||||||
|
const component = new ConsoleWrapperComponent(consoleService, themeService, mapSettingsService);
|
||||||
|
|
||||||
|
component.ngOnInit();
|
||||||
|
|
||||||
|
expect(component.isLightThemeEnabled).toBe(true);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
export type SpyOf<T> = T & { [k in keyof T]: jasmine.Spy };
|
||||||
|
|
||||||
|
export function autoSpy<T>(obj: new (...args: any[]) => T): SpyOf<T> {
|
||||||
|
const res: SpyOf<T> = {} as any;
|
||||||
|
|
||||||
|
const keys = Object.getOwnPropertyNames(obj.prototype);
|
||||||
|
keys.forEach((key) => {
|
||||||
|
res[key] = jasmine.createSpy(key);
|
||||||
|
});
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
@ -17,7 +17,7 @@ import { Node } from '../../../cartography/models/node';
|
|||||||
import { ConsoleDeviceActionComponent } from '../context-menu/actions/console-device-action/console-device-action.component';
|
import { ConsoleDeviceActionComponent } from '../context-menu/actions/console-device-action/console-device-action.component';
|
||||||
import { ConsoleDeviceActionBrowserComponent } from '../context-menu/actions/console-device-action-browser/console-device-action-browser.component';
|
import { ConsoleDeviceActionBrowserComponent } from '../context-menu/actions/console-device-action-browser/console-device-action-browser.component';
|
||||||
|
|
||||||
fdescribe('ContextConsoleMenuComponent', () => {
|
describe('ContextConsoleMenuComponent', () => {
|
||||||
let component: ContextConsoleMenuComponent;
|
let component: ContextConsoleMenuComponent;
|
||||||
let fixture: ComponentFixture<ContextConsoleMenuComponent>;
|
let fixture: ComponentFixture<ContextConsoleMenuComponent>;
|
||||||
let toasterService: MockedToasterService = new MockedToasterService();
|
let toasterService: MockedToasterService = new MockedToasterService();
|
||||||
|
@ -154,6 +154,6 @@ export class ImportApplianceComponent implements OnInit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private getUploadPath(server: Server, emulator: string, filename: string) {
|
private getUploadPath(server: Server, emulator: string, filename: string) {
|
||||||
return `http://${server.host}:${server.port}/v2/${emulator}/images/${filename}`;
|
return `${server.protocol}//${server.host}:${server.port}/v2/${emulator}/images/${filename}`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -76,7 +76,7 @@ describe('LogConsoleComponent', () => {
|
|||||||
|
|
||||||
component.handleCommand();
|
component.handleCommand();
|
||||||
|
|
||||||
expect(component.showMessage).toHaveBeenCalledWith({type: 'command', message: 'Current version: 2020.3.0-beta.4'});
|
expect(component.showMessage).toHaveBeenCalledWith({type: 'command', message: 'Current version: 2.2.18dev'});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should call show message when unknown command entered', () => {
|
it('should call show message when unknown command entered', () => {
|
||||||
|
@ -167,7 +167,7 @@
|
|||||||
type="file"
|
type="file"
|
||||||
class="non-visible"
|
class="non-visible"
|
||||||
#file2
|
#file2
|
||||||
(change)="importImage($event)"
|
(change)="importImage($event, version.images.hda_disk_image)"
|
||||||
ng2FileSelect
|
ng2FileSelect
|
||||||
[uploader]="uploaderImage"/>
|
[uploader]="uploaderImage"/>
|
||||||
<button class="button" mat-raised-button (click)="file2.click()">Import</button>
|
<button class="button" mat-raised-button (click)="file2.click()">Import</button>
|
||||||
@ -187,11 +187,11 @@
|
|||||||
<input
|
<input
|
||||||
type="file"
|
type="file"
|
||||||
class="non-visible"
|
class="non-visible"
|
||||||
#file2
|
#file3
|
||||||
(change)="importImage($event)"
|
(change)="importImage($event, version.images.hdb_disk_image)"
|
||||||
ng2FileSelect
|
ng2FileSelect
|
||||||
[uploader]="uploaderImage"/>
|
[uploader]="uploaderImage"/>
|
||||||
<button class="button" mat-raised-button (click)="file2.click()">Import</button>
|
<button class="button" mat-raised-button (click)="file3.click()">Import</button>
|
||||||
<button class="button" mat-raised-button (click)="downloadImageFromVersion(version.images.hdb_disk_image)">Download</button>
|
<button class="button" mat-raised-button (click)="downloadImageFromVersion(version.images.hdb_disk_image)">Download</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -235,7 +235,7 @@
|
|||||||
type="file"
|
type="file"
|
||||||
class="non-visible"
|
class="non-visible"
|
||||||
#file2
|
#file2
|
||||||
(change)="importImage($event)"
|
(change)="importImage($event, image.filename)"
|
||||||
ng2FileSelect
|
ng2FileSelect
|
||||||
[uploader]="uploaderImage"/>
|
[uploader]="uploaderImage"/>
|
||||||
<button class="button" mat-raised-button (click)="file2.click()">Import</button>
|
<button class="button" mat-raised-button (click)="file2.click()">Import</button>
|
||||||
@ -271,7 +271,7 @@
|
|||||||
type="file"
|
type="file"
|
||||||
class="non-visible"
|
class="non-visible"
|
||||||
#file2
|
#file2
|
||||||
(change)="importImage($event)"
|
(change)="importImage($, image.filename)"
|
||||||
ng2FileSelect
|
ng2FileSelect
|
||||||
[uploader]="uploaderImage"/>
|
[uploader]="uploaderImage"/>
|
||||||
<button class="button" mat-raised-button (click)="file2.click()">Import</button>
|
<button class="button" mat-raised-button (click)="file2.click()">Import</button>
|
||||||
|
@ -30,6 +30,7 @@ import { ComputeService } from '../../../services/compute.service';
|
|||||||
import { InformationDialogComponent } from '../../../components/dialogs/information-dialog.component';
|
import { InformationDialogComponent } from '../../../components/dialogs/information-dialog.component';
|
||||||
import { ProgressService } from '../../../common/progress/progress.service';
|
import { ProgressService } from '../../../common/progress/progress.service';
|
||||||
import { TemplateNameDialogComponent } from './template-name-dialog/template-name-dialog.component';
|
import { TemplateNameDialogComponent } from './template-name-dialog/template-name-dialog.component';
|
||||||
|
import * as SparkMD5 from 'spark-md5';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-new-template-dialog',
|
selector: 'app-new-template-dialog',
|
||||||
@ -166,12 +167,14 @@ export class NewTemplateDialogComponent implements OnInit {
|
|||||||
this.uploaderImage.onErrorItem = (item: FileItem, response: string, status: number, headers: ParsedResponseHeaders) => {
|
this.uploaderImage.onErrorItem = (item: FileItem, response: string, status: number, headers: ParsedResponseHeaders) => {
|
||||||
this.toasterService.error('An error has occured');
|
this.toasterService.error('An error has occured');
|
||||||
this.progressService.deactivate();
|
this.progressService.deactivate();
|
||||||
|
this.uploaderImage.clearQueue();
|
||||||
};
|
};
|
||||||
|
|
||||||
this.uploaderImage.onSuccessItem = (item: FileItem, response: string, status: number, headers: ParsedResponseHeaders) => {
|
this.uploaderImage.onSuccessItem = (item: FileItem, response: string, status: number, headers: ParsedResponseHeaders) => {
|
||||||
this.toasterService.success('Image imported succesfully');
|
this.toasterService.success('Image imported succesfully');
|
||||||
this.refreshImages();
|
this.refreshImages();
|
||||||
this.progressService.deactivate();
|
this.progressService.deactivate();
|
||||||
|
this.uploaderImage.clearQueue();
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -332,7 +335,35 @@ export class NewTemplateDialogComponent implements OnInit {
|
|||||||
dialogRef.componentInstance.appliance = object;
|
dialogRef.componentInstance.appliance = object;
|
||||||
}
|
}
|
||||||
|
|
||||||
importImage(event) {
|
importImage(event, imageName) {
|
||||||
|
this.progressService.activate();
|
||||||
|
this.computeChecksumMd5(event.target.files[0], false).then((output) => {
|
||||||
|
let imageToInstall = this.applianceToInstall.images.filter(n => n.filename === imageName)[0];
|
||||||
|
|
||||||
|
if (imageToInstall.md5sum !== output) {
|
||||||
|
this.progressService.deactivate();
|
||||||
|
const dialogRef = this.dialog.open(InformationDialogComponent, {
|
||||||
|
width: '400px',
|
||||||
|
height: '200px',
|
||||||
|
autoFocus: false,
|
||||||
|
disableClose: true
|
||||||
|
});
|
||||||
|
dialogRef.componentInstance.confirmationMessage = `This is not the correct file.
|
||||||
|
The MD5 sum is ${output} and should be ${imageToInstall.md5sum}. Do you want to accept it at your own risks?`;
|
||||||
|
dialogRef.afterClosed().subscribe((answer: boolean) => {
|
||||||
|
if (answer) {
|
||||||
|
this.importImageFile(event)
|
||||||
|
} else {
|
||||||
|
this.uploaderImage.clearQueue();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
this.importImageFile(event);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
importImageFile(event) {
|
||||||
let name = event.target.files[0].name.split('-')[0];
|
let name = event.target.files[0].name.split('-')[0];
|
||||||
let fileName = event.target.files[0].name;
|
let fileName = event.target.files[0].name;
|
||||||
let file = event.target.files[0];
|
let file = event.target.files[0];
|
||||||
@ -373,10 +404,10 @@ export class NewTemplateDialogComponent implements OnInit {
|
|||||||
checkImages(version: Version): boolean {
|
checkImages(version: Version): boolean {
|
||||||
if (version.images.hdb_disk_image) {
|
if (version.images.hdb_disk_image) {
|
||||||
if (this.checkImageFromVersion(version.images.hda_disk_image) && this.checkImageFromVersion(version.images.hdb_disk_image)) return true;
|
if (this.checkImageFromVersion(version.images.hda_disk_image) && this.checkImageFromVersion(version.images.hdb_disk_image)) return true;
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.checkImageFromVersion(version.images.hda_disk_image)) return true;
|
if (this.checkImageFromVersion(version.images.hda_disk_image)) return true;
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -611,6 +642,36 @@ export class NewTemplateDialogComponent implements OnInit {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private computeChecksumMd5(file: File, encode = false): Promise<string> {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
const chunkSize = 2097152;
|
||||||
|
const spark = new SparkMD5.ArrayBuffer();
|
||||||
|
const fileReader = new FileReader();
|
||||||
|
let cursor = 0;
|
||||||
|
|
||||||
|
fileReader.onerror = function(): void {
|
||||||
|
reject('MD5 computation failed - error reading the file');
|
||||||
|
};
|
||||||
|
|
||||||
|
function processChunk(chunkStart: number): void {
|
||||||
|
const chunkEnd = Math.min(file.size, chunkStart + chunkSize);
|
||||||
|
fileReader.readAsArrayBuffer(file.slice(chunkStart, chunkEnd));
|
||||||
|
}
|
||||||
|
|
||||||
|
fileReader.onload = function(e: any): void {
|
||||||
|
spark.append(e.target.result);
|
||||||
|
cursor += chunkSize;
|
||||||
|
if (cursor < file.size) {
|
||||||
|
processChunk(cursor);
|
||||||
|
} else {
|
||||||
|
resolve(spark.end(encode));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
processChunk(0);
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function compareNames(a: string, b: string, isAsc: boolean) {
|
function compareNames(a: string, b: string, isAsc: boolean) {
|
||||||
|
@ -1,114 +0,0 @@
|
|||||||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
|
||||||
import { HttpClientTestingModule } from '@angular/common/http/testing';
|
|
||||||
import { inject } from '@angular/core/testing';
|
|
||||||
|
|
||||||
import { mock, instance, capture, when, anything } from 'ts-mockito';
|
|
||||||
import { HotkeyModule, HotkeysService, Hotkey } from 'angular2-hotkeys';
|
|
||||||
import { of } from 'rxjs';
|
|
||||||
|
|
||||||
import { ProjectMapShortcutsComponent } from './project-map-shortcuts.component';
|
|
||||||
import { ToasterService } from '../../../services/toaster.service';
|
|
||||||
import { NodeService } from '../../../services/node.service';
|
|
||||||
import { HttpServer } from '../../../services/http-server.service';
|
|
||||||
import { SelectionManager } from '../../../cartography/managers/selection-manager';
|
|
||||||
import { Server } from '../../../models/server';
|
|
||||||
import { Project } from '../../../models/project';
|
|
||||||
import { ProjectService } from '../../../services/project.service';
|
|
||||||
import { MockedProjectService } from '../../../services/project.service.spec';
|
|
||||||
import { SettingsService } from '../../../services/settings.service';
|
|
||||||
import { MockedToasterService } from '../../../services/toaster.service.spec';
|
|
||||||
import { mapTo } from 'rxjs/internal/operators';
|
|
||||||
import { MapNodeToNodeConverter } from '../../../cartography/converters/map/map-node-to-node-converter';
|
|
||||||
import { MapNode } from '../../../cartography/models/map/map-node';
|
|
||||||
import { MapLabelToLabelConverter } from '../../../cartography/converters/map/map-label-to-label-converter';
|
|
||||||
import { MapPortToPortConverter } from '../../../cartography/converters/map/map-port-to-port-converter';
|
|
||||||
import { Node } from '../../../cartography/models/node';
|
|
||||||
import { FontBBoxCalculator } from '../../../cartography/helpers/font-bbox-calculator';
|
|
||||||
import { CssFixer } from '../../../cartography/helpers/css-fixer';
|
|
||||||
import { FontFixer } from '../../../cartography/helpers/font-fixer';
|
|
||||||
|
|
||||||
describe('ProjectMapShortcutsComponent', () => {
|
|
||||||
let component: ProjectMapShortcutsComponent;
|
|
||||||
let fixture: ComponentFixture<ProjectMapShortcutsComponent>;
|
|
||||||
let hotkeyServiceMock: HotkeysService;
|
|
||||||
let hotkeyServiceInstanceMock: HotkeysService;
|
|
||||||
let nodeServiceMock: NodeService;
|
|
||||||
let node: MapNode;
|
|
||||||
|
|
||||||
beforeEach(async(() => {
|
|
||||||
node = new MapNode();
|
|
||||||
const selectionManagerMock = mock(SelectionManager);
|
|
||||||
when(selectionManagerMock.getSelected()).thenReturn([node]);
|
|
||||||
|
|
||||||
nodeServiceMock = mock(NodeService);
|
|
||||||
hotkeyServiceMock = mock(HotkeysService);
|
|
||||||
hotkeyServiceInstanceMock = instance(hotkeyServiceMock);
|
|
||||||
TestBed.configureTestingModule({
|
|
||||||
imports: [HotkeyModule.forRoot(), HttpClientTestingModule],
|
|
||||||
providers: [
|
|
||||||
HttpServer,
|
|
||||||
{ provide: NodeService, useFactory: () => instance(nodeServiceMock) },
|
|
||||||
{ provide: HotkeysService, useFactory: () => hotkeyServiceInstanceMock },
|
|
||||||
{ provide: ToasterService, useClass: MockedToasterService },
|
|
||||||
{ provide: ProjectService, useClass: MockedProjectService },
|
|
||||||
{ provide: SelectionManager, useValue: instance(selectionManagerMock) },
|
|
||||||
SettingsService,
|
|
||||||
MapNodeToNodeConverter,
|
|
||||||
MapLabelToLabelConverter,
|
|
||||||
MapPortToPortConverter,
|
|
||||||
MapLabelToLabelConverter,
|
|
||||||
FontBBoxCalculator,
|
|
||||||
CssFixer,
|
|
||||||
FontFixer
|
|
||||||
],
|
|
||||||
declarations: [ProjectMapShortcutsComponent]
|
|
||||||
}).compileComponents();
|
|
||||||
}));
|
|
||||||
|
|
||||||
beforeEach(() => {
|
|
||||||
fixture = TestBed.createComponent(ProjectMapShortcutsComponent);
|
|
||||||
component = fixture.componentInstance;
|
|
||||||
fixture.detectChanges();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should create', () => {
|
|
||||||
expect(component).toBeTruthy();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should bind delete key', () => {
|
|
||||||
component.ngOnInit();
|
|
||||||
const [hotkey] = capture(hotkeyServiceMock.add).last();
|
|
||||||
expect((hotkey as Hotkey).combo).toEqual(['del']);
|
|
||||||
expect((hotkey as Hotkey).callback).toBeDefined();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should remove binding', () => {
|
|
||||||
component.ngOnDestroy();
|
|
||||||
const [hotkey] = capture(hotkeyServiceMock.remove).last();
|
|
||||||
expect((hotkey as Hotkey).combo).toEqual(['del']);
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('onDeleteHandler', () => {
|
|
||||||
beforeEach(() => {
|
|
||||||
const server = new Server();
|
|
||||||
const project = new Project();
|
|
||||||
|
|
||||||
when(nodeServiceMock.delete(server, anything())).thenReturn(of(new Node()).pipe(mapTo(null)));
|
|
||||||
|
|
||||||
component.project = project;
|
|
||||||
component.server = server;
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should handle delete', inject([ToasterService], (toaster: MockedToasterService) => {
|
|
||||||
component.project.readonly = false;
|
|
||||||
component.onDeleteHandler(null);
|
|
||||||
expect(toaster.successes).toEqual(['Node has been deleted']);
|
|
||||||
}));
|
|
||||||
|
|
||||||
it('should not delete when project in readonly mode', inject([ToasterService], (toaster: MockedToasterService) => {
|
|
||||||
component.project.readonly = true;
|
|
||||||
component.onDeleteHandler(null);
|
|
||||||
expect(toaster.successes).toEqual([]);
|
|
||||||
}));
|
|
||||||
});
|
|
||||||
});
|
|
@ -1,59 +0,0 @@
|
|||||||
import { Component, OnInit, OnDestroy, Input } from '@angular/core';
|
|
||||||
import { HotkeysService, Hotkey } from 'angular2-hotkeys';
|
|
||||||
|
|
||||||
import { SelectionManager } from '../../../cartography/managers/selection-manager';
|
|
||||||
import { NodeService } from '../../../services/node.service';
|
|
||||||
import { Server } from '../../../models/server';
|
|
||||||
import { ToasterService } from '../../../services/toaster.service';
|
|
||||||
import { Project } from '../../../models/project';
|
|
||||||
import { ProjectService } from '../../../services/project.service';
|
|
||||||
import { MapNode } from '../../../cartography/models/map/map-node';
|
|
||||||
import { MapNodeToNodeConverter } from '../../../cartography/converters/map/map-node-to-node-converter';
|
|
||||||
|
|
||||||
@Component({
|
|
||||||
selector: 'app-project-map-shortcuts',
|
|
||||||
template: ''
|
|
||||||
})
|
|
||||||
export class ProjectMapShortcutsComponent implements OnInit, OnDestroy {
|
|
||||||
@Input() project: Project;
|
|
||||||
@Input() server: Server;
|
|
||||||
|
|
||||||
private deleteHotkey: Hotkey;
|
|
||||||
|
|
||||||
constructor(
|
|
||||||
private hotkeysService: HotkeysService,
|
|
||||||
private toaster: ToasterService,
|
|
||||||
private nodesService: NodeService,
|
|
||||||
private projectService: ProjectService,
|
|
||||||
private mapNodeToNode: MapNodeToNodeConverter,
|
|
||||||
private selectionManager: SelectionManager
|
|
||||||
) {}
|
|
||||||
|
|
||||||
ngOnInit() {
|
|
||||||
const self = this;
|
|
||||||
this.deleteHotkey = new Hotkey('del', (event: KeyboardEvent) => {
|
|
||||||
return self.onDeleteHandler(event);
|
|
||||||
});
|
|
||||||
this.hotkeysService.add(this.deleteHotkey);
|
|
||||||
}
|
|
||||||
|
|
||||||
onDeleteHandler(event: KeyboardEvent): boolean {
|
|
||||||
if (!this.projectService.isReadOnly(this.project)) {
|
|
||||||
const selected = this.selectionManager.getSelected();
|
|
||||||
|
|
||||||
selected
|
|
||||||
.filter(item => item instanceof MapNode)
|
|
||||||
.forEach((item: MapNode) => {
|
|
||||||
const node = this.mapNodeToNode.convert(item);
|
|
||||||
this.nodesService.delete(this.server, node).subscribe(data => {
|
|
||||||
this.toaster.success('Node has been deleted');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
ngOnDestroy() {
|
|
||||||
this.hotkeysService.remove(this.deleteHotkey);
|
|
||||||
}
|
|
||||||
}
|
|
@ -193,7 +193,6 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<app-progress></app-progress>
|
<app-progress></app-progress>
|
||||||
<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-draw-link-tool [links]="links" *ngIf="tools.draw_link"></app-draw-link-tool>
|
||||||
|
|
||||||
<app-drawing-dragged [server]="server" [project]="project"></app-drawing-dragged>
|
<app-drawing-dragged [server]="server" [project]="project"></app-drawing-dragged>
|
||||||
|
@ -73,6 +73,7 @@ import { Title } from '@angular/platform-browser';
|
|||||||
import { NewTemplateDialogComponent } from './new-template-dialog/new-template-dialog.component';
|
import { NewTemplateDialogComponent } from './new-template-dialog/new-template-dialog.component';
|
||||||
import { NodeConsoleService } from '../../services/nodeConsole.service';
|
import { NodeConsoleService } from '../../services/nodeConsole.service';
|
||||||
import { ProjectReadmeComponent } from './project-readme/project-readme.component';
|
import { ProjectReadmeComponent } from './project-readme/project-readme.component';
|
||||||
|
import * as Mousetrap from 'mousetrap';
|
||||||
|
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
@ -168,12 +169,7 @@ export class ProjectMapComponent implements OnInit, OnDestroy {
|
|||||||
) {}
|
) {}
|
||||||
|
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
this.themeService.getActualTheme() === 'light' ? this.isLightThemeEnabled = true : this.isLightThemeEnabled = false;
|
this.getSettings();
|
||||||
this.settings = this.settingsService.getAll();
|
|
||||||
this.isTopologySummaryVisible = this.mapSettingsService.isTopologySummaryVisible;
|
|
||||||
this.isConsoleVisible = this.mapSettingsService.isLogConsoleVisible;
|
|
||||||
this.mapSettingsService.logConsoleSubject.subscribe(value => this.isConsoleVisible = value);
|
|
||||||
|
|
||||||
this.progressService.activate();
|
this.progressService.activate();
|
||||||
|
|
||||||
if (this.serverService.isServiceInitialized) {
|
if (this.serverService.isServiceInitialized) {
|
||||||
@ -186,6 +182,22 @@ export class ProjectMapComponent implements OnInit, OnDestroy {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.addSubscriptions();
|
||||||
|
this.addKeyboardListeners();
|
||||||
|
}
|
||||||
|
|
||||||
|
getSettings() {
|
||||||
|
this.themeService.getActualTheme() === 'light' ? this.isLightThemeEnabled = true : this.isLightThemeEnabled = false;
|
||||||
|
this.settings = this.settingsService.getAll();
|
||||||
|
this.isTopologySummaryVisible = this.mapSettingsService.isTopologySummaryVisible;
|
||||||
|
this.isConsoleVisible = this.mapSettingsService.isLogConsoleVisible;
|
||||||
|
this.mapSettingsService.logConsoleSubject.subscribe(value => this.isConsoleVisible = value);
|
||||||
|
this.notificationsVisibility = localStorage.getItem('notificationsVisibility') === 'true' ? true : false;
|
||||||
|
this.layersVisibility = localStorage.getItem('layersVisibility') === 'true' ? true : false;
|
||||||
|
this.gridVisibility = localStorage.getItem('gridVisibility') === 'true' ? true : false;
|
||||||
|
}
|
||||||
|
|
||||||
|
addSubscriptions() {
|
||||||
this.projectMapSubscription.add(
|
this.projectMapSubscription.add(
|
||||||
this.mapSettingsService.mapRenderedEmitter.subscribe((value: boolean) => {
|
this.mapSettingsService.mapRenderedEmitter.subscribe((value: boolean) => {
|
||||||
if (this.scrollEnabled) this.centerCanvas();
|
if (this.scrollEnabled) this.centerCanvas();
|
||||||
@ -203,7 +215,7 @@ export class ProjectMapComponent implements OnInit, OnDestroy {
|
|||||||
this.nodesDataSource.changes.subscribe((nodes: Node[]) => {
|
this.nodesDataSource.changes.subscribe((nodes: Node[]) => {
|
||||||
if (!this.server) return;
|
if (!this.server) return;
|
||||||
nodes.forEach((node: Node) => {
|
nodes.forEach((node: Node) => {
|
||||||
node.symbol_url = `http://${this.server.host}:${this.server.port}/v2/symbols/${node.symbol}/raw`;
|
node.symbol_url = `${this.server.protocol}//${this.server.host}:${this.server.port}/v2/symbols/${node.symbol}/raw`;
|
||||||
});
|
});
|
||||||
|
|
||||||
this.nodes = nodes;
|
this.nodes = nodes;
|
||||||
@ -231,11 +243,6 @@ export class ProjectMapComponent implements OnInit, OnDestroy {
|
|||||||
message: message
|
message: message
|
||||||
});
|
});
|
||||||
}));
|
}));
|
||||||
|
|
||||||
this.notificationsVisibility = localStorage.getItem('notificationsVisibility') === 'true' ? true : false;
|
|
||||||
this.layersVisibility = localStorage.getItem('layersVisibility') === 'true' ? true : false;
|
|
||||||
this.gridVisibility = localStorage.getItem('gridVisibility') === 'true' ? true : false;
|
|
||||||
this.addKeyboardListeners();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
getData() {
|
getData() {
|
||||||
@ -330,6 +337,20 @@ export class ProjectMapComponent implements OnInit, OnDestroy {
|
|||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
this.router.navigate(['/server', this.server.id, 'preferences']);
|
this.router.navigate(['/server', this.server.id, 'preferences']);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Mousetrap.bind('del', (event: Event) => {
|
||||||
|
event.preventDefault();
|
||||||
|
const selected = this.selectionManager.getSelected();
|
||||||
|
|
||||||
|
selected
|
||||||
|
.filter(item => item instanceof MapNode)
|
||||||
|
.forEach((item: MapNode) => {
|
||||||
|
const node = this.mapNodeToNode.convert(item);
|
||||||
|
this.nodeService.delete(this.server, node).subscribe(data => {
|
||||||
|
this.toasterService.success('Node has been deleted');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
onProjectLoad(project: Project) {
|
onProjectLoad(project: Project) {
|
||||||
|
@ -15,7 +15,7 @@ import { projectNameAsyncValidator } from '../../../validators/project-name-asyn
|
|||||||
@Component({
|
@Component({
|
||||||
selector: 'app-add-blank-project-dialog',
|
selector: 'app-add-blank-project-dialog',
|
||||||
templateUrl: './add-blank-project-dialog.component.html',
|
templateUrl: './add-blank-project-dialog.component.html',
|
||||||
styleUrls: ['./add-blank-project-dialog.component.css'],
|
styleUrls: ['./add-blank-project-dialog.component.scss'],
|
||||||
providers: [ProjectNameValidator]
|
providers: [ProjectNameValidator]
|
||||||
})
|
})
|
||||||
export class AddBlankProjectDialogComponent implements OnInit {
|
export class AddBlankProjectDialogComponent implements OnInit {
|
||||||
|
@ -5,7 +5,7 @@ import { Project } from '../../../models/project';
|
|||||||
@Component({
|
@Component({
|
||||||
selector: 'app-import-project-dialog',
|
selector: 'app-import-project-dialog',
|
||||||
templateUrl: 'confirmation-dialog.component.html',
|
templateUrl: 'confirmation-dialog.component.html',
|
||||||
styleUrls: ['confirmation-dialog.component.css']
|
styleUrls: ['confirmation-dialog.component.scss']
|
||||||
})
|
})
|
||||||
export class ConfirmationDialogComponent implements OnInit {
|
export class ConfirmationDialogComponent implements OnInit {
|
||||||
private existingProject: Project;
|
private existingProject: Project;
|
||||||
|
@ -13,7 +13,7 @@ import { ProjectNameValidator } from '../models/projectNameValidator';
|
|||||||
@Component({
|
@Component({
|
||||||
selector: 'app-import-project-dialog',
|
selector: 'app-import-project-dialog',
|
||||||
templateUrl: 'import-project-dialog.component.html',
|
templateUrl: 'import-project-dialog.component.html',
|
||||||
styleUrls: ['import-project-dialog.component.css'],
|
styleUrls: ['import-project-dialog.component.scss'],
|
||||||
providers: [ProjectNameValidator]
|
providers: [ProjectNameValidator]
|
||||||
})
|
})
|
||||||
export class ImportProjectDialogComponent implements OnInit {
|
export class ImportProjectDialogComponent implements OnInit {
|
||||||
|
@ -28,7 +28,7 @@ import { ElectronService } from 'ngx-electron';
|
|||||||
@Component({
|
@Component({
|
||||||
selector: 'app-projects',
|
selector: 'app-projects',
|
||||||
templateUrl: './projects.component.html',
|
templateUrl: './projects.component.html',
|
||||||
styleUrls: ['./projects.component.css']
|
styleUrls: ['./projects.component.scss']
|
||||||
})
|
})
|
||||||
export class ProjectsComponent implements OnInit {
|
export class ProjectsComponent implements OnInit {
|
||||||
server: Server;
|
server: Server;
|
||||||
|
@ -14,7 +14,7 @@ import { NodesDataSource } from '../../../cartography/datasources/nodes-datasour
|
|||||||
@Component({
|
@Component({
|
||||||
selector: 'app-save-project-dialog',
|
selector: 'app-save-project-dialog',
|
||||||
templateUrl: './save-project-dialog.component.html',
|
templateUrl: './save-project-dialog.component.html',
|
||||||
styleUrls: ['./save-project-dialog.component.css'],
|
styleUrls: ['./save-project-dialog.component.scss'],
|
||||||
providers: [ProjectNameValidator]
|
providers: [ProjectNameValidator]
|
||||||
})
|
})
|
||||||
export class SaveProjectDialogComponent implements OnInit {
|
export class SaveProjectDialogComponent implements OnInit {
|
||||||
|
@ -28,6 +28,12 @@
|
|||||||
<input matInput tabindex="1" formControlName="port" placeholder="Port" />
|
<input matInput tabindex="1" formControlName="port" placeholder="Port" />
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
|
|
||||||
|
<mat-form-field>
|
||||||
|
<mat-select placeholder="Protocol" formControlName="protocol" >
|
||||||
|
<mat-option *ngFor="let protocol of protocols" [value]="protocol.key"> {{ protocol.name }} </mat-option>
|
||||||
|
</mat-select>
|
||||||
|
</mat-form-field>
|
||||||
|
|
||||||
<mat-form-field *ngIf="serverForm.get('location').value === 'remote'">
|
<mat-form-field *ngIf="serverForm.get('location').value === 'remote'">
|
||||||
<mat-select placeholder="Authorization" formControlName="authorization" >
|
<mat-select placeholder="Authorization" formControlName="authorization" >
|
||||||
<mat-option *ngFor="let auth of authorizations" [value]="auth.key"> {{ auth.name }} </mat-option>
|
<mat-option *ngFor="let auth of authorizations" [value]="auth.key"> {{ auth.name }} </mat-option>
|
||||||
|
@ -13,6 +13,7 @@ import { ToasterService } from '../../../services/toaster.service';
|
|||||||
})
|
})
|
||||||
export class AddServerDialogComponent implements OnInit {
|
export class AddServerDialogComponent implements OnInit {
|
||||||
authorizations = [{ key: 'none', name: 'No authorization' }, { key: 'basic', name: 'Basic authorization' }];
|
authorizations = [{ key: 'none', name: 'No authorization' }, { key: 'basic', name: 'Basic authorization' }];
|
||||||
|
protocols = [{ key: 'http:', name: 'HTTP' }, { key: 'https:', name: 'HTTPS' }];
|
||||||
locations = [];
|
locations = [];
|
||||||
|
|
||||||
serverForm = new FormGroup({
|
serverForm = new FormGroup({
|
||||||
@ -22,6 +23,7 @@ export class AddServerDialogComponent implements OnInit {
|
|||||||
'ubridge_path': new FormControl(''),
|
'ubridge_path': new FormControl(''),
|
||||||
'host': new FormControl('', [ Validators.required ]),
|
'host': new FormControl('', [ Validators.required ]),
|
||||||
'port': new FormControl('', [ Validators.required, Validators.min(1) ]),
|
'port': new FormControl('', [ Validators.required, Validators.min(1) ]),
|
||||||
|
'protocol': new FormControl('http:'),
|
||||||
'authorization': new FormControl('none'),
|
'authorization': new FormControl('none'),
|
||||||
'login': new FormControl(''),
|
'login': new FormControl(''),
|
||||||
'password': new FormControl('')
|
'password': new FormControl('')
|
||||||
|
@ -3,13 +3,14 @@ import { Component, OnInit } from '@angular/core';
|
|||||||
import { Observable } from 'rxjs/Rx';
|
import { Observable } from 'rxjs/Rx';
|
||||||
import { map } from 'rxjs//operators';
|
import { map } from 'rxjs//operators';
|
||||||
|
|
||||||
import { Server } from '../../../models/server';
|
import { Server, ServerProtocol } from '../../../models/server';
|
||||||
import { VersionService } from '../../../services/version.service';
|
import { VersionService } from '../../../services/version.service';
|
||||||
import { Version } from '../../../models/version';
|
import { Version } from '../../../models/version';
|
||||||
import { forkJoin } from 'rxjs';
|
import { forkJoin } from 'rxjs';
|
||||||
import { ServerService } from '../../../services/server.service';
|
import { ServerService } from '../../../services/server.service';
|
||||||
import { ServerDatabase } from '../../../services/server.database';
|
import { ServerDatabase } from '../../../services/server.database';
|
||||||
import { from } from 'rxjs';
|
import { from } from 'rxjs';
|
||||||
|
import { ActivatedRoute } from '@angular/router';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-server-discovery',
|
selector: 'app-server-discovery',
|
||||||
@ -29,33 +30,62 @@ export class ServerDiscoveryComponent implements OnInit {
|
|||||||
constructor(
|
constructor(
|
||||||
private versionService: VersionService,
|
private versionService: VersionService,
|
||||||
private serverService: ServerService,
|
private serverService: ServerService,
|
||||||
private serverDatabase: ServerDatabase
|
private serverDatabase: ServerDatabase,
|
||||||
|
private route : ActivatedRoute
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
if (this.serverService.isServiceInitialized) this.discoverFirstAvailableServer();
|
if (this.serverService.isServiceInitialized) this.discoverFirstServer();
|
||||||
|
|
||||||
this.serverService.serviceInitialized.subscribe(async (value: boolean) => {
|
this.serverService.serviceInitialized.subscribe(async (value: boolean) => {
|
||||||
if (value) {
|
if (value) {
|
||||||
this.discoverFirstAvailableServer();
|
this.discoverFirstServer();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async discoverFirstServer() {
|
||||||
|
let discovered = await this.discoverServers();
|
||||||
|
let local = await this.serverService.findAll();
|
||||||
|
|
||||||
|
local.forEach(added => {
|
||||||
|
discovered = discovered.filter(server => {
|
||||||
|
return !(server.host == added.host && server.port == added.port);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
if (discovered.length > 0) {
|
||||||
|
this.discoveredServer = discovered.shift();
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
async discoverServers() {
|
||||||
|
let discoveredServers: Server[] = [];
|
||||||
|
this.defaultServers.forEach(async (testServer) => {
|
||||||
|
const server = new Server();
|
||||||
|
server.host = testServer.host;
|
||||||
|
server.port = testServer.port;
|
||||||
|
let version = await this.versionService.get(server).toPromise().catch(error => null);
|
||||||
|
if (version) discoveredServers.push(server);
|
||||||
|
});
|
||||||
|
return discoveredServers;
|
||||||
|
}
|
||||||
|
|
||||||
discoverFirstAvailableServer() {
|
discoverFirstAvailableServer() {
|
||||||
forkJoin(
|
forkJoin(
|
||||||
[from(this.serverService.findAll()).pipe(map((s: Server[]) => s)),
|
[from(this.serverService.findAll()).pipe(map((s: Server[]) => s)),
|
||||||
this.discovery()]
|
this.discovery()]
|
||||||
).subscribe(([local, discovered]) => {
|
).subscribe(
|
||||||
local.forEach(added => {
|
([local, discovered]) => {
|
||||||
discovered = discovered.filter(server => {
|
local.forEach(added => {
|
||||||
return !(server.host == added.host && server.port == added.port);
|
discovered = discovered.filter(server => {
|
||||||
|
return !(server.host == added.host && server.port == added.port);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
if (discovered.length > 0) {
|
||||||
if (discovered.length > 0) {
|
this.discoveredServer = discovered.shift();
|
||||||
this.discoveredServer = discovered.shift();
|
}
|
||||||
}
|
},
|
||||||
});
|
error => {});
|
||||||
}
|
}
|
||||||
|
|
||||||
discovery(): Observable<Server[]> {
|
discovery(): Observable<Server[]> {
|
||||||
@ -94,6 +124,7 @@ export class ServerDiscoveryComponent implements OnInit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
server.location = 'remote';
|
server.location = 'remote';
|
||||||
|
server.protocol = location.protocol as ServerProtocol;
|
||||||
|
|
||||||
this.serverService.create(server).then((created: Server) => {
|
this.serverService.create(server).then((created: Server) => {
|
||||||
this.serverDatabase.addServer(created);
|
this.serverDatabase.addServer(created);
|
||||||
|
@ -4,8 +4,8 @@ import { MatBottomSheet } from '@angular/material/bottom-sheet';
|
|||||||
import { MatDialog, MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';
|
import { MatDialog, MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';
|
||||||
import { Observable, merge, Subscription } from 'rxjs';
|
import { Observable, merge, Subscription } from 'rxjs';
|
||||||
import { map } from 'rxjs/operators';
|
import { map } from 'rxjs/operators';
|
||||||
import { Router } from '@angular/router';
|
import { ActivatedRoute, Router } from '@angular/router';
|
||||||
import { Server } from '../../models/server';
|
import { Server, ServerProtocol } from '../../models/server';
|
||||||
import { ServerService } from '../../services/server.service';
|
import { ServerService } from '../../services/server.service';
|
||||||
import { ServerDatabase } from '../../services/server.database';
|
import { ServerDatabase } from '../../services/server.database';
|
||||||
import { AddServerDialogComponent } from './add-server-dialog/add-server-dialog.component';
|
import { AddServerDialogComponent } from './add-server-dialog/add-server-dialog.component';
|
||||||
@ -18,7 +18,7 @@ import { ConfirmationBottomSheetComponent } from '../projects/confirmation-botto
|
|||||||
@Component({
|
@Component({
|
||||||
selector: 'app-server-list',
|
selector: 'app-server-list',
|
||||||
templateUrl: './servers.component.html',
|
templateUrl: './servers.component.html',
|
||||||
styleUrls: ['./servers.component.css']
|
styleUrls: ['./servers.component.scss']
|
||||||
})
|
})
|
||||||
export class ServersComponent implements OnInit, OnDestroy {
|
export class ServersComponent implements OnInit, OnDestroy {
|
||||||
dataSource: ServerDataSource;
|
dataSource: ServerDataSource;
|
||||||
@ -35,6 +35,7 @@ export class ServersComponent implements OnInit, OnDestroy {
|
|||||||
private electronService: ElectronService,
|
private electronService: ElectronService,
|
||||||
private childProcessService: ChildProcessService,
|
private childProcessService: ChildProcessService,
|
||||||
private bottomSheet: MatBottomSheet,
|
private bottomSheet: MatBottomSheet,
|
||||||
|
private route : ActivatedRoute
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
getServers() {
|
getServers() {
|
||||||
@ -52,6 +53,7 @@ export class ServersComponent implements OnInit, OnDestroy {
|
|||||||
this.serverService.checkServerVersion(server).subscribe(
|
this.serverService.checkServerVersion(server).subscribe(
|
||||||
(serverInfo) => {
|
(serverInfo) => {
|
||||||
if ((serverInfo.version.split('.')[1]>=2) && (serverInfo.version.split('.')[0]>=2)) {
|
if ((serverInfo.version.split('.')[1]>=2) && (serverInfo.version.split('.')[0]>=2)) {
|
||||||
|
if (!server.protocol) server.protocol = location.protocol as ServerProtocol;
|
||||||
if (!this.serverDatabase.find(server.name)) this.serverDatabase.addServer(server);
|
if (!this.serverDatabase.find(server.name)) this.serverDatabase.addServer(server);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -15,6 +15,8 @@ import { ToasterService } from '../../services/toaster.service';
|
|||||||
import { MockedToasterService } from '../../services/toaster.service.spec';
|
import { MockedToasterService } from '../../services/toaster.service.spec';
|
||||||
import { ConsoleService } from '../../services/settings/console.service';
|
import { ConsoleService } from '../../services/settings/console.service';
|
||||||
import { MapSettingsService } from '../../services/mapsettings.service';
|
import { MapSettingsService } from '../../services/mapsettings.service';
|
||||||
|
import { UpdatesService } from '../../services/updates.service';
|
||||||
|
import { autoSpy } from '../project-map/console-wrapper/console-wrapper.component.spec';
|
||||||
|
|
||||||
describe('SettingsComponent', () => {
|
describe('SettingsComponent', () => {
|
||||||
let component: SettingsComponent;
|
let component: SettingsComponent;
|
||||||
@ -25,6 +27,7 @@ describe('SettingsComponent', () => {
|
|||||||
toggleIntegrateInterfaceLabels(val: boolean) {}
|
toggleIntegrateInterfaceLabels(val: boolean) {}
|
||||||
};
|
};
|
||||||
let consoleService;
|
let consoleService;
|
||||||
|
let updatesService = autoSpy(UpdatesService);
|
||||||
|
|
||||||
beforeEach(async(() => {
|
beforeEach(async(() => {
|
||||||
consoleService = {
|
consoleService = {
|
||||||
@ -37,7 +40,8 @@ describe('SettingsComponent', () => {
|
|||||||
SettingsService,
|
SettingsService,
|
||||||
{ provide: ToasterService, useClass: MockedToasterService },
|
{ provide: ToasterService, useClass: MockedToasterService },
|
||||||
{ provide: ConsoleService, useValue: consoleService },
|
{ provide: ConsoleService, useValue: consoleService },
|
||||||
{ provide: MapSettingsService, useValue: mapSettingsService }
|
{ provide: MapSettingsService, useValue: mapSettingsService },
|
||||||
|
{ provide: UpdatesService, useValue: updatesService }
|
||||||
],
|
],
|
||||||
declarations: [SettingsComponent]
|
declarations: [SettingsComponent]
|
||||||
}).compileComponents();
|
}).compileComponents();
|
||||||
|
@ -116,7 +116,7 @@ export class TemplateComponent implements OnInit, OnDestroy {
|
|||||||
}
|
}
|
||||||
|
|
||||||
getImageSourceForTemplate(template: Template) {
|
getImageSourceForTemplate(template: Template) {
|
||||||
return `http://${this.server.host}:${this.server.port}/v2/symbols/${template.symbol}/raw`;
|
return `${this.server.protocol}//${this.server.host}:${this.server.port}/v2/symbols/${template.symbol}/raw`;
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnDestroy() {
|
ngOnDestroy() {
|
||||||
|
@ -72,6 +72,12 @@
|
|||||||
<div class="summaryContentServers">
|
<div class="summaryContentServers">
|
||||||
<div class="nodeRow" *ngFor="let compute of computes">
|
<div class="nodeRow" *ngFor="let compute of computes">
|
||||||
<div>
|
<div>
|
||||||
|
<svg *ngIf="compute.connected" width="10" height="10">
|
||||||
|
<rect class="status_started" x="0" y="0" width="10" height="10" fill="green"></rect>
|
||||||
|
</svg>
|
||||||
|
<svg *ngIf="!compute.connected" width="10" height="10">
|
||||||
|
<rect class="status_stopped" x="0" y="0" width="10" height="10" fill="red"></rect>
|
||||||
|
</svg>
|
||||||
{{compute.name}}
|
{{compute.name}}
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
|
@ -1,3 +1,9 @@
|
|||||||
|
@media screen and (max-width: 600px) {
|
||||||
|
.summaryWrapper {
|
||||||
|
visibility: hidden;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.summaryWrapper {
|
.summaryWrapper {
|
||||||
box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);
|
box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);
|
||||||
position: fixed;
|
position: fixed;
|
||||||
|
12
src/app/directives/LazyImg.directive.ts
Normal file
12
src/app/directives/LazyImg.directive.ts
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
import { Directive, ElementRef } from '@angular/core';
|
||||||
|
|
||||||
|
@Directive({ selector: '[lazyimg]' })
|
||||||
|
export class LazyImgDirective {
|
||||||
|
constructor({ nativeElement }: ElementRef<HTMLImageElement>) {
|
||||||
|
const supports = 'loading' in HTMLImageElement.prototype;
|
||||||
|
|
||||||
|
if (supports) {
|
||||||
|
nativeElement.setAttribute('loading', 'lazy');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -13,7 +13,7 @@ import { Router } from '@angular/router';
|
|||||||
selector: 'app-default-layout',
|
selector: 'app-default-layout',
|
||||||
encapsulation: ViewEncapsulation.None,
|
encapsulation: ViewEncapsulation.None,
|
||||||
templateUrl: './default-layout.component.html',
|
templateUrl: './default-layout.component.html',
|
||||||
styleUrls: ['./default-layout.component.css']
|
styleUrls: ['./default-layout.component.scss']
|
||||||
})
|
})
|
||||||
export class DefaultLayoutComponent implements OnInit, OnDestroy {
|
export class DefaultLayoutComponent implements OnInit, OnDestroy {
|
||||||
public isInstalledSoftwareAvailable = false;
|
public isInstalledSoftwareAvailable = false;
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
export type ServerAuthorization = 'basic' | 'none';
|
export type ServerAuthorization = 'basic' | 'none';
|
||||||
export type ServerLocation = 'local' | 'remote' | 'bundled';
|
export type ServerLocation = 'local' | 'remote' | 'bundled';
|
||||||
export type ServerStatus = 'stopped' | 'starting' | 'running';
|
export type ServerStatus = 'stopped' | 'starting' | 'running';
|
||||||
|
export type ServerProtocol = 'http:' | 'https:'
|
||||||
|
|
||||||
export class Server {
|
export class Server {
|
||||||
id: number;
|
id: number;
|
||||||
@ -14,4 +15,5 @@ export class Server {
|
|||||||
login: string;
|
login: string;
|
||||||
password: string;
|
password: string;
|
||||||
status: ServerStatus;
|
status: ServerStatus;
|
||||||
|
protocol: ServerProtocol;
|
||||||
}
|
}
|
||||||
|
@ -19,7 +19,7 @@ export class ApplianceService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
getUploadPath(server: Server, emulator: string, filename: string) {
|
getUploadPath(server: Server, emulator: string, filename: string) {
|
||||||
return `http://${server.host}:${server.port}/v2/compute/${emulator}/images/${filename}`;
|
return `${server.protocol}//${server.host}:${server.port}/v2/compute/${emulator}/images/${filename}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
updateAppliances(server: Server): Observable<Appliance[]> {
|
updateAppliances(server: Server): Observable<Appliance[]> {
|
||||||
|
@ -6,8 +6,8 @@ export class BuiltInTemplatesConfigurationService {
|
|||||||
let categories = [["Default", "guest"],
|
let categories = [["Default", "guest"],
|
||||||
["Routers", "router"],
|
["Routers", "router"],
|
||||||
["Switches", "switch"],
|
["Switches", "switch"],
|
||||||
["End devices", "end_device"],
|
["End devices", "guest"],
|
||||||
["Security devices", "security_device"]];
|
["Security devices", "firewall"]];
|
||||||
|
|
||||||
return categories;
|
return categories;
|
||||||
}
|
}
|
||||||
@ -20,8 +20,8 @@ export class BuiltInTemplatesConfigurationService {
|
|||||||
let categories = [["Default", "guest"],
|
let categories = [["Default", "guest"],
|
||||||
["Routers", "router"],
|
["Routers", "router"],
|
||||||
["Switches", "switch"],
|
["Switches", "switch"],
|
||||||
["End devices", "end_device"],
|
["End devices", "guest"],
|
||||||
["Security devices", "security_device"]];
|
["Security devices", "firewall"]];
|
||||||
|
|
||||||
return categories;
|
return categories;
|
||||||
}
|
}
|
||||||
@ -30,8 +30,8 @@ export class BuiltInTemplatesConfigurationService {
|
|||||||
let categories = [["Default", "guest"],
|
let categories = [["Default", "guest"],
|
||||||
["Routers", "router"],
|
["Routers", "router"],
|
||||||
["Switches", "switch"],
|
["Switches", "switch"],
|
||||||
["End devices", "end_device"],
|
["End devices", "guest"],
|
||||||
["Security devices", "security_device"]];
|
["Security devices", "firewall"]];
|
||||||
|
|
||||||
return categories;
|
return categories;
|
||||||
}
|
}
|
||||||
|
@ -14,7 +14,7 @@ export class ComputeService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
getUploadPath(server: Server, emulator: string, filename: string) {
|
getUploadPath(server: Server, emulator: string, filename: string) {
|
||||||
return `http://${server.host}:${server.port}/v2/${emulator}/images/${filename}`;
|
return `${server.protocol}//${server.host}:${server.port}/v2/${emulator}/images/${filename}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
getStatistics(server: Server): Observable<ComputeStatistics[]> {
|
getStatistics(server: Server): Observable<ComputeStatistics[]> {
|
||||||
|
@ -8,10 +8,10 @@ export class DockerConfigurationService {
|
|||||||
|
|
||||||
getCategories() {
|
getCategories() {
|
||||||
let categories = [["Default", "guest"],
|
let categories = [["Default", "guest"],
|
||||||
["Routers", "routers"],
|
["Routers", "router"],
|
||||||
["Switches", "switches"],
|
["Switches", "switch"],
|
||||||
["End devices", "end_devices"],
|
["End devices", "guest"],
|
||||||
["Security devices", "security_devices"]];
|
["Security devices", "firewall"]];
|
||||||
|
|
||||||
return categories;
|
return categories;
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,7 @@ import { HttpHeaders, HttpClient, HttpParams, HttpErrorResponse } from '@angular
|
|||||||
import { Observable, throwError } from 'rxjs';
|
import { Observable, throwError } from 'rxjs';
|
||||||
import { catchError } from 'rxjs/operators';
|
import { catchError } from 'rxjs/operators';
|
||||||
|
|
||||||
import { Server } from '../models/server';
|
import { Server, ServerProtocol } from '../models/server';
|
||||||
|
|
||||||
/* tslint:disable:interface-over-type-literal */
|
/* tslint:disable:interface-over-type-literal */
|
||||||
export type JsonOptions = {
|
export type JsonOptions = {
|
||||||
@ -177,13 +177,10 @@ export class HttpServer {
|
|||||||
|
|
||||||
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.authorization === 'basic') {
|
if (!server.protocol) {
|
||||||
url = `https://${server.host}:${server.port}/v2${url}`;
|
server.protocol = location.protocol as ServerProtocol;
|
||||||
console.log(url);
|
|
||||||
} else {
|
|
||||||
url = `http://${server.host}:${server.port}/v2${url}`;
|
|
||||||
console.log(url);
|
|
||||||
}
|
}
|
||||||
|
url = `${server.protocol}//${server.host}:${server.port}/v2${url}`;
|
||||||
} else {
|
} else {
|
||||||
url = `/v2${url}`;
|
url = `/v2${url}`;
|
||||||
}
|
}
|
||||||
|
@ -14,7 +14,7 @@ export class IosService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
getImagePath(server: Server, filename: string): string {
|
getImagePath(server: Server, filename: string): string {
|
||||||
return `http://${server.host}:${server.port}/v2/compute/dynamips/images/${filename}`;
|
return `${server.protocol}//${server.host}:${server.port}/v2/compute/dynamips/images/${filename}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
getTemplates(server: Server): Observable<IosTemplate[]> {
|
getTemplates(server: Server): Observable<IosTemplate[]> {
|
||||||
|
@ -10,8 +10,8 @@ export class IouConfigurationService {
|
|||||||
let categories = [["Default", "guest"],
|
let categories = [["Default", "guest"],
|
||||||
["Routers", "router"],
|
["Routers", "router"],
|
||||||
["Switches", "switch"],
|
["Switches", "switch"],
|
||||||
["End devices", "end_device"],
|
["End devices", "guest"],
|
||||||
["Security devices", "security_device"]];
|
["Security devices", "firewall"]];
|
||||||
|
|
||||||
return categories;
|
return categories;
|
||||||
}
|
}
|
||||||
|
@ -22,7 +22,7 @@ export class IouService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
getImagePath(server: Server, filename: string): string {
|
getImagePath(server: Server, filename: string): string {
|
||||||
return `http://${server.host}:${server.port}/v2/compute/iou/images/${filename}`;
|
return `${server.protocol}//${server.host}:${server.port}/v2/compute/iou/images/${filename}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
addTemplate(server: Server, iouTemplate: any): Observable<any> {
|
addTemplate(server: Server, iouTemplate: any): Observable<any> {
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
import { Injectable, EventEmitter } from "@angular/core";
|
import { Injectable, EventEmitter } from "@angular/core";
|
||||||
import { Subject } from 'rxjs';
|
import { Subject } from 'rxjs';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable({
|
||||||
|
providedIn: 'root'
|
||||||
|
})
|
||||||
export class MapSettingsService {
|
export class MapSettingsService {
|
||||||
public isScrollDisabled = new Subject<boolean>();
|
public isScrollDisabled = new Subject<boolean>();
|
||||||
public isMapLocked = new Subject<boolean>();
|
public isMapLocked = new Subject<boolean>();
|
||||||
|
@ -77,11 +77,11 @@ export class ProjectService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
getUploadPath(server: Server, uuid: string, project_name: string) {
|
getUploadPath(server: Server, uuid: string, project_name: string) {
|
||||||
return `http://${server.host}:${server.port}/v2/projects/${uuid}/import?name=${project_name}`;
|
return `${server.protocol}//${server.host}:${server.port}/v2/projects/${uuid}/import?name=${project_name}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
getExportPath(server: Server, project: Project) {
|
getExportPath(server: Server, project: Project) {
|
||||||
return `http://${server.host}:${server.port}/v2/projects/${project.project_id}/export`;
|
return `${server.protocol}//${server.host}:${server.port}/v2/projects/${project.project_id}/export`;
|
||||||
}
|
}
|
||||||
|
|
||||||
export(server: Server, project_id: string): Observable<any> {
|
export(server: Server, project_id: string): Observable<any> {
|
||||||
|
@ -64,17 +64,17 @@ export class QemuConfigurationService {
|
|||||||
|
|
||||||
getBootPriorities() {
|
getBootPriorities() {
|
||||||
let bootPriorities = [["HDD", "c"],
|
let bootPriorities = [["HDD", "c"],
|
||||||
["CD/DVD-ROM", "d"],
|
["CD/DVD-ROM", "d"],
|
||||||
["Network", "n"],
|
["Network", "n"],
|
||||||
["HDD or Network", "cn"],
|
["HDD or Network", "cn"],
|
||||||
["HDD or CD/DVD-ROM", "cd"]];
|
["HDD or CD/DVD-ROM", "cd"]];
|
||||||
|
|
||||||
return bootPriorities;
|
return bootPriorities;
|
||||||
}
|
}
|
||||||
|
|
||||||
getOnCloseOptions() {
|
getOnCloseOptions() {
|
||||||
let onCloseOptions = [["Power off the VM", "power_off"],
|
let onCloseOptions = [["Power off the VM", "power_off"],
|
||||||
["Send the shutdown signal (ACPI)", "shutdown_signal"],
|
["Send the shutdown signal (ACPI)", "shutdown_signal"],
|
||||||
["Save the VM state", "save_vm_state"]];
|
["Save the VM state", "save_vm_state"]];
|
||||||
|
|
||||||
return onCloseOptions;
|
return onCloseOptions;
|
||||||
@ -82,10 +82,10 @@ export class QemuConfigurationService {
|
|||||||
|
|
||||||
getCategories() {
|
getCategories() {
|
||||||
let categories = [["Default", "guest"],
|
let categories = [["Default", "guest"],
|
||||||
["Routers", "routers"],
|
["Routers", "router"],
|
||||||
["Switches", "switches"],
|
["Switches", "switch"],
|
||||||
["End devices", "end_devices"],
|
["End devices", "guest"],
|
||||||
["Security devices", "security_devices"]];
|
["Security devices", "firewall"]];
|
||||||
|
|
||||||
return categories;
|
return categories;
|
||||||
}
|
}
|
||||||
|
@ -20,7 +20,7 @@ export class QemuService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
getImagePath(server: Server, filename: string): string {
|
getImagePath(server: Server, filename: string): string {
|
||||||
return `http://${server.host}:${server.port}/v2/compute/qemu/images/${filename}`;
|
return `${server.protocol}//${server.host}:${server.port}/v2/compute/qemu/images/${filename}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
getBinaries(server: Server): Observable<QemuBinary[]> {
|
getBinaries(server: Server): Observable<QemuBinary[]> {
|
||||||
|
@ -150,6 +150,7 @@ describe('ServerService', () => {
|
|||||||
expectedServer.host = 'hostname';
|
expectedServer.host = 'hostname';
|
||||||
expectedServer.port = 9999;
|
expectedServer.port = 9999;
|
||||||
expectedServer.location = 'bundled';
|
expectedServer.location = 'bundled';
|
||||||
|
expectedServer.protocol = 'http:';
|
||||||
|
|
||||||
service.getLocalServer('hostname', 9999).then(() => {
|
service.getLocalServer('hostname', 9999).then(() => {
|
||||||
expect(service.create).toHaveBeenCalledWith(expectedServer);
|
expect(service.create).toHaveBeenCalledWith(expectedServer);
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { Injectable, EventEmitter } from '@angular/core';
|
import { Injectable, EventEmitter } from '@angular/core';
|
||||||
import { IndexedDbService } from './indexed-db.service';
|
import { IndexedDbService } from './indexed-db.service';
|
||||||
import { Server } from '../models/server';
|
import { Server, ServerProtocol } from '../models/server';
|
||||||
import { Observable, Subject } from 'rxjs';
|
import { Observable, Subject } from 'rxjs';
|
||||||
import { HttpServer } from './http-server.service';
|
import { HttpServer } from './http-server.service';
|
||||||
|
|
||||||
@ -138,7 +138,7 @@ export class ServerService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public getServerUrl(server: Server) {
|
public getServerUrl(server: Server) {
|
||||||
return `http://${server.host}:${server.port}/`;
|
return `${server.protocol}//${server.host}:${server.port}/`;
|
||||||
}
|
}
|
||||||
|
|
||||||
public checkServerVersion(server: Server): Observable<any> {
|
public checkServerVersion(server: Server): Observable<any> {
|
||||||
@ -152,6 +152,7 @@ export class ServerService {
|
|||||||
if (local) {
|
if (local) {
|
||||||
local.host = host;
|
local.host = host;
|
||||||
local.port = port;
|
local.port = port;
|
||||||
|
local.protocol = location.protocol as ServerProtocol;
|
||||||
this.update(local).then(updated => {
|
this.update(local).then(updated => {
|
||||||
resolve(updated);
|
resolve(updated);
|
||||||
}, reject);
|
}, reject);
|
||||||
@ -161,6 +162,7 @@ export class ServerService {
|
|||||||
server.host = host;
|
server.host = host;
|
||||||
server.port = port;
|
server.port = port;
|
||||||
server.location = 'bundled';
|
server.location = 'bundled';
|
||||||
|
server.protocol = location.protocol as ServerProtocol;
|
||||||
this.create(server).then(created => {
|
this.create(server).then(created => {
|
||||||
resolve(created);
|
resolve(created);
|
||||||
}, reject);
|
}, reject);
|
||||||
|
@ -9,7 +9,9 @@ export interface Settings {
|
|||||||
console_command: string;
|
console_command: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Injectable()
|
@Injectable({
|
||||||
|
providedIn: 'root'
|
||||||
|
})
|
||||||
export class SettingsService {
|
export class SettingsService {
|
||||||
static DEFAULTS: Settings = {
|
static DEFAULTS: Settings = {
|
||||||
crash_reports: true,
|
crash_reports: true,
|
||||||
|
@ -5,5 +5,6 @@ export function getTestServer(): Server {
|
|||||||
server.host = '127.0.0.1';
|
server.host = '127.0.0.1';
|
||||||
server.port = 3080;
|
server.port = 3080;
|
||||||
server.authorization = 'none';
|
server.authorization = 'none';
|
||||||
|
server.protocol = 'http:';
|
||||||
return server;
|
return server;
|
||||||
}
|
}
|
||||||
|
@ -7,8 +7,8 @@ export class VirtualBoxConfigurationService{
|
|||||||
}
|
}
|
||||||
|
|
||||||
getOnCloseoptions() {
|
getOnCloseoptions() {
|
||||||
let onCloseOptions = [["Power off the VM", "power_off"],
|
let onCloseOptions = [["Power off the VM", "power_off"],
|
||||||
["Send the shutdown signal (ACPI)", "shutdown_signal"],
|
["Send the shutdown signal (ACPI)", "shutdown_signal"],
|
||||||
["Save the VM state", "save_vm_state"]];
|
["Save the VM state", "save_vm_state"]];
|
||||||
|
|
||||||
return onCloseOptions;
|
return onCloseOptions;
|
||||||
@ -16,10 +16,10 @@ export class VirtualBoxConfigurationService{
|
|||||||
|
|
||||||
getCategories() {
|
getCategories() {
|
||||||
let categories = [["Default", "guest"],
|
let categories = [["Default", "guest"],
|
||||||
["Routers", "routers"],
|
["Routers", "router"],
|
||||||
["Switches", "switches"],
|
["Switches", "switch"],
|
||||||
["End devices", "end_devices"],
|
["End devices", "guest"],
|
||||||
["Security devices", "security_devices"]];
|
["Security devices", "firewall"]];
|
||||||
|
|
||||||
return categories;
|
return categories;
|
||||||
}
|
}
|
||||||
@ -33,5 +33,5 @@ export class VirtualBoxConfigurationService{
|
|||||||
"Paravirtualized Network (virtio-net)"];
|
"Paravirtualized Network (virtio-net)"];
|
||||||
|
|
||||||
return networkTypes;
|
return networkTypes;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,8 +7,8 @@ export class VmwareConfigurationService{
|
|||||||
}
|
}
|
||||||
|
|
||||||
getOnCloseoptions() {
|
getOnCloseoptions() {
|
||||||
let onCloseOptions = [["Power off the VM", "power_off"],
|
let onCloseOptions = [["Power off the VM", "power_off"],
|
||||||
["Send the shutdown signal (ACPI)", "shutdown_signal"],
|
["Send the shutdown signal (ACPI)", "shutdown_signal"],
|
||||||
["Save the VM state", "save_vm_state"]];
|
["Save the VM state", "save_vm_state"]];
|
||||||
|
|
||||||
return onCloseOptions;
|
return onCloseOptions;
|
||||||
@ -16,10 +16,10 @@ export class VmwareConfigurationService{
|
|||||||
|
|
||||||
getCategories() {
|
getCategories() {
|
||||||
let categories = [["Default", "guest"],
|
let categories = [["Default", "guest"],
|
||||||
["Routers", "routers"],
|
["Routers", "router"],
|
||||||
["Switches", "switches"],
|
["Switches", "switch"],
|
||||||
["End devices", "end_devices"],
|
["End devices", "guest"],
|
||||||
["Security devices", "security_devices"]];
|
["Security devices", "firewall"]];
|
||||||
|
|
||||||
return categories;
|
return categories;
|
||||||
}
|
}
|
||||||
@ -35,5 +35,5 @@ export class VmwareConfigurationService{
|
|||||||
"vmxnet3"];
|
"vmxnet3"];
|
||||||
|
|
||||||
return networkTypes;
|
return networkTypes;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,10 +8,10 @@ export class VpcsConfigurationService {
|
|||||||
|
|
||||||
getCategories(){
|
getCategories(){
|
||||||
let categories = [["Default", "guest"],
|
let categories = [["Default", "guest"],
|
||||||
["Routers", "routers"],
|
["Routers", "router"],
|
||||||
["Switches", "switches"],
|
["Switches", "switch"],
|
||||||
["End devices", "end_devices"],
|
["End devices", "guest"],
|
||||||
["Security devices", "security_devices"]];
|
["Security devices", "firewall"]];
|
||||||
|
|
||||||
return categories;
|
return categories;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user