Browse Source

Redesign of service check form; first draft for service check editor (WIP)

Christian Kahlau 2 years ago
parent
commit
0164d2ce98
25 changed files with 339 additions and 52 deletions
  1. 10 0
      ng/src/app/app.module.ts
  2. 11 0
      ng/src/app/components/service-check-editor/service-check-adapter/service-check-adapter.component.html
  3. 0 0
      ng/src/app/components/service-check-editor/service-check-adapter/service-check-adapter.component.scss
  4. 23 0
      ng/src/app/components/service-check-editor/service-check-adapter/service-check-adapter.component.spec.ts
  5. 30 0
      ng/src/app/components/service-check-editor/service-check-adapter/service-check-adapter.component.ts
  6. 6 0
      ng/src/app/components/service-check-editor/service-check-button-controls/service-check-button-controls.component.html
  7. 0 0
      ng/src/app/components/service-check-editor/service-check-button-controls/service-check-button-controls.component.scss
  8. 23 0
      ng/src/app/components/service-check-editor/service-check-button-controls/service-check-button-controls.component.spec.ts
  9. 13 0
      ng/src/app/components/service-check-editor/service-check-button-controls/service-check-button-controls.component.ts
  10. 18 0
      ng/src/app/components/service-check-editor/service-check-conjunction/service-check-conjunction.component.html
  11. 0 0
      ng/src/app/components/service-check-editor/service-check-conjunction/service-check-conjunction.component.scss
  12. 23 0
      ng/src/app/components/service-check-editor/service-check-conjunction/service-check-conjunction.component.spec.ts
  13. 10 0
      ng/src/app/components/service-check-editor/service-check-conjunction/service-check-conjunction.component.ts
  14. 18 0
      ng/src/app/components/service-check-editor/service-check-disjunction/service-check-disjunction.component.html
  15. 0 0
      ng/src/app/components/service-check-editor/service-check-disjunction/service-check-disjunction.component.scss
  16. 23 0
      ng/src/app/components/service-check-editor/service-check-disjunction/service-check-disjunction.component.spec.ts
  17. 10 0
      ng/src/app/components/service-check-editor/service-check-disjunction/service-check-disjunction.component.ts
  18. 1 0
      ng/src/app/components/service-check-editor/service-check-string/service-check-string.component.html
  19. 0 0
      ng/src/app/components/service-check-editor/service-check-string/service-check-string.component.scss
  20. 23 0
      ng/src/app/components/service-check-editor/service-check-string/service-check-string.component.spec.ts
  21. 10 0
      ng/src/app/components/service-check-editor/service-check-string/service-check-string.component.ts
  22. 73 47
      ng/src/app/components/service-check-form/service-check-form.component.html
  23. 0 4
      ng/src/app/components/service-check-form/service-check-form.component.scss
  24. 1 1
      ng/src/app/pages/admin-panel/admin-panel.component.html
  25. 13 0
      ng/src/styles.scss

+ 10 - 0
ng/src/app/app.module.ts

@@ -12,6 +12,11 @@ import { AdminPanelComponent } from './pages/admin-panel/admin-panel.component';
 import { HeaderComponent } from './components/header/header.component';
 import { ServerDataChartComponent } from './components/server-data-chart/server-data-chart.component';
 import { ServerMetricsWidgetComponent } from './components/server-metrics-widget/server-metrics-widget.component';
+import { ServiceCheckAdapterComponent } from './components/service-check-editor/service-check-adapter/service-check-adapter.component';
+import { ServiceCheckButtonControlsComponent } from './components/service-check-editor/service-check-button-controls/service-check-button-controls.component';
+import { ServiceCheckConjunctionComponent } from './components/service-check-editor/service-check-conjunction/service-check-conjunction.component';
+import { ServiceCheckDisjunctionComponent } from './components/service-check-editor/service-check-disjunction/service-check-disjunction.component';
+import { ServiceCheckStringComponent } from './components/service-check-editor/service-check-string/service-check-string.component';
 import { ServiceCheckFormComponent } from './components/service-check-form/service-check-form.component';
 import { ServiceChecksWidgetComponent } from './components/service-checks-widget/service-checks-widget.component';
 import { StatusTimelineWidgetComponent } from './components/status-timeline-widget/status-timeline-widget.component';
@@ -36,8 +41,13 @@ import { StatusColorPipe } from './pipes/status-color.pipe';
     ServerDataChartComponent,
     ServerDataPageComponent,
     ServerMetricsWidgetComponent,
+    ServiceCheckAdapterComponent,
+    ServiceCheckButtonControlsComponent,
+    ServiceCheckConjunctionComponent,
     ServiceCheckDetailPageComponent,
+    ServiceCheckDisjunctionComponent,
     ServiceCheckFormComponent,
+    ServiceCheckStringComponent,
     ServiceChecksWidgetComponent,
     StatusColorPipe,
     StatusTimelineWidgetComponent

+ 11 - 0
ng/src/app/components/service-check-editor/service-check-adapter/service-check-adapter.component.html

@@ -0,0 +1,11 @@
+<ng-container *ngIf="stringModel !== undefined; else complexModel">
+  <app-service-check-string [model]="stringModel"></app-service-check-string>
+</ng-container>
+<ng-template #complexModel>
+  <ng-container *ngIf="conjunction; else disjunctModel">
+    <app-service-check-conjunction [model]="conjunction"></app-service-check-conjunction>
+  </ng-container>
+  <ng-template #disjunctModel>
+    <app-service-check-disjunction [model]="disjunction"></app-service-check-disjunction>
+  </ng-template>
+</ng-template>

+ 0 - 0
ng/src/app/components/service-check-editor/service-check-adapter/service-check-adapter.component.scss


+ 23 - 0
ng/src/app/components/service-check-editor/service-check-adapter/service-check-adapter.component.spec.ts

@@ -0,0 +1,23 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { ServiceCheckAdapterComponent } from './service-check-adapter.component';
+
+describe('ServiceCheckAdapterComponent', () => {
+  let component: ServiceCheckAdapterComponent;
+  let fixture: ComponentFixture<ServiceCheckAdapterComponent>;
+
+  beforeEach(async () => {
+    await TestBed.configureTestingModule({
+      declarations: [ ServiceCheckAdapterComponent ]
+    })
+    .compileComponents();
+
+    fixture = TestBed.createComponent(ServiceCheckAdapterComponent);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+  });
+
+  it('should create', () => {
+    expect(component).toBeTruthy();
+  });
+});

+ 30 - 0
ng/src/app/components/service-check-editor/service-check-adapter/service-check-adapter.component.ts

@@ -0,0 +1,30 @@
+import { Component, Input } from '@angular/core';
+
+@Component({
+  selector: 'app-service-check-adapter',
+  templateUrl: './service-check-adapter.component.html',
+  styleUrls: ['./service-check-adapter.component.scss']
+})
+export class ServiceCheckAdapterComponent {
+  @Input() set model(model: string | CheckDisjunction | CheckConjunction) {
+    if (typeof model === 'string') {
+      this.stringModel = model;
+    } else {
+      if (Object.keys(model).includes('and')) {
+        this.conjunction = model as CheckConjunction;
+      } else {
+        this.disjunction = model as CheckDisjunction;
+      }
+    }
+
+    this._model = model;
+  }
+  public get model() {
+    return this._model;
+  }
+
+  private _model!: string | CheckDisjunction | CheckConjunction;
+  public stringModel?: string;
+  public disjunction?: CheckDisjunction;
+  public conjunction?: CheckConjunction;
+}

+ 6 - 0
ng/src/app/components/service-check-editor/service-check-button-controls/service-check-button-controls.component.html

@@ -0,0 +1,6 @@
+<label class="col-form-label"><fa-icon [icon]="fa.plus" class="pe-2"></fa-icon></label>
+<div class="btn-group">
+  <button type="button" class="btn btn-sm bd-blue-100" (click)="create.emit([])">OR</button>
+  <button type="button" class="btn btn-sm bd-red-200" (click)="create.emit({ and: [] })">AND</button>
+  <button type="button" class="btn btn-sm btn-outline-primary" (click)="create.emit('')"><fa-icon [icon]="fa.terminal"></fa-icon>Expression</button>
+</div>

+ 0 - 0
ng/src/app/components/service-check-editor/service-check-button-controls/service-check-button-controls.component.scss


+ 23 - 0
ng/src/app/components/service-check-editor/service-check-button-controls/service-check-button-controls.component.spec.ts

@@ -0,0 +1,23 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { ServiceCheckButtonControlsComponent } from './service-check-button-controls.component';
+
+describe('ServiceCheckButtonControlsComponent', () => {
+  let component: ServiceCheckButtonControlsComponent;
+  let fixture: ComponentFixture<ServiceCheckButtonControlsComponent>;
+
+  beforeEach(async () => {
+    await TestBed.configureTestingModule({
+      declarations: [ ServiceCheckButtonControlsComponent ]
+    })
+    .compileComponents();
+
+    fixture = TestBed.createComponent(ServiceCheckButtonControlsComponent);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+  });
+
+  it('should create', () => {
+    expect(component).toBeTruthy();
+  });
+});

+ 13 - 0
ng/src/app/components/service-check-editor/service-check-button-controls/service-check-button-controls.component.ts

@@ -0,0 +1,13 @@
+import { Component, EventEmitter, Output } from '@angular/core';
+import { faPlus, faTerminal } from '@fortawesome/free-solid-svg-icons';
+
+@Component({
+  selector: 'app-service-check-button-controls',
+  templateUrl: './service-check-button-controls.component.html',
+  styleUrls: ['./service-check-button-controls.component.scss']
+})
+export class ServiceCheckButtonControlsComponent {
+  @Output() create = new EventEmitter<CheckConjunction | CheckDisjunction | string>();
+
+  public fa = { plus: faPlus, terminal: faTerminal };
+}

+ 18 - 0
ng/src/app/components/service-check-editor/service-check-conjunction/service-check-conjunction.component.html

@@ -0,0 +1,18 @@
+<table *ngIf="model?.and" class="check-conjunction border w-100">
+  <colgroup>
+    <col width="20" />
+    <col width="*" />
+  </colgroup>
+  <tr>
+    <td [attr.rowspan]="(model?.and?.length || 1) + 1" class="bg-max label-upright-vertical">AND</td>
+    <td *ngIf="model?.and?.length" class="ps-2"><app-service-check-adapter [model]="model?.and?.[0] ?? ''"></app-service-check-adapter></td>
+  </tr>
+  <tr *ngFor="let check of model?.and | slice : 1">
+    <td class="ps-2"><app-service-check-adapter [model]="check"></app-service-check-adapter></td>
+  </tr>
+  <tr>
+    <td class="ps-2">
+      <app-service-check-button-controls (create)="model?.and?.push($event)"></app-service-check-button-controls>
+    </td>
+  </tr>
+</table>

+ 0 - 0
ng/src/app/components/service-check-editor/service-check-conjunction/service-check-conjunction.component.scss


+ 23 - 0
ng/src/app/components/service-check-editor/service-check-conjunction/service-check-conjunction.component.spec.ts

@@ -0,0 +1,23 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { ServiceCheckConjunctionComponent } from './service-check-conjunction.component';
+
+describe('ServiceCheckConjunctionComponent', () => {
+  let component: ServiceCheckConjunctionComponent;
+  let fixture: ComponentFixture<ServiceCheckConjunctionComponent>;
+
+  beforeEach(async () => {
+    await TestBed.configureTestingModule({
+      declarations: [ ServiceCheckConjunctionComponent ]
+    })
+    .compileComponents();
+
+    fixture = TestBed.createComponent(ServiceCheckConjunctionComponent);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+  });
+
+  it('should create', () => {
+    expect(component).toBeTruthy();
+  });
+});

+ 10 - 0
ng/src/app/components/service-check-editor/service-check-conjunction/service-check-conjunction.component.ts

@@ -0,0 +1,10 @@
+import { Component, Input } from '@angular/core';
+
+@Component({
+  selector: 'app-service-check-conjunction',
+  templateUrl: './service-check-conjunction.component.html',
+  styleUrls: ['./service-check-conjunction.component.scss']
+})
+export class ServiceCheckConjunctionComponent {
+  @Input() model?: CheckConjunction;
+}

+ 18 - 0
ng/src/app/components/service-check-editor/service-check-disjunction/service-check-disjunction.component.html

@@ -0,0 +1,18 @@
+<table *ngIf="model" class="check-disjunction border w-100">
+  <colgroup>
+    <col width="20" />
+    <col width="*" />
+  </colgroup>
+  <tr>
+    <td [attr.rowspan]="(model.length || 1) + 1" class="bg-peak label-upright-vertical">OR</td>
+    <td *ngIf="model.length" class="ps-2"><app-service-check-adapter [model]="model[0]"></app-service-check-adapter></td>
+  </tr>
+  <tr *ngFor="let check of model | slice : 1">
+    <td class="ps-2"><app-service-check-adapter [model]="check"></app-service-check-adapter></td>
+  </tr>
+  <tr>
+    <td class="ps-2">
+      <app-service-check-button-controls (create)="model.push($event)"></app-service-check-button-controls>
+    </td>
+  </tr>
+</table>

+ 0 - 0
ng/src/app/components/service-check-editor/service-check-disjunction/service-check-disjunction.component.scss


+ 23 - 0
ng/src/app/components/service-check-editor/service-check-disjunction/service-check-disjunction.component.spec.ts

@@ -0,0 +1,23 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { ServiceCheckDisjunctionComponent } from './service-check-disjunction.component';
+
+describe('ServiceCheckDisjunctionComponent', () => {
+  let component: ServiceCheckDisjunctionComponent;
+  let fixture: ComponentFixture<ServiceCheckDisjunctionComponent>;
+
+  beforeEach(async () => {
+    await TestBed.configureTestingModule({
+      declarations: [ ServiceCheckDisjunctionComponent ]
+    })
+    .compileComponents();
+
+    fixture = TestBed.createComponent(ServiceCheckDisjunctionComponent);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+  });
+
+  it('should create', () => {
+    expect(component).toBeTruthy();
+  });
+});

+ 10 - 0
ng/src/app/components/service-check-editor/service-check-disjunction/service-check-disjunction.component.ts

@@ -0,0 +1,10 @@
+import { Component, Input } from '@angular/core';
+
+@Component({
+  selector: 'app-service-check-disjunction',
+  templateUrl: './service-check-disjunction.component.html',
+  styleUrls: ['./service-check-disjunction.component.scss']
+})
+export class ServiceCheckDisjunctionComponent {
+  @Input() model?: CheckDisjunction;
+}

+ 1 - 0
ng/src/app/components/service-check-editor/service-check-string/service-check-string.component.html

@@ -0,0 +1 @@
+<input type="text" class="border-0 form-control w-100" [(ngModel)]="model" />

+ 0 - 0
ng/src/app/components/service-check-editor/service-check-string/service-check-string.component.scss


+ 23 - 0
ng/src/app/components/service-check-editor/service-check-string/service-check-string.component.spec.ts

@@ -0,0 +1,23 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { ServiceCheckStringComponent } from './service-check-string.component';
+
+describe('ServiceCheckStringComponent', () => {
+  let component: ServiceCheckStringComponent;
+  let fixture: ComponentFixture<ServiceCheckStringComponent>;
+
+  beforeEach(async () => {
+    await TestBed.configureTestingModule({
+      declarations: [ ServiceCheckStringComponent ]
+    })
+    .compileComponents();
+
+    fixture = TestBed.createComponent(ServiceCheckStringComponent);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+  });
+
+  it('should create', () => {
+    expect(component).toBeTruthy();
+  });
+});

+ 10 - 0
ng/src/app/components/service-check-editor/service-check-string/service-check-string.component.ts

@@ -0,0 +1,10 @@
+import { Component, Input } from '@angular/core';
+
+@Component({
+  selector: 'app-service-check-string',
+  templateUrl: './service-check-string.component.html',
+  styleUrls: ['./service-check-string.component.scss']
+})
+export class ServiceCheckStringComponent {
+  @Input() model?: string;
+}

+ 73 - 47
ng/src/app/components/service-check-form/service-check-form.component.html

@@ -1,61 +1,87 @@
-<div [formGroup]="serviceCheckForm" class="row form-row-service-check position-relative">
-  <div class="col-7">
-    <div class="row mb-2">
-      <label [for]="'Title_' + serviceCheck.id" class="col-sm-3 col-form-label">Title</label>
-      <div class="col-sm-9">
-        <input type="text" formControlName="title" class="form-control" [id]="'Title_' + serviceCheck.id" />
-      </div>
-    </div>
-    <div class="row mb-2">
-      <label class="col-sm-3 form-check-label" [for]="'Active_' + serviceCheck.id">Active</label>
-      <div class="col-sm-9">
-        <input class="form-check-input" formControlName="active" type="checkbox" value="" [id]="'Active_' + serviceCheck.id" />
+<div [formGroup]="serviceCheckForm">
+  <div class="row">
+    <div class="col-8">
+      <div class="row mb-2">
+        <label class="col-3 col-form-label">Title</label>
+        <div class="col-9">
+          <input type="text" formControlName="title" class="form-control" />
+        </div>
       </div>
     </div>
-    <div class="row mb-2">
-      <label [for]="'Interval_' + serviceCheck.id" class="col-sm-3 col-form-label">Interval (secs)</label>
-      <div class="col-sm-9">
-        <input type="number" step="10" formControlName="interval" class="form-control" [id]="'Interval_' + serviceCheck.id" />
+    <div class="col-4 h-100 overflow-auto">
+      <div class="row mb-2 mt-2">
+        <label class="form-check-label text-end">
+          <input class="form-check-input" formControlName="active" type="checkbox" value="" />
+          Active
+        </label>
       </div>
     </div>
-    <div class="row mb-2">
-      <label [for]="'Timeout_' + serviceCheck.id" class="col-sm-3 col-form-label">Timeout (ms)</label>
-      <div class="col-sm-9">
-        <input type="number" step="100" formControlName="timeout" class="form-control" [id]="'Timeout_' + serviceCheck.id" />
+  </div>
+  <div class="row border-top">
+    <div class="col-12">
+      <div class="row mb-2 mt-2">
+        <label class="col-2 col-form-label">Url</label>
+        <div class="col-10">
+          <input type="text" formControlName="url" class="form-control" />
+        </div>
       </div>
     </div>
-    <div class="row mb-2">
-      <label [for]="'Url_' + serviceCheck.id" class="col-sm-3 col-form-label">Url</label>
-      <div class="col-sm-9">
-        <input type="text" formControlName="url" class="form-control" [id]="'Url_' + serviceCheck.id" />
+  </div>
+  <div class="row border-top">
+    <label class="col-lg-2 col-form-label mt-2">Settings</label>
+    <div class="col-lg-10">
+      <div class="row">
+        <div class="col-lg-6">
+          <div class="row mb-2 mt-2">
+            <label class="col-2 col-lg-5 col-form-label">Interval:</label>
+            <div class="col-10 col-lg-7">
+              <div class="input-group">
+                <input type="number" step="10" formControlName="interval" class="form-control" />
+                <span class="input-group-text">s</span>
+              </div>
+            </div>
+          </div>
+        </div>
+        <div class="col-lg-6">
+          <div class="row mb-2 mt-2">
+            <label class="col-2 col-lg-5 col-form-label">Timeout:</label>
+            <div class="col-10 col-lg-7">
+              <div class="input-group">
+                <input type="number" step="100" formControlName="timeout" class="form-control" />
+                <span class="input-group-text">ms</span>
+              </div>
+            </div>
+          </div>
+        </div>
       </div>
     </div>
-    <div class="row mb-2">
-      <label [for]="'Notify_' + serviceCheck.id" class="col-sm-3 col-form-label">Notify</label>
-      <div class="col-sm-9">
-        <input type="checkbox" formControlName="notify" class="form-check-input" [id]="'Notify_' + serviceCheck.id" />
+  </div>
+  <div class="row border-top">
+    <label class="col-lg-2 col-form-label mt-2">Notification</label>
+    <div class="col-lg-10">
+      <div class="row mb-2 mt-2">
+        <label class="col-sm-3 col-form-label">
+          <input type="checkbox" formControlName="notify" class="form-check-input" />
+          Notify
+        </label>
+
+        <div class="col-sm-9">
+          <div class="row">
+            <label class="col-4 col-form-label text-end">Threshold:</label>
+            <div class="col-8">
+              <input type="number" formControlName="notifyThreshold" class="form-control" />
+            </div>
+          </div>
+        </div>
       </div>
     </div>
-    <div class="row mb-2">
-      <label [for]="'NotifyThreshold_' + serviceCheck.id" class="col-sm-3 col-form-label">Notify Threshold</label>
-      <div class="col-sm-9">
-        <input type="number" formControlName="notifyThreshold" class="form-control" [id]="'NotifyThreshold_' + serviceCheck.id" />
+  </div>
+  <div class="row border-top">
+    <div class="col-12">
+      <label class="mt-2">Check</label>
+      <div class="mt-2 position-relative">
+        <app-service-check-disjunction [model]="serviceCheck.checks"></app-service-check-disjunction>
       </div>
     </div>
   </div>
-  <div class="col-5 h-100 overflow-auto">
-    <ul formArrayName="checks" class="list-group">
-      <li class="list-group-item">
-        <div class="btn w-100" title="Add new search pattern" (click)="addPattern()"><fa-icon [icon]="fa.plus"></fa-icon></div>
-      </li>
-      <li *ngFor="let checkEntry of checks.controls; let i = index" class="list-group-item">
-        <div class="flex-row d-flex">
-          <input #checkInput type="text" class="flex-grow-1 flex-shrink-1 form-control-plaintext" [formControlName]="i" />
-          <div class="btn flex-grow-0 flex-shrink-0" title="Remove search pattern" (click)="removePattern(i)">
-            <fa-icon [icon]="fa.delete"></fa-icon>
-          </div>
-        </div>
-      </li>
-    </ul>
-  </div>
 </div>

+ 0 - 4
ng/src/app/components/service-check-form/service-check-form.component.scss

@@ -1,4 +0,0 @@
-.form-row-service-check {
-  max-height: 320px;
-  height: 320px;
-}

+ 1 - 1
ng/src/app/pages/admin-panel/admin-panel.component.html

@@ -18,7 +18,7 @@
           <ngb-accordion #acc="ngbAccordion" className="flex-fill">
             <ngb-panel *ngFor="let serviceCheck of serviceChecks; let i = index">
               <ng-template ngbPanelHeader let-opened="opened">
-                <button class="accordion-button" ngbPanelToggle [class.collapsed]="!opened">
+                <button class="accordion-button" ngbPanelToggle [class.collapsed]="!opened" [ngClass]="{ 'bg-primary text-white': opened }">
                   <p class="flex-fill m-0">{{ serviceCheck.title }}</p>
 
                   <fa-icon class="me-1" (click)="saveServiceCheck(i, $event)" *ngIf="opened" [icon]="fa.save"></fa-icon>

+ 13 - 0
ng/src/styles.scss

@@ -31,3 +31,16 @@
 .text-max {
   color: #941320 !important;
 }
+
+.check-disjunction,
+.check-conjunction {
+  .label-upright-vertical {
+    writing-mode: vertical-lr;
+    text-orientation: upright;
+    text-align: center;
+  }
+
+  tr:not(:first-child) {
+    border-top: 1px solid $border-color !important;
+  }
+}