mirror of
https://github.com/GNS3/gns3-web-ui.git
synced 2025-06-03 07:50:50 +00:00
Merge branch 'master-2.3' into Project-readme-support
This commit is contained in:
commit
1fc48b28b3
@ -1,5 +1,5 @@
|
|||||||
# Dockerfile for GNS3 Web-ui development
|
# Dockerfile for GNS3 Web-ui development
|
||||||
FROM node:carbon
|
FROM node:stretch
|
||||||
|
|
||||||
# Create user
|
# Create user
|
||||||
RUN useradd --user-group --create-home --shell /bin/false gns3-web-ui
|
RUN useradd --user-group --create-home --shell /bin/false gns3-web-ui
|
||||||
|
@ -6,6 +6,9 @@
|
|||||||
[](https://circleci.com/gh/GNS3/gns3-web-ui/tree/master.png)
|
[](https://circleci.com/gh/GNS3/gns3-web-ui/tree/master.png)
|
||||||
[](https://codecov.io/gh/GNS3/gns3-web-ui)
|
[](https://codecov.io/gh/GNS3/gns3-web-ui)
|
||||||
|
|
||||||
|
[](https://libraries.io/github/GNS3/gns3-web-ui)
|
||||||
|
[](https://repology.org/metapackage/gns3/versions)
|
||||||
|
[](https://repology.org/metapackage/gns3/versions)
|
||||||
|
|
||||||
Test WebUI implementation for GNS3.
|
Test WebUI implementation for GNS3.
|
||||||
|
|
||||||
|
102
package.json
102
package.json
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "gns3-web-ui",
|
"name": "gns3-web-ui",
|
||||||
"version": "2020.3.0-beta.2",
|
"version": "2.2.16dev1",
|
||||||
"author": {
|
"author": {
|
||||||
"name": "GNS3 Technology Inc.",
|
"name": "GNS3 Technology Inc.",
|
||||||
"email": "developers@gns3.com"
|
"email": "developers@gns3.com"
|
||||||
@ -40,27 +40,27 @@
|
|||||||
},
|
},
|
||||||
"private": true,
|
"private": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@angular/animations": "^10.0.2",
|
"@angular/animations": "^10.1.5",
|
||||||
"@angular/cdk": "^10.0.1",
|
"@angular/cdk": "^10.2.4",
|
||||||
"@angular/common": "^10.0.2",
|
"@angular/common": "^10.1.5",
|
||||||
"@angular/compiler": "^10.0.2",
|
"@angular/compiler": "^10.1.5",
|
||||||
"@angular/core": "^10.0.2",
|
"@angular/core": "^10.1.5",
|
||||||
"@angular/forms": "^10.0.2",
|
"@angular/forms": "^10.1.5",
|
||||||
"@angular/http": "^7.2.16",
|
"@angular/http": "^7.2.16",
|
||||||
"@angular/material": "^10.0.1",
|
"@angular/material": "^10.2.4",
|
||||||
"@angular/platform-browser": "^10.0.2",
|
"@angular/platform-browser": "^10.1.5",
|
||||||
"@angular/platform-browser-dynamic": "^10.0.2",
|
"@angular/platform-browser-dynamic": "^10.1.5",
|
||||||
"@angular/router": "^10.0.2",
|
"@angular/router": "^10.1.5",
|
||||||
"@sentry/browser": "^5.18.0",
|
"@sentry/browser": "^5.26.0",
|
||||||
"@types/jest": "^26.0.3",
|
"@types/jest": "^26.0.14",
|
||||||
"@types/mocha": "^7.0.2",
|
"@types/mocha": "^8.0.3",
|
||||||
"angular-draggable-droppable": "^4.5.1",
|
"angular-draggable-droppable": "^4.5.4",
|
||||||
"angular-persistence": "^1.0.1",
|
"angular-persistence": "^1.0.1",
|
||||||
"angular-resizable-element": "^3.3.2",
|
"angular-resizable-element": "^3.3.3",
|
||||||
"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.0",
|
"bootstrap": "4.5.2",
|
||||||
"command-exists": "^1.2.9",
|
"command-exists": "^1.2.9",
|
||||||
"core-js": "^3.6.5",
|
"core-js": "^3.6.5",
|
||||||
"css-tree": "^1.0.0-alpha.36",
|
"css-tree": "^1.0.0-alpha.36",
|
||||||
@ -69,64 +69,64 @@
|
|||||||
"ini": "^1.3.5",
|
"ini": "^1.3.5",
|
||||||
"marked": "^1.1.1",
|
"marked": "^1.1.1",
|
||||||
"material-design-icons": "^3.0.1",
|
"material-design-icons": "^3.0.1",
|
||||||
"ng-circle-progress": "^1.5.1",
|
"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": "^1.4.5",
|
"ngx-device-detector": "^2.0.0",
|
||||||
"ngx-electron": "^2.1.1",
|
"ngx-electron": "^2.1.1",
|
||||||
"node-fetch": "^2.6.0",
|
"node-fetch": "^2.6.1",
|
||||||
"notosans-fontface": "1.1.0",
|
"notosans-fontface": "1.2.2",
|
||||||
"rxjs": "^6.5.5",
|
"rxjs": "^6.6.3",
|
||||||
"rxjs-compat": "^6.5.5",
|
"rxjs-compat": "^6.6.3",
|
||||||
"save-html-as-image": "^1.3.3",
|
"save-html-as-image": "^1.3.4",
|
||||||
"save-svg-as-png": "^1.4.14",
|
"save-svg-as-png": "^1.4.14",
|
||||||
"snyk": "^1.361.3",
|
"snyk": "^1.413.3",
|
||||||
"svg-crowbar": "^0.6.0",
|
"svg-crowbar": "^0.6.1",
|
||||||
"tree-kill": "^1.2.1",
|
"tree-kill": "^1.2.1",
|
||||||
"tslib": "^2.0.0",
|
"tslib": "^2.0.3",
|
||||||
"typeface-roboto": "^0.0.75",
|
"typeface-roboto": "^0.0.75",
|
||||||
"xterm": "^4.1.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": "^15.3.1",
|
"yargs": "^16.0.3",
|
||||||
"zone.js": "~0.10.3"
|
"zone.js": "~0.11.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@angular-devkit/build-angular": "~0.1000.0",
|
"@angular-devkit/build-angular": "^0.1001.6",
|
||||||
"@angular/cli": "^10.0.0",
|
"@angular/cli": "^10.1.6",
|
||||||
"@angular/compiler-cli": "^10.0.2",
|
"@angular/compiler-cli": "^10.1.5",
|
||||||
"@angular/language-service": "^10.0.2",
|
"@angular/language-service": "^10.1.5",
|
||||||
"@sentry/cli": "^1.53.0",
|
"@sentry/cli": "^1.58.0",
|
||||||
"@sentry/electron": "^1.3.0",
|
"@sentry/electron": "^2.0.1",
|
||||||
"@types/jasmine": "^3.5.11",
|
"@types/jasmine": "^3.5.14",
|
||||||
"@types/jasminewd2": "^2.0.8",
|
"@types/jasminewd2": "^2.0.8",
|
||||||
"@types/node": "12.12.6",
|
"@types/node": "14.11.2",
|
||||||
"codelyzer": "^5.2.2",
|
"codelyzer": "^6.0.1",
|
||||||
"electron": "^9.0.5",
|
"electron": "^10.1.3",
|
||||||
"electron-builder": "22.7.0",
|
"electron-builder": "22.8.1",
|
||||||
"file-loader": "^6.0.0",
|
"file-loader": "^6.1.1",
|
||||||
"jasmine-core": "^3.5.0",
|
"jasmine-core": "^3.6.0",
|
||||||
"jasmine-spec-reporter": "^5.0.2",
|
"jasmine-spec-reporter": "^6.0.0",
|
||||||
"jquery": "^3.5.1",
|
"jquery": "^3.5.1",
|
||||||
"karma": "^5.1.0",
|
"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": "^3.3.1",
|
"karma-jasmine": "^4.0.1",
|
||||||
"karma-jasmine-html-reporter": "^1.5.4",
|
"karma-jasmine-html-reporter": "^1.5.4",
|
||||||
"license-checker": "^25.0.1",
|
"license-checker": "^25.0.1",
|
||||||
"node-sass": "^4.14.1",
|
"node-sass": "^4.14.1",
|
||||||
"popper.js": "^1.16.1",
|
"popper.js": "^1.16.1",
|
||||||
"prettier": "^2.0.5",
|
"prettier": "^2.1.2",
|
||||||
"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",
|
||||||
"ts-mockito": "^2.6.1",
|
"ts-mockito": "^2.6.1",
|
||||||
"ts-node": "~8.10.2",
|
"ts-node": "~9.0.0",
|
||||||
"tslint": "^6.1.2",
|
"tslint": "^6.1.3",
|
||||||
"tslint-config-prettier": "^1.18.0",
|
"tslint-config-prettier": "^1.18.0",
|
||||||
"typescript": "^3.9.5",
|
"typescript": "^4.0.3",
|
||||||
"webpack": "^4.43.0"
|
"webpack": "^4.44.2"
|
||||||
},
|
},
|
||||||
"greenkeeper": {
|
"greenkeeper": {
|
||||||
"ignore": [
|
"ignore": [
|
||||||
|
@ -5,3 +5,5 @@ packaging==19.0
|
|||||||
appdirs==1.4.3
|
appdirs==1.4.3
|
||||||
psutil==5.6.7
|
psutil==5.6.7
|
||||||
jsonschema==2.6.0 # lock down jsonschema, 3.0 makes problems
|
jsonschema==2.6.0 # lock down jsonschema, 3.0 makes problems
|
||||||
|
|
||||||
|
urllib3>=1.25.9 # not directly required, pinned by Snyk to avoid a vulnerability
|
@ -1,6 +1,29 @@
|
|||||||
GNS3 WebUI is web implementation of user interface for GNS3 software.
|
GNS3 WebUI is web implementation of user interface for GNS3 software.
|
||||||
|
|
||||||
Current version: 2020.3.0-beta.1
|
Current version: 2020.4.0-beta.1
|
||||||
|
|
||||||
|
Bug Fixes & enhancements
|
||||||
|
- symbol is not properly selected in change symbol dialog
|
||||||
|
- issue when using the scroll wheel on the web console
|
||||||
|
- missing settings for Docker nodes
|
||||||
|
- error on servers page
|
||||||
|
|
||||||
|
What's new
|
||||||
|
- double click nodes to open the console
|
||||||
|
|
||||||
|
Current version: 2020.3.0-beta.3
|
||||||
|
|
||||||
|
Bug Fixes & enhancements
|
||||||
|
- direct download URL in template dialog
|
||||||
|
- fix for issues with suspnded nodes
|
||||||
|
- fix for bug with deleting templates
|
||||||
|
- fix for importing images
|
||||||
|
|
||||||
|
What's new
|
||||||
|
- Option to resize console
|
||||||
|
- Improvements in creating templates
|
||||||
|
|
||||||
|
GNS3 Web UI 2020.3.0-beta.1
|
||||||
|
|
||||||
Bug Fixes & enhancements
|
Bug Fixes & enhancements
|
||||||
- refreshing list of templates after adding new template from project map
|
- refreshing list of templates after adding new template from project map
|
||||||
@ -15,7 +38,7 @@ Bug Fixes & enhancements
|
|||||||
What's new
|
What's new
|
||||||
- Option to import appliances
|
- Option to import appliances
|
||||||
|
|
||||||
Current version: 2020.2.0-beta.5
|
GNS3 Web UI 2020.2.0-beta.5
|
||||||
|
|
||||||
Bug Fixes
|
Bug Fixes
|
||||||
|
|
||||||
|
@ -2,14 +2,14 @@ import { TestBed, async, ComponentFixture } from '@angular/core/testing';
|
|||||||
import { RouterTestingModule } from '@angular/router/testing';
|
import { RouterTestingModule } from '@angular/router/testing';
|
||||||
|
|
||||||
import { AppComponent } from './app.component';
|
import { AppComponent } from './app.component';
|
||||||
import { MatIconModule } from '@angular/material';
|
import { MatIconModule } from '@angular/material/icon';
|
||||||
import { SettingsService } from './services/settings.service';
|
import { SettingsService } from './services/settings.service';
|
||||||
import { PersistenceService } from 'angular-persistence';
|
import { PersistenceService } from 'angular-persistence';
|
||||||
import { ElectronService, NgxElectronModule } from 'ngx-electron';
|
import { ElectronService, NgxElectronModule } from 'ngx-electron';
|
||||||
import createSpyObj = jasmine.createSpyObj;
|
import createSpyObj = jasmine.createSpyObj;
|
||||||
import { NO_ERRORS_SCHEMA } from '@angular/core';
|
import { NO_ERRORS_SCHEMA } from '@angular/core';
|
||||||
import { ProgressService } from './common/progress/progress.service';
|
import { ProgressService } from './common/progress/progress.service';
|
||||||
import 'jasmine';
|
// import 'jasmine';
|
||||||
|
|
||||||
describe('AppComponent', () => {
|
describe('AppComponent', () => {
|
||||||
let component: AppComponent;
|
let component: AppComponent;
|
||||||
|
@ -37,6 +37,7 @@ import { ProjectMapComponent } from './components/project-map/project-map.compon
|
|||||||
import { ServersComponent } from './components/servers/servers.component';
|
import { ServersComponent } from './components/servers/servers.component';
|
||||||
import { AddServerDialogComponent } from './components/servers/add-server-dialog/add-server-dialog.component';
|
import { AddServerDialogComponent } from './components/servers/add-server-dialog/add-server-dialog.component';
|
||||||
import { ContextMenuComponent } from './components/project-map/context-menu/context-menu.component';
|
import { ContextMenuComponent } from './components/project-map/context-menu/context-menu.component';
|
||||||
|
import { ContextConsoleMenuComponent } from './components/project-map/context-console-menu/context-console-menu.component';
|
||||||
import { StartNodeActionComponent } from './components/project-map/context-menu/actions/start-node-action/start-node-action.component';
|
import { StartNodeActionComponent } from './components/project-map/context-menu/actions/start-node-action/start-node-action.component';
|
||||||
import { StopNodeActionComponent } from './components/project-map/context-menu/actions/stop-node-action/stop-node-action.component';
|
import { StopNodeActionComponent } from './components/project-map/context-menu/actions/stop-node-action/stop-node-action.component';
|
||||||
import { TemplateComponent } from './components/template/template.component';
|
import { TemplateComponent } from './components/template/template.component';
|
||||||
@ -226,6 +227,8 @@ import { ConfiguratorDialogVmwareComponent } from './components/project-map/node
|
|||||||
import { ConfiguratorDialogIouComponent } from './components/project-map/node-editors/configurator/iou/configurator-iou.component';
|
import { ConfiguratorDialogIouComponent } from './components/project-map/node-editors/configurator/iou/configurator-iou.component';
|
||||||
import { ConfiguratorDialogIosComponent } from './components/project-map/node-editors/configurator/ios/configurator-ios.component';
|
import { ConfiguratorDialogIosComponent } from './components/project-map/node-editors/configurator/ios/configurator-ios.component';
|
||||||
import { ConfiguratorDialogDockerComponent } from './components/project-map/node-editors/configurator/docker/configurator-docker.component';
|
import { ConfiguratorDialogDockerComponent } from './components/project-map/node-editors/configurator/docker/configurator-docker.component';
|
||||||
|
import { EditNetworkConfigurationDialogComponent } from './components/project-map/node-editors/configurator/docker/edit-network-configuration/edit-network-configuration.component';
|
||||||
|
import { ConfigureCustomAdaptersDialogComponent } from './components/project-map/node-editors/configurator/docker/configure-custom-adapters/configure-custom-adapters.component';
|
||||||
import { ConfiguratorDialogNatComponent } from './components/project-map/node-editors/configurator/nat/configurator-nat.component';
|
import { ConfiguratorDialogNatComponent } from './components/project-map/node-editors/configurator/nat/configurator-nat.component';
|
||||||
import { ConfiguratorDialogTracengComponent } from './components/project-map/node-editors/configurator/traceng/configurator-traceng.component';
|
import { ConfiguratorDialogTracengComponent } from './components/project-map/node-editors/configurator/traceng/configurator-traceng.component';
|
||||||
import { AddTracengTemplateComponent } from './components/preferences/traceng/add-traceng/add-traceng-template.component';
|
import { AddTracengTemplateComponent } from './components/preferences/traceng/add-traceng/add-traceng-template.component';
|
||||||
@ -249,7 +252,6 @@ import { AlignVerticallyActionComponent } from './components/project-map/context
|
|||||||
import { ConfirmationBottomSheetComponent } from './components/projects/confirmation-bottomsheet/confirmation-bottomsheet.component';
|
import { ConfirmationBottomSheetComponent } from './components/projects/confirmation-bottomsheet/confirmation-bottomsheet.component';
|
||||||
import { TemplateFilter } from './filters/templateFilter.pipe';
|
import { TemplateFilter } from './filters/templateFilter.pipe';
|
||||||
import { NotificationService } from './services/notification.service';
|
import { NotificationService } from './services/notification.service';
|
||||||
import { DeviceDetectorModule } from 'ngx-device-detector';
|
|
||||||
import { ConfigDialogComponent } from './components/project-map/context-menu/dialogs/config-dialog/config-dialog.component';
|
import { ConfigDialogComponent } from './components/project-map/context-menu/dialogs/config-dialog/config-dialog.component';
|
||||||
import { Gns3vmComponent } from './components/preferences/gns3vm/gns3vm.component';
|
import { Gns3vmComponent } from './components/preferences/gns3vm/gns3vm.component';
|
||||||
import { Gns3vmService } from './services/gns3vm.service';
|
import { Gns3vmService } from './services/gns3vm.service';
|
||||||
@ -281,6 +283,10 @@ import { ApplianceInfoDialogComponent } from './components/project-map/new-templ
|
|||||||
import { ResetLinkActionComponent } from './components/project-map/context-menu/actions/reset-link/reset-link-action.component';
|
import { ResetLinkActionComponent } from './components/project-map/context-menu/actions/reset-link/reset-link-action.component';
|
||||||
import { ReadmeEditorComponent } from './components/projects/edit-project-dialog/readme-editor/readme-editor.component';
|
import { ReadmeEditorComponent } from './components/projects/edit-project-dialog/readme-editor/readme-editor.component';
|
||||||
import { MarkedDirective } from './directives/marked.directive';
|
import { MarkedDirective } from './directives/marked.directive';
|
||||||
|
import { InformationDialogComponent } from './components/dialogs/information-dialog.component';
|
||||||
|
import { TemplateNameDialogComponent } from './components/project-map/new-template-dialog/template-name-dialog/template-name-dialog.component';
|
||||||
|
import { UpdatesService } from './services/updates.service';
|
||||||
|
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
declarations: [
|
declarations: [
|
||||||
@ -297,6 +303,7 @@ import { MarkedDirective } from './directives/marked.directive';
|
|||||||
DefaultLayoutComponent,
|
DefaultLayoutComponent,
|
||||||
ProgressDialogComponent,
|
ProgressDialogComponent,
|
||||||
ContextMenuComponent,
|
ContextMenuComponent,
|
||||||
|
ContextConsoleMenuComponent,
|
||||||
StartNodeActionComponent,
|
StartNodeActionComponent,
|
||||||
StopNodeActionComponent,
|
StopNodeActionComponent,
|
||||||
TemplateComponent,
|
TemplateComponent,
|
||||||
@ -466,7 +473,11 @@ import { MarkedDirective } from './directives/marked.directive';
|
|||||||
ChangeHostnameDialogComponent,
|
ChangeHostnameDialogComponent,
|
||||||
ApplianceInfoDialogComponent,
|
ApplianceInfoDialogComponent,
|
||||||
ReadmeEditorComponent,
|
ReadmeEditorComponent,
|
||||||
MarkedDirective
|
MarkedDirective,
|
||||||
|
InformationDialogComponent,
|
||||||
|
TemplateNameDialogComponent,
|
||||||
|
ConfigureCustomAdaptersDialogComponent,
|
||||||
|
EditNetworkConfigurationDialogComponent
|
||||||
],
|
],
|
||||||
imports: [
|
imports: [
|
||||||
BrowserModule,
|
BrowserModule,
|
||||||
@ -487,7 +498,6 @@ import { MarkedDirective } from './directives/marked.directive';
|
|||||||
DragDropModule,
|
DragDropModule,
|
||||||
NgxChildProcessModule,
|
NgxChildProcessModule,
|
||||||
MATERIAL_IMPORTS,
|
MATERIAL_IMPORTS,
|
||||||
DeviceDetectorModule.forRoot(),
|
|
||||||
NgCircleProgressModule.forRoot()
|
NgCircleProgressModule.forRoot()
|
||||||
],
|
],
|
||||||
providers: [
|
providers: [
|
||||||
@ -562,7 +572,8 @@ import { MarkedDirective } from './directives/marked.directive';
|
|||||||
ServerResolve,
|
ServerResolve,
|
||||||
ConsoleGuard,
|
ConsoleGuard,
|
||||||
Title,
|
Title,
|
||||||
ApplianceService
|
ApplianceService,
|
||||||
|
UpdatesService
|
||||||
],
|
],
|
||||||
entryComponents: [
|
entryComponents: [
|
||||||
AddServerDialogComponent,
|
AddServerDialogComponent,
|
||||||
@ -608,7 +619,9 @@ import { MarkedDirective } from './directives/marked.directive';
|
|||||||
AdbutlerComponent,
|
AdbutlerComponent,
|
||||||
NewTemplateDialogComponent,
|
NewTemplateDialogComponent,
|
||||||
ChangeHostnameDialogComponent,
|
ChangeHostnameDialogComponent,
|
||||||
ApplianceInfoDialogComponent
|
ApplianceInfoDialogComponent,
|
||||||
|
ConfigureCustomAdaptersDialogComponent,
|
||||||
|
EditNetworkConfigurationDialogComponent
|
||||||
],
|
],
|
||||||
bootstrap: [AppComponent]
|
bootstrap: [AppComponent]
|
||||||
})
|
})
|
||||||
|
@ -104,6 +104,14 @@ export class D3MapComponent implements OnInit, OnChanges, OnDestroy {
|
|||||||
this.mapSettings.isReadOnly = value;
|
this.mapSettings.isReadOnly = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
resize(val: boolean) {
|
||||||
|
if (val) {
|
||||||
|
this.svg.attr('height', window.innerHeight + window.scrollY - 16);
|
||||||
|
} else {
|
||||||
|
this.svg.attr('height', this.height);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ngOnChanges(changes: { [propKey: string]: SimpleChange }) {
|
ngOnChanges(changes: { [propKey: string]: SimpleChange }) {
|
||||||
if (
|
if (
|
||||||
(changes['width'] && !changes['width'].isFirstChange()) ||
|
(changes['width'] && !changes['width'].isFirstChange()) ||
|
||||||
@ -158,6 +166,7 @@ export class D3MapComponent implements OnInit, OnChanges, OnDestroy {
|
|||||||
);
|
);
|
||||||
|
|
||||||
this.gridVisibility = localStorage.getItem('gridVisibility') === 'true' ? 1 : 0;
|
this.gridVisibility = localStorage.getItem('gridVisibility') === 'true' ? 1 : 0;
|
||||||
|
this.mapSettingsService.isScrollDisabled.subscribe(val => this.resize(val));
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnDestroy() {
|
ngOnDestroy() {
|
||||||
|
@ -65,7 +65,7 @@ export class Node {
|
|||||||
console_auto_start: boolean;
|
console_auto_start: boolean;
|
||||||
console_host: string;
|
console_host: string;
|
||||||
console_type: string;
|
console_type: string;
|
||||||
custom_adapters?: CustomAdapter[];
|
custom_adapters?: any[];
|
||||||
ethernet_adapters?: any;
|
ethernet_adapters?: any;
|
||||||
serial_adapters?: any;
|
serial_adapters?: any;
|
||||||
first_port_name: string;
|
first_port_name: string;
|
||||||
|
@ -15,6 +15,7 @@ import { MapSettingsService } from '../../services/mapsettings.service';
|
|||||||
@Injectable()
|
@Injectable()
|
||||||
export class NodeWidget implements Widget {
|
export class NodeWidget implements Widget {
|
||||||
public onContextMenu = new EventEmitter<NodeContextMenu>();
|
public onContextMenu = new EventEmitter<NodeContextMenu>();
|
||||||
|
public onContextConsoleMenu = new EventEmitter<NodeContextMenu>();
|
||||||
public onNodeClicked = new EventEmitter<NodeClicked>();
|
public onNodeClicked = new EventEmitter<NodeClicked>();
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
@ -85,13 +86,19 @@ export class NodeWidget implements Widget {
|
|||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
self.onContextMenu.emit(new NodeContextMenu(event, n));
|
self.onContextMenu.emit(new NodeContextMenu(event, n));
|
||||||
})
|
})
|
||||||
|
.on('dblclick', function(n: MapNode, i: number) {
|
||||||
|
event.preventDefault();
|
||||||
|
self.onContextConsoleMenu.emit(new NodeContextMenu(event, n));
|
||||||
|
})
|
||||||
.attr('xnode:href', (n: MapNode) => n.symbolUrl)
|
.attr('xnode:href', (n: MapNode) => n.symbolUrl)
|
||||||
.attr('width', (n: MapNode) => {
|
.attr('width', (n: MapNode) => {
|
||||||
|
if (n.nodeType === 'cloud' || n.nodeType === 'nat') return 120;
|
||||||
if (!n.width) return 60;
|
if (!n.width) return 60;
|
||||||
if (n.width > 64) return 64;
|
if (n.width > 64) return 64;
|
||||||
return n.width;
|
return n.width;
|
||||||
})
|
})
|
||||||
.attr('height', (n: MapNode) => {
|
.attr('height', (n: MapNode) => {
|
||||||
|
if (n.nodeType === 'cloud' || n.nodeType === 'nat') return 60;
|
||||||
if (!n.height) return 60;
|
if (!n.height) return 60;
|
||||||
if (n.height > 64) return 64;
|
if (n.height > 64) return 64;
|
||||||
return n.height;
|
return n.height;
|
||||||
|
@ -9,7 +9,7 @@ import * as Sentry from "@sentry/browser";
|
|||||||
import { BrowserOptions, init } from '@sentry/browser';
|
import { BrowserOptions, init } from '@sentry/browser';
|
||||||
|
|
||||||
const config = {
|
const config = {
|
||||||
dsn: "https://b2b1cfd9b043491eb6b566fd8acee358@o19455.ingest.sentry.io/842726"
|
dsn: "https://d8be3a98530f49eb90968ff396db326c@o19455.ingest.sentry.io/842726"
|
||||||
};
|
};
|
||||||
init(config as BrowserOptions);
|
init(config as BrowserOptions);
|
||||||
|
|
||||||
@ -59,12 +59,12 @@ export class SentryErrorHandler implements ErrorHandler {
|
|||||||
|
|
||||||
// Capture handled exception and send it to Sentry.
|
// Capture handled exception and send it to Sentry.
|
||||||
const eventId = Sentry.captureException(extractedError);
|
const eventId = Sentry.captureException(extractedError);
|
||||||
|
|
||||||
// When in development mode, log the error to console for immediate feedback.
|
// When in development mode, log the error to console for immediate feedback.
|
||||||
if (!environment.production) {
|
if (!environment.production) {
|
||||||
console.error(extractedError);
|
console.error(extractedError);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Optionally show user dialog to provide details on what happened.
|
// Optionally show user dialog to provide details on what happened.
|
||||||
// Sentry.showReportDialog({ eventId });
|
// Sentry.showReportDialog({ eventId });
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,7 @@ import { SentryErrorHandler } from './sentry-error-handler';
|
|||||||
@Injectable()
|
@Injectable()
|
||||||
export class ToasterErrorHandler extends SentryErrorHandler {
|
export class ToasterErrorHandler extends SentryErrorHandler {
|
||||||
handleError(err: any): void {
|
handleError(err: any): void {
|
||||||
if (err.error && err.error.status && !(err.error.status === 403 || err.error.status === 404 || err.error.status === 405)) {
|
if (err.error && err.error.status && !(err.error.status === 400 || err.error.status === 403 || err.error.status === 404 || err.error.status === 409)) {
|
||||||
super.handleError(err);
|
super.handleError(err);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
right: 0;
|
right: 0;
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
background-color: rgba(0, 0, 0, 0.5);
|
background-color: rgba(0, 0, 0, 0.5);
|
||||||
z-index: 1000;
|
z-index: 2000;
|
||||||
}
|
}
|
||||||
|
|
||||||
.loading-spinner,
|
.loading-spinner,
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
import { ProgressComponent } from './progress.component';
|
import { ProgressComponent } from './progress.component';
|
||||||
import { MatIconModule, MatProgressSpinnerModule } from '@angular/material';
|
import { MatIconModule } from '@angular/material/icon';
|
||||||
|
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
|
||||||
import { ProgressService } from './progress.service';
|
import { ProgressService } from './progress.service';
|
||||||
import { RouterTestingModule } from '@angular/router/testing';
|
import { RouterTestingModule } from '@angular/router/testing';
|
||||||
import { Router } from '@angular/router';
|
import { Router } from '@angular/router';
|
||||||
|
@ -14,6 +14,15 @@ export class AdbutlerComponent implements OnInit {
|
|||||||
theme: string;
|
theme: string;
|
||||||
onLoad = new EventEmitter();
|
onLoad = new EventEmitter();
|
||||||
htmlCode: string;
|
htmlCode: string;
|
||||||
|
staticCode: string = `<a href="https://try.solarwinds.com/gns3-free-toolset-giveaway?CMP=LEC-HAD-GNS3-SW_NA_X_NP_X_X_EN_STSGA_SW-ST-20200901_ST_OF1_TRY-NWSLTR">
|
||||||
|
Access Our Favorite Network Free Tools!
|
||||||
|
</a><br/>
|
||||||
|
Access 20+ network performance management, monitoring, and troubleshooting tools for FREE ($200 Value).<br/>
|
||||||
|
<button>
|
||||||
|
<a target="_blank" href="https://try.solarwinds.com/gns3-free-toolset-giveaway?CMP=LEC-HAD-GNS3-SW_NA_X_NP_X_X_EN_STSGA_SW-ST-20200901_ST_OF1_TRY-NWSLTR">
|
||||||
|
Check it out!
|
||||||
|
</a>
|
||||||
|
</button>`;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private httpClient: HttpClient
|
private httpClient: HttpClient
|
||||||
@ -28,7 +37,8 @@ export class AdbutlerComponent implements OnInit {
|
|||||||
this.htmlCode = response['placements'].placement_1.body;
|
this.htmlCode = response['placements'].placement_1.body;
|
||||||
this.ad.nativeElement.insertAdjacentHTML('beforeend', this.htmlCode);
|
this.ad.nativeElement.insertAdjacentHTML('beforeend', this.htmlCode);
|
||||||
} else {
|
} else {
|
||||||
this.onLoad.emit(false);
|
this.onLoad.emit(true);
|
||||||
|
this.htmlCode = this.staticCode;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
error => {}
|
error => {}
|
||||||
|
@ -0,0 +1,7 @@
|
|||||||
|
<span>{{ confirmationMessage }}</span>
|
||||||
|
<div mat-dialog-actions>
|
||||||
|
<button mat-button class="cancelButton" (click)="onNoClick()" color="accent">No</button>
|
||||||
|
<button mat-button class="confirmButton" (click)="onYesClick()" tabindex="2" mat-raised-button color="primary">
|
||||||
|
Yes
|
||||||
|
</button>
|
||||||
|
</div>
|
22
src/app/components/dialogs/information-dialog.component.ts
Normal file
22
src/app/components/dialogs/information-dialog.component.ts
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
import { Component, OnInit, Inject } from '@angular/core';
|
||||||
|
import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-information-dialog',
|
||||||
|
templateUrl: 'information-dialog.component.html',
|
||||||
|
styleUrls: ['information-dialog.component.css']
|
||||||
|
})
|
||||||
|
export class InformationDialogComponent implements OnInit {
|
||||||
|
public confirmationMessage: string;
|
||||||
|
constructor(public dialogRef: MatDialogRef<InformationDialogComponent>) {}
|
||||||
|
|
||||||
|
ngOnInit() {}
|
||||||
|
|
||||||
|
onNoClick(): void {
|
||||||
|
this.dialogRef.close(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
onYesClick(): void {
|
||||||
|
this.dialogRef.close(true);
|
||||||
|
}
|
||||||
|
}
|
@ -1,5 +1,8 @@
|
|||||||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
import { MatCheckboxModule, MatIconModule, MatToolbarModule, MatMenuModule } from '@angular/material';
|
import { MatCheckboxModule } from '@angular/material/checkbox';
|
||||||
|
import { MatIconModule } from '@angular/material/icon';
|
||||||
|
import { MatMenuModule } from '@angular/material/menu';
|
||||||
|
import { MatToolbarModule } from '@angular/material/toolbar';
|
||||||
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
||||||
import { ActivatedRoute } from '@angular/router';
|
import { ActivatedRoute } from '@angular/router';
|
||||||
import { CommonModule } from '@angular/common';
|
import { CommonModule } from '@angular/common';
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
import { ComponentFixture, async, TestBed } from '@angular/core/testing';
|
import { ComponentFixture, async, TestBed } from '@angular/core/testing';
|
||||||
import { MatIconModule, MatToolbarModule, MatMenuModule, MatCheckboxModule } from '@angular/material';
|
import { MatCheckboxModule } from '@angular/material/checkbox';
|
||||||
|
import { MatIconModule } from '@angular/material/icon';
|
||||||
|
import { MatMenuModule } from '@angular/material/menu';
|
||||||
|
import { MatToolbarModule } from '@angular/material/toolbar';
|
||||||
import { CommonModule } from '@angular/common';
|
import { CommonModule } from '@angular/common';
|
||||||
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
||||||
import { RouterTestingModule } from '@angular/router/testing';
|
import { RouterTestingModule } from '@angular/router/testing';
|
||||||
@ -17,6 +20,8 @@ import { BuiltInTemplatesService } from '../../../../../services/built-in-templa
|
|||||||
import { ToasterService } from '../../../../../services/toaster.service';
|
import { ToasterService } from '../../../../../services/toaster.service';
|
||||||
import { TemplateMocksService } from '../../../../../services/template-mocks.service';
|
import { TemplateMocksService } from '../../../../../services/template-mocks.service';
|
||||||
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
|
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
|
||||||
|
import { ComputeService } from '../../../../../services/compute.service';
|
||||||
|
import {MockedComputeService} from '../../../../preferences/vpcs/add-vpcs-template/add-vpcs-template.component.spec'
|
||||||
|
|
||||||
export class MockedBuiltInTemplatesService {
|
export class MockedBuiltInTemplatesService {
|
||||||
public addTemplate(server: Server, cloudTemplate: CloudTemplate) {
|
public addTemplate(server: Server, cloudTemplate: CloudTemplate) {
|
||||||
@ -31,6 +36,7 @@ describe('CloudNodesAddTemplateComponent', () => {
|
|||||||
let mockedServerService = new MockedServerService;
|
let mockedServerService = new MockedServerService;
|
||||||
let mockedBuiltInTemplatesService = new MockedBuiltInTemplatesService;
|
let mockedBuiltInTemplatesService = new MockedBuiltInTemplatesService;
|
||||||
let mockedToasterService = new MockedToasterService;
|
let mockedToasterService = new MockedToasterService;
|
||||||
|
let mockedComputeService = new MockedComputeService();
|
||||||
let activatedRoute = new MockedActivatedRoute().get();
|
let activatedRoute = new MockedActivatedRoute().get();
|
||||||
|
|
||||||
beforeEach(async(() => {
|
beforeEach(async(() => {
|
||||||
@ -51,6 +57,7 @@ describe('CloudNodesAddTemplateComponent', () => {
|
|||||||
{ provide: ServerService, useValue: mockedServerService },
|
{ provide: ServerService, useValue: mockedServerService },
|
||||||
{ provide: BuiltInTemplatesService, useValue: mockedBuiltInTemplatesService },
|
{ provide: BuiltInTemplatesService, useValue: mockedBuiltInTemplatesService },
|
||||||
{ provide: ToasterService, useValue: mockedToasterService },
|
{ provide: ToasterService, useValue: mockedToasterService },
|
||||||
|
{ provide: ComputeService, useValue: mockedComputeService },
|
||||||
{ provide: TemplateMocksService, useClass: TemplateMocksService }
|
{ provide: TemplateMocksService, useClass: TemplateMocksService }
|
||||||
],
|
],
|
||||||
declarations: [
|
declarations: [
|
||||||
|
@ -1,5 +1,9 @@
|
|||||||
import { ComponentFixture, async, TestBed } from '@angular/core/testing';
|
import { ComponentFixture, async, TestBed } from '@angular/core/testing';
|
||||||
import { MatIconModule, MatToolbarModule, MatMenuModule, MatCheckboxModule, MatTableModule } from '@angular/material';
|
import { MatCheckboxModule } from '@angular/material/checkbox';
|
||||||
|
import { MatIconModule } from '@angular/material/icon';
|
||||||
|
import { MatMenuModule } from '@angular/material/menu';
|
||||||
|
import { MatTableModule } from '@angular/material/table';
|
||||||
|
import { MatToolbarModule } from '@angular/material/toolbar';
|
||||||
import { CommonModule } from '@angular/common';
|
import { CommonModule } from '@angular/common';
|
||||||
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
||||||
import { RouterTestingModule } from '@angular/router/testing';
|
import { RouterTestingModule } from '@angular/router/testing';
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
import { ComponentFixture, async, TestBed } from '@angular/core/testing';
|
import { ComponentFixture, async, TestBed } from '@angular/core/testing';
|
||||||
import { MatIconModule, MatToolbarModule, MatMenuModule, MatCheckboxModule } from '@angular/material';
|
import { MatCheckboxModule } from '@angular/material/checkbox';
|
||||||
|
import { MatIconModule } from '@angular/material/icon';
|
||||||
|
import { MatMenuModule } from '@angular/material/menu';
|
||||||
|
import { MatToolbarModule } from '@angular/material/toolbar';
|
||||||
import { CommonModule } from '@angular/common';
|
import { CommonModule } from '@angular/common';
|
||||||
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
||||||
import { RouterTestingModule } from '@angular/router/testing';
|
import { RouterTestingModule } from '@angular/router/testing';
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
import { ComponentFixture, async, TestBed } from '@angular/core/testing';
|
import { ComponentFixture, async, TestBed } from '@angular/core/testing';
|
||||||
import { MatIconModule, MatToolbarModule, MatMenuModule, MatCheckboxModule } from '@angular/material';
|
import { MatCheckboxModule } from '@angular/material/checkbox';
|
||||||
|
import { MatIconModule } from '@angular/material/icon';
|
||||||
|
import { MatMenuModule } from '@angular/material/menu';
|
||||||
|
import { MatToolbarModule } from '@angular/material/toolbar';
|
||||||
import { CommonModule } from '@angular/common';
|
import { CommonModule } from '@angular/common';
|
||||||
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
||||||
import { RouterTestingModule } from '@angular/router/testing';
|
import { RouterTestingModule } from '@angular/router/testing';
|
||||||
@ -17,6 +20,8 @@ import { TemplateMocksService } from '../../../../../services/template-mocks.ser
|
|||||||
import { EthernetHubTemplate } from '../../../../../models/templates/ethernet-hub-template';
|
import { EthernetHubTemplate } from '../../../../../models/templates/ethernet-hub-template';
|
||||||
import { EthernetHubsAddTemplateComponent } from './ethernet-hubs-add-template.component';
|
import { EthernetHubsAddTemplateComponent } from './ethernet-hubs-add-template.component';
|
||||||
import { ReactiveFormsModule, FormsModule } from '@angular/forms';
|
import { ReactiveFormsModule, FormsModule } from '@angular/forms';
|
||||||
|
import { ComputeService } from '../../../../../services/compute.service';
|
||||||
|
import {MockedComputeService} from '../../../../preferences/vpcs/add-vpcs-template/add-vpcs-template.component.spec';
|
||||||
|
|
||||||
export class MockedBuiltInTemplatesService {
|
export class MockedBuiltInTemplatesService {
|
||||||
public addTemplate(server: Server, ethernetHubTemplate: EthernetHubTemplate) {
|
public addTemplate(server: Server, ethernetHubTemplate: EthernetHubTemplate) {
|
||||||
@ -31,6 +36,7 @@ describe('EthernetHubsAddTemplateComponent', () => {
|
|||||||
let mockedServerService = new MockedServerService;
|
let mockedServerService = new MockedServerService;
|
||||||
let mockedBuiltInTemplatesService = new MockedBuiltInTemplatesService;
|
let mockedBuiltInTemplatesService = new MockedBuiltInTemplatesService;
|
||||||
let mockedToasterService = new MockedToasterService;
|
let mockedToasterService = new MockedToasterService;
|
||||||
|
let mockedComputeService = new MockedComputeService();
|
||||||
let activatedRoute = new MockedActivatedRoute().get();
|
let activatedRoute = new MockedActivatedRoute().get();
|
||||||
|
|
||||||
beforeEach(async(() => {
|
beforeEach(async(() => {
|
||||||
@ -53,6 +59,7 @@ describe('EthernetHubsAddTemplateComponent', () => {
|
|||||||
{ provide: ServerService, useValue: mockedServerService },
|
{ provide: ServerService, useValue: mockedServerService },
|
||||||
{ provide: BuiltInTemplatesService, useValue: mockedBuiltInTemplatesService },
|
{ provide: BuiltInTemplatesService, useValue: mockedBuiltInTemplatesService },
|
||||||
{ provide: ToasterService, useValue: mockedToasterService},
|
{ provide: ToasterService, useValue: mockedToasterService},
|
||||||
|
{ provide: ComputeService, useValue: mockedComputeService },
|
||||||
{ provide: TemplateMocksService, useClass: TemplateMocksService }
|
{ provide: TemplateMocksService, useClass: TemplateMocksService }
|
||||||
],
|
],
|
||||||
declarations: [
|
declarations: [
|
||||||
|
@ -1,5 +1,9 @@
|
|||||||
import { ComponentFixture, async, TestBed } from '@angular/core/testing';
|
import { ComponentFixture, async, TestBed } from '@angular/core/testing';
|
||||||
import { MatIconModule, MatToolbarModule, MatMenuModule, MatCheckboxModule, MatTableModule } from '@angular/material';
|
import { MatCheckboxModule } from '@angular/material/checkbox';
|
||||||
|
import { MatIconModule } from '@angular/material/icon';
|
||||||
|
import { MatMenuModule } from '@angular/material/menu';
|
||||||
|
import { MatTableModule } from '@angular/material/table';
|
||||||
|
import { MatToolbarModule } from '@angular/material/toolbar';
|
||||||
import { CommonModule } from '@angular/common';
|
import { CommonModule } from '@angular/common';
|
||||||
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
||||||
import { RouterTestingModule } from '@angular/router/testing';
|
import { RouterTestingModule } from '@angular/router/testing';
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
import { ComponentFixture, async, TestBed } from '@angular/core/testing';
|
import { ComponentFixture, async, TestBed } from '@angular/core/testing';
|
||||||
import { MatIconModule, MatToolbarModule, MatMenuModule, MatCheckboxModule } from '@angular/material';
|
import { MatCheckboxModule } from '@angular/material/checkbox';
|
||||||
|
import { MatIconModule } from '@angular/material/icon';
|
||||||
|
import { MatMenuModule } from '@angular/material/menu';
|
||||||
|
import { MatToolbarModule } from '@angular/material/toolbar';
|
||||||
import { CommonModule } from '@angular/common';
|
import { CommonModule } from '@angular/common';
|
||||||
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
||||||
import { RouterTestingModule } from '@angular/router/testing';
|
import { RouterTestingModule } from '@angular/router/testing';
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
import { ComponentFixture, async, TestBed } from '@angular/core/testing';
|
import { ComponentFixture, async, TestBed } from '@angular/core/testing';
|
||||||
import { MatIconModule, MatToolbarModule, MatMenuModule, MatCheckboxModule } from '@angular/material';
|
import { MatCheckboxModule } from '@angular/material/checkbox';
|
||||||
|
import { MatIconModule } from '@angular/material/icon';
|
||||||
|
import { MatMenuModule } from '@angular/material/menu';
|
||||||
|
import { MatToolbarModule } from '@angular/material/toolbar';
|
||||||
import { CommonModule } from '@angular/common';
|
import { CommonModule } from '@angular/common';
|
||||||
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
||||||
import { RouterTestingModule } from '@angular/router/testing';
|
import { RouterTestingModule } from '@angular/router/testing';
|
||||||
@ -17,6 +20,8 @@ import { TemplateMocksService } from '../../../../../services/template-mocks.ser
|
|||||||
import { EthernetSwitchTemplate } from '../../../../../models/templates/ethernet-switch-template';
|
import { EthernetSwitchTemplate } from '../../../../../models/templates/ethernet-switch-template';
|
||||||
import { EthernetSwitchesAddTemplateComponent } from './ethernet-switches-add-template.component';
|
import { EthernetSwitchesAddTemplateComponent } from './ethernet-switches-add-template.component';
|
||||||
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
|
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
|
||||||
|
import { ComputeService } from '../../../../../services/compute.service';
|
||||||
|
import {MockedComputeService} from '../../../../preferences/vpcs/add-vpcs-template/add-vpcs-template.component.spec';
|
||||||
|
|
||||||
export class MockedBuiltInTemplatesService {
|
export class MockedBuiltInTemplatesService {
|
||||||
public addTemplate(server: Server, ethernetHubTemplate: EthernetSwitchTemplate) {
|
public addTemplate(server: Server, ethernetHubTemplate: EthernetSwitchTemplate) {
|
||||||
@ -31,6 +36,7 @@ describe('EthernetSwitchesAddTemplateComponent', () => {
|
|||||||
let mockedServerService = new MockedServerService;
|
let mockedServerService = new MockedServerService;
|
||||||
let mockedBuiltInTemplatesService = new MockedBuiltInTemplatesService;
|
let mockedBuiltInTemplatesService = new MockedBuiltInTemplatesService;
|
||||||
let mockedToasterService = new MockedToasterService;
|
let mockedToasterService = new MockedToasterService;
|
||||||
|
let mockedComputeService = new MockedComputeService();
|
||||||
let activatedRoute = new MockedActivatedRoute().get();
|
let activatedRoute = new MockedActivatedRoute().get();
|
||||||
|
|
||||||
beforeEach(async(() => {
|
beforeEach(async(() => {
|
||||||
@ -53,6 +59,7 @@ describe('EthernetSwitchesAddTemplateComponent', () => {
|
|||||||
{ provide: ServerService, useValue: mockedServerService },
|
{ provide: ServerService, useValue: mockedServerService },
|
||||||
{ provide: BuiltInTemplatesService, useValue: mockedBuiltInTemplatesService },
|
{ provide: BuiltInTemplatesService, useValue: mockedBuiltInTemplatesService },
|
||||||
{ provide: ToasterService, useValue: mockedToasterService},
|
{ provide: ToasterService, useValue: mockedToasterService},
|
||||||
|
{ provide: ComputeService, useValue: mockedComputeService },
|
||||||
{ provide: TemplateMocksService, useClass: TemplateMocksService }
|
{ provide: TemplateMocksService, useClass: TemplateMocksService }
|
||||||
],
|
],
|
||||||
declarations: [
|
declarations: [
|
||||||
@ -96,7 +103,7 @@ describe('EthernetSwitchesAddTemplateComponent', () => {
|
|||||||
expect(mockedToasterService.error).toHaveBeenCalled();
|
expect(mockedToasterService.error).toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should not call add template when number of ports is missing', () => {
|
xit('should not call add template when number of ports is missing', () => {
|
||||||
spyOn(mockedBuiltInTemplatesService, 'addTemplate').and.returnValue(of({} as EthernetSwitchTemplate));
|
spyOn(mockedBuiltInTemplatesService, 'addTemplate').and.returnValue(of({} as EthernetSwitchTemplate));
|
||||||
spyOn(mockedToasterService, 'error');
|
spyOn(mockedToasterService, 'error');
|
||||||
component.formGroup.controls['templateName'].setValue('template name');
|
component.formGroup.controls['templateName'].setValue('template name');
|
||||||
|
@ -1,5 +1,9 @@
|
|||||||
import { ComponentFixture, async, TestBed } from '@angular/core/testing';
|
import { ComponentFixture, async, TestBed } from '@angular/core/testing';
|
||||||
import { MatIconModule, MatToolbarModule, MatMenuModule, MatCheckboxModule, MatTableModule } from '@angular/material';
|
import { MatCheckboxModule } from '@angular/material/checkbox';
|
||||||
|
import { MatIconModule } from '@angular/material/icon';
|
||||||
|
import { MatMenuModule } from '@angular/material/menu';
|
||||||
|
import { MatTableModule } from '@angular/material/table';
|
||||||
|
import { MatToolbarModule } from '@angular/material/toolbar';
|
||||||
import { CommonModule } from '@angular/common';
|
import { CommonModule } from '@angular/common';
|
||||||
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
||||||
import { RouterTestingModule } from '@angular/router/testing';
|
import { RouterTestingModule } from '@angular/router/testing';
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
import { ComponentFixture, async, TestBed } from '@angular/core/testing';
|
import { ComponentFixture, async, TestBed } from '@angular/core/testing';
|
||||||
import { MatIconModule, MatToolbarModule, MatMenuModule, MatCheckboxModule } from '@angular/material';
|
import { MatCheckboxModule } from '@angular/material/checkbox';
|
||||||
|
import { MatIconModule } from '@angular/material/icon';
|
||||||
|
import { MatMenuModule } from '@angular/material/menu';
|
||||||
|
import { MatToolbarModule } from '@angular/material/toolbar';
|
||||||
import { CommonModule } from '@angular/common';
|
import { CommonModule } from '@angular/common';
|
||||||
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
||||||
import { RouterTestingModule } from '@angular/router/testing';
|
import { RouterTestingModule } from '@angular/router/testing';
|
||||||
|
@ -1,5 +1,9 @@
|
|||||||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
import { MatCheckboxModule, MatIconModule, MatToolbarModule, MatMenuModule, MatTableModule } from '@angular/material';
|
import { MatCheckboxModule } from '@angular/material/checkbox';
|
||||||
|
import { MatIconModule } from '@angular/material/icon';
|
||||||
|
import { MatMenuModule } from '@angular/material/menu';
|
||||||
|
import { MatTableModule } from '@angular/material/table';
|
||||||
|
import { MatToolbarModule } from '@angular/material/toolbar';
|
||||||
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
||||||
import { CommonModule } from '@angular/common';
|
import { CommonModule } from '@angular/common';
|
||||||
import { NO_ERRORS_SCHEMA } from '@angular/core';
|
import { NO_ERRORS_SCHEMA } from '@angular/core';
|
||||||
|
@ -33,11 +33,9 @@ export class DeleteTemplateComponent {
|
|||||||
|
|
||||||
dialogRef.afterClosed().subscribe((answer: boolean) => {
|
dialogRef.afterClosed().subscribe((answer: boolean) => {
|
||||||
if (answer) {
|
if (answer) {
|
||||||
this.templateService.deleteTemplate(this.server, templateId).subscribe((answer: boolean) => {
|
this.templateService.deleteTemplate(this.server, templateId).subscribe((answer) => {
|
||||||
if(answer) {
|
this.deleteEvent.emit(templateId);
|
||||||
this.deleteEvent.emit(templateId);
|
this.toasterService.success(`Template ${templateName} deleted.`);
|
||||||
this.toasterService.success(`Template ${templateName} deleted.`);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -21,8 +21,7 @@
|
|||||||
|
|
||||||
.buttonSelected {
|
.buttonSelected {
|
||||||
border-width: 3px;
|
border-width: 3px;
|
||||||
border-color: #0097a7;
|
background: #0097a7!important;
|
||||||
width: 77px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.image {
|
.image {
|
||||||
@ -33,7 +32,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.imageSelected {
|
.imageSelected {
|
||||||
margin-left: -3px;
|
margin-left: 0px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.wrapper {
|
.wrapper {
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
import { MatCheckboxModule, MatIconModule, MatToolbarModule, MatMenuModule } from '@angular/material';
|
import { MatCheckboxModule } from '@angular/material/checkbox';
|
||||||
|
import { MatIconModule } from '@angular/material/icon';
|
||||||
|
import { MatMenuModule } from '@angular/material/menu';
|
||||||
|
import { MatToolbarModule } from '@angular/material/toolbar';
|
||||||
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
||||||
import { of } from 'rxjs';
|
import { of } from 'rxjs';
|
||||||
import { CommonModule } from '@angular/common';
|
import { CommonModule } from '@angular/common';
|
||||||
|
@ -1,5 +1,16 @@
|
|||||||
import { ComponentFixture, async, TestBed } from '@angular/core/testing';
|
import { ComponentFixture, async, TestBed } from '@angular/core/testing';
|
||||||
import { MatInputModule, MatIconModule, MatToolbarModule, MatMenuModule, MatCheckboxModule, MatSelectModule, MatFormFieldModule, MatAutocompleteModule, MatTableModule, MatStepperModule, MatRadioModule, MatCommonModule } from '@angular/material';
|
import { MatAutocompleteModule } from '@angular/material/autocomplete';
|
||||||
|
import { MatCheckboxModule } from '@angular/material/checkbox';
|
||||||
|
import { MatCommonModule } from '@angular/material/core';
|
||||||
|
import { MatFormFieldModule } from '@angular/material/form-field';
|
||||||
|
import { MatIconModule } from '@angular/material/icon';
|
||||||
|
import { MatInputModule } from '@angular/material/input';
|
||||||
|
import { MatMenuModule } from '@angular/material/menu';
|
||||||
|
import { MatRadioModule } from '@angular/material/radio';
|
||||||
|
import { MatSelectModule } from '@angular/material/select';
|
||||||
|
import { MatStepperModule } from '@angular/material/stepper';
|
||||||
|
import { MatTableModule } from '@angular/material/table';
|
||||||
|
import { MatToolbarModule } from '@angular/material/toolbar';
|
||||||
import { CommonModule } from '@angular/common';
|
import { CommonModule } from '@angular/common';
|
||||||
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
||||||
import { RouterTestingModule } from '@angular/router/testing';
|
import { RouterTestingModule } from '@angular/router/testing';
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
import { ComponentFixture, async, TestBed } from '@angular/core/testing';
|
import { ComponentFixture, async, TestBed } from '@angular/core/testing';
|
||||||
import { MatIconModule, MatToolbarModule, MatMenuModule, MatCheckboxModule } from '@angular/material';
|
import { MatCheckboxModule } from '@angular/material/checkbox';
|
||||||
|
import { MatIconModule } from '@angular/material/icon';
|
||||||
|
import { MatMenuModule } from '@angular/material/menu';
|
||||||
|
import { MatToolbarModule } from '@angular/material/toolbar';
|
||||||
import { CommonModule } from '@angular/common';
|
import { CommonModule } from '@angular/common';
|
||||||
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
||||||
import { RouterTestingModule } from '@angular/router/testing';
|
import { RouterTestingModule } from '@angular/router/testing';
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
import { ComponentFixture, async, TestBed } from '@angular/core/testing';
|
import { ComponentFixture, async, TestBed } from '@angular/core/testing';
|
||||||
import { MatIconModule, MatToolbarModule, MatMenuModule, MatCheckboxModule } from '@angular/material';
|
import { MatCheckboxModule } from '@angular/material/checkbox';
|
||||||
|
import { MatIconModule } from '@angular/material/icon';
|
||||||
|
import { MatMenuModule } from '@angular/material/menu';
|
||||||
|
import { MatToolbarModule } from '@angular/material/toolbar';
|
||||||
import { CommonModule } from '@angular/common';
|
import { CommonModule } from '@angular/common';
|
||||||
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
||||||
import { RouterTestingModule } from '@angular/router/testing';
|
import { RouterTestingModule } from '@angular/router/testing';
|
||||||
|
@ -1,5 +1,14 @@
|
|||||||
import { ComponentFixture, async, TestBed } from '@angular/core/testing';
|
import { ComponentFixture, async, TestBed } from '@angular/core/testing';
|
||||||
import { MatInputModule, MatIconModule, MatToolbarModule, MatMenuModule, MatCheckboxModule, MatSelectModule, MatFormFieldModule, MatAutocompleteModule, MatTableModule, MatStepperModule } from '@angular/material';
|
import { MatAutocompleteModule } from '@angular/material/autocomplete';
|
||||||
|
import { MatCheckboxModule } from '@angular/material/checkbox';
|
||||||
|
import { MatFormFieldModule } from '@angular/material/form-field';
|
||||||
|
import { MatIconModule } from '@angular/material/icon';
|
||||||
|
import { MatInputModule } from '@angular/material/input';
|
||||||
|
import { MatMenuModule } from '@angular/material/menu';
|
||||||
|
import { MatSelectModule } from '@angular/material/select';
|
||||||
|
import { MatStepperModule } from '@angular/material/stepper';
|
||||||
|
import { MatTableModule } from '@angular/material/table';
|
||||||
|
import { MatToolbarModule } from '@angular/material/toolbar';
|
||||||
import { CommonModule } from '@angular/common';
|
import { CommonModule } from '@angular/common';
|
||||||
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
||||||
import { RouterTestingModule } from '@angular/router/testing';
|
import { RouterTestingModule } from '@angular/router/testing';
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
import { ComponentFixture, async, TestBed } from '@angular/core/testing';
|
import { ComponentFixture, async, TestBed } from '@angular/core/testing';
|
||||||
import { MatIconModule, MatToolbarModule, MatMenuModule, MatCheckboxModule } from '@angular/material';
|
import { MatCheckboxModule } from '@angular/material/checkbox';
|
||||||
|
import { MatIconModule } from '@angular/material/icon';
|
||||||
|
import { MatMenuModule } from '@angular/material/menu';
|
||||||
|
import { MatToolbarModule } from '@angular/material/toolbar';
|
||||||
import { CommonModule } from '@angular/common';
|
import { CommonModule } from '@angular/common';
|
||||||
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
||||||
import { RouterTestingModule } from '@angular/router/testing';
|
import { RouterTestingModule } from '@angular/router/testing';
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
import { ComponentFixture, async, TestBed } from '@angular/core/testing';
|
import { ComponentFixture, async, TestBed } from '@angular/core/testing';
|
||||||
import { MatIconModule, MatToolbarModule, MatMenuModule, MatCheckboxModule } from '@angular/material';
|
import { MatCheckboxModule } from '@angular/material/checkbox';
|
||||||
|
import { MatIconModule } from '@angular/material/icon';
|
||||||
|
import { MatMenuModule } from '@angular/material/menu';
|
||||||
|
import { MatToolbarModule } from '@angular/material/toolbar';
|
||||||
import { CommonModule } from '@angular/common';
|
import { CommonModule } from '@angular/common';
|
||||||
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
||||||
import { RouterTestingModule } from '@angular/router/testing';
|
import { RouterTestingModule } from '@angular/router/testing';
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
import { ComponentFixture, async, TestBed } from '@angular/core/testing';
|
import { ComponentFixture, async, TestBed } from '@angular/core/testing';
|
||||||
import { MatIconModule, MatToolbarModule, MatMenuModule, MatCheckboxModule } from '@angular/material';
|
import { MatCheckboxModule } from '@angular/material/checkbox';
|
||||||
|
import { MatIconModule } from '@angular/material/icon';
|
||||||
|
import { MatMenuModule } from '@angular/material/menu';
|
||||||
|
import { MatToolbarModule } from '@angular/material/toolbar';
|
||||||
import { CommonModule } from '@angular/common';
|
import { CommonModule } from '@angular/common';
|
||||||
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
||||||
import { RouterTestingModule } from '@angular/router/testing';
|
import { RouterTestingModule } from '@angular/router/testing';
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
import { MatCheckboxModule, MatIconModule, MatToolbarModule, MatMenuModule } from '@angular/material';
|
import { MatCheckboxModule } from '@angular/material/checkbox';
|
||||||
|
import { MatIconModule } from '@angular/material/icon';
|
||||||
|
import { MatMenuModule } from '@angular/material/menu';
|
||||||
|
import { MatToolbarModule } from '@angular/material/toolbar';
|
||||||
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
||||||
import { ActivatedRoute } from '@angular/router';
|
import { ActivatedRoute } from '@angular/router';
|
||||||
import { CommonModule } from '@angular/common';
|
import { CommonModule } from '@angular/common';
|
||||||
|
@ -1,5 +1,14 @@
|
|||||||
import { ComponentFixture, async, TestBed } from '@angular/core/testing';
|
import { ComponentFixture, async, TestBed } from '@angular/core/testing';
|
||||||
import { MatInputModule, MatIconModule, MatToolbarModule, MatMenuModule, MatCheckboxModule, MatSelectModule, MatFormFieldModule, MatAutocompleteModule, MatTableModule, MatStepperModule } from '@angular/material';
|
import { MatAutocompleteModule } from '@angular/material/autocomplete';
|
||||||
|
import { MatCheckboxModule } from '@angular/material/checkbox';
|
||||||
|
import { MatFormFieldModule } from '@angular/material/form-field';
|
||||||
|
import { MatIconModule } from '@angular/material/icon';
|
||||||
|
import { MatInputModule } from '@angular/material/input';
|
||||||
|
import { MatMenuModule } from '@angular/material/menu';
|
||||||
|
import { MatSelectModule } from '@angular/material/select';
|
||||||
|
import { MatStepperModule } from '@angular/material/stepper';
|
||||||
|
import { MatTableModule } from '@angular/material/table';
|
||||||
|
import { MatToolbarModule } from '@angular/material/toolbar';
|
||||||
import { CommonModule } from '@angular/common';
|
import { CommonModule } from '@angular/common';
|
||||||
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
||||||
import { RouterTestingModule } from '@angular/router/testing';
|
import { RouterTestingModule } from '@angular/router/testing';
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
import { ComponentFixture, async, TestBed } from '@angular/core/testing';
|
import { ComponentFixture, async, TestBed } from '@angular/core/testing';
|
||||||
import { MatIconModule, MatToolbarModule, MatMenuModule, MatCheckboxModule } from '@angular/material';
|
import { MatCheckboxModule } from '@angular/material/checkbox';
|
||||||
|
import { MatIconModule } from '@angular/material/icon';
|
||||||
|
import { MatMenuModule } from '@angular/material/menu';
|
||||||
|
import { MatToolbarModule } from '@angular/material/toolbar';
|
||||||
import { CommonModule } from '@angular/common';
|
import { CommonModule } from '@angular/common';
|
||||||
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
||||||
import { RouterTestingModule } from '@angular/router/testing';
|
import { RouterTestingModule } from '@angular/router/testing';
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
import { ComponentFixture, async, TestBed } from '@angular/core/testing';
|
import { ComponentFixture, async, TestBed } from '@angular/core/testing';
|
||||||
import { MatIconModule, MatToolbarModule, MatMenuModule, MatCheckboxModule } from '@angular/material';
|
import { MatCheckboxModule } from '@angular/material/checkbox';
|
||||||
|
import { MatIconModule } from '@angular/material/icon';
|
||||||
|
import { MatMenuModule } from '@angular/material/menu';
|
||||||
|
import { MatToolbarModule } from '@angular/material/toolbar';
|
||||||
import { CommonModule } from '@angular/common';
|
import { CommonModule } from '@angular/common';
|
||||||
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
||||||
import { RouterTestingModule } from '@angular/router/testing';
|
import { RouterTestingModule } from '@angular/router/testing';
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
import { MatCheckboxModule, MatIconModule, MatToolbarModule, MatMenuModule } from '@angular/material';
|
import { MatCheckboxModule } from '@angular/material/checkbox';
|
||||||
|
import { MatIconModule } from '@angular/material/icon';
|
||||||
|
import { MatMenuModule } from '@angular/material/menu';
|
||||||
|
import { MatToolbarModule } from '@angular/material/toolbar';
|
||||||
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
||||||
import { PreferencesComponent } from './preferences.component';
|
import { PreferencesComponent } from './preferences.component';
|
||||||
import { ActivatedRoute } from '@angular/router';
|
import { ActivatedRoute } from '@angular/router';
|
||||||
|
@ -1,5 +1,13 @@
|
|||||||
import { ComponentFixture, async, TestBed } from '@angular/core/testing';
|
import { ComponentFixture, async, TestBed } from '@angular/core/testing';
|
||||||
import { MatIconModule, MatToolbarModule, MatMenuModule, MatCheckboxModule, MatSelectModule, MatAutocompleteModule, MatFormFieldModule, MatInputModule, MatStepperModule } from '@angular/material';
|
import { MatAutocompleteModule } from '@angular/material/autocomplete';
|
||||||
|
import { MatCheckboxModule } from '@angular/material/checkbox';
|
||||||
|
import { MatFormFieldModule } from '@angular/material/form-field';
|
||||||
|
import { MatIconModule } from '@angular/material/icon';
|
||||||
|
import { MatInputModule } from '@angular/material/input';
|
||||||
|
import { MatMenuModule } from '@angular/material/menu';
|
||||||
|
import { MatSelectModule } from '@angular/material/select';
|
||||||
|
import { MatStepperModule } from '@angular/material/stepper';
|
||||||
|
import { MatToolbarModule } from '@angular/material/toolbar';
|
||||||
import { CommonModule } from '@angular/common';
|
import { CommonModule } from '@angular/common';
|
||||||
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
||||||
import { RouterTestingModule } from '@angular/router/testing';
|
import { RouterTestingModule } from '@angular/router/testing';
|
||||||
|
@ -146,7 +146,7 @@ export class AddQemuVmTemplateComponent implements OnInit {
|
|||||||
|
|
||||||
addTemplate() {
|
addTemplate() {
|
||||||
if (!this.nameForm.invalid && !this.memoryForm.invalid && (this.selectedImage || this.chosenImage)) {
|
if (!this.nameForm.invalid && !this.memoryForm.invalid && (this.selectedImage || this.chosenImage)) {
|
||||||
this.qemuTemplate.ram = this.memoryForm.get("ramMemory").value;
|
this.qemuTemplate.ram = +this.memoryForm.get("ramMemory").value;
|
||||||
this.qemuTemplate.qemu_path = this.selectedBinary.path;
|
this.qemuTemplate.qemu_path = this.selectedBinary.path;
|
||||||
if (this.newImageSelected) {
|
if (this.newImageSelected) {
|
||||||
this.qemuTemplate.hda_disk_image = this.diskForm.get("fileName").value;
|
this.qemuTemplate.hda_disk_image = this.diskForm.get("fileName").value;
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
import { ComponentFixture, async, TestBed } from '@angular/core/testing';
|
import { ComponentFixture, async, TestBed } from '@angular/core/testing';
|
||||||
import { MatIconModule, MatToolbarModule, MatMenuModule, MatCheckboxModule } from '@angular/material';
|
import { MatCheckboxModule } from '@angular/material/checkbox';
|
||||||
|
import { MatIconModule } from '@angular/material/icon';
|
||||||
|
import { MatMenuModule } from '@angular/material/menu';
|
||||||
|
import { MatToolbarModule } from '@angular/material/toolbar';
|
||||||
import { CommonModule } from '@angular/common';
|
import { CommonModule } from '@angular/common';
|
||||||
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
||||||
import { RouterTestingModule } from '@angular/router/testing';
|
import { RouterTestingModule } from '@angular/router/testing';
|
||||||
|
@ -1,5 +1,9 @@
|
|||||||
import { ComponentFixture, async, TestBed } from '@angular/core/testing';
|
import { ComponentFixture, async, TestBed } from '@angular/core/testing';
|
||||||
import { MatIconModule, MatToolbarModule, MatMenuModule, MatCheckboxModule, MatTableModule } from '@angular/material';
|
import { MatCheckboxModule } from '@angular/material/checkbox';
|
||||||
|
import { MatIconModule } from '@angular/material/icon';
|
||||||
|
import { MatMenuModule } from '@angular/material/menu';
|
||||||
|
import { MatTableModule } from '@angular/material/table';
|
||||||
|
import { MatToolbarModule } from '@angular/material/toolbar';
|
||||||
import { CommonModule } from '@angular/common';
|
import { CommonModule } from '@angular/common';
|
||||||
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
||||||
import { RouterTestingModule } from '@angular/router/testing';
|
import { RouterTestingModule } from '@angular/router/testing';
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
import { ComponentFixture, async, TestBed } from '@angular/core/testing';
|
import { ComponentFixture, async, TestBed } from '@angular/core/testing';
|
||||||
import { MatIconModule, MatToolbarModule, MatMenuModule, MatCheckboxModule } from '@angular/material';
|
import { MatCheckboxModule } from '@angular/material/checkbox';
|
||||||
|
import { MatIconModule } from '@angular/material/icon';
|
||||||
|
import { MatMenuModule } from '@angular/material/menu';
|
||||||
|
import { MatToolbarModule } from '@angular/material/toolbar';
|
||||||
import { CommonModule } from '@angular/common';
|
import { CommonModule } from '@angular/common';
|
||||||
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
||||||
import { RouterTestingModule } from '@angular/router/testing';
|
import { RouterTestingModule } from '@angular/router/testing';
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
import { ComponentFixture, async, TestBed } from '@angular/core/testing';
|
import { ComponentFixture, async, TestBed } from '@angular/core/testing';
|
||||||
import { MatIconModule, MatToolbarModule, MatMenuModule, MatCheckboxModule } from '@angular/material';
|
import { MatCheckboxModule } from '@angular/material/checkbox';
|
||||||
|
import { MatIconModule } from '@angular/material/icon';
|
||||||
|
import { MatMenuModule } from '@angular/material/menu';
|
||||||
|
import { MatToolbarModule } from '@angular/material/toolbar';
|
||||||
import { CommonModule } from '@angular/common';
|
import { CommonModule } from '@angular/common';
|
||||||
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
||||||
import { RouterTestingModule } from '@angular/router/testing';
|
import { RouterTestingModule } from '@angular/router/testing';
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
import { ComponentFixture, async, TestBed } from '@angular/core/testing';
|
import { ComponentFixture, async, TestBed } from '@angular/core/testing';
|
||||||
import { MatIconModule, MatToolbarModule, MatMenuModule, MatCheckboxModule } from '@angular/material';
|
import { MatCheckboxModule } from '@angular/material/checkbox';
|
||||||
|
import { MatIconModule } from '@angular/material/icon';
|
||||||
|
import { MatMenuModule } from '@angular/material/menu';
|
||||||
|
import { MatToolbarModule } from '@angular/material/toolbar';
|
||||||
import { CommonModule } from '@angular/common';
|
import { CommonModule } from '@angular/common';
|
||||||
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
||||||
import { RouterTestingModule } from '@angular/router/testing';
|
import { RouterTestingModule } from '@angular/router/testing';
|
||||||
|
@ -1,5 +1,9 @@
|
|||||||
import { ComponentFixture, async, TestBed } from '@angular/core/testing';
|
import { ComponentFixture, async, TestBed } from '@angular/core/testing';
|
||||||
import { MatIconModule, MatToolbarModule, MatMenuModule, MatCheckboxModule, MatTableModule } from '@angular/material';
|
import { MatCheckboxModule } from '@angular/material/checkbox';
|
||||||
|
import { MatIconModule } from '@angular/material/icon';
|
||||||
|
import { MatMenuModule } from '@angular/material/menu';
|
||||||
|
import { MatTableModule } from '@angular/material/table';
|
||||||
|
import { MatToolbarModule } from '@angular/material/toolbar';
|
||||||
import { CommonModule } from '@angular/common';
|
import { CommonModule } from '@angular/common';
|
||||||
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
||||||
import { RouterTestingModule } from '@angular/router/testing';
|
import { RouterTestingModule } from '@angular/router/testing';
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
import { ComponentFixture, async, TestBed } from '@angular/core/testing';
|
import { ComponentFixture, async, TestBed } from '@angular/core/testing';
|
||||||
import { MatIconModule, MatToolbarModule, MatMenuModule, MatCheckboxModule } from '@angular/material';
|
import { MatCheckboxModule } from '@angular/material/checkbox';
|
||||||
|
import { MatIconModule } from '@angular/material/icon';
|
||||||
|
import { MatMenuModule } from '@angular/material/menu';
|
||||||
|
import { MatToolbarModule } from '@angular/material/toolbar';
|
||||||
import { CommonModule } from '@angular/common';
|
import { CommonModule } from '@angular/common';
|
||||||
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
||||||
import { RouterTestingModule } from '@angular/router/testing';
|
import { RouterTestingModule } from '@angular/router/testing';
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
import { ComponentFixture, async, TestBed } from '@angular/core/testing';
|
import { ComponentFixture, async, TestBed } from '@angular/core/testing';
|
||||||
import { MatIconModule, MatToolbarModule, MatMenuModule, MatCheckboxModule } from '@angular/material';
|
import { MatCheckboxModule } from '@angular/material/checkbox';
|
||||||
|
import { MatIconModule } from '@angular/material/icon';
|
||||||
|
import { MatMenuModule } from '@angular/material/menu';
|
||||||
|
import { MatToolbarModule } from '@angular/material/toolbar';
|
||||||
import { CommonModule } from '@angular/common';
|
import { CommonModule } from '@angular/common';
|
||||||
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
||||||
import { RouterTestingModule } from '@angular/router/testing';
|
import { RouterTestingModule } from '@angular/router/testing';
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
import { ComponentFixture, async, TestBed } from '@angular/core/testing';
|
import { ComponentFixture, async, TestBed } from '@angular/core/testing';
|
||||||
import { MatIconModule, MatToolbarModule, MatMenuModule, MatCheckboxModule } from '@angular/material';
|
import { MatCheckboxModule } from '@angular/material/checkbox';
|
||||||
|
import { MatIconModule } from '@angular/material/icon';
|
||||||
|
import { MatMenuModule } from '@angular/material/menu';
|
||||||
|
import { MatToolbarModule } from '@angular/material/toolbar';
|
||||||
import { CommonModule } from '@angular/common';
|
import { CommonModule } from '@angular/common';
|
||||||
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
||||||
import { RouterTestingModule } from '@angular/router/testing';
|
import { RouterTestingModule } from '@angular/router/testing';
|
||||||
|
@ -1,5 +1,9 @@
|
|||||||
import { ComponentFixture, async, TestBed } from '@angular/core/testing';
|
import { ComponentFixture, async, TestBed } from '@angular/core/testing';
|
||||||
import { MatIconModule, MatToolbarModule, MatMenuModule, MatCheckboxModule, MatTableModule } from '@angular/material';
|
import { MatCheckboxModule } from '@angular/material/checkbox';
|
||||||
|
import { MatIconModule } from '@angular/material/icon';
|
||||||
|
import { MatMenuModule } from '@angular/material/menu';
|
||||||
|
import { MatTableModule } from '@angular/material/table';
|
||||||
|
import { MatToolbarModule } from '@angular/material/toolbar';
|
||||||
import { CommonModule } from '@angular/common';
|
import { CommonModule } from '@angular/common';
|
||||||
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
||||||
import { RouterTestingModule } from '@angular/router/testing';
|
import { RouterTestingModule } from '@angular/router/testing';
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
import { ComponentFixture, async, TestBed } from '@angular/core/testing';
|
import { ComponentFixture, async, TestBed } from '@angular/core/testing';
|
||||||
import { MatIconModule, MatToolbarModule, MatMenuModule, MatCheckboxModule } from '@angular/material';
|
import { MatCheckboxModule } from '@angular/material/checkbox';
|
||||||
|
import { MatIconModule } from '@angular/material/icon';
|
||||||
|
import { MatMenuModule } from '@angular/material/menu';
|
||||||
|
import { MatToolbarModule } from '@angular/material/toolbar';
|
||||||
import { CommonModule } from '@angular/common';
|
import { CommonModule } from '@angular/common';
|
||||||
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
||||||
import { RouterTestingModule } from '@angular/router/testing';
|
import { RouterTestingModule } from '@angular/router/testing';
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
import { ComponentFixture, async, TestBed } from '@angular/core/testing';
|
import { ComponentFixture, async, TestBed } from '@angular/core/testing';
|
||||||
import { MatIconModule, MatToolbarModule, MatMenuModule, MatCheckboxModule } from '@angular/material';
|
import { MatCheckboxModule } from '@angular/material/checkbox';
|
||||||
|
import { MatIconModule } from '@angular/material/icon';
|
||||||
|
import { MatMenuModule } from '@angular/material/menu';
|
||||||
|
import { MatToolbarModule } from '@angular/material/toolbar';
|
||||||
import { CommonModule } from '@angular/common';
|
import { CommonModule } from '@angular/common';
|
||||||
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
||||||
import { RouterTestingModule } from '@angular/router/testing';
|
import { RouterTestingModule } from '@angular/router/testing';
|
||||||
@ -17,6 +20,13 @@ import { MockedToasterService } from '../../../../services/toaster.service.spec'
|
|||||||
import { VpcsTemplate } from '../../../../models/templates/vpcs-template';
|
import { VpcsTemplate } from '../../../../models/templates/vpcs-template';
|
||||||
import { MockedActivatedRoute } from '../../preferences.component.spec';
|
import { MockedActivatedRoute } from '../../preferences.component.spec';
|
||||||
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
|
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
|
||||||
|
import { ComputeService } from '../../../../services/compute.service';
|
||||||
|
|
||||||
|
export class MockedComputeService {
|
||||||
|
getComputes(server: Server) {
|
||||||
|
return of([]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export class MockedVpcsService {
|
export class MockedVpcsService {
|
||||||
public addTemplate(server: Server, vpcsTemplate: VpcsTemplate) {
|
public addTemplate(server: Server, vpcsTemplate: VpcsTemplate) {
|
||||||
@ -32,6 +42,7 @@ describe('AddVpcsTemplateComponent', () => {
|
|||||||
let mockedVpcsService = new MockedVpcsService;
|
let mockedVpcsService = new MockedVpcsService;
|
||||||
let mockedToasterService = new MockedToasterService;
|
let mockedToasterService = new MockedToasterService;
|
||||||
let activatedRoute = new MockedActivatedRoute().get();
|
let activatedRoute = new MockedActivatedRoute().get();
|
||||||
|
let mockedComputeService = new MockedComputeService();
|
||||||
|
|
||||||
beforeEach(async(() => {
|
beforeEach(async(() => {
|
||||||
TestBed.configureTestingModule({
|
TestBed.configureTestingModule({
|
||||||
@ -51,6 +62,7 @@ describe('AddVpcsTemplateComponent', () => {
|
|||||||
{ provide: ServerService, useValue: mockedServerService },
|
{ provide: ServerService, useValue: mockedServerService },
|
||||||
{ provide: VpcsService, useValue: mockedVpcsService },
|
{ provide: VpcsService, useValue: mockedVpcsService },
|
||||||
{ provide: ToasterService, useValue: mockedToasterService },
|
{ provide: ToasterService, useValue: mockedToasterService },
|
||||||
|
{ provide: ComputeService, useValue: mockedComputeService },
|
||||||
{ provide: TemplateMocksService, useClass: TemplateMocksService }
|
{ provide: TemplateMocksService, useClass: TemplateMocksService }
|
||||||
],
|
],
|
||||||
declarations: [
|
declarations: [
|
||||||
|
@ -1,6 +1,9 @@
|
|||||||
import { VpcsPreferencesComponent } from "./vpcs-preferences.component";
|
import { VpcsPreferencesComponent } from "./vpcs-preferences.component";
|
||||||
import { ComponentFixture, async, TestBed } from '@angular/core/testing';
|
import { ComponentFixture, async, TestBed } from '@angular/core/testing';
|
||||||
import { MatIconModule, MatToolbarModule, MatMenuModule, MatCheckboxModule } from '@angular/material';
|
import { MatCheckboxModule } from '@angular/material/checkbox';
|
||||||
|
import { MatIconModule } from '@angular/material/icon';
|
||||||
|
import { MatMenuModule } from '@angular/material/menu';
|
||||||
|
import { MatToolbarModule } from '@angular/material/toolbar';
|
||||||
import { CommonModule } from '@angular/common';
|
import { CommonModule } from '@angular/common';
|
||||||
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
||||||
import { RouterTestingModule } from '@angular/router/testing';
|
import { RouterTestingModule } from '@angular/router/testing';
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
import { ComponentFixture, async, TestBed } from '@angular/core/testing';
|
import { ComponentFixture, async, TestBed } from '@angular/core/testing';
|
||||||
import { MatIconModule, MatToolbarModule, MatMenuModule, MatCheckboxModule } from '@angular/material';
|
import { MatCheckboxModule } from '@angular/material/checkbox';
|
||||||
|
import { MatIconModule } from '@angular/material/icon';
|
||||||
|
import { MatMenuModule } from '@angular/material/menu';
|
||||||
|
import { MatToolbarModule } from '@angular/material/toolbar';
|
||||||
import { CommonModule } from '@angular/common';
|
import { CommonModule } from '@angular/common';
|
||||||
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
||||||
import { RouterTestingModule } from '@angular/router/testing';
|
import { RouterTestingModule } from '@angular/router/testing';
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
import { ComponentFixture, async, TestBed } from '@angular/core/testing';
|
import { ComponentFixture, async, TestBed } from '@angular/core/testing';
|
||||||
import { MatIconModule, MatToolbarModule, MatMenuModule, MatCheckboxModule } from '@angular/material';
|
import { MatCheckboxModule } from '@angular/material/checkbox';
|
||||||
|
import { MatIconModule } from '@angular/material/icon';
|
||||||
|
import { MatMenuModule } from '@angular/material/menu';
|
||||||
|
import { MatToolbarModule } from '@angular/material/toolbar';
|
||||||
import { CommonModule } from '@angular/common';
|
import { CommonModule } from '@angular/common';
|
||||||
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
||||||
import { RouterTestingModule } from '@angular/router/testing';
|
import { RouterTestingModule } from '@angular/router/testing';
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
(document:mousemove)="dragWidget($event)"
|
(document:mousemove)="dragWidget($event)"
|
||||||
(document:mouseup)="toggleDragging(false)">
|
(document:mouseup)="toggleDragging(false)">
|
||||||
</div>
|
</div>
|
||||||
<!-- Option with resizing
|
<!-- Option with resizing -->
|
||||||
<div
|
<div
|
||||||
class="consoleWrapper"
|
class="consoleWrapper"
|
||||||
[ngClass]="{lightTheme: isLightThemeEnabled}"
|
[ngClass]="{lightTheme: isLightThemeEnabled}"
|
||||||
@ -14,14 +14,14 @@
|
|||||||
[resizeEdges]="{ right: true, left: true, bottom: true, top: true }"
|
[resizeEdges]="{ right: true, left: true, bottom: true, top: true }"
|
||||||
[enableGhostResize]="true"
|
[enableGhostResize]="true"
|
||||||
(resizeStart)="toggleDragging(false)"
|
(resizeStart)="toggleDragging(false)"
|
||||||
(resizeEnd)="onResizeEnd($event)"> -->
|
(resizeEnd)="onResizeEnd($event)">
|
||||||
<div
|
<!-- <div
|
||||||
class="consoleWrapper"
|
class="consoleWrapper"
|
||||||
[ngClass]="{lightTheme: isLightThemeEnabled}"
|
[ngClass]="{lightTheme: isLightThemeEnabled}"
|
||||||
(mousedown)="toggleDragging(true)"
|
(mousedown)="toggleDragging(true)"
|
||||||
[ngStyle]="style">
|
[ngStyle]="style"> -->
|
||||||
|
|
||||||
<div class="consoleHeader">
|
<div class="consoleHeader" [ngClass]="{lightThemeConsoleHeader: isLightThemeEnabled}">
|
||||||
<mat-tab-group class="tabs" [selectedIndex]="selected.value" (selectedIndexChange)="selected.setValue($event)">
|
<mat-tab-group class="tabs" [selectedIndex]="selected.value" (selectedIndexChange)="selected.setValue($event)">
|
||||||
<mat-tab>
|
<mat-tab>
|
||||||
<ng-template mat-tab-label>
|
<ng-template mat-tab-label>
|
||||||
@ -32,7 +32,7 @@
|
|||||||
<mat-tab *ngFor="let node of nodes; let index = index" [label]="tab">
|
<mat-tab *ngFor="let node of nodes; let index = index" [label]="tab">
|
||||||
<ng-template mat-tab-label>
|
<ng-template mat-tab-label>
|
||||||
<div class="col" style="margin-left: 20px;">{{node.name}}</div>
|
<div class="col" style="margin-left: 20px;">{{node.name}}</div>
|
||||||
<button style="color:white" mat-icon-button (click)="removeTab(index)">
|
<button [ngClass]="{lightThemeConsoleHeader: isLightThemeEnabled}" style="color:white" mat-icon-button (click)="removeTab(index)">
|
||||||
<mat-icon>close</mat-icon>
|
<mat-icon>close</mat-icon>
|
||||||
</button>
|
</button>
|
||||||
</ng-template>
|
</ng-template>
|
||||||
@ -40,20 +40,20 @@
|
|||||||
|
|
||||||
</mat-tab-group>
|
</mat-tab-group>
|
||||||
|
|
||||||
<button *ngIf="!isMinimized" style="color:white" mat-icon-button (click)="minimize(true)">
|
<button *ngIf="!isMinimized" [ngClass]="{lightThemeConsoleHeader: isLightThemeEnabled}" style="color:white" mat-icon-button (click)="minimize(true)">
|
||||||
<mat-icon>remove</mat-icon>
|
<mat-icon>remove</mat-icon>
|
||||||
</button>
|
</button>
|
||||||
<button *ngIf="isMinimized" style="color:white" mat-icon-button (click)="minimize(false)">
|
<button *ngIf="isMinimized" [ngClass]="{lightThemeConsoleHeader: isLightThemeEnabled}" style="color:white" mat-icon-button (click)="minimize(false)">
|
||||||
<mat-icon>web_asset</mat-icon>
|
<mat-icon>web_asset</mat-icon>
|
||||||
</button>
|
</button>
|
||||||
<button style="color:white" mat-icon-button (click)="close()">
|
<button [ngClass]="{lightThemeConsoleHeader: isLightThemeEnabled}" style="color:white" mat-icon-button (click)="close()">
|
||||||
<mat-icon>close</mat-icon>
|
<mat-icon>close</mat-icon>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<app-log-console [hidden]="!(selected.value===0) || isMinimized" [server]="server" [project]="project"></app-log-console>
|
<app-log-console [hidden]="!(selected.value===0) || isMinimized" [server]="server" [project]="project"></app-log-console>
|
||||||
|
|
||||||
<div [hidden]="isMinimized" *ngFor="let node of nodes; let index = index">
|
<div (mouseover)="disableScroll($event)" (mouseout)="enableScroll($event)" class="xterm-console" [hidden]="isMinimized" *ngFor="let node of nodes; let index = index">
|
||||||
<app-web-console [hidden]="!(selected.value===(index+1))" [server]="server" [node]="nodes[index]"></app-web-console>
|
<app-web-console [hidden]="!(selected.value===(index+1))" [server]="server" [node]="nodes[index]"></app-web-console>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
left: 20px;
|
left: 20px;
|
||||||
height: 180px;
|
height: 180px;
|
||||||
width: 600px;
|
width: 600px;
|
||||||
background: #263238;
|
background: #000000!important;
|
||||||
color: white;
|
color: white;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
@ -38,10 +38,31 @@
|
|||||||
display: flex;
|
display: flex;
|
||||||
padding: 2px;
|
padding: 2px;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
|
background: #263238!important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.lightThemeConsoleHeader {
|
||||||
|
background: white!important;
|
||||||
|
color: black!important;
|
||||||
|
}
|
||||||
|
|
||||||
|
:host ::ng-deep .mat-tab-label {
|
||||||
|
height: 3rem !important;
|
||||||
|
min-width: 8rem !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
:host ::ng-deep .mat-tab-label.mat-tab-label-active {
|
||||||
|
border-bottom: 2px solid #0097a7;
|
||||||
|
box-sizing: border-box;
|
||||||
|
font-weight: 1200;
|
||||||
|
}
|
||||||
|
|
||||||
|
:host ::ng-deep .mat-ink-bar {
|
||||||
|
display: none !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.tabs {
|
.tabs {
|
||||||
width: 630px;
|
width: 80%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.console {
|
.console {
|
||||||
@ -54,6 +75,10 @@
|
|||||||
scrollbar-width: thin;
|
scrollbar-width: thin;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.xterm-console {
|
||||||
|
background: black;
|
||||||
|
}
|
||||||
|
|
||||||
.consoleInput {
|
.consoleInput {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 30px;
|
height: 30px;
|
||||||
|
@ -7,6 +7,7 @@ import { ThemeService } from '../../../services/theme.service';
|
|||||||
import { FormControl } from '@angular/forms';
|
import { FormControl } from '@angular/forms';
|
||||||
import { NodeConsoleService } from '../../../services/nodeConsole.service';
|
import { NodeConsoleService } from '../../../services/nodeConsole.service';
|
||||||
import { Node } from '../../../cartography/models/node';
|
import { Node } from '../../../cartography/models/node';
|
||||||
|
import { MapSettingsService } from '../../../services/mapsettings.service';
|
||||||
|
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
@ -24,15 +25,17 @@ export class ConsoleWrapperComponent implements OnInit {
|
|||||||
|
|
||||||
public style: object = {};
|
public style: object = {};
|
||||||
public styleInside: object = { height: `120px` };
|
public styleInside: object = { height: `120px` };
|
||||||
|
|
||||||
public isDraggingEnabled: boolean = false;
|
public isDraggingEnabled: boolean = false;
|
||||||
public isLightThemeEnabled: boolean = false;
|
public isLightThemeEnabled: boolean = false;
|
||||||
|
|
||||||
public isMinimized: boolean = false;
|
public isMinimized: boolean = false;
|
||||||
|
|
||||||
|
public resizedWidth: number = 720;
|
||||||
|
public resizedHeight: number = 480;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private consoleService: NodeConsoleService,
|
private consoleService: NodeConsoleService,
|
||||||
private themeService: ThemeService
|
private themeService: ThemeService,
|
||||||
|
private mapSettingsService: MapSettingsService
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
nodes: Node[] = [];
|
nodes: Node[] = [];
|
||||||
@ -55,9 +58,9 @@ export class ConsoleWrapperComponent implements OnInit {
|
|||||||
minimize(value: boolean) {
|
minimize(value: boolean) {
|
||||||
this.isMinimized = value;
|
this.isMinimized = value;
|
||||||
if (!value) {
|
if (!value) {
|
||||||
this.style = { bottom: '20px', left: '20px', width: '720px', height: '460px'};
|
this.style = { bottom: '20px', left: '20px', width: `${this.resizedWidth}px`, height: `${this.resizedHeight}px`}
|
||||||
} else {
|
} else {
|
||||||
this.style = { bottom: '20px', left: '20px', width: '720px', height: '56px'};
|
this.style = { bottom: '20px', left: '20px', width: `${this.resizedWidth}px`, height: '56px'};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -113,8 +116,8 @@ export class ConsoleWrapperComponent implements OnInit {
|
|||||||
if (
|
if (
|
||||||
event.rectangle.width &&
|
event.rectangle.width &&
|
||||||
event.rectangle.height &&
|
event.rectangle.height &&
|
||||||
(event.rectangle.width < 720 ||
|
(event.rectangle.width < 500 ||
|
||||||
event.rectangle.height < 460)
|
event.rectangle.height < 100)
|
||||||
) {
|
) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -134,9 +137,25 @@ export class ConsoleWrapperComponent implements OnInit {
|
|||||||
height: `${event.rectangle.height - 60}px`,
|
height: `${event.rectangle.height - 60}px`,
|
||||||
width: `${event.rectangle.width}px`
|
width: `${event.rectangle.width}px`
|
||||||
};
|
};
|
||||||
|
|
||||||
|
this.consoleService.consoleResized.next({
|
||||||
|
width: event.rectangle.width,
|
||||||
|
height: event.rectangle.height - 53
|
||||||
|
});
|
||||||
|
|
||||||
|
this.resizedWidth = event.rectangle.width;
|
||||||
|
this.resizedHeight = event.rectangle.height;
|
||||||
}
|
}
|
||||||
|
|
||||||
close() {
|
close() {
|
||||||
this.closeConsole.emit(false);
|
this.closeConsole.emit(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enableScroll(e) {
|
||||||
|
this.mapSettingsService.isScrollDisabled.next(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
disableScroll(e) {
|
||||||
|
this.mapSettingsService.isScrollDisabled.next(true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,22 @@
|
|||||||
|
<div class="context-menu" [style.left]="leftPosition" [style.top]="topPosition">
|
||||||
|
<span [matMenuTriggerFor]="contextConsoleMenu"></span>
|
||||||
|
<mat-menu #contextConsoleMenu="matMenu" class="context-menu-items">
|
||||||
|
<span class="title">
|
||||||
|
Choose default behavior for double click on node
|
||||||
|
</span>
|
||||||
|
<button mat-menu-item (click)="openConsole()">
|
||||||
|
<mat-icon>web_asset</mat-icon>
|
||||||
|
<span>Open console</span>
|
||||||
|
</button>
|
||||||
|
<button mat-menu-item (click)="openWebConsole()">
|
||||||
|
<mat-icon>http</mat-icon>
|
||||||
|
<span>Open web console</span>
|
||||||
|
</button>
|
||||||
|
<button mat-menu-item (click)="openWebConsoleInNewTab()">
|
||||||
|
<mat-icon>http</mat-icon>
|
||||||
|
<span>Open web console in new tab</span>
|
||||||
|
</button>
|
||||||
|
</mat-menu>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<template [hidden]="true" #container></template>
|
@ -0,0 +1,12 @@
|
|||||||
|
.context-menu {
|
||||||
|
position: absolute;
|
||||||
|
min-height: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mat-menu-panel ng-trigger ng-trigger-transformMenu ng-tns-c7-5 context-menu-items mat-menu-after mat-menu-below ng-star-inserted mat-elevation-z4 {
|
||||||
|
min-height: 0px!important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.title {
|
||||||
|
margin: 10px;
|
||||||
|
}
|
@ -0,0 +1,109 @@
|
|||||||
|
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
import { BrowserModule } from '@angular/platform-browser';
|
||||||
|
import { ChangeDetectorRef, NO_ERRORS_SCHEMA } from '@angular/core';
|
||||||
|
import { ProjectService } from '../../../services/project.service';
|
||||||
|
import { MockedProjectService } from '../../projects/add-blank-project-dialog/add-blank-project-dialog.component.spec';
|
||||||
|
import { MatMenuModule, MatMenuTrigger } from '@angular/material/menu';
|
||||||
|
import { Server } from '../../../models/server';
|
||||||
|
import { ElectronService } from 'ngx-electron';
|
||||||
|
import { ContextConsoleMenuComponent } from './context-console-menu.component';
|
||||||
|
import { MapSettingsService } from '../../../services/mapsettings.service';
|
||||||
|
import { NodeConsoleService } from '../../../services/nodeConsole.service';
|
||||||
|
import { ConsoleService } from '../../../services/settings/console.service';
|
||||||
|
import { ToasterService } from '../../../services/toaster.service';
|
||||||
|
import { MockedToasterService } from '../../../services/toaster.service.spec';
|
||||||
|
import { Router } from '@angular/router';
|
||||||
|
import { Node } from '../../../cartography/models/node';
|
||||||
|
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';
|
||||||
|
|
||||||
|
fdescribe('ContextConsoleMenuComponent', () => {
|
||||||
|
let component: ContextConsoleMenuComponent;
|
||||||
|
let fixture: ComponentFixture<ContextConsoleMenuComponent>;
|
||||||
|
let toasterService: MockedToasterService = new MockedToasterService();
|
||||||
|
let router = {
|
||||||
|
url: '',
|
||||||
|
navigate: jasmine.createSpy('navigate')
|
||||||
|
};
|
||||||
|
let node = {
|
||||||
|
status: 'started'
|
||||||
|
};
|
||||||
|
let mapSettingsService = new MapSettingsService();
|
||||||
|
|
||||||
|
beforeEach(async(() => {
|
||||||
|
const electronMock = {
|
||||||
|
isElectronApp: true
|
||||||
|
};
|
||||||
|
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
imports: [MatMenuModule, BrowserModule],
|
||||||
|
providers: [
|
||||||
|
{ provide: ChangeDetectorRef },
|
||||||
|
{ provide: ProjectService, useClass: MockedProjectService },
|
||||||
|
{ provide: ElectronService, useValue: electronMock },
|
||||||
|
{ provide: MapSettingsService, useValue: mapSettingsService },
|
||||||
|
{ provide: NodeConsoleService },
|
||||||
|
{ provide: ConsoleService },
|
||||||
|
{ provide: ToasterService, useValue: toasterService },
|
||||||
|
{ provide: Router, useValue: router }
|
||||||
|
],
|
||||||
|
declarations: [
|
||||||
|
ContextConsoleMenuComponent,
|
||||||
|
ConsoleDeviceActionComponent,
|
||||||
|
ConsoleDeviceActionBrowserComponent
|
||||||
|
],
|
||||||
|
schemas: [NO_ERRORS_SCHEMA]
|
||||||
|
}).compileComponents();
|
||||||
|
}));
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
fixture = TestBed.createComponent(ContextConsoleMenuComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
component.server = {location: 'local'} as Server;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should define property if running in electron ', () => {
|
||||||
|
expect(component.isElectronApp).toBeTruthy();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should open menu if there is no default settings', () => {
|
||||||
|
let spy = spyOn(component.contextConsoleMenu, 'openMenu');
|
||||||
|
localStorage.removeItem('consoleContextMenu');
|
||||||
|
|
||||||
|
component.openMenu(node as unknown as Node, 0, 0);
|
||||||
|
|
||||||
|
expect(spy.calls.any()).toBeTruthy();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should call open web console when web console action in settings', () => {
|
||||||
|
let spy = spyOn(component, 'openWebConsole');
|
||||||
|
mapSettingsService.setConsoleContextMenuAction('web console');
|
||||||
|
|
||||||
|
component.openMenu(node as unknown as Node, 0, 0);
|
||||||
|
|
||||||
|
expect(spy.calls.any()).toBeTruthy();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should call open web console in new tab when web console in new tab action in settings', () => {
|
||||||
|
let spy = spyOn(component, 'openWebConsoleInNewTab');
|
||||||
|
mapSettingsService.setConsoleContextMenuAction('web console in new tab');
|
||||||
|
|
||||||
|
component.openMenu(node as unknown as Node, 0, 0);
|
||||||
|
|
||||||
|
expect(spy.calls.any()).toBeTruthy();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should call open console when console action in settings', () => {
|
||||||
|
let spy = spyOn(component, 'openConsole');
|
||||||
|
mapSettingsService.setConsoleContextMenuAction('console');
|
||||||
|
|
||||||
|
component.openMenu(node as unknown as Node, 0, 0);
|
||||||
|
|
||||||
|
expect(spy.calls.any()).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
@ -0,0 +1,112 @@
|
|||||||
|
import { ChangeDetectorRef, Component, ComponentFactory, ComponentRef, Input, OnInit, ViewChild, ViewContainerRef } from '@angular/core';
|
||||||
|
import { MatMenuTrigger } from '@angular/material/menu';
|
||||||
|
import { DomSanitizer } from '@angular/platform-browser';
|
||||||
|
import { Node } from '../../../cartography/models/node';
|
||||||
|
import { Server } from '../../../models/server';
|
||||||
|
import { Project } from '../../../models/project';
|
||||||
|
import { MapSettingsService } from '../../../services/mapsettings.service';
|
||||||
|
import { ElectronService } from 'ngx-electron';
|
||||||
|
import { NodeConsoleService } from '../../../services/nodeConsole.service';
|
||||||
|
import { ToasterService } from '../../../services/toaster.service';
|
||||||
|
import { Router } from '@angular/router';
|
||||||
|
import { ComponentFactoryResolver } from '@angular/core';
|
||||||
|
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';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-context-console-menu',
|
||||||
|
templateUrl: './context-console-menu.component.html',
|
||||||
|
styleUrls: ['./context-console-menu.component.scss']
|
||||||
|
})
|
||||||
|
export class ContextConsoleMenuComponent implements OnInit {
|
||||||
|
@Input() project: Project;
|
||||||
|
@Input() server: Server;
|
||||||
|
@ViewChild(MatMenuTrigger) contextConsoleMenu: MatMenuTrigger;
|
||||||
|
@ViewChild("container", { read: ViewContainerRef }) container;
|
||||||
|
componentRef: ComponentRef<ConsoleDeviceActionComponent>;
|
||||||
|
componentBrowserRef: ComponentRef<ConsoleDeviceActionBrowserComponent>;
|
||||||
|
|
||||||
|
topPosition;
|
||||||
|
leftPosition;
|
||||||
|
isElectronApp = false;
|
||||||
|
node: Node;;
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
private sanitizer: DomSanitizer,
|
||||||
|
private changeDetector: ChangeDetectorRef,
|
||||||
|
private mapSettingsService: MapSettingsService,
|
||||||
|
private electronService: ElectronService,
|
||||||
|
private consoleService: NodeConsoleService,
|
||||||
|
private toasterService: ToasterService,
|
||||||
|
private router: Router,
|
||||||
|
private resolver: ComponentFactoryResolver
|
||||||
|
) {}
|
||||||
|
|
||||||
|
ngOnInit() {
|
||||||
|
this.setPosition(0, 0);
|
||||||
|
this.isElectronApp = this.electronService.isElectronApp;
|
||||||
|
}
|
||||||
|
|
||||||
|
public setPosition(top: number, left: number) {
|
||||||
|
this.topPosition = this.sanitizer.bypassSecurityTrustStyle(top + 'px');
|
||||||
|
this.leftPosition = this.sanitizer.bypassSecurityTrustStyle(left + 'px');
|
||||||
|
this.changeDetector.detectChanges();
|
||||||
|
}
|
||||||
|
|
||||||
|
public openMenu(node: Node, top: number, left: number) {
|
||||||
|
this.node = node;
|
||||||
|
let action = this.mapSettingsService.getConsoleContextManuAction();
|
||||||
|
if (action) {
|
||||||
|
if (action === 'web console') {
|
||||||
|
this.openWebConsole();
|
||||||
|
} else if (action === 'web console in new tab') {
|
||||||
|
this.openWebConsoleInNewTab();
|
||||||
|
} else if (action === 'console') {
|
||||||
|
this.openConsole();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this.setPosition(top, left);
|
||||||
|
this.contextConsoleMenu.openMenu();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
openConsole() {
|
||||||
|
this.mapSettingsService.setConsoleContextMenuAction('console');
|
||||||
|
if (this.isElectronApp) {
|
||||||
|
const factory: ComponentFactory<ConsoleDeviceActionComponent> = this.resolver.resolveComponentFactory(ConsoleDeviceActionComponent);
|
||||||
|
this.componentRef = this.container.createComponent(factory);
|
||||||
|
this.componentRef.instance.server = this.server;
|
||||||
|
this.componentRef.instance.nodes = [this.node];
|
||||||
|
|
||||||
|
this.componentRef.instance.console();
|
||||||
|
} else {
|
||||||
|
const factory: ComponentFactory<ConsoleDeviceActionBrowserComponent> = this.resolver.resolveComponentFactory(ConsoleDeviceActionBrowserComponent);
|
||||||
|
this.componentBrowserRef = this.container.createComponent(factory);
|
||||||
|
this.componentBrowserRef.instance.server = this.server;
|
||||||
|
this.componentBrowserRef.instance.node = this.node;
|
||||||
|
|
||||||
|
this.componentBrowserRef.instance.openConsole();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
openWebConsole() {
|
||||||
|
this.mapSettingsService.setConsoleContextMenuAction('web console');
|
||||||
|
if (this.node.status === 'started') {
|
||||||
|
this.mapSettingsService.logConsoleSubject.next(true);
|
||||||
|
this.consoleService.openConsoleForNode(this.node);
|
||||||
|
} else {
|
||||||
|
this.toasterService.error('To open console please start the node');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
openWebConsoleInNewTab() {
|
||||||
|
this.mapSettingsService.setConsoleContextMenuAction('web console in new tab');
|
||||||
|
if (this.node.status === 'started') {
|
||||||
|
let url = this.router.url.split('/');
|
||||||
|
let urlString = `/static/web-ui/${url[1]}/${url[2]}/${url[3]}/${url[4]}/nodes/${this.node.node_id}`
|
||||||
|
window.open(urlString);
|
||||||
|
} else {
|
||||||
|
this.toasterService.error('To open console please start the node');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,6 +1,9 @@
|
|||||||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
import { BringToFrontActionComponent } from './bring-to-front-action.component';
|
import { BringToFrontActionComponent } from './bring-to-front-action.component';
|
||||||
import { MatIconModule, MatToolbarModule, MatMenuModule, MatCheckboxModule } from '@angular/material';
|
import { MatCheckboxModule } from '@angular/material/checkbox';
|
||||||
|
import { MatIconModule } from '@angular/material/icon';
|
||||||
|
import { MatMenuModule } from '@angular/material/menu';
|
||||||
|
import { MatToolbarModule } from '@angular/material/toolbar';
|
||||||
import { CommonModule } from '@angular/common';
|
import { CommonModule } from '@angular/common';
|
||||||
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
||||||
import { MockedDrawingService, MockedDrawingsDataSource, MockedNodesDataSource, MockedNodeService } from '../../../project-map.component.spec';
|
import { MockedDrawingService, MockedDrawingsDataSource, MockedNodesDataSource, MockedNodeService } from '../../../project-map.component.spec';
|
||||||
|
@ -33,12 +33,12 @@ export class ConsoleDeviceActionBrowserComponent {
|
|||||||
this.node.console_host = this.server.host;
|
this.node.console_host = this.server.host;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.node.console_type === "telnet") {
|
if (this.node.console_type === "telnet" || this.node.console_type === "vnc" || this.node.console_type === "spice") {
|
||||||
location.assign(`gns3+telnet://${this.node.console_host}:${this.node.console}?name=${this.node.name}&project_id=${this.node.project_id}&node_id=${this.node.node_id}`);
|
try {
|
||||||
} else if (this.node.console_type === "vnc") {
|
location.assign(`gns3+${this.node.console_type}://${this.node.console_host}:${this.node.console}?name=${this.node.name}&project_id=${this.node.project_id}&node_id=${this.node.node_id}`);
|
||||||
location.assign(`gns3+vnc://${this.node.console_host}:${this.node.console}?name=${this.node.name}&project_id=${this.node.project_id}&node_id=${this.node.node_id}`);
|
} catch (e) {
|
||||||
} else if(this.node.console_type === "spice") {
|
this.toasterService.error(e);
|
||||||
location.assign(`gns3+spice://${this.node.console_host}:${this.node.console}?name=${this.node.name}&project_id=${this.node.project_id}&node_id=${this.node.node_id}`);
|
}
|
||||||
} else {
|
} else {
|
||||||
this.toasterService.error("Supported console types: telnet, vnc, spice.");
|
this.toasterService.error("Supported console types: telnet, vnc, spice.");
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
import { MatIconModule } from '@angular/material';
|
import { MatIconModule } from '@angular/material/icon';
|
||||||
import { ElectronService } from 'ngx-electron';
|
import { ElectronService } from 'ngx-electron';
|
||||||
|
|
||||||
import { ConsoleDeviceActionComponent } from './console-device-action.component';
|
import { ConsoleDeviceActionComponent } from './console-device-action.component';
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
import { DeleteActionComponent } from './delete-action.component';
|
import { DeleteActionComponent } from './delete-action.component';
|
||||||
import { MatIconModule, MatMenuModule } from '@angular/material';
|
import { MatIconModule } from '@angular/material/icon';
|
||||||
|
import { MatMenuModule } from '@angular/material/menu';
|
||||||
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
||||||
import { NodesDataSource } from '../../../../../cartography/datasources/nodes-datasource';
|
import { NodesDataSource } from '../../../../../cartography/datasources/nodes-datasource';
|
||||||
import { DrawingsDataSource } from '../../../../../cartography/datasources/drawings-datasource';
|
import { DrawingsDataSource } from '../../../../../cartography/datasources/drawings-datasource';
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
import { MatIconModule, MatMenuModule } from '@angular/material';
|
import { MatIconModule } from '@angular/material/icon';
|
||||||
|
import { MatMenuModule } from '@angular/material/menu';
|
||||||
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
||||||
import { NodesDataSource } from '../../../../../cartography/datasources/nodes-datasource';
|
import { NodesDataSource } from '../../../../../cartography/datasources/nodes-datasource';
|
||||||
import { DrawingsDataSource } from '../../../../../cartography/datasources/drawings-datasource';
|
import { DrawingsDataSource } from '../../../../../cartography/datasources/drawings-datasource';
|
||||||
|
@ -25,7 +25,7 @@ export class StartNodeActionComponent implements OnInit, OnChanges {
|
|||||||
if(changes.nodes) {
|
if(changes.nodes) {
|
||||||
this.isNodeWithStoppedStatus = false;
|
this.isNodeWithStoppedStatus = false;
|
||||||
this.nodes.forEach((node) => {
|
this.nodes.forEach((node) => {
|
||||||
if (node.status === 'stopped') {
|
if (node.status === 'stopped' || node.status === 'suspended') {
|
||||||
this.isNodeWithStoppedStatus = true;
|
this.isNodeWithStoppedStatus = true;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -5,4 +5,4 @@
|
|||||||
|
|
||||||
.mat-menu-panel ng-trigger ng-trigger-transformMenu ng-tns-c7-5 context-menu-items mat-menu-after mat-menu-below ng-star-inserted mat-elevation-z4 {
|
.mat-menu-panel ng-trigger ng-trigger-transformMenu ng-tns-c7-5 context-menu-items mat-menu-after mat-menu-below ng-star-inserted mat-elevation-z4 {
|
||||||
min-height: 0px!important;
|
min-height: 0px!important;
|
||||||
}
|
}
|
@ -4,7 +4,7 @@ import { BrowserModule } from '@angular/platform-browser';
|
|||||||
import { ChangeDetectorRef, NO_ERRORS_SCHEMA } from '@angular/core';
|
import { ChangeDetectorRef, NO_ERRORS_SCHEMA } from '@angular/core';
|
||||||
import { ProjectService } from '../../../services/project.service';
|
import { ProjectService } from '../../../services/project.service';
|
||||||
import { MockedProjectService } from '../../projects/add-blank-project-dialog/add-blank-project-dialog.component.spec';
|
import { MockedProjectService } from '../../projects/add-blank-project-dialog/add-blank-project-dialog.component.spec';
|
||||||
import { MatMenuModule, MatMenuTrigger } from '@angular/material';
|
import { MatMenuModule, MatMenuTrigger } from '@angular/material/menu';
|
||||||
import { Drawing } from '../../../cartography/models/drawing';
|
import { Drawing } from '../../../cartography/models/drawing';
|
||||||
import { RectElement } from '../../../cartography/models/drawings/rect-element';
|
import { RectElement } from '../../../cartography/models/drawings/rect-element';
|
||||||
import { TextElement } from '../../../cartography/models/drawings/text-element';
|
import { TextElement } from '../../../cartography/models/drawings/text-element';
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
import { BrowserModule } from '@angular/platform-browser';
|
import { BrowserModule } from '@angular/platform-browser';
|
||||||
import { NO_ERRORS_SCHEMA, EventEmitter, inject } from '@angular/core';
|
import { NO_ERRORS_SCHEMA, EventEmitter, inject } from '@angular/core';
|
||||||
import { MatMenuModule } from '@angular/material';
|
import { MatMenuModule } from '@angular/material/menu';
|
||||||
import { Server } from '../../../models/server';
|
import { Server } from '../../../models/server';
|
||||||
import { LogConsoleComponent } from './log-console.component';
|
import { LogConsoleComponent } from './log-console.component';
|
||||||
import { ProjectWebServiceHandler, WebServiceMessage } from '../../../handlers/project-web-service-handler';
|
import { ProjectWebServiceHandler, WebServiceMessage } from '../../../handlers/project-web-service-handler';
|
||||||
@ -13,6 +13,7 @@ import { LogEventsDataSource } from './log-events-datasource';
|
|||||||
import { HttpServer, ServerErrorHandler } from '../../../services/http-server.service';
|
import { HttpServer, ServerErrorHandler } from '../../../services/http-server.service';
|
||||||
import { HttpClientTestingModule } from '@angular/common/http/testing';
|
import { HttpClientTestingModule } from '@angular/common/http/testing';
|
||||||
import { HttpClient } from '@angular/common/http';
|
import { HttpClient } from '@angular/common/http';
|
||||||
|
import { NodeConsoleService } from '../../../services/nodeConsole.service';
|
||||||
|
|
||||||
export class MockedProjectWebServiceHandler {
|
export class MockedProjectWebServiceHandler {
|
||||||
public nodeNotificationEmitter = new EventEmitter<WebServiceMessage>();
|
public nodeNotificationEmitter = new EventEmitter<WebServiceMessage>();
|
||||||
@ -41,7 +42,8 @@ describe('LogConsoleComponent', () => {
|
|||||||
{ provide: NodeService, useValue: mockedNodeService },
|
{ provide: NodeService, useValue: mockedNodeService },
|
||||||
{ provide: NodesDataSource, useValue: mockedNodesDataSource },
|
{ provide: NodesDataSource, useValue: mockedNodesDataSource },
|
||||||
{ provide: LogEventsDataSource, useClass: LogEventsDataSource },
|
{ provide: LogEventsDataSource, useClass: LogEventsDataSource },
|
||||||
{ provide: HttpServer, useValue: httpServer }
|
{ provide: HttpServer, useValue: httpServer },
|
||||||
|
{ provide: NodeConsoleService }
|
||||||
],
|
],
|
||||||
declarations: [LogConsoleComponent],
|
declarations: [LogConsoleComponent],
|
||||||
schemas: [NO_ERRORS_SCHEMA]
|
schemas: [NO_ERRORS_SCHEMA]
|
||||||
@ -74,7 +76,7 @@ describe('LogConsoleComponent', () => {
|
|||||||
|
|
||||||
component.handleCommand();
|
component.handleCommand();
|
||||||
|
|
||||||
expect(component.showMessage).toHaveBeenCalledWith({type: 'command', message: 'Current version: 2020.2.0-beta.1'});
|
expect(component.showMessage).toHaveBeenCalledWith({type: 'command', message: 'Current version: 2020.3.0-beta.4'});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should call show message when unknown command entered', () => {
|
it('should call show message when unknown command entered', () => {
|
||||||
|
@ -16,6 +16,7 @@ import { ResizeEvent } from 'angular-resizable-element';
|
|||||||
import { ThemeService } from '../../../services/theme.service';
|
import { ThemeService } from '../../../services/theme.service';
|
||||||
import { FormControl } from '@angular/forms';
|
import { FormControl } from '@angular/forms';
|
||||||
import { version } from '../../../version';
|
import { version } from '../../../version';
|
||||||
|
import { NodeConsoleService } from '../../../services/nodeConsole.service';
|
||||||
|
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
@ -63,10 +64,17 @@ export class LogConsoleComponent implements OnInit, AfterViewInit, OnDestroy {
|
|||||||
private logEventsDataSource: LogEventsDataSource,
|
private logEventsDataSource: LogEventsDataSource,
|
||||||
private httpService: HttpServer,
|
private httpService: HttpServer,
|
||||||
private themeService: ThemeService,
|
private themeService: ThemeService,
|
||||||
private cd: ChangeDetectorRef
|
private cd: ChangeDetectorRef,
|
||||||
|
private nodeConsoleService: NodeConsoleService,
|
||||||
|
private changeDetectorRef: ChangeDetectorRef
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
|
this.nodeConsoleService.consoleResized.subscribe(ev => {
|
||||||
|
this.style = { bottom: '20px', left: '20px', width: `${ev.width}px`, height: `${ev.height - 70}px`};
|
||||||
|
this.changeDetectorRef.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
this.themeService.getActualTheme() === 'light' ? this.isLightThemeEnabled = true : this.isLightThemeEnabled = false
|
this.themeService.getActualTheme() === 'light' ? this.isLightThemeEnabled = true : this.isLightThemeEnabled = false
|
||||||
this.style = { bottom: '20px', left: '20px', width: '720px', height: '340px'};
|
this.style = { bottom: '20px', left: '20px', width: '720px', height: '340px'};
|
||||||
|
|
||||||
|
@ -106,6 +106,7 @@
|
|||||||
|
|
||||||
<div>
|
<div>
|
||||||
<button mat-button matStepperPrevious>Back</button>
|
<button mat-button matStepperPrevious>Back</button>
|
||||||
|
<button mat-button [hidden]="action!=='install'" (click)="updateAppliances()">Update from online registry</button>
|
||||||
<button mat-button (click)="onCloseClick()">Cancel</button>
|
<button mat-button (click)="onCloseClick()">Cancel</button>
|
||||||
</div>
|
</div>
|
||||||
</mat-step>
|
</mat-step>
|
||||||
@ -139,7 +140,10 @@
|
|||||||
</mat-select>
|
</mat-select>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
Install required files <br/>
|
Install required files
|
||||||
|
<button mat-icon-button matTooltip="Refresh list of images" matTooltipClass="custom-tooltip" (click)="refreshImages()">
|
||||||
|
<mat-icon aria-label="Refresh list of images">refresh</mat-icon>
|
||||||
|
</button><br/>
|
||||||
<div>
|
<div>
|
||||||
<div *ngFor="let version of applianceToInstall.versions">
|
<div *ngFor="let version of applianceToInstall.versions">
|
||||||
<div class="list-item">
|
<div class="list-item">
|
||||||
@ -216,7 +220,10 @@
|
|||||||
</mat-radio-group>
|
</mat-radio-group>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
Install required files
|
Install required files
|
||||||
|
<button mat-icon-button matTooltip="Refresh list of images" matTooltipClass="custom-tooltip" (click)="refreshImages()">
|
||||||
|
<mat-icon aria-label="Refresh list of images">refresh</mat-icon>
|
||||||
|
</button><br/>
|
||||||
<mat-list>
|
<mat-list>
|
||||||
<mat-list-item *ngFor="let image of applianceToInstall.images">
|
<mat-list-item *ngFor="let image of applianceToInstall.images">
|
||||||
<div class="list-item">
|
<div class="list-item">
|
||||||
@ -249,7 +256,10 @@
|
|||||||
</mat-radio-group>
|
</mat-radio-group>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
Install required files
|
Install required files
|
||||||
|
<button mat-icon-button matTooltip="Refresh list of images" matTooltipClass="custom-tooltip" (click)="refreshImages()">
|
||||||
|
<mat-icon aria-label="Refresh list of images">refresh</mat-icon>
|
||||||
|
</button><br/>
|
||||||
<mat-list>
|
<mat-list>
|
||||||
<mat-list-item *ngFor="let image of applianceToInstall.images">
|
<mat-list-item *ngFor="let image of applianceToInstall.images">
|
||||||
<div class="list-item">
|
<div class="list-item">
|
||||||
|
@ -27,6 +27,9 @@ import { IouTemplate } from '../../../models/templates/iou-template';
|
|||||||
import { TemplateService } from '../../../services/template.service';
|
import { TemplateService } from '../../../services/template.service';
|
||||||
import { Template } from '../../../models/template';
|
import { Template } from '../../../models/template';
|
||||||
import { ComputeService } from '../../../services/compute.service';
|
import { ComputeService } from '../../../services/compute.service';
|
||||||
|
import { InformationDialogComponent } from '../../../components/dialogs/information-dialog.component';
|
||||||
|
import { ProgressService } from '../../../common/progress/progress.service';
|
||||||
|
import { TemplateNameDialogComponent } from './template-name-dialog/template-name-dialog.component';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-new-template-dialog',
|
selector: 'app-new-template-dialog',
|
||||||
@ -76,6 +79,8 @@ export class NewTemplateDialogComponent implements OnInit {
|
|||||||
private iosImages: Image[] = [];
|
private iosImages: Image[] = [];
|
||||||
private iouImages: Image[] = [];
|
private iouImages: Image[] = [];
|
||||||
|
|
||||||
|
private templates: Template[] = [];
|
||||||
|
|
||||||
@ViewChild(MatPaginator, {static: true}) paginator: MatPaginator;
|
@ViewChild(MatPaginator, {static: true}) paginator: MatPaginator;
|
||||||
@ViewChild('stepper', {static: true}) stepper: MatStepper;
|
@ViewChild('stepper', {static: true}) stepper: MatStepper;
|
||||||
|
|
||||||
@ -90,10 +95,16 @@ export class NewTemplateDialogComponent implements OnInit {
|
|||||||
private iouService: IouService,
|
private iouService: IouService,
|
||||||
private templateService: TemplateService,
|
private templateService: TemplateService,
|
||||||
public dialog: MatDialog,
|
public dialog: MatDialog,
|
||||||
private computeService: ComputeService
|
private computeService: ComputeService,
|
||||||
|
private changeDetectorRef: ChangeDetectorRef,
|
||||||
|
private progressService: ProgressService
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
|
this.templateService.list(this.server).subscribe((templates) => {
|
||||||
|
this.templates = templates;
|
||||||
|
});
|
||||||
|
|
||||||
this.computeService.getComputes(this.server).subscribe((computes) => {
|
this.computeService.getComputes(this.server).subscribe((computes) => {
|
||||||
computes.forEach(compute => {
|
computes.forEach(compute => {
|
||||||
if (compute.compute_id === 'vm') {
|
if (compute.compute_id === 'vm') {
|
||||||
@ -154,13 +165,42 @@ 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.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.progressService.deactivate();
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
updateAppliances() {
|
||||||
|
this.progressService.activate();
|
||||||
|
this.applianceService.updateAppliances(this.server).subscribe((appliances) => {
|
||||||
|
this.appliances = appliances;
|
||||||
|
this.progressService.deactivate();
|
||||||
|
this.toasterService.success('Appliances are up-to-date.');
|
||||||
|
}, error => {
|
||||||
|
this.progressService.deactivate();
|
||||||
|
this.toasterService.error('Appliances were not updated correctly.');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
refreshImages() {
|
||||||
|
this.qemuService.getImages(this.server).subscribe((qemuImages) => {
|
||||||
|
this.qemuImages = qemuImages;
|
||||||
|
});
|
||||||
|
|
||||||
|
this.iosService.getImages(this.server).subscribe((iosImages) => {
|
||||||
|
this.iosImages = iosImages;
|
||||||
|
});
|
||||||
|
|
||||||
|
this.iouService.getImages(this.server).subscribe((iouImages) => {
|
||||||
|
this.iouImages = iouImages;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
getAppliance(url: string) {
|
getAppliance(url: string) {
|
||||||
let str = url.split('/v2');
|
let str = url.split('/v2');
|
||||||
let appliancePath = str[str.length-1];
|
let appliancePath = str[str.length-1];
|
||||||
@ -257,6 +297,30 @@ export class NewTemplateDialogComponent implements OnInit {
|
|||||||
this.applianceToInstall = object;
|
this.applianceToInstall = object;
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
this.stepper.next();
|
this.stepper.next();
|
||||||
|
if (this.applianceToInstall.qemu) {
|
||||||
|
setTimeout(() => {
|
||||||
|
if (this.qemuBinaries.length) {
|
||||||
|
if (this.applianceToInstall.qemu.arch === 'x86_64') {
|
||||||
|
let filtered_binaries = this.qemuBinaries.filter(n => n.path.includes('qemu-system-x86_64'));
|
||||||
|
if (filtered_binaries.length) {
|
||||||
|
this.selectedBinary = filtered_binaries[0];
|
||||||
|
}
|
||||||
|
} else if (this.applianceToInstall.qemu.arch === 'i386') {
|
||||||
|
let filtered_binaries = this.qemuBinaries.filter(n => n.path.includes('qemu-system-i386'));
|
||||||
|
if (filtered_binaries.length) {
|
||||||
|
this.selectedBinary = filtered_binaries[0];
|
||||||
|
}
|
||||||
|
} else if (this.applianceToInstall.qemu.arch === 'x86_64') {
|
||||||
|
let filtered_binaries = this.qemuBinaries.filter(n => n.path.includes('qemu-system-arm'));
|
||||||
|
if (filtered_binaries.length) {
|
||||||
|
this.selectedBinary = filtered_binaries[0];
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this.selectedBinary = this.qemuBinaries[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, 100);
|
||||||
|
}
|
||||||
}, 100);
|
}, 100);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -287,42 +351,64 @@ export class NewTemplateDialogComponent implements OnInit {
|
|||||||
(itemToUpload as any).options.disableMultipart = true;
|
(itemToUpload as any).options.disableMultipart = true;
|
||||||
|
|
||||||
this.uploaderImage.uploadItem(itemToUpload);
|
this.uploaderImage.uploadItem(itemToUpload);
|
||||||
|
this.progressService.activate();
|
||||||
};
|
};
|
||||||
|
|
||||||
fileReader.readAsText(file);
|
fileReader.readAsText(file);
|
||||||
}
|
}
|
||||||
|
|
||||||
checkImage(image: Image): boolean {
|
|
||||||
if (this.applianceToInstall.qemu) {
|
|
||||||
if (this.qemuImages.filter(n => n.filename === image.filename).length > 0) return true;
|
|
||||||
} else if (this.applianceToInstall.dynamips) {
|
|
||||||
if (this.iosImages.filter(n => n.filename === image.filename).length > 0) return true;
|
|
||||||
} else if (this.applianceToInstall.iou) {
|
|
||||||
if (this.iouImages.filter(n => n.filename === image.filename).length > 0) return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
checkImageFromVersion(image: string): boolean {
|
checkImageFromVersion(image: string): boolean {
|
||||||
|
let imageToInstall = this.applianceToInstall.images.filter(n => n.filename === image)[0];
|
||||||
if (this.applianceToInstall.qemu) {
|
if (this.applianceToInstall.qemu) {
|
||||||
if (this.qemuImages.filter(n => n.filename === image).length > 0) return true;
|
if (this.qemuImages.filter(n => n.md5sum === imageToInstall.md5sum).length > 0) return true;
|
||||||
} else if (this.applianceToInstall.dynamips) {
|
} else if (this.applianceToInstall.dynamips) {
|
||||||
if (this.iosImages.filter(n => n.filename === image).length > 0) return true;
|
if (this.iosImages.filter(n => n.md5sum === imageToInstall.md5sum).length > 0) return true;
|
||||||
} else if (this.applianceToInstall.iou) {
|
} else if (this.applianceToInstall.iou) {
|
||||||
if (this.iouImages.filter(n => n.filename === image).length > 0) return true;
|
if (this.iouImages.filter(n => n.md5sum === imageToInstall.md5sum).length > 0) return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
checkImages(version: Version): boolean {
|
checkImages(version: Version): boolean {
|
||||||
if (this.checkImageFromVersion(version.images.hda_disk_image) && this.checkImageFromVersion(version.images.hdb_disk_image)) return true;
|
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)) return true;
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
openConfirmationDialog(message: string, link: string) {
|
||||||
|
const dialogRef = this.dialog.open(InformationDialogComponent, {
|
||||||
|
width: '400px',
|
||||||
|
height: '200px',
|
||||||
|
autoFocus: false,
|
||||||
|
disableClose: true
|
||||||
|
});
|
||||||
|
dialogRef.componentInstance.confirmationMessage = message;
|
||||||
|
|
||||||
|
dialogRef.afterClosed().subscribe((answer: boolean) => {
|
||||||
|
if (answer) {
|
||||||
|
window.open(link);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
downloadImage(image: Image) {
|
downloadImage(image: Image) {
|
||||||
window.open(image.download_url);
|
const directDownloadMessage: string = "Download will redirect you where the required file can be downloaded, you may have to be registered with the vendor in order to download the file.";
|
||||||
|
const compressionMessage: string = `The file is compressed with ${image.compression}, it must be uncompressed first.`;
|
||||||
|
|
||||||
|
if (image.direct_download_url) {
|
||||||
|
if (image.compression) {
|
||||||
|
this.openConfirmationDialog(compressionMessage, image.direct_download_url);
|
||||||
|
} else {
|
||||||
|
window.open(image.direct_download_url);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this.openConfirmationDialog(directDownloadMessage, image.download_url);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
downloadImageFromVersion(image: string) {
|
downloadImageFromVersion(image: string) {
|
||||||
@ -331,16 +417,22 @@ export class NewTemplateDialogComponent implements OnInit {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getCategory() {
|
||||||
|
if (this.applianceToInstall.category === 'multilayer_switch') {
|
||||||
|
return 'switch';
|
||||||
|
}
|
||||||
|
return this.applianceToInstall.category;
|
||||||
|
}
|
||||||
|
|
||||||
createIouTemplate (image: Image) {
|
createIouTemplate (image: Image) {
|
||||||
let iouTemplate: IouTemplate = new IouTemplate();
|
let iouTemplate: IouTemplate = new IouTemplate();
|
||||||
iouTemplate.name = this.applianceToInstall.name;
|
|
||||||
iouTemplate.nvram = this.applianceToInstall.iou.nvram;
|
iouTemplate.nvram = this.applianceToInstall.iou.nvram;
|
||||||
iouTemplate.ram = this.applianceToInstall.iou.ram;
|
iouTemplate.ram = this.applianceToInstall.iou.ram;
|
||||||
iouTemplate.ethernet_adapters = this.applianceToInstall.iou.ethernet_adapters;
|
iouTemplate.ethernet_adapters = this.applianceToInstall.iou.ethernet_adapters;
|
||||||
iouTemplate.serial_adapters = this.applianceToInstall.iou.serial_adapters;
|
iouTemplate.serial_adapters = this.applianceToInstall.iou.serial_adapters;
|
||||||
iouTemplate.startup_config = this.applianceToInstall.iou.startup_config;
|
iouTemplate.startup_config = this.applianceToInstall.iou.startup_config;
|
||||||
iouTemplate.builtin = this.applianceToInstall.builtin;
|
iouTemplate.builtin = this.applianceToInstall.builtin;
|
||||||
iouTemplate.category = this.applianceToInstall.category;
|
iouTemplate.category = this.getCategory();
|
||||||
iouTemplate.default_name_format = this.applianceToInstall.port_name_format;
|
iouTemplate.default_name_format = this.applianceToInstall.port_name_format;
|
||||||
iouTemplate.symbol = this.applianceToInstall.symbol;
|
iouTemplate.symbol = this.applianceToInstall.symbol;
|
||||||
iouTemplate.compute_id = this.isGns3VmChosen ? 'vm' : 'local';
|
iouTemplate.compute_id = this.isGns3VmChosen ? 'vm' : 'local';
|
||||||
@ -348,16 +440,33 @@ export class NewTemplateDialogComponent implements OnInit {
|
|||||||
iouTemplate.path = image.filename;
|
iouTemplate.path = image.filename;
|
||||||
iouTemplate.template_type = 'iou';
|
iouTemplate.template_type = 'iou';
|
||||||
|
|
||||||
this.iouService.addTemplate(this.server, iouTemplate).subscribe((template) => {
|
const dialogRef = this.dialog.open(TemplateNameDialogComponent, {
|
||||||
this.templateService.newTemplateCreated.next(template);
|
width: '400px',
|
||||||
this.toasterService.success('Template added');
|
height: '250px',
|
||||||
this.dialogRef.close();
|
autoFocus: false,
|
||||||
|
disableClose: true,
|
||||||
|
data: {
|
||||||
|
name: this.applianceToInstall.name
|
||||||
|
}
|
||||||
|
});
|
||||||
|
dialogRef.componentInstance.server = this.server;
|
||||||
|
dialogRef.afterClosed().subscribe((answer: string) => {
|
||||||
|
if (answer) {
|
||||||
|
iouTemplate.name = answer;
|
||||||
|
|
||||||
|
this.iouService.addTemplate(this.server, iouTemplate).subscribe((template) => {
|
||||||
|
this.templateService.newTemplateCreated.next(template);
|
||||||
|
this.toasterService.success('Template added');
|
||||||
|
this.dialogRef.close();
|
||||||
|
});
|
||||||
|
} else{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
createIosTemplate(image: Image) {
|
createIosTemplate(image: Image) {
|
||||||
let iosTemplate: IosTemplate = new IosTemplate();
|
let iosTemplate: IosTemplate = new IosTemplate();
|
||||||
iosTemplate.name = this.applianceToInstall.name;
|
|
||||||
iosTemplate.chassis = this.applianceToInstall.dynamips.chassis;
|
iosTemplate.chassis = this.applianceToInstall.dynamips.chassis;
|
||||||
iosTemplate.nvram = this.applianceToInstall.dynamips.nvram;
|
iosTemplate.nvram = this.applianceToInstall.dynamips.nvram;
|
||||||
iosTemplate.platform = this.applianceToInstall.dynamips.platform;
|
iosTemplate.platform = this.applianceToInstall.dynamips.platform;
|
||||||
@ -372,7 +481,7 @@ export class NewTemplateDialogComponent implements OnInit {
|
|||||||
iosTemplate.slot6 = this.applianceToInstall.dynamips.slot6;
|
iosTemplate.slot6 = this.applianceToInstall.dynamips.slot6;
|
||||||
iosTemplate.slot7 = this.applianceToInstall.dynamips.slot7;
|
iosTemplate.slot7 = this.applianceToInstall.dynamips.slot7;
|
||||||
iosTemplate.builtin = this.applianceToInstall.builtin;
|
iosTemplate.builtin = this.applianceToInstall.builtin;
|
||||||
iosTemplate.category = this.applianceToInstall.category;
|
iosTemplate.category = this.getCategory();
|
||||||
iosTemplate.default_name_format = this.applianceToInstall.port_name_format;
|
iosTemplate.default_name_format = this.applianceToInstall.port_name_format;
|
||||||
iosTemplate.symbol = this.applianceToInstall.symbol;
|
iosTemplate.symbol = this.applianceToInstall.symbol;
|
||||||
iosTemplate.compute_id = this.isGns3VmChosen ? 'vm' : 'local';
|
iosTemplate.compute_id = this.isGns3VmChosen ? 'vm' : 'local';
|
||||||
@ -380,20 +489,37 @@ export class NewTemplateDialogComponent implements OnInit {
|
|||||||
iosTemplate.image = image.filename;
|
iosTemplate.image = image.filename;
|
||||||
iosTemplate.template_type = 'dynamips';
|
iosTemplate.template_type = 'dynamips';
|
||||||
|
|
||||||
this.iosService.addTemplate(this.server, iosTemplate).subscribe((template) => {
|
const dialogRef = this.dialog.open(TemplateNameDialogComponent, {
|
||||||
this.templateService.newTemplateCreated.next(template as any as Template);
|
width: '400px',
|
||||||
this.toasterService.success('Template added');
|
height: '250px',
|
||||||
this.dialogRef.close();
|
autoFocus: false,
|
||||||
|
disableClose: true,
|
||||||
|
data: {
|
||||||
|
name: this.applianceToInstall.name
|
||||||
|
}
|
||||||
|
});
|
||||||
|
dialogRef.componentInstance.server = this.server;
|
||||||
|
dialogRef.afterClosed().subscribe((answer: string) => {
|
||||||
|
if (answer) {
|
||||||
|
iosTemplate.name = answer;
|
||||||
|
|
||||||
|
this.iosService.addTemplate(this.server, iosTemplate).subscribe((template) => {
|
||||||
|
this.templateService.newTemplateCreated.next(template as any as Template);
|
||||||
|
this.toasterService.success('Template added');
|
||||||
|
this.dialogRef.close();
|
||||||
|
});
|
||||||
|
} else{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
createDockerTemplate() {
|
createDockerTemplate() {
|
||||||
let dockerTemplate: DockerTemplate = new DockerTemplate();
|
let dockerTemplate: DockerTemplate = new DockerTemplate();
|
||||||
dockerTemplate.name = this.applianceToInstall.name;
|
|
||||||
dockerTemplate.adapters = this.applianceToInstall.docker.adapters;
|
dockerTemplate.adapters = this.applianceToInstall.docker.adapters;
|
||||||
dockerTemplate.console_type = this.applianceToInstall.docker.console_type;
|
dockerTemplate.console_type = this.applianceToInstall.docker.console_type;
|
||||||
dockerTemplate.builtin = this.applianceToInstall.builtin;
|
dockerTemplate.builtin = this.applianceToInstall.builtin;
|
||||||
dockerTemplate.category = this.applianceToInstall.category;
|
dockerTemplate.category = this.getCategory();
|
||||||
dockerTemplate.default_name_format = this.applianceToInstall.port_name_format;
|
dockerTemplate.default_name_format = this.applianceToInstall.port_name_format;
|
||||||
dockerTemplate.symbol = this.applianceToInstall.symbol;
|
dockerTemplate.symbol = this.applianceToInstall.symbol;
|
||||||
dockerTemplate.compute_id = this.isGns3VmChosen ? 'vm' : 'local';
|
dockerTemplate.compute_id = this.isGns3VmChosen ? 'vm' : 'local';
|
||||||
@ -401,10 +527,28 @@ export class NewTemplateDialogComponent implements OnInit {
|
|||||||
dockerTemplate.image = this.applianceToInstall.docker.image;
|
dockerTemplate.image = this.applianceToInstall.docker.image;
|
||||||
dockerTemplate.template_type = 'docker';
|
dockerTemplate.template_type = 'docker';
|
||||||
|
|
||||||
this.dockerService.addTemplate(this.server, dockerTemplate).subscribe((template) => {
|
const dialogRef = this.dialog.open(TemplateNameDialogComponent, {
|
||||||
this.templateService.newTemplateCreated.next(template as any as Template);
|
width: '400px',
|
||||||
this.toasterService.success('Template added');
|
height: '250px',
|
||||||
this.dialogRef.close();
|
autoFocus: false,
|
||||||
|
disableClose: true,
|
||||||
|
data: {
|
||||||
|
name: this.applianceToInstall.name
|
||||||
|
}
|
||||||
|
});
|
||||||
|
dialogRef.componentInstance.server = this.server;
|
||||||
|
dialogRef.afterClosed().subscribe((answer: string) => {
|
||||||
|
if (answer) {
|
||||||
|
dockerTemplate.name = answer;
|
||||||
|
|
||||||
|
this.dockerService.addTemplate(this.server, dockerTemplate).subscribe((template) => {
|
||||||
|
this.templateService.newTemplateCreated.next(template as any as Template);
|
||||||
|
this.toasterService.success('Template added');
|
||||||
|
this.dialogRef.close();
|
||||||
|
});
|
||||||
|
} else{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -418,8 +562,8 @@ export class NewTemplateDialogComponent implements OnInit {
|
|||||||
this.toasterService.error('Please select QEMU binary first');
|
this.toasterService.error('Please select QEMU binary first');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let qemuTemplate: QemuTemplate = new QemuTemplate();
|
let qemuTemplate: QemuTemplate = new QemuTemplate();
|
||||||
qemuTemplate.name = this.applianceToInstall.name;
|
|
||||||
qemuTemplate.ram = this.applianceToInstall.qemu.ram;
|
qemuTemplate.ram = this.applianceToInstall.qemu.ram;
|
||||||
qemuTemplate.adapters = this.applianceToInstall.qemu.adapters;
|
qemuTemplate.adapters = this.applianceToInstall.qemu.adapters;
|
||||||
qemuTemplate.adapter_type = this.applianceToInstall.qemu.adapter_type;
|
qemuTemplate.adapter_type = this.applianceToInstall.qemu.adapter_type;
|
||||||
@ -430,7 +574,7 @@ export class NewTemplateDialogComponent implements OnInit {
|
|||||||
qemuTemplate.hdc_disk_interface = this.applianceToInstall.qemu.hdc_disk_interface;
|
qemuTemplate.hdc_disk_interface = this.applianceToInstall.qemu.hdc_disk_interface;
|
||||||
qemuTemplate.hdd_disk_interface = this.applianceToInstall.qemu.hdd_disk_interface;
|
qemuTemplate.hdd_disk_interface = this.applianceToInstall.qemu.hdd_disk_interface;
|
||||||
qemuTemplate.builtin = this.applianceToInstall.builtin;
|
qemuTemplate.builtin = this.applianceToInstall.builtin;
|
||||||
qemuTemplate.category = this.applianceToInstall.category;
|
qemuTemplate.category = this.getCategory();
|
||||||
qemuTemplate.first_port_name = this.applianceToInstall.first_port_name;
|
qemuTemplate.first_port_name = this.applianceToInstall.first_port_name;
|
||||||
qemuTemplate.port_name_format = this.applianceToInstall.port_name_format;
|
qemuTemplate.port_name_format = this.applianceToInstall.port_name_format;
|
||||||
qemuTemplate.symbol = this.applianceToInstall.symbol;
|
qemuTemplate.symbol = this.applianceToInstall.symbol;
|
||||||
@ -442,10 +586,29 @@ export class NewTemplateDialogComponent implements OnInit {
|
|||||||
qemuTemplate.template_type = 'qemu';
|
qemuTemplate.template_type = 'qemu';
|
||||||
qemuTemplate.usage = this.applianceToInstall.usage;
|
qemuTemplate.usage = this.applianceToInstall.usage;
|
||||||
|
|
||||||
this.qemuService.addTemplate(this.server, qemuTemplate).subscribe((template) => {
|
|
||||||
this.templateService.newTemplateCreated.next(template as any as Template);
|
const dialogRef = this.dialog.open(TemplateNameDialogComponent, {
|
||||||
this.toasterService.success('Template added');
|
width: '400px',
|
||||||
this.dialogRef.close();
|
height: '250px',
|
||||||
|
autoFocus: false,
|
||||||
|
disableClose: true,
|
||||||
|
data: {
|
||||||
|
name: this.applianceToInstall.name
|
||||||
|
}
|
||||||
|
});
|
||||||
|
dialogRef.componentInstance.server = this.server;
|
||||||
|
dialogRef.afterClosed().subscribe((answer: string) => {
|
||||||
|
if (answer) {
|
||||||
|
qemuTemplate.name = answer;
|
||||||
|
|
||||||
|
this.qemuService.addTemplate(this.server, qemuTemplate).subscribe((template) => {
|
||||||
|
this.templateService.newTemplateCreated.next(template as any as Template);
|
||||||
|
this.toasterService.success('Template added');
|
||||||
|
this.dialogRef.close();
|
||||||
|
});
|
||||||
|
} else{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,26 @@
|
|||||||
|
<h1 mat-dialog-title>Please enter name for the new template</h1>
|
||||||
|
<form [formGroup]="templateNameForm" class="file-name-form">
|
||||||
|
<mat-form-field class="file-name-form-field">
|
||||||
|
<input
|
||||||
|
matInput
|
||||||
|
(keydown)="onKeyDown($event)"
|
||||||
|
type="text"
|
||||||
|
formControlName="templateName"
|
||||||
|
[ngClass]="{ 'is-invalid': form.templateName?.errors }"
|
||||||
|
placeholder="Template name"
|
||||||
|
/>
|
||||||
|
<mat-error *ngIf="form.templateName?.touched && form.templateName?.errors && form.templateName?.errors.required"
|
||||||
|
>Template name is required</mat-error
|
||||||
|
>
|
||||||
|
<mat-error *ngIf="form.templateName?.errors && form.templateName?.errors.invalidName"
|
||||||
|
>Template name is incorrect</mat-error
|
||||||
|
>
|
||||||
|
<mat-error *ngIf="form.templateName?.errors && form.templateName?.errors.templateExist"
|
||||||
|
>Template with this name exists</mat-error
|
||||||
|
>
|
||||||
|
</mat-form-field>
|
||||||
|
<div mat-dialog-actions>
|
||||||
|
<button mat-button (click)="onNoClick()" color="accent">Cancel</button>
|
||||||
|
<button mat-button (click)="onAddClick()" tabindex="2" class="add-project-button" mat-raised-button color="primary">Add template</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
@ -0,0 +1,7 @@
|
|||||||
|
.file-name-form-field {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.project-snackbar {
|
||||||
|
background: #2196F3;
|
||||||
|
}
|
@ -0,0 +1,76 @@
|
|||||||
|
import { Component, OnInit, EventEmitter, Inject } from '@angular/core';
|
||||||
|
import { Router } from '@angular/router';
|
||||||
|
import { MatDialog, MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';
|
||||||
|
import { FormBuilder, FormGroup, Validators, FormControl } from '@angular/forms';
|
||||||
|
import { Server } from '../../../../models/server';
|
||||||
|
import { v4 as uuid } from 'uuid';
|
||||||
|
import { ProjectNameValidator } from '../../../projects/models/projectNameValidator';
|
||||||
|
import { ToasterService } from '../../../../services/toaster.service';
|
||||||
|
import { TemplateService } from '../../../../services/template.service';
|
||||||
|
import { templateNameAsyncValidator } from '../../../../validators/template-name-async-validator';
|
||||||
|
import { Template } from '../../../../models/template';
|
||||||
|
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-template-name-dialog',
|
||||||
|
templateUrl: './template-name-dialog.component.html',
|
||||||
|
styleUrls: ['./template-name-dialog.component.scss'],
|
||||||
|
providers: [ProjectNameValidator]
|
||||||
|
})
|
||||||
|
export class TemplateNameDialogComponent implements OnInit {
|
||||||
|
server: Server;
|
||||||
|
templateNameForm: FormGroup;
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
public dialogRef: MatDialogRef<TemplateNameDialogComponent>,
|
||||||
|
private router: Router,
|
||||||
|
private dialog: MatDialog,
|
||||||
|
private toasterService: ToasterService,
|
||||||
|
private formBuilder: FormBuilder,
|
||||||
|
private templateNameValidator: ProjectNameValidator,
|
||||||
|
private templateService: TemplateService,
|
||||||
|
@Inject(MAT_DIALOG_DATA) public data: any
|
||||||
|
) {}
|
||||||
|
|
||||||
|
ngOnInit() {
|
||||||
|
let name = this.data['name'];
|
||||||
|
this.templateNameForm = this.formBuilder.group({
|
||||||
|
templateName: new FormControl(name, [Validators.required, this.templateNameValidator.get], [templateNameAsyncValidator(this.server, this.templateService)])
|
||||||
|
});
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
this.templateNameForm.controls['templateName'].markAsTouched();
|
||||||
|
}, 100);
|
||||||
|
}
|
||||||
|
|
||||||
|
get form() {
|
||||||
|
return this.templateNameForm.controls;
|
||||||
|
}
|
||||||
|
|
||||||
|
onAddClick(): void {
|
||||||
|
if (this.templateNameForm.invalid) {
|
||||||
|
this.toasterService.error('Please enter correct name for new template');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.templateService.list(this.server).subscribe((templates: Template[]) => {
|
||||||
|
const templateName = this.templateNameForm.controls['templateName'].value;
|
||||||
|
let existingProject = templates.find(t => t.name === templateName);
|
||||||
|
|
||||||
|
if (existingProject) {
|
||||||
|
this.toasterService.error('Template with this name exists');
|
||||||
|
} else {
|
||||||
|
this.dialogRef.close(this.templateNameForm.controls['templateName'].value);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
onNoClick(): void {
|
||||||
|
this.dialogRef.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
onKeyDown(event) {
|
||||||
|
if (event.key === "Enter") {
|
||||||
|
this.onAddClick();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,13 +1,9 @@
|
|||||||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
import { Server } from '../../../../models/server';
|
import { Server } from '../../../../models/server';
|
||||||
import {
|
import { MatDialogModule, MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';
|
||||||
MatDialogModule,
|
import { MatFormFieldModule } from '@angular/material/form-field';
|
||||||
MatFormFieldModule,
|
import { MatSnackBarModule } from '@angular/material/snack-bar';
|
||||||
MatDialogRef,
|
import { MatTabsModule } from '@angular/material/tabs';
|
||||||
MAT_DIALOG_DATA,
|
|
||||||
MatSnackBarModule,
|
|
||||||
MatTabsModule
|
|
||||||
} from '@angular/material';
|
|
||||||
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
||||||
import { ToasterService } from '../../../../services/toaster.service';
|
import { ToasterService } from '../../../../services/toaster.service';
|
||||||
import { of } from 'rxjs/internal/observable/of';
|
import { of } from 'rxjs/internal/observable/of';
|
||||||
@ -42,7 +38,7 @@ describe('ConfigEditorDialogComponent', () => {
|
|||||||
],
|
],
|
||||||
providers: [
|
providers: [
|
||||||
{ provide: MatDialogRef, useValue: dialogRef },
|
{ provide: MatDialogRef, useValue: dialogRef },
|
||||||
{ provide: MAT_DIALOG_DATA },
|
{ provide: MAT_DIALOG_DATA, useValue: [] },
|
||||||
{ provide: NodeService, useValue: mockedNodeService },
|
{ provide: NodeService, useValue: mockedNodeService },
|
||||||
{ provide: ToasterService, useValue: toaster }
|
{ provide: ToasterService, useValue: toaster }
|
||||||
],
|
],
|
||||||
|
@ -11,17 +11,26 @@
|
|||||||
<input matInput formControlName="name" type="text" [(ngModel)]="node.name" placeholder="Name">
|
<input matInput formControlName="name" type="text" [(ngModel)]="node.name" placeholder="Name">
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
|
|
||||||
|
<mat-form-field class="form-field">
|
||||||
|
<input matInput formControlName="startCommand" type="text" [(ngModel)]="node.properties.start_command" placeholder="Start command">
|
||||||
|
</mat-form-field>
|
||||||
|
|
||||||
<mat-form-field class="form-field">
|
<mat-form-field class="form-field">
|
||||||
<input formControlName="adapter" matInput type="number" [(ngModel)]="node.properties.adapters" placeholder="Adapters">
|
<input formControlName="adapter" matInput type="number" [(ngModel)]="node.properties.adapters" placeholder="Adapters">
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
|
|
||||||
<mat-form-field class="form-field">
|
<mat-form-field class="form-field">
|
||||||
<input formControlName="memory" matInput type="number" [(ngModel)]="node.properties.memory" placeholder="Maximum memory">
|
<input formControlName="memory" matInput type="number" [(ngModel)]="node.properties.memory" placeholder="Maximum memory">
|
||||||
|
<span matSuffix>MB</span>
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
|
|
||||||
<mat-form-field class="form-field">
|
<mat-form-field class="form-field">
|
||||||
<input formControlName="cpus" matInput type="number" [(ngModel)]="node.properties.cpus" placeholder="Maximum CPUs">
|
<input formControlName="cpus" matInput type="number" [(ngModel)]="node.properties.cpus" placeholder="Maximum CPUs">
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
|
|
||||||
|
<button mat-button class="form-field" (click)="configureCustomAdapters()">
|
||||||
|
Configure custom adapters
|
||||||
|
</button>
|
||||||
|
|
||||||
<mat-form-field class="select">
|
<mat-form-field class="select">
|
||||||
<mat-select [ngModelOptions]="{standalone: true}" placeholder="Console type" [(ngModel)]="node.console_type">
|
<mat-select [ngModelOptions]="{standalone: true}" placeholder="Console type" [(ngModel)]="node.console_type">
|
||||||
@ -33,6 +42,26 @@
|
|||||||
<mat-checkbox [ngModelOptions]="{standalone: true}" [(ngModel)]="node.console_auto_start">
|
<mat-checkbox [ngModelOptions]="{standalone: true}" [(ngModel)]="node.console_auto_start">
|
||||||
Auto start console
|
Auto start console
|
||||||
</mat-checkbox>
|
</mat-checkbox>
|
||||||
|
|
||||||
|
<mat-form-field class="form-field">
|
||||||
|
<mat-select [ngModelOptions]="{standalone: true}" placeholder="VNC console resolution" [(ngModel)]="node.properties.console_resolution">
|
||||||
|
<mat-option *ngFor="let resolution of consoleResolutions" [value]="resolution">
|
||||||
|
{{resolution}}
|
||||||
|
</mat-option>
|
||||||
|
</mat-select>
|
||||||
|
</mat-form-field>
|
||||||
|
|
||||||
|
<mat-form-field class="form-field">
|
||||||
|
<input formControlName="consoleHttpPort" matInput type="number" [(ngModel)]="node.properties.console_http_port" placeholder="HTTP port in the container">
|
||||||
|
</mat-form-field>
|
||||||
|
|
||||||
|
<mat-form-field class="form-field">
|
||||||
|
<input matInput formControlName="consoleHttpPath" type="text" [(ngModel)]="node.properties.console_http_path" placeholder="HTTP path">
|
||||||
|
</mat-form-field>
|
||||||
|
|
||||||
|
<button mat-button class="form-field" (click)="editNetworkConfiguration()">
|
||||||
|
Edit network configuration
|
||||||
|
</button>
|
||||||
</form>
|
</form>
|
||||||
<h6>Environment</h6>
|
<h6>Environment</h6>
|
||||||
<mat-form-field class="form-field">
|
<mat-form-field class="form-field">
|
||||||
@ -44,6 +73,11 @@
|
|||||||
<h6>Extra hosts</h6>
|
<h6>Extra hosts</h6>
|
||||||
<mat-form-field class="form-field">
|
<mat-form-field class="form-field">
|
||||||
<textarea matInput type="text" [(ngModel)]="node.properties.extra_hosts"></textarea>
|
<textarea matInput type="text" [(ngModel)]="node.properties.extra_hosts"></textarea>
|
||||||
|
</mat-form-field><br/>
|
||||||
|
|
||||||
|
<h6>Additional directories</h6>
|
||||||
|
<mat-form-field class="form-field">
|
||||||
|
<textarea matInput type="text" [(ngModel)]="node.properties.extra_volumes"></textarea>
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
</mat-tab>
|
</mat-tab>
|
||||||
|
|
||||||
|
@ -4,8 +4,11 @@ import { Node } from '../../../../../cartography/models/node';
|
|||||||
import { Server } from '../../../../../models/server';
|
import { Server } from '../../../../../models/server';
|
||||||
import { NodeService } from '../../../../../services/node.service';
|
import { NodeService } from '../../../../../services/node.service';
|
||||||
import { ToasterService } from '../../../../../services/toaster.service';
|
import { ToasterService } from '../../../../../services/toaster.service';
|
||||||
import { MatDialogRef } from '@angular/material/dialog';
|
import { MatDialog, MatDialogRef } from '@angular/material/dialog';
|
||||||
import { DockerConfigurationService } from '../../../../../services/docker-configuration.service';
|
import { DockerConfigurationService } from '../../../../../services/docker-configuration.service';
|
||||||
|
import { NonNegativeValidator } from '../../../../../validators/non-negative-validator';
|
||||||
|
import { EditNetworkConfigurationDialogComponent } from './edit-network-configuration/edit-network-configuration.component';
|
||||||
|
import { ConfigureCustomAdaptersDialogComponent } from './configure-custom-adapters/configure-custom-adapters.component';
|
||||||
|
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
@ -19,19 +22,39 @@ export class ConfiguratorDialogDockerComponent implements OnInit {
|
|||||||
name: string;
|
name: string;
|
||||||
generalSettingsForm: FormGroup;
|
generalSettingsForm: FormGroup;
|
||||||
consoleTypes: string[] = [];
|
consoleTypes: string[] = [];
|
||||||
|
consoleResolutions: string[] = [
|
||||||
|
'640x480',
|
||||||
|
'800x600',
|
||||||
|
'1024x768',
|
||||||
|
'1280x800',
|
||||||
|
'1280x1024',
|
||||||
|
'1366x768',
|
||||||
|
'1920x1080'
|
||||||
|
];
|
||||||
|
private conf = {
|
||||||
|
autoFocus: false,
|
||||||
|
width: '800px',
|
||||||
|
disableClose: true
|
||||||
|
};
|
||||||
|
dialogRef;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
public dialogRef: MatDialogRef<ConfiguratorDialogDockerComponent>,
|
public dialogReference: MatDialogRef<ConfiguratorDialogDockerComponent>,
|
||||||
public nodeService: NodeService,
|
public nodeService: NodeService,
|
||||||
private toasterService: ToasterService,
|
private toasterService: ToasterService,
|
||||||
private formBuilder: FormBuilder,
|
private formBuilder: FormBuilder,
|
||||||
private dockerConfigurationService: DockerConfigurationService
|
private dockerConfigurationService: DockerConfigurationService,
|
||||||
|
private nonNegativeValidator: NonNegativeValidator,
|
||||||
|
private dialog: MatDialog
|
||||||
) {
|
) {
|
||||||
this.generalSettingsForm = this.formBuilder.group({
|
this.generalSettingsForm = this.formBuilder.group({
|
||||||
name: new FormControl('', Validators.required),
|
name: new FormControl('', Validators.required),
|
||||||
adapter: new FormControl('', Validators.required),
|
adapter: new FormControl('', Validators.required),
|
||||||
memory: new FormControl(''),
|
memory: new FormControl('', nonNegativeValidator.get),
|
||||||
cpus: new FormControl('')
|
cpus: new FormControl('', nonNegativeValidator.get),
|
||||||
|
startCommand: new FormControl('', Validators.required),
|
||||||
|
consoleHttpPort: new FormControl('', Validators.required),
|
||||||
|
consoleHttpPath: new FormControl('', Validators.required)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -40,6 +63,7 @@ export class ConfiguratorDialogDockerComponent implements OnInit {
|
|||||||
this.node = node;
|
this.node = node;
|
||||||
this.name = node.name;
|
this.name = node.name;
|
||||||
this.getConfiguration();
|
this.getConfiguration();
|
||||||
|
if (!this.node.properties.cpus) this.node.properties.cpus = 0.0;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -47,6 +71,20 @@ export class ConfiguratorDialogDockerComponent implements OnInit {
|
|||||||
this.consoleTypes = this.dockerConfigurationService.getConsoleTypes();
|
this.consoleTypes = this.dockerConfigurationService.getConsoleTypes();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
configureCustomAdapters() {
|
||||||
|
this.dialogRef = this.dialog.open(ConfigureCustomAdaptersDialogComponent, this.conf);
|
||||||
|
let instance = this.dialogRef.componentInstance;
|
||||||
|
instance.server = this.server;
|
||||||
|
instance.node = this.node;
|
||||||
|
}
|
||||||
|
|
||||||
|
editNetworkConfiguration() {
|
||||||
|
this.dialogRef = this.dialog.open(EditNetworkConfigurationDialogComponent, this.conf);
|
||||||
|
let instance = this.dialogRef.componentInstance;
|
||||||
|
instance.server = this.server;
|
||||||
|
instance.node = this.node;
|
||||||
|
}
|
||||||
|
|
||||||
onSaveClick() {
|
onSaveClick() {
|
||||||
if (this.generalSettingsForm.valid) {
|
if (this.generalSettingsForm.valid) {
|
||||||
this.nodeService.updateNode(this.server, this.node).subscribe(() => {
|
this.nodeService.updateNode(this.server, this.node).subscribe(() => {
|
||||||
@ -59,6 +97,6 @@ export class ConfiguratorDialogDockerComponent implements OnInit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
onCancelClick() {
|
onCancelClick() {
|
||||||
this.dialogRef.close();
|
this.dialogReference.close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,32 @@
|
|||||||
|
<h1 mat-dialog-title>Configure custom adapters for node {{node.name}}</h1>
|
||||||
|
|
||||||
|
<div *ngIf="node" class="modal-form-container">
|
||||||
|
<div class="header">
|
||||||
|
<span class="column">
|
||||||
|
Adapter number
|
||||||
|
</span>
|
||||||
|
<span class="column">
|
||||||
|
Port name
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<mat-list>
|
||||||
|
<mat-list-item *ngFor="let adapter of adapters; index as i">
|
||||||
|
<div class="header">
|
||||||
|
<span class="column">
|
||||||
|
Adapter {{adapter.adapter_number}}
|
||||||
|
</span>
|
||||||
|
<span class="column">
|
||||||
|
<input matInput type="text" [(ngModel)]="adapter.port_name" placeholder="Edit port name">
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</mat-list-item>
|
||||||
|
</mat-list>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div mat-dialog-actions>
|
||||||
|
<button mat-button (click)="onCancelClick()" color="accent">Cancel</button>
|
||||||
|
<button mat-button (click)="onSaveClick()" tabindex="2" mat-raised-button color="primary">Apply</button>
|
||||||
|
</div>
|
@ -0,0 +1,21 @@
|
|||||||
|
th {
|
||||||
|
border: 0px!important;
|
||||||
|
}
|
||||||
|
|
||||||
|
th.mat-header-cell {
|
||||||
|
padding-bottom: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
td.mat-cell {
|
||||||
|
padding-top: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.column {
|
||||||
|
width: 50%;
|
||||||
|
}
|
@ -0,0 +1,60 @@
|
|||||||
|
import { Component, OnInit, Input, ViewChild } from "@angular/core";
|
||||||
|
import { FormBuilder, FormGroup, Validators, FormControl } from '@angular/forms';
|
||||||
|
import { Node } from '../../../../../../cartography/models/node';
|
||||||
|
import { Server } from '../../../../../../models/server';
|
||||||
|
import { NodeService } from '../../../../../../services/node.service';
|
||||||
|
import { ToasterService } from '../../../../../../services/toaster.service';
|
||||||
|
import { MatDialogRef } from '@angular/material/dialog';
|
||||||
|
import { DockerConfigurationService } from '../../../../../../services/docker-configuration.service';
|
||||||
|
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-configure-custom-adapters',
|
||||||
|
templateUrl: './configure-custom-adapters.component.html',
|
||||||
|
styleUrls: ['./configure-custom-adapters.component.scss']
|
||||||
|
})
|
||||||
|
export class ConfigureCustomAdaptersDialogComponent implements OnInit {
|
||||||
|
server: Server;
|
||||||
|
node: Node;
|
||||||
|
displayedColumns: string[] = ['adapter_number', 'port_name'];
|
||||||
|
adapters: CustomAdapter[] = [];
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
public dialogRef: MatDialogRef<ConfigureCustomAdaptersDialogComponent>,
|
||||||
|
public nodeService: NodeService,
|
||||||
|
private toasterService: ToasterService,
|
||||||
|
private formBuilder: FormBuilder,
|
||||||
|
private dockerConfigurationService: DockerConfigurationService
|
||||||
|
) {}
|
||||||
|
|
||||||
|
ngOnInit() {
|
||||||
|
let i: number = 0;
|
||||||
|
if (!this.node.custom_adapters) {
|
||||||
|
this.node.ports.forEach((port) => {
|
||||||
|
this.adapters.push({
|
||||||
|
adapter_number: i,
|
||||||
|
port_name: ''
|
||||||
|
});
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
this.adapters = this.node.custom_adapters;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onSaveClick() {
|
||||||
|
this.node.custom_adapters = this.adapters;
|
||||||
|
this.nodeService.updateNodeWithCustomAdapters(this.server, this.node).subscribe(() => {
|
||||||
|
this.onCancelClick();
|
||||||
|
this.toasterService.success(`Configuration saved for node ${this.node.name}`);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
onCancelClick() {
|
||||||
|
this.dialogRef.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class CustomAdapter {
|
||||||
|
adapter_number: number;
|
||||||
|
port_name: string;
|
||||||
|
}
|
@ -0,0 +1,10 @@
|
|||||||
|
<h1 mat-dialog-title>Edit network configuration for node {{node.name}}</h1>
|
||||||
|
|
||||||
|
<div *ngIf="node" class="modal-form-container">
|
||||||
|
<textarea matInput [(ngModel)]="configuration" class="textArea" type="text"></textarea>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div mat-dialog-actions>
|
||||||
|
<button mat-button (click)="onCancelClick()" color="accent">Cancel</button>
|
||||||
|
<button mat-button (click)="onSaveClick()" tabindex="2" mat-raised-button color="primary">Apply</button>
|
||||||
|
</div>
|
@ -0,0 +1,4 @@
|
|||||||
|
.textArea {
|
||||||
|
width: 100%;
|
||||||
|
height: 350px;
|
||||||
|
}
|
@ -0,0 +1,43 @@
|
|||||||
|
import { Component, OnInit, Input, ViewChild } from "@angular/core";
|
||||||
|
import { FormBuilder, FormGroup, Validators, FormControl } from '@angular/forms';
|
||||||
|
import { Node } from '../../../../../../cartography/models/node';
|
||||||
|
import { Server } from '../../../../../../models/server';
|
||||||
|
import { NodeService } from '../../../../../../services/node.service';
|
||||||
|
import { ToasterService } from '../../../../../../services/toaster.service';
|
||||||
|
import { MatDialogRef } from '@angular/material/dialog';
|
||||||
|
import { DockerConfigurationService } from '../../../../../../services/docker-configuration.service';
|
||||||
|
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-edit-network-configuration',
|
||||||
|
templateUrl: './edit-network-configuration.component.html',
|
||||||
|
styleUrls: ['./edit-network-configuration.component.scss']
|
||||||
|
})
|
||||||
|
export class EditNetworkConfigurationDialogComponent implements OnInit {
|
||||||
|
server: Server;
|
||||||
|
node: Node;
|
||||||
|
configuration: string;
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
public dialogRef: MatDialogRef<EditNetworkConfigurationDialogComponent>,
|
||||||
|
public nodeService: NodeService,
|
||||||
|
private toasterService: ToasterService
|
||||||
|
) {}
|
||||||
|
|
||||||
|
ngOnInit() {
|
||||||
|
this.nodeService.getNetworkConfiguration(this.server, this.node).subscribe((response: string) => {
|
||||||
|
this.configuration = response;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
onSaveClick() {
|
||||||
|
this.nodeService.saveNetworkConfiguration(this.server, this.node, this.configuration).subscribe((response: string) => {
|
||||||
|
this.onCancelClick();
|
||||||
|
this.toasterService.success(`Configuration for node ${this.node.name} saved.`);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
onCancelClick() {
|
||||||
|
this.dialogRef.close();
|
||||||
|
}
|
||||||
|
}
|
@ -2,7 +2,8 @@ import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
|||||||
import { NodesMenuComponent } from './nodes-menu.component';
|
import { NodesMenuComponent } from './nodes-menu.component';
|
||||||
import { MockedToasterService } from '../../../services/toaster.service.spec';
|
import { MockedToasterService } from '../../../services/toaster.service.spec';
|
||||||
import { MockedNodeService, MockedNodesDataSource } from '../project-map.component.spec';
|
import { MockedNodeService, MockedNodesDataSource } from '../project-map.component.spec';
|
||||||
import { MatButtonModule, MatIconModule } from '@angular/material';
|
import { MatButtonModule } from '@angular/material/button';
|
||||||
|
import { MatIconModule } from '@angular/material/icon';
|
||||||
import { CommonModule } from '@angular/common';
|
import { CommonModule } from '@angular/common';
|
||||||
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
||||||
import { NO_ERRORS_SCHEMA } from '@angular/core';
|
import { NO_ERRORS_SCHEMA } from '@angular/core';
|
||||||
@ -14,7 +15,7 @@ import { ServerService } from '../../../services/server.service';
|
|||||||
import { SettingsService } from '../../../services/settings.service';
|
import { SettingsService } from '../../../services/settings.service';
|
||||||
import { ElectronService } from 'ngx-electron';
|
import { ElectronService } from 'ngx-electron';
|
||||||
|
|
||||||
describe('NodesMenuComponent', () => {
|
xdescribe('NodesMenuComponent', () => {
|
||||||
let component: NodesMenuComponent;
|
let component: NodesMenuComponent;
|
||||||
let fixture: ComponentFixture<NodesMenuComponent>;
|
let fixture: ComponentFixture<NodesMenuComponent>;
|
||||||
let mockedToasterService: MockedToasterService = new MockedToasterService();
|
let mockedToasterService: MockedToasterService = new MockedToasterService();
|
||||||
|
@ -1,6 +1,10 @@
|
|||||||
import { ComponentFixture, TestBed, async } from '@angular/core/testing';
|
import { ComponentFixture, TestBed, async } from '@angular/core/testing';
|
||||||
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
|
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
|
||||||
import { MatIconModule, MatToolbarModule, MatMenuModule, MatCheckboxModule, MatDialogModule, MatDialogRef, MAT_DIALOG_DATA } from '@angular/material';
|
import { MatCheckboxModule } from '@angular/material/checkbox';
|
||||||
|
import { MatDialogModule, MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';
|
||||||
|
import { MatIconModule } from '@angular/material/icon';
|
||||||
|
import { MatMenuModule } from '@angular/material/menu';
|
||||||
|
import { MatToolbarModule } from '@angular/material/toolbar';
|
||||||
import { CommonModule } from '@angular/common';
|
import { CommonModule } from '@angular/common';
|
||||||
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
||||||
import { NO_ERRORS_SCHEMA } from '@angular/core';
|
import { NO_ERRORS_SCHEMA } from '@angular/core';
|
||||||
|
@ -1,7 +1,11 @@
|
|||||||
import { StartCaptureDialogComponent } from "./start-capture.component";
|
import { StartCaptureDialogComponent } from "./start-capture.component";
|
||||||
import { ComponentFixture, TestBed, async } from '@angular/core/testing';
|
import { ComponentFixture, TestBed, async } from '@angular/core/testing';
|
||||||
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
|
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
|
||||||
import { MatIconModule, MatToolbarModule, MatMenuModule, MatCheckboxModule, MatDialogModule, MatDialogRef, MAT_DIALOG_DATA } from '@angular/material';
|
import { MatCheckboxModule } from '@angular/material/checkbox';
|
||||||
|
import { MatDialogModule, MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';
|
||||||
|
import { MatIconModule } from '@angular/material/icon';
|
||||||
|
import { MatMenuModule } from '@angular/material/menu';
|
||||||
|
import { MatToolbarModule } from '@angular/material/toolbar';
|
||||||
import { CommonModule } from '@angular/common';
|
import { CommonModule } from '@angular/common';
|
||||||
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
||||||
import { ToasterService } from '../../../../services/toaster.service';
|
import { ToasterService } from '../../../../services/toaster.service';
|
||||||
|
@ -2,7 +2,11 @@ import { ProjectMapMenuComponent } from "./project-map-menu.component";
|
|||||||
import { ComponentFixture, async, TestBed } from '@angular/core/testing';
|
import { ComponentFixture, async, TestBed } from '@angular/core/testing';
|
||||||
import { MockedDrawingService } from '../project-map.component.spec';
|
import { MockedDrawingService } from '../project-map.component.spec';
|
||||||
import { MapSettingsService } from '../../../services/mapsettings.service';
|
import { MapSettingsService } from '../../../services/mapsettings.service';
|
||||||
import { MatIconModule, MatToolbarModule, MatMenuModule, MatCheckboxModule, MatDialogModule } from '@angular/material';
|
import { MatCheckboxModule } from '@angular/material/checkbox';
|
||||||
|
import { MatDialogModule } from '@angular/material/dialog';
|
||||||
|
import { MatIconModule } from '@angular/material/icon';
|
||||||
|
import { MatMenuModule } from '@angular/material/menu';
|
||||||
|
import { MatToolbarModule } from '@angular/material/toolbar';
|
||||||
import { CommonModule } from '@angular/common';
|
import { CommonModule } from '@angular/common';
|
||||||
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
||||||
import { DrawingService } from '../../../services/drawing.service';
|
import { DrawingService } from '../../../services/drawing.service';
|
||||||
|
@ -59,6 +59,10 @@
|
|||||||
<mat-icon>info</mat-icon>
|
<mat-icon>info</mat-icon>
|
||||||
<span>Go to system status</span>
|
<span>Go to system status</span>
|
||||||
</button>
|
</button>
|
||||||
|
<button mat-menu-item routerLink="/settings">
|
||||||
|
<mat-icon>settings</mat-icon>
|
||||||
|
<span>Go to settings</span>
|
||||||
|
</button>
|
||||||
<button mat-menu-item (click)="addNewTemplate()">
|
<button mat-menu-item (click)="addNewTemplate()">
|
||||||
<mat-icon>control_point</mat-icon>
|
<mat-icon>control_point</mat-icon>
|
||||||
<span>New template</span>
|
<span>New template</span>
|
||||||
@ -179,6 +183,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<app-context-menu [project]="project" [server]="server"></app-context-menu>
|
<app-context-menu [project]="project" [server]="server"></app-context-menu>
|
||||||
|
<app-context-console-menu [project]="project" [server]="server"></app-context-console-menu>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div [ngClass]="{lightTheme: isLightThemeEnabled}" class="zoom-buttons">
|
<div [ngClass]="{lightTheme: isLightThemeEnabled}" class="zoom-buttons">
|
||||||
|
@ -1,7 +1,12 @@
|
|||||||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
import { ProjectMapComponent } from './project-map.component';
|
import { ProjectMapComponent } from './project-map.component';
|
||||||
import { MatIconModule, MatToolbarModule, MatMenuModule, MatCheckboxModule, MatDialogModule, MatBottomSheetModule } from '@angular/material';
|
import { MatBottomSheetModule } from '@angular/material/bottom-sheet';
|
||||||
|
import { MatCheckboxModule } from '@angular/material/checkbox';
|
||||||
|
import { MatDialogModule } from '@angular/material/dialog';
|
||||||
|
import { MatIconModule } from '@angular/material/icon';
|
||||||
|
import { MatMenuModule } from '@angular/material/menu';
|
||||||
|
import { MatToolbarModule } from '@angular/material/toolbar';
|
||||||
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
||||||
import { ServerService } from '../../services/server.service';
|
import { ServerService } from '../../services/server.service';
|
||||||
import { ProjectService } from '../../services/project.service';
|
import { ProjectService } from '../../services/project.service';
|
||||||
@ -57,6 +62,7 @@ import { MapNodesDataSource, MapLinksDataSource, MapDrawingsDataSource, MapSymbo
|
|||||||
import { EthernetLinkWidget } from '../../cartography/widgets/links/ethernet-link';
|
import { EthernetLinkWidget } from '../../cartography/widgets/links/ethernet-link';
|
||||||
import { SerialLinkWidget } from '../../cartography/widgets/links/serial-link';
|
import { SerialLinkWidget } from '../../cartography/widgets/links/serial-link';
|
||||||
import { NotificationService } from '../../services/notification.service';
|
import { NotificationService } from '../../services/notification.service';
|
||||||
|
import {} from 'mousetrap';
|
||||||
|
|
||||||
export class MockedProgressService {
|
export class MockedProgressService {
|
||||||
public activate() {}
|
public activate() {}
|
||||||
@ -238,7 +244,7 @@ export class MockedLinksDataSource {
|
|||||||
clear() {}
|
clear() {}
|
||||||
}
|
}
|
||||||
|
|
||||||
describe('ProjectMapComponent', () => {
|
xdescribe('ProjectMapComponent', () => {
|
||||||
let component: ProjectMapComponent;
|
let component: ProjectMapComponent;
|
||||||
let fixture: ComponentFixture<ProjectMapComponent>;
|
let fixture: ComponentFixture<ProjectMapComponent>;
|
||||||
let drawingService = new MockedDrawingService();
|
let drawingService = new MockedDrawingService();
|
||||||
|
@ -13,6 +13,7 @@ import { ProjectService } from '../../services/project.service';
|
|||||||
import { Server } from '../../models/server';
|
import { Server } from '../../models/server';
|
||||||
import { Drawing } from '../../cartography/models/drawing';
|
import { Drawing } from '../../cartography/models/drawing';
|
||||||
import { ContextMenuComponent } from './context-menu/context-menu.component';
|
import { ContextMenuComponent } from './context-menu/context-menu.component';
|
||||||
|
import { ContextConsoleMenuComponent } from './context-console-menu/context-console-menu.component';
|
||||||
import { Template } from '../../models/template';
|
import { Template } from '../../models/template';
|
||||||
import { NodeService } from '../../services/node.service';
|
import { NodeService } from '../../services/node.service';
|
||||||
import { Symbol } from '../../models/symbol';
|
import { Symbol } from '../../models/symbol';
|
||||||
@ -112,6 +113,7 @@ export class ProjectMapComponent implements OnInit, OnDestroy {
|
|||||||
public isLightThemeEnabled: boolean = false;
|
public isLightThemeEnabled: boolean = false;
|
||||||
|
|
||||||
@ViewChild(ContextMenuComponent) contextMenu: ContextMenuComponent;
|
@ViewChild(ContextMenuComponent) contextMenu: ContextMenuComponent;
|
||||||
|
@ViewChild(ContextConsoleMenuComponent) consoleContextMenu: ContextConsoleMenuComponent;
|
||||||
@ViewChild(D3MapComponent) mapChild: D3MapComponent;
|
@ViewChild(D3MapComponent) mapChild: D3MapComponent;
|
||||||
@ViewChild(ProjectMapMenuComponent) projectMapMenuComponent: ProjectMapMenuComponent;
|
@ViewChild(ProjectMapMenuComponent) projectMapMenuComponent: ProjectMapMenuComponent;
|
||||||
|
|
||||||
@ -437,6 +439,11 @@ export class ProjectMapComponent implements OnInit, OnDestroy {
|
|||||||
this.contextMenu.openMenuForListOfElements(drawings, nodes, labels, links, event.pageY, event.pageX);
|
this.contextMenu.openMenuForListOfElements(drawings, nodes, labels, links, event.pageY, event.pageX);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const onContextConsoleMenu = this.nodeWidget.onContextConsoleMenu.subscribe((eventNode: NodeContextMenu) => {
|
||||||
|
const node = this.mapNodeToNode.convert(eventNode.node);
|
||||||
|
this.consoleContextMenu.openMenu(node, eventNode.event.pageY, eventNode.event.pageX);
|
||||||
|
});
|
||||||
|
|
||||||
this.projectMapSubscription.add(onLinkContextMenu);
|
this.projectMapSubscription.add(onLinkContextMenu);
|
||||||
this.projectMapSubscription.add(onEthernetLinkContextMenu);
|
this.projectMapSubscription.add(onEthernetLinkContextMenu);
|
||||||
this.projectMapSubscription.add(onSerialLinkContextMenu);
|
this.projectMapSubscription.add(onSerialLinkContextMenu);
|
||||||
@ -445,6 +452,7 @@ export class ProjectMapComponent implements OnInit, OnDestroy {
|
|||||||
this.projectMapSubscription.add(onContextMenu);
|
this.projectMapSubscription.add(onContextMenu);
|
||||||
this.projectMapSubscription.add(onLabelContextMenu);
|
this.projectMapSubscription.add(onLabelContextMenu);
|
||||||
this.projectMapSubscription.add(onInterfaceLabelContextMenu);
|
this.projectMapSubscription.add(onInterfaceLabelContextMenu);
|
||||||
|
this.projectMapSubscription.add(onContextConsoleMenu);
|
||||||
this.mapChangeDetectorRef.detectChanges();
|
this.mapChangeDetectorRef.detectChanges();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -880,7 +888,7 @@ export class ProjectMapComponent implements OnInit, OnDestroy {
|
|||||||
public addNewTemplate() {
|
public addNewTemplate() {
|
||||||
const dialogRef = this.dialog.open(NewTemplateDialogComponent, {
|
const dialogRef = this.dialog.open(NewTemplateDialogComponent, {
|
||||||
width: '1000px',
|
width: '1000px',
|
||||||
maxHeight: '500px',
|
maxHeight: '700px',
|
||||||
autoFocus: false,
|
autoFocus: false,
|
||||||
disableClose: true
|
disableClose: true
|
||||||
});
|
});
|
||||||
|
@ -1 +1 @@
|
|||||||
<div #terminal id="terminal"></div>
|
<div class="lightTheme" #terminal id="terminal"></div>
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user