From 069afd02b19726b19fa669850630739a3fa1ceb7 Mon Sep 17 00:00:00 2001 From: Dragos Date: Tue, 1 Jun 2021 10:55:41 +0300 Subject: [PATCH] TRIX-26 affinity rule editor also renamed all occurrences of "instance" to "machine" because there were many inconsistencies --- app/.vs/VSWorkspaceState.json | 2 +- app/src/app/app-routing.module.ts | 2 +- app/src/app/app.module.ts | 2 +- .../custom-image-editor.component.html | 2 +- .../custom-image-editor.component.ts | 2 +- .../app/catalog/helpers/catalog.service.ts | 4 +- .../affinity-rule-editor.component.html | 43 ++ .../affinity-rule-editor.component.scss | 7 + .../affinity-rule-editor.component.spec.ts | 25 ++ .../affinity-rule-editor.component.ts | 144 +++++++ .../inline-editor/inline-editor.component.ts | 11 +- .../nav-menu/nav-menu.component.html | 2 +- .../directives/alpha-only.directive.spec.ts | 2 +- .../directives/autofocus.directive.spec.ts | 2 +- .../directives/lazy-load.directive.spec.ts | 2 +- app/src/app/help/help/help.component.ts | 4 +- .../instance-snapshots.component.spec.ts | 25 -- .../instance-tag-editor.component.spec.ts | 25 -- .../helpers/machines.service.spec.ts} | 8 +- .../helpers/machines.service.ts} | 144 +++---- .../helpers/migrations.service.spec.ts | 0 .../helpers/migrations.service.ts | 14 +- .../helpers/snapshots.service.spec.ts | 0 .../helpers/snapshots.service.ts | 26 +- .../machine-history.component.html} | 0 .../machine-history.component.scss} | 0 .../machine-history.component.spec.ts | 25 ++ .../machine-history.component.ts} | 18 +- .../machine-info/machine-info.component.html} | 14 +- .../machine-info/machine-info.component.scss} | 0 .../machine-info.component.spec.ts} | 12 +- .../machine-info/machine-info.component.ts} | 36 +- .../machine-networks.component.html} | 8 +- .../machine-networks.component.scss} | 0 .../machine-networks.component.spec.ts} | 12 +- .../machine-networks.component.ts} | 80 ++-- .../machine-security.component.html} | 6 +- .../machine-security.component.scss} | 0 .../machine-security.component.spec.ts | 25 ++ .../machine-security.component.ts} | 20 +- .../machine-snapshots.component.html} | 0 .../machine-snapshots.component.scss} | 0 .../machine-snapshots.component.spec.ts} | 12 +- .../machine-snapshots.component.ts} | 56 +-- .../machine-tag-editor.component.html} | 0 .../machine-tag-editor.component.scss} | 0 .../machine-tag-editor.component.spec.ts} | 12 +- .../machine-tag-editor.component.ts} | 30 +- .../machine-wizard.component.html} | 53 +-- .../machine-wizard.component.scss} | 0 .../machine-wizard.component.spec.ts} | 12 +- .../machine-wizard.component.ts} | 135 +++--- .../machines.component.html} | 198 ++++----- .../machines.component.scss} | 0 .../machines.component.spec.ts} | 12 +- .../machines.component.ts} | 384 +++++++++--------- .../machines.module.ts} | 54 +-- .../models/machine-disk.ts} | 2 +- .../models/machine-volume.ts} | 2 +- .../models/machine.ts} | 14 +- .../app/{instances => machines}/models/nic.ts | 0 .../models/snapshot.ts | 0 .../package-selector.component.html | 4 +- .../package-selector.component.scss | 0 .../package-selector.component.spec.ts | 0 .../package-selector.component.ts | 4 +- .../firewall-editor.component.html | 4 +- .../firewall-editor.component.ts | 10 +- .../firewall-rule-editor.component.html | 2 +- .../firewall-rule-editor.component.ts | 10 +- .../firewall-rules.component.html | 6 +- .../firewall-rules.component.ts | 10 +- .../networking/helpers/firewall.service.ts | 4 +- .../networking/helpers/networking.service.ts | 36 +- .../machines.component.html} | 0 .../machines.component.scss} | 0 .../machines.component.spec.ts} | 2 +- .../machines.component.ts} | 4 +- app/src/app/pipes/file-size.pipe.spec.ts | 2 +- app/src/app/shared.module.ts | 3 + .../app/volumes/helpers/volumes.service.ts | 4 +- app/src/app/volumes/volumes.component.ts | 10 +- app/src/assets/i18n/en.json | 4 +- .../i18n/{dashboard => machines}/en.json | 15 +- app/src/styles/_virtualScroll.scss | 6 +- 85 files changed, 1053 insertions(+), 817 deletions(-) create mode 100644 app/src/app/components/affinity-rule-editor/affinity-rule-editor.component.html create mode 100644 app/src/app/components/affinity-rule-editor/affinity-rule-editor.component.scss create mode 100644 app/src/app/components/affinity-rule-editor/affinity-rule-editor.component.spec.ts create mode 100644 app/src/app/components/affinity-rule-editor/affinity-rule-editor.component.ts delete mode 100644 app/src/app/instances/instance-snapshots/instance-snapshots.component.spec.ts delete mode 100644 app/src/app/instances/instance-tag-editor/instance-tag-editor.component.spec.ts rename app/src/app/{instances/helpers/instances.service.spec.ts => machines/helpers/machines.service.spec.ts} (53%) rename app/src/app/{instances/helpers/instances.service.ts => machines/helpers/machines.service.ts} (58%) rename app/src/app/{instances => machines}/helpers/migrations.service.spec.ts (100%) rename app/src/app/{instances => machines}/helpers/migrations.service.ts (73%) rename app/src/app/{instances => machines}/helpers/snapshots.service.spec.ts (100%) rename app/src/app/{instances => machines}/helpers/snapshots.service.ts (64%) rename app/src/app/{instances/instance-history/instance-history.component.html => machines/machine-history/machine-history.component.html} (100%) rename app/src/app/{instances/instance-history/instance-history.component.scss => machines/machine-history/machine-history.component.scss} (100%) create mode 100644 app/src/app/machines/machine-history/machine-history.component.spec.ts rename app/src/app/{instances/instance-history/instance-history.component.ts => machines/machine-history/machine-history.component.ts} (79%) rename app/src/app/{instances/instance-info/instance-info.component.html => machines/machine-info/machine-info.component.html} (71%) rename app/src/app/{instances/instance-info/instance-info.component.scss => machines/machine-info/machine-info.component.scss} (100%) rename app/src/app/{instances/instance-info/instance-info.component.spec.ts => machines/machine-info/machine-info.component.spec.ts} (53%) rename app/src/app/{instances/instance-info/instance-info.component.ts => machines/machine-info/machine-info.component.ts} (77%) rename app/src/app/{instances/instance-networks/instance-networks.component.html => machines/machine-networks/machine-networks.component.html} (94%) rename app/src/app/{instances/instance-networks/instance-networks.component.scss => machines/machine-networks/machine-networks.component.scss} (100%) rename app/src/app/{instances/instance-history/instance-history.component.spec.ts => machines/machine-networks/machine-networks.component.spec.ts} (53%) rename app/src/app/{instances/instance-networks/instance-networks.component.ts => machines/machine-networks/machine-networks.component.ts} (75%) rename app/src/app/{instances/instance-security/instance-security.component.html => machines/machine-security/machine-security.component.html} (81%) rename app/src/app/{instances/instance-security/instance-security.component.scss => machines/machine-security/machine-security.component.scss} (100%) create mode 100644 app/src/app/machines/machine-security/machine-security.component.spec.ts rename app/src/app/{instances/instance-security/instance-security.component.ts => machines/machine-security/machine-security.component.ts} (86%) rename app/src/app/{instances/instance-snapshots/instance-snapshots.component.html => machines/machine-snapshots/machine-snapshots.component.html} (100%) rename app/src/app/{instances/instance-snapshots/instance-snapshots.component.scss => machines/machine-snapshots/machine-snapshots.component.scss} (100%) rename app/src/app/{instances/instance-security/instance-security.component.spec.ts => machines/machine-snapshots/machine-snapshots.component.spec.ts} (52%) rename app/src/app/{instances/instance-snapshots/instance-snapshots.component.ts => machines/machine-snapshots/machine-snapshots.component.ts} (80%) rename app/src/app/{instances/instance-tag-editor/instance-tag-editor.component.html => machines/machine-tag-editor/machine-tag-editor.component.html} (100%) rename app/src/app/{instances/instance-tag-editor/instance-tag-editor.component.scss => machines/machine-tag-editor/machine-tag-editor.component.scss} (100%) rename app/src/app/{instances/instance-networks/instance-networks.component.spec.ts => machines/machine-tag-editor/machine-tag-editor.component.spec.ts} (51%) rename app/src/app/{instances/instance-tag-editor/instance-tag-editor.component.ts => machines/machine-tag-editor/machine-tag-editor.component.ts} (79%) rename app/src/app/{instances/instance-wizard/instance-wizard.component.html => machines/machine-wizard/machine-wizard.component.html} (88%) rename app/src/app/{instances/instance-wizard/instance-wizard.component.scss => machines/machine-wizard/machine-wizard.component.scss} (100%) rename app/src/app/{instances/instance-wizard/instance-wizard.component.spec.ts => machines/machine-wizard/machine-wizard.component.spec.ts} (52%) rename app/src/app/{instances/instance-wizard/instance-wizard.component.ts => machines/machine-wizard/machine-wizard.component.ts} (85%) rename app/src/app/{instances/instances.component.html => machines/machines.component.html} (68%) rename app/src/app/{instances/instances.component.scss => machines/machines.component.scss} (100%) rename app/src/app/{instances/instances.component.spec.ts => machines/machines.component.spec.ts} (55%) rename app/src/app/{instances/instances.component.ts => machines/machines.component.ts} (67%) rename app/src/app/{instances/instances.module.ts => machines/machines.module.ts} (55%) rename app/src/app/{instances/models/instance-disk.ts => machines/models/machine-disk.ts} (72%) rename app/src/app/{instances/models/instance-volume.ts => machines/models/machine-volume.ts} (82%) rename app/src/app/{instances/models/instance.ts => machines/models/machine.ts} (72%) rename app/src/app/{instances => machines}/models/nic.ts (100%) rename app/src/app/{instances => machines}/models/snapshot.ts (100%) rename app/src/app/{instances => machines}/package-selector/package-selector.component.html (85%) rename app/src/app/{instances => machines}/package-selector/package-selector.component.scss (100%) rename app/src/app/{instances => machines}/package-selector/package-selector.component.spec.ts (100%) rename app/src/app/{instances => machines}/package-selector/package-selector.component.ts (98%) rename app/src/app/pages/{dashboard/dashboard.component.html => machines/machines.component.html} (100%) rename app/src/app/pages/{dashboard/dashboard.component.scss => machines/machines.component.scss} (100%) rename app/src/app/pages/{dashboard/dashboard.component.spec.ts => machines/machines.component.spec.ts} (90%) rename app/src/app/pages/{dashboard/dashboard.component.ts => machines/machines.component.ts} (69%) rename app/src/assets/i18n/{dashboard => machines}/en.json (96%) diff --git a/app/.vs/VSWorkspaceState.json b/app/.vs/VSWorkspaceState.json index 93ffcca..079caa0 100644 --- a/app/.vs/VSWorkspaceState.json +++ b/app/.vs/VSWorkspaceState.json @@ -11,6 +11,6 @@ "\\src\\assets\\i18n", "\\src\\assets\\i18n\\networking" ], - "SelectedNode": "\\src\\app\\instances\\instances.component.html", + "SelectedNode": "\\src\\app\\instances\\machines.component.html", "PreviewInSolutionExplorer": false } \ No newline at end of file diff --git a/app/src/app/app-routing.module.ts b/app/src/app/app-routing.module.ts index c041396..79e775e 100644 --- a/app/src/app/app-routing.module.ts +++ b/app/src/app/app-routing.module.ts @@ -13,7 +13,7 @@ const appRoutes: Routes = [ }, { path: 'machines', - loadChildren: () => import('./instances/instances.module').then(x => x.InstancesModule), + loadChildren: () => import('./machines/machines.module').then(x => x.MachinesModule), canActivate: [AuthGuardService], canLoad: [AuthGuardService], }, diff --git a/app/src/app/app.module.ts b/app/src/app/app.module.ts index 54e0890..8bcd416 100644 --- a/app/src/app/app.module.ts +++ b/app/src/app/app.module.ts @@ -14,7 +14,7 @@ import { SharedModule } from './shared.module'; import { AppRoutingModule } from './app-routing.module'; import { AppComponent } from './app.component'; -import { DashboardComponent } from './pages/dashboard/dashboard.component'; +import { DashboardComponent } from './pages/machines/machines.component'; import { UnauthorizedComponent } from './pages/unauthorized/unauthorized.component'; import { NotFoundComponent } from './pages/not-found/not-found.component'; import { NavMenuComponent } from './components/nav-menu/nav-menu.component'; diff --git a/app/src/app/catalog/custom-image-editor/custom-image-editor.component.html b/app/src/app/catalog/custom-image-editor/custom-image-editor.component.html index 282bbf2..d7f30d3 100644 --- a/app/src/app/catalog/custom-image-editor/custom-image-editor.component.html +++ b/app/src/app/catalog/custom-image-editor/custom-image-editor.component.html @@ -7,7 +7,7 @@

Create image from machine

-

Fill in the name and version for a new image based on the "{{ instance.name }}" machine

+

Fill in the name and version for a new image based on the "{{ machine.name }}" machine

diff --git a/app/src/app/catalog/custom-image-editor/custom-image-editor.component.ts b/app/src/app/catalog/custom-image-editor/custom-image-editor.component.ts index edf2a95..8041db3 100644 --- a/app/src/app/catalog/custom-image-editor/custom-image-editor.component.ts +++ b/app/src/app/catalog/custom-image-editor/custom-image-editor.component.ts @@ -13,7 +13,7 @@ import { filter, takeUntil } from 'rxjs/operators'; export class CustomImageEditorComponent implements OnInit { @Input() - instance: any; + machine: any; save = new Subject(); editorForm: FormGroup; diff --git a/app/src/app/catalog/helpers/catalog.service.ts b/app/src/app/catalog/helpers/catalog.service.ts index 9066d0d..d3a3b22 100644 --- a/app/src/app/catalog/helpers/catalog.service.ts +++ b/app/src/app/catalog/helpers/catalog.service.ts @@ -129,12 +129,12 @@ export class CatalogService } // ---------------------------------------------------------------------------------------------------------------- - createImage(instanceId: string, name: string, version: string, + createImage(machineId: string, name: string, version: string, description?: string, homepage?: string, eula?: string, acl?: string, tags?: string): Observable { return this.httpClient.post(`/api/my/images`, { - machine: instanceId, + machine: machineId, name, version, description, diff --git a/app/src/app/components/affinity-rule-editor/affinity-rule-editor.component.html b/app/src/app/components/affinity-rule-editor/affinity-rule-editor.component.html new file mode 100644 index 0000000..381178e --- /dev/null +++ b/app/src/app/components/affinity-rule-editor/affinity-rule-editor.component.html @@ -0,0 +1,43 @@ + + +
+
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ + +
+
+
diff --git a/app/src/app/components/affinity-rule-editor/affinity-rule-editor.component.scss b/app/src/app/components/affinity-rule-editor/affinity-rule-editor.component.scss new file mode 100644 index 0000000..bcf57b6 --- /dev/null +++ b/app/src/app/components/affinity-rule-editor/affinity-rule-editor.component.scss @@ -0,0 +1,7 @@ +.form-control +{ + background: #0c1321; + border-color: #00e7ff; + border-radius: 3rem; + color: #ff9c07; +} diff --git a/app/src/app/components/affinity-rule-editor/affinity-rule-editor.component.spec.ts b/app/src/app/components/affinity-rule-editor/affinity-rule-editor.component.spec.ts new file mode 100644 index 0000000..ae2206b --- /dev/null +++ b/app/src/app/components/affinity-rule-editor/affinity-rule-editor.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { AffinityRuleEditorComponent } from './affinity-rule-editor.component'; + +describe('AffinityRuleEditorComponent', () => { + let component: AffinityRuleEditorComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ AffinityRuleEditorComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(AffinityRuleEditorComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/app/src/app/components/affinity-rule-editor/affinity-rule-editor.component.ts b/app/src/app/components/affinity-rule-editor/affinity-rule-editor.component.ts new file mode 100644 index 0000000..da57a0f --- /dev/null +++ b/app/src/app/components/affinity-rule-editor/affinity-rule-editor.component.ts @@ -0,0 +1,144 @@ +import { Component, OnInit, OnDestroy, Input, Output, EventEmitter, ElementRef, HostListener } from '@angular/core'; +import { FormGroup, FormBuilder, Validators, AbstractControl, FormArray } from '@angular/forms'; +import { Subject } from 'rxjs'; +import { takeUntil } from 'rxjs/operators'; + +@Component({ + selector: 'app-affinity-rule-editor', + templateUrl: './affinity-rule-editor.component.html', + styleUrls: ['./affinity-rule-editor.component.scss'] +}) +export class AffinityRuleEditorComponent implements OnInit, OnDestroy +{ + @Input() + disabled: boolean; + + @Output() + saved = new EventEmitter(); + + editorVisible: boolean; + editorForm: FormGroup; + + private destroy$ = new Subject(); + + // -------------------------------------------------------------------------------------------------- + constructor(private readonly elementRef: ElementRef, + private readonly fb: FormBuilder) { } + + // ---------------------------------------------------------------------------------------------------------------- + private createForm() + { + this.editorForm = this.fb.group( + { + strict: [null, Validators.required], + operator: [null, Validators.required], + target: [null, Validators.required], + tagName: [null], + value: [null, Validators.required] + }); + + this.editorForm.get('target').valueChanges + .pipe(takeUntil(this.destroy$)) + .subscribe(target => + { + if (target === 'tagName') + this.editorForm.get('tagName').setValidators(Validators.required); + else + this.editorForm.get('tagName').clearValidators(); + }); + } + + // -------------------------------------------------------------------------------------------------- + showEditor() + { + if (this.disabled) return; + + this.editorVisible = true; + + addEventListener('click', this.onDocumentClick.bind(this)); + } + + // -------------------------------------------------------------------------------------------------- + saveChanges() + { + event.preventDefault(); + event.stopPropagation(); + + this.editorVisible = false; + + this.removeEventListeners(); + + let rule: string; + + if (this.editorForm.get('target').value === 'machine') + rule = `machine${this.editorForm.get('operator').value}${this.editorForm.get('strict').value}${this.editorForm.get('value').value}`; + else + rule = `${this.editorForm.get('tagName').value}${this.editorForm.get('operator').value}${this.editorForm.get('strict').value}${this.editorForm.get('value').value}`; + + this.saved.emit({ + strict: this.editorForm.get('strict').value === '=', + closeTo: this.editorForm.get('operator').value === '=', + targetMachine: this.editorForm.get('target').value === 'machine', + tagName: this.editorForm.get('tagName').value, + value: this.editorForm.get('value').value, + rule + }); + + this.resetForm(); + } + + // -------------------------------------------------------------------------------------------------- + cancelChanges() + { + this.editorVisible = false; + + this.removeEventListeners(); + + this.resetForm(); + } + + // -------------------------------------------------------------------------------------------------- + private resetForm() + { + this.editorForm.get('strict').setValue(null); + this.editorForm.get('operator').setValue(null); + this.editorForm.get('target').setValue(null); + this.editorForm.get('tagName').setValue(null); + this.editorForm.get('value').setValue(null); + } + + // -------------------------------------------------------------------------------------------------- + @HostListener('document:keydown.escape', ['$event']) + escapePressed(event) + { + this.cancelChanges(); + } + + // -------------------------------------------------------------------------------------------------- + protected onDocumentClick(event: MouseEvent) + { + if (!this.elementRef.nativeElement.contains(event.target)) + this.cancelChanges(); + } + + // -------------------------------------------------------------------------------------------------- + private removeEventListeners() + { + removeEventListener('click', this.onDocumentClick); + removeEventListener('document:keydown.escape', this.escapePressed); + } + + // -------------------------------------------------------------------------------------------------- + ngOnInit(): void + { + this.createForm(); + } + + // -------------------------------------------------------------------------------------------------- + ngOnDestroy() + { + this.removeEventListeners(); + + this.destroy$.next(); + } +} diff --git a/app/src/app/components/inline-editor/inline-editor.component.ts b/app/src/app/components/inline-editor/inline-editor.component.ts index a95bf33..27594da 100644 --- a/app/src/app/components/inline-editor/inline-editor.component.ts +++ b/app/src/app/components/inline-editor/inline-editor.component.ts @@ -102,9 +102,8 @@ export class InlineEditorComponent implements OnInit, OnDestroy else this.saved.emit(this.editorForm.get('key').value); - this.editorForm.get('key').setValue(null); - this.editorForm.get('value').setValue(null); - } + this.resetForm(); + } // -------------------------------------------------------------------------------------------------- cancelChanges() @@ -113,6 +112,12 @@ export class InlineEditorComponent implements OnInit, OnDestroy this.removeEventListeners(); + this.resetForm(); + } + + // -------------------------------------------------------------------------------------------------- + private resetForm() + { this.editorForm.get('key').setValue(null); this.editorForm.get('value').setValue(null); } diff --git a/app/src/app/components/nav-menu/nav-menu.component.html b/app/src/app/components/nav-menu/nav-menu.component.html index 302c68f..ea9bc6c 100644 --- a/app/src/app/components/nav-menu/nav-menu.component.html +++ b/app/src/app/components/nav-menu/nav-menu.component.html @@ -3,7 +3,7 @@