Skip to content

Commit

Permalink
add validation for tasks to scenario wizard
Browse files Browse the repository at this point in the history
  • Loading branch information
Philip Prinz authored and Philip Prinz committed Apr 10, 2024
1 parent df15b5c commit c3d92e5
Show file tree
Hide file tree
Showing 7 changed files with 91 additions and 30 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<div class="code-editor" #codeEditor>
<textarea (input)="onValueChange($event)" (resize)="manualResizeEvent($event)" [(ngModel)]="_textValue" readonly="readonly" #textarea>
<textarea (input)="onValueChange($event)" (resize)="manualResizeEvent($event)" [(ngModel)]="_textValue" [readonly]="readonly" #textarea>
</textarea>
<code #code class="{{ language }}" [innerHTML]="highlightedText"></code>
</div>
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ export class CodeWithSyntaxHighlightingComponent
resizeable: boolean = false;

@Input()
readonly: boolean = false
readonly: boolean = false;

@Input()
outline: string = 'solid 1px';
Expand Down
21 changes: 18 additions & 3 deletions src/app/scenario/scenario-wizard/scenario-wizard.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,17 @@
(clrWizardOnFinish)="finishScenario()"
(clrWizardOnCancel)="doCancel()"
>
<clr-alert *ngFor="let error of validationErrors" [clrAlertType]="'alert-danger'" [clrAlertClosable]="false">
<clr-alert-item>
{{ error.message }}
</clr-alert-item>
</clr-alert>
<clr-wizard-title>{{ wizardTitle }} </clr-wizard-title>

<clr-wizard-button [type]="'cancel'">Cancel</clr-wizard-button>
<clr-wizard-button [type]="'previous'">Back</clr-wizard-button>
<clr-wizard-button [type]="'next'">Next</clr-wizard-button>
<clr-wizard-button [type]="'finish'">Finish</clr-wizard-button>
<clr-wizard-button [type]="'finish'" [clrWizardButtonDisabled]="disableFinalizeButton">Finish</clr-wizard-button>

<clr-wizard-page
[clrWizardPageNextDisabled]="!scenarioDetails.valid"
Expand Down Expand Up @@ -232,7 +237,7 @@
</ng-container>
</clr-wizard-page>

<clr-wizard-page>
<clr-wizard-page #taskPage>
<ng-template clrPageTitle>Tasks</ng-template>
<app-task *ngIf="!!selectedscenario" [selectedScenario]="selectedscenario" (tasksChanged)="replaceVmTasks($event)"></app-task>
</clr-wizard-page>
Expand Down Expand Up @@ -358,7 +363,7 @@
</ng-container>
</clr-wizard-page>

<clr-wizard-page>
<clr-wizard-page #finalizePage>
<ng-template clrPageTitle>Finalize</ng-template>
<p>Confirm the following details before finishing</p>
<h4>Scenario</h4>
Expand Down Expand Up @@ -398,6 +403,16 @@ <h4>Scenario</h4>
>
</td>
</tr>
<tr>
<td>Tasks</td>
<td>
<ng-container *ngFor="let vm_task of selectedscenario.vm_tasks">
<span class="label" *ngFor="let task of vm_task.tasks">
{{ vm_task.vm_name }}: {{ task.name }}</span
>
</ng-container>
</td>
</tr>
<tr>
<td>Categories</td>
<td>
Expand Down
77 changes: 69 additions & 8 deletions src/app/scenario/scenario-wizard/scenario-wizard.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import {
ViewChild,
} from '@angular/core';
import { FormControl, FormGroup, Validators } from '@angular/forms';
import { ClrModal, ClrWizard } from '@clr/angular';
import { ClrModal, ClrWizard, ClrWizardPage } from '@clr/angular';
import { RbacService } from 'src/app/data/rbac.service';
import { Scenario } from 'src/app/data/scenario';
import { ScenarioService } from 'src/app/data/scenario.service';
Expand All @@ -22,6 +22,9 @@ import { AlertDetails } from 'src/app/alert/alert';
import { ClrAlertType } from 'src/app/clr-alert-type';
import { VMTasks } from 'src/app/data/vm-tasks';

interface ValidationError {
message: string
}
@Component({
selector: 'scenario-wizard',
templateUrl: './scenario-wizard.component.html',
Expand Down Expand Up @@ -53,6 +56,9 @@ export class ScenarioWizardComponent implements OnInit {

public selectedscenario: Scenario;

public disableFinalizeButton: boolean = false;
public validationErrors: ValidationError[] = [];

get keepaliveRequired() {
const ka = this.scenarioDetails.controls.keepalive_amount;
const ku = this.scenarioDetails.controls.keepalive_unit;
Expand All @@ -71,6 +77,8 @@ export class ScenarioWizardComponent implements OnInit {
@ViewChild('createvmmodal', { static: true }) createVMModal: ClrModal;
@ViewChild('stepsscenario', { static: true })
stepScenario: StepsScenarioComponent;
@ViewChild('taskPage') taskWizardPage: ClrWizardPage;
@ViewChild('finalizePage') finalizeWizardPage: ClrWizardPage;

constructor(
public scenarioService: ScenarioService,
Expand Down Expand Up @@ -147,6 +155,59 @@ export class ScenarioWizardComponent implements OnInit {
});
}
});

this.wizard.currentPageChanged.subscribe(() => {
this.validationErrors = []
if (this.selectedscenario.vm_tasks.length > 0) {
this.validateTaskDefinitions()
}
this.disableFinalizeButton = !(this.validationErrors.length == 0)
});
}

validateTaskDefinitions() {
this.taskWizardPage.hasError = false
this.validateVMsExist();
this.validateNoDuplicateNames();
this.validateAllFieldsHaveValues()
}


private validateVMsExist() {
const vmNames = this.selectedscenario.virtualmachines.map(vm => Object.keys(vm)).reduce((acc, val) => acc.concat(val), []);
const taskVmNames = this.selectedscenario.vm_tasks.map(vmTask => vmTask.vm_name);
taskVmNames.forEach((name) => {
if (!vmNames.includes(name)) {
this.taskWizardPage.hasError = true;
this.validationErrors.push({ message: "One or more Tasks reference a Virtual Machnine Name, that does not exist" });
}
});
}

private validateNoDuplicateNames() {
this.selectedscenario.vm_tasks.forEach(vmTask => {
let tmpArr = [];
vmTask.tasks.forEach(task => {
const taskName = task.name;
if (tmpArr.indexOf(taskName) < 0) {
tmpArr.push(taskName);
} else {
this.taskWizardPage.hasError = true;
this.validationErrors.push({ message: "Task " + vmTask.vm_name + ": " + taskName + " is a Duplicate" });
}
});
});
}

private validateAllFieldsHaveValues() {
this.selectedscenario.vm_tasks.forEach(vmTask => {
vmTask.tasks.forEach((task) => {
if (task.name.length == 0 || task.command.length == 0 || task.description.length == 0 || task.return_type.length == 0) {
this.taskWizardPage.hasError = true;
this.validationErrors.push({ message: "Task " + vmTask.vm_name + ": " + task.name + " is missing required information" });
}
})
})
}

open(wizardMode: 'create' | 'edit', scenario?: Scenario) {
Expand Down Expand Up @@ -296,31 +357,31 @@ export class ScenarioWizardComponent implements OnInit {
}
addVMSet() {
this.selectedscenario.virtualmachines.push({});
this.updateSelectedScenarioRef()
this.updateSelectedScenarioRef();
}
addVM() {
this.selectedScenarioHasVM();
this.selectedscenario.virtualmachines[this.newvmindex][
this.vmform.controls.vm_name.value
] = this.vmform.controls.vm_template.value;
this.createVMModal.close();
this.updateSelectedScenarioRef()
this.updateSelectedScenarioRef();
}

deleteVMSet(i: number) {
this.deletingVMSetIndex = i;
this.deleteVMSetModal.open();
this.updateSelectedScenarioRef()
this.updateSelectedScenarioRef();
}

public deleteVM(setIndex: number, key: string) {
delete this.selectedscenario.virtualmachines[setIndex][key];
this.updateSelectedScenarioRef()
this.updateSelectedScenarioRef();
}
doDeleteVMSet() {
this.selectedscenario.virtualmachines.splice(this.deletingVMSetIndex, 1);
this.deleteVMSetModal.close();
this.updateSelectedScenarioRef()
this.updateSelectedScenarioRef();
}
public openCreateVM(i: number) {
this.vmform.reset();
Expand Down Expand Up @@ -400,10 +461,10 @@ export class ScenarioWizardComponent implements OnInit {
}

updateSelectedScenarioRef() {
this.selectedscenario = {...this.selectedscenario} // Force an Update on Child Components using the selectedscenario as Input
this.selectedscenario = { ...this.selectedscenario }; // Force an Update on Child Components using the selectedscenario as Input
}

replaceVmTasks(vmTasks: VMTasks[]) {
this.selectedscenario.vm_tasks = vmTasks
this.selectedscenario.vm_tasks = vmTasks;
}
}
2 changes: 0 additions & 2 deletions src/app/scenario/task-form/task-form.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@
<label>Command</label>
<app-code-with-syntax-highlighting
[language]="supportedLanguages.BASH"
[readonly]="readonly"
[height]="'2rem'"
[width]="'90%'"
[outline]="'none'"
Expand Down Expand Up @@ -85,7 +84,6 @@
<label>Regex to match</label>
<app-code-with-syntax-highlighting
[language]="supportedLanguages.REGEX"
[readonly]="readonly"
[height]="'2rem'"
[width]="'90%'"
[outline]="'none'"
Expand Down
9 changes: 2 additions & 7 deletions src/app/scenario/task-form/task-form.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,6 @@ export class TaskFormComponent implements OnInit {

@Input() editTask: EditTask;

@Input() readonly = false;

@Output() taskChanged = new EventEmitter<EditTask>();

supportedLanguages = supportedLanguages;
Expand All @@ -40,12 +38,10 @@ export class TaskFormComponent implements OnInit {
taskCommand: new FormControl(this.editTask.command, [
Validators.required,
]),
taskExpectedOutput: new FormControl(this.editTask.expected_output_value, [
Validators.required,
]),
taskExpectedOutput: new FormControl(this.editTask.expected_output_value, []),
taskExpectedReurncode: new FormControl(
this.editTask.expected_return_code,
[Validators.required]
[]
),
taskReturnType: new FormControl(ReturnType[this.editTask.return_type], [
Validators.required,
Expand Down Expand Up @@ -77,7 +73,6 @@ export class TaskFormComponent implements OnInit {
}
this.previousReturnType = newValue;
});
if (this.readonly) this.taskForm.disable()
}

private buildEditTaskFromFormData(): EditTask {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
<div class="container">
<div class="clr-row">
<!-- <div class="clr-col-6"></div> -->
<div class="clr-col-5">
<h6><b>Node</b></h6>
</div>
Expand All @@ -10,7 +9,6 @@ <h6><b>Node</b></h6>
</div>

<div class="clr-row">
<!-- <div class="clr-col-6"></div> -->
<div class="clr-col-5">
<h6><b>Name</b></h6>
</div>
Expand All @@ -20,7 +18,6 @@ <h6><b>Name</b></h6>
</div>

<div class="clr-row">
<!-- <div class="clr-col-6"></div> -->
<div class="clr-col-5">
<h6><b>Description</b></h6>
</div>
Expand All @@ -30,7 +27,6 @@ <h6><b>Description</b></h6>
</div>

<div class="clr-row">
<!-- <div class="clr-col-6"></div> -->
<div class="clr-col-5">
<h6><b>Command</b></h6>
</div>
Expand All @@ -48,7 +44,6 @@ <h6><b>Command</b></h6>
</div>

<div class="clr-row">
<!-- <div class="clr-col-6"></div> -->
<div class="clr-col-5">
<h6><b>Return Type</b></h6>
</div>
Expand All @@ -60,7 +55,6 @@ <h6><b>Return Type</b></h6>
class="clr-row"
*ngIf="isOfReturnType(['Return Text', 'Return Code and Text'])"
>
<!-- <div class="clr-col-6"></div> -->
<div class="clr-col-5">
<h6><b>Expected Output</b></h6>
</div>
Expand All @@ -70,7 +64,6 @@ <h6><b>Expected Output</b></h6>
</div>

<div class="clr-row" *ngIf="isOfReturnType(['Match Regex'])">
<!-- <div class="clr-col-6"></div> -->
<div class="clr-col-5">
<h6><b>Regex to match</b></h6>
</div>
Expand All @@ -91,7 +84,6 @@ <h6><b>Regex to match</b></h6>
class="clr-row"
*ngIf="isOfReturnType(['Return Code', 'Return Code and Text'])"
>
<!-- <div class="clr-col-6"></div> -->
<div class="clr-col-5">
<h6><b>Return Code</b></h6>
</div>
Expand Down

0 comments on commit c3d92e5

Please sign in to comment.