]> git.apps.os.sepia.ceph.com Git - ceph-ci.git/commitdiff
mgr/dashboard: Fixes typeahead regression in the silence matcher
authorStephan Müller <smueller@suse.com>
Fri, 19 Jun 2020 15:22:40 +0000 (17:22 +0200)
committerStephan Müller <smueller@suse.com>
Wed, 1 Jul 2020 09:01:20 +0000 (11:01 +0200)
This regression was introduced by PR #35300 which updated the typeahead
module usage from ngx-bootstrap to ng-bootstrap's typeahead module.

The regression was that the typeahead didn't open on click into the
input field. Another regression was that the suggestions didn't overlap
the modal anymore.

Fixes: https://tracker.ceph.com/issues/46135
Signed-off-by: Stephan Müller <smueller@suse.com>
src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/prometheus/silence-matcher-modal/silence-matcher-modal.component.html
src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/prometheus/silence-matcher-modal/silence-matcher-modal.component.spec.ts
src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/prometheus/silence-matcher-modal/silence-matcher-modal.component.ts

index 853b24520d20d6a1b3083cc708a6c11bc993016c..c41e700431991338f1d0998ddf8ed9f5b90ae3d2 100644 (file)
@@ -38,6 +38,9 @@
                  i18n>Value</label>
           <div class="cd-col-form-input">
             <input id="value"
+                   (focus)="valueFocus.next($any($event).target.value)"
+                   (click)="valueClick.next($any($event).target.value)"
+                   container="body"
                    class="form-control"
                    type="text"
                    [ngbTypeahead]="search"
index dc8117809635ba32dae3c46df224de0de55d46aa..08d408fbac1f7b37c14c5ec2a55b6bd8ae0c1e98 100644 (file)
@@ -4,6 +4,8 @@ import { ReactiveFormsModule } from '@angular/forms';
 import { RouterTestingModule } from '@angular/router/testing';
 
 import { NgbActiveModal, NgbTypeaheadModule } from '@ng-bootstrap/ng-bootstrap';
+import * as _ from 'lodash';
+import { of } from 'rxjs';
 
 import {
   configureTestBed,
@@ -159,4 +161,50 @@ describe('SilenceMatcherModalComponent', () => {
     });
     component.onSubmit();
   });
+
+  describe('typeahead', () => {
+    let equality: { [key: string]: boolean };
+    let expectations: { [key: string]: string[] };
+
+    const search = (s: string) => {
+      Object.keys(expectations).forEach((key) => {
+        formH.setValue('name', key);
+        component.search(of(s)).subscribe((result) => {
+          // Expect won't fail the test inside subscribe
+          equality[key] = _.isEqual(result, expectations[key]);
+        });
+        expect(equality[key]).toBeTruthy();
+      });
+    };
+
+    beforeEach(() => {
+      equality = {
+        alertname: false,
+        instance: false,
+        job: false,
+        severity: false
+      };
+      expectations = {
+        alertname: ['alert0', 'alert1'],
+        instance: ['someInstance'],
+        job: ['someJob'],
+        severity: ['someSeverity']
+      };
+    });
+
+    it('should show all values on name switch', () => {
+      search('');
+    });
+
+    it('should search for "some"', () => {
+      expectations['alertname'] = [];
+      search('some');
+    });
+
+    it('should search for "er"', () => {
+      expectations['instance'] = [];
+      expectations['job'] = [];
+      search('er');
+    });
+  });
 });
index cef04ef55595ef3398f0bbf3b59f8ae30cbebbb7..e0afaa805bd556ea0905b70626256294d6692acb 100644 (file)
@@ -1,10 +1,10 @@
-import { Component, EventEmitter, Output } from '@angular/core';
+import { Component, EventEmitter, Output, ViewChild } from '@angular/core';
 import { FormControl, Validators } from '@angular/forms';
 
-import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap';
+import { NgbActiveModal, NgbTypeahead } from '@ng-bootstrap/ng-bootstrap';
 import * as _ from 'lodash';
-import { Observable } from 'rxjs';
-import { debounceTime, distinctUntilChanged, map } from 'rxjs/operators';
+import { merge, Observable, Subject } from 'rxjs';
+import { debounceTime, distinctUntilChanged, filter, map } from 'rxjs/operators';
 
 import { CdFormBuilder } from '../../../../shared/forms/cd-form-builder';
 import { CdFormGroup } from '../../../../shared/forms/cd-form-group';
@@ -21,6 +21,8 @@ import { PrometheusSilenceMatcherService } from '../../../../shared/services/pro
   styleUrls: ['./silence-matcher-modal.component.scss']
 })
 export class SilenceMatcherModalComponent {
+  @ViewChild(NgbTypeahead, { static: true })
+  typeahead: NgbTypeahead;
   @Output()
   submitAction = new EventEmitter();
 
@@ -31,6 +33,24 @@ export class SilenceMatcherModalComponent {
   possibleValues: string[] = [];
   matcherMatch: AlertmanagerSilenceMatcherMatch = undefined;
 
+  // For typeahead usage
+  valueClick = new Subject<string>();
+  valueFocus = new Subject<string>();
+  search = (text$: Observable<string>) => {
+    return merge(
+      text$.pipe(debounceTime(200), distinctUntilChanged()),
+      this.valueFocus,
+      this.valueClick.pipe(filter(() => !this.typeahead.isPopupOpen()))
+    ).pipe(
+      map((term) =>
+        (term === ''
+          ? this.possibleValues
+          : this.possibleValues.filter((v) => v.toLowerCase().indexOf(term.toLowerCase()) > -1)
+        ).slice(0, 10)
+      )
+    );
+  };
+
   constructor(
     private formBuilder: CdFormBuilder,
     private silenceMatcher: PrometheusSilenceMatcherService,
@@ -43,7 +63,7 @@ export class SilenceMatcherModalComponent {
   private createForm() {
     this.form = this.formBuilder.group({
       name: [null, [Validators.required]],
-      value: [{ value: null, disabled: true }, [Validators.required]],
+      value: [{ value: '', disabled: true }, [Validators.required]],
       isRegex: new FormControl(false)
     });
   }
@@ -78,16 +98,4 @@ export class SilenceMatcherModalComponent {
     this.submitAction.emit(this.form.value);
     this.activeModal.close();
   }
-
-  search = (text$: Observable<string>) => {
-    return text$.pipe(
-      debounceTime(200),
-      distinctUntilChanged(),
-      map((term) =>
-        this.possibleValues
-          .filter((v) => v.toLowerCase().indexOf(term.toLowerCase()) > -1)
-          .slice(0, 10)
-      )
-    );
-  };
 }