mirror of
https://github.com/GNS3/gns3-web-ui.git
synced 2025-02-22 18:22:35 +00:00
Dialog for Qemu template name
This commit is contained in:
parent
b32fdf4fc2
commit
87aa6c4b59
@ -279,6 +279,7 @@ import { ChangeHostnameActionComponent } from './components/project-map/context-
|
|||||||
import { ChangeHostnameDialogComponent } from './components/project-map/change-hostname-dialog/change-hostname-dialog.component';
|
import { ChangeHostnameDialogComponent } from './components/project-map/change-hostname-dialog/change-hostname-dialog.component';
|
||||||
import { ApplianceInfoDialogComponent } from './components/project-map/new-template-dialog/appliance-info-dialog/appliance-info-dialog.component';
|
import { ApplianceInfoDialogComponent } from './components/project-map/new-template-dialog/appliance-info-dialog/appliance-info-dialog.component';
|
||||||
import { InformationDialogComponent } from './components/dialogs/information-dialog.component';
|
import { InformationDialogComponent } from './components/dialogs/information-dialog.component';
|
||||||
|
import { TemplateNameDialogComponent } from './components/project-map/new-template-dialog/template-name-dialog/template-name-dialog.component';
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
declarations: [
|
declarations: [
|
||||||
@ -462,7 +463,8 @@ import { InformationDialogComponent } from './components/dialogs/information-dia
|
|||||||
ChangeHostnameActionComponent,
|
ChangeHostnameActionComponent,
|
||||||
ChangeHostnameDialogComponent,
|
ChangeHostnameDialogComponent,
|
||||||
ApplianceInfoDialogComponent,
|
ApplianceInfoDialogComponent,
|
||||||
InformationDialogComponent
|
InformationDialogComponent,
|
||||||
|
TemplateNameDialogComponent
|
||||||
],
|
],
|
||||||
imports: [
|
imports: [
|
||||||
BrowserModule,
|
BrowserModule,
|
||||||
|
@ -29,6 +29,7 @@ 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 { InformationDialogComponent } from '../../../components/dialogs/information-dialog.component';
|
||||||
import { ProgressService } from '../../../common/progress/progress.service';
|
import { ProgressService } from '../../../common/progress/progress.service';
|
||||||
|
import { TemplateNameDialogComponent } from './template-name-dialog/template-name-dialog.component';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-new-template-dialog',
|
selector: 'app-new-template-dialog',
|
||||||
@ -78,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;
|
||||||
|
|
||||||
@ -98,6 +101,10 @@ export class NewTemplateDialogComponent implements OnInit {
|
|||||||
) {}
|
) {}
|
||||||
|
|
||||||
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') {
|
||||||
@ -423,6 +430,8 @@ export class NewTemplateDialogComponent implements OnInit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
createIouTemplate (image: Image) {
|
createIouTemplate (image: Image) {
|
||||||
|
if (!this.validateTemplateName()) return;
|
||||||
|
|
||||||
let iouTemplate: IouTemplate = new IouTemplate();
|
let iouTemplate: IouTemplate = new IouTemplate();
|
||||||
iouTemplate.name = this.applianceToInstall.name;
|
iouTemplate.name = this.applianceToInstall.name;
|
||||||
iouTemplate.nvram = this.applianceToInstall.iou.nvram;
|
iouTemplate.nvram = this.applianceToInstall.iou.nvram;
|
||||||
@ -447,6 +456,8 @@ export class NewTemplateDialogComponent implements OnInit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
createIosTemplate(image: Image) {
|
createIosTemplate(image: Image) {
|
||||||
|
if (!this.validateTemplateName()) return;
|
||||||
|
|
||||||
let iosTemplate: IosTemplate = new IosTemplate();
|
let iosTemplate: IosTemplate = new IosTemplate();
|
||||||
iosTemplate.name = this.applianceToInstall.name;
|
iosTemplate.name = this.applianceToInstall.name;
|
||||||
iosTemplate.chassis = this.applianceToInstall.dynamips.chassis;
|
iosTemplate.chassis = this.applianceToInstall.dynamips.chassis;
|
||||||
@ -479,6 +490,8 @@ export class NewTemplateDialogComponent implements OnInit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
createDockerTemplate() {
|
createDockerTemplate() {
|
||||||
|
if (!this.validateTemplateName()) return;
|
||||||
|
|
||||||
let dockerTemplate: DockerTemplate = new DockerTemplate();
|
let dockerTemplate: DockerTemplate = new DockerTemplate();
|
||||||
dockerTemplate.name = this.applianceToInstall.name;
|
dockerTemplate.name = this.applianceToInstall.name;
|
||||||
dockerTemplate.adapters = this.applianceToInstall.docker.adapters;
|
dockerTemplate.adapters = this.applianceToInstall.docker.adapters;
|
||||||
@ -509,8 +522,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;
|
||||||
@ -533,11 +546,58 @@ 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) => {
|
if (this.templates.filter(t => t.name === this.applianceToInstall.name).length === 0) {
|
||||||
this.templateService.newTemplateCreated.next(template as any as Template);
|
qemuTemplate.name = this.applianceToInstall.name;
|
||||||
this.toasterService.success('Template added');
|
|
||||||
this.dialogRef.close();
|
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 {
|
||||||
|
const dialogRef = this.dialog.open(TemplateNameDialogComponent, {
|
||||||
|
width: '400px',
|
||||||
|
height: '250px',
|
||||||
|
autoFocus: false,
|
||||||
|
disableClose: true
|
||||||
|
});
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
validateTemplateName() {
|
||||||
|
if (this.templates.filter(t => t.name === this.applianceToInstall.name).length === 0) {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
const dialogRef = this.dialog.open(TemplateNameDialogComponent, {
|
||||||
|
width: '400px',
|
||||||
|
height: '300px',
|
||||||
|
autoFocus: false,
|
||||||
|
disableClose: true
|
||||||
|
});
|
||||||
|
dialogRef.componentInstance.server = this.server;
|
||||||
|
dialogRef.afterClosed().subscribe((answer: string) => {
|
||||||
|
if (answer) {
|
||||||
|
this.applianceToInstall.name = answer;
|
||||||
|
return true;
|
||||||
|
} 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,70 @@
|
|||||||
|
import { Component, OnInit, EventEmitter } from '@angular/core';
|
||||||
|
import { Router } from '@angular/router';
|
||||||
|
import { MatDialog, MatDialogRef } 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
|
||||||
|
) {}
|
||||||
|
|
||||||
|
ngOnInit() {
|
||||||
|
this.templateNameForm = this.formBuilder.group({
|
||||||
|
templateName: new FormControl(null, [Validators.required, this.templateNameValidator.get], [templateNameAsyncValidator(this.server, this.templateService)])
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
14
src/app/validators/template-name-async-validator.ts
Normal file
14
src/app/validators/template-name-async-validator.ts
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
import { TemplateService } from '../services/template.service';
|
||||||
|
import { FormControl } from '@angular/forms';
|
||||||
|
import { timer } from 'rxjs';
|
||||||
|
import { map, switchMap } from 'rxjs/operators';
|
||||||
|
import { Server } from '../models/server';
|
||||||
|
|
||||||
|
export const templateNameAsyncValidator = (server: Server, templateService: TemplateService) => {
|
||||||
|
return (control: FormControl) => {
|
||||||
|
return timer(500).pipe(
|
||||||
|
switchMap(() => templateService.list(server)),
|
||||||
|
map(response => (response.find(n => n.name === control.value) ? {templateExist: true} : null))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user