From 855f214b29c8ed935c8f4ba0b8a8396692f946a1 Mon Sep 17 00:00:00 2001 From: Patrick Seidensal Date: Wed, 27 Nov 2019 20:34:12 +0000 Subject: [PATCH] mgr/dashboard: move monitoring tabs to a single page with a tab for 'active alerts', 'all alerts' and 'silences'. Due to ambiguity with existing names, `AlertListComponent` has been renamed to `ActiveAlertListComponent`. Introduces `MonitoringListComponent` as first page for monitoring concerns, using path `/monitoring`. Keeps the activated tab open, independent of the way that's used to go back to the previous page, be it the cancel button or submit button or the link on the breadcrumb. Also keeps the active tab open even when the page is reloaded. Fixes: https://tracker.ceph.com/issues/42877 Signed-off-by: Patrick Seidensal --- .../frontend/e2e/cluster/alerts.e2e-spec.ts | 23 --------- .../frontend/e2e/cluster/alerts.po.ts | 5 -- .../frontend/src/app/app-routing.module.ts | 28 +++++------ .../src/app/ceph/cluster/cluster.module.ts | 10 ++-- .../active-alert-list.component.html} | 8 --- .../active-alert-list.component.scss} | 0 .../active-alert-list.component.spec.ts} | 50 +++++++++---------- .../active-alert-list.component.ts} | 13 ++--- .../monitoring-list.component.html | 20 ++++++++ .../monitoring-list.component.scss} | 0 .../monitoring-list.component.spec.ts | 46 +++++++++++++++++ .../monitoring-list.component.ts | 40 +++++++++++++++ .../prometheus-tabs.component.html | 13 ----- .../prometheus-tabs.component.spec.ts | 47 ----------------- .../prometheus-tabs.component.ts | 19 ------- .../silence-form.component.spec.ts | 40 +++++++-------- .../silence-form/silence-form.component.ts | 6 +-- .../silence-list/silence-list.component.html | 2 - .../silence-list.component.spec.ts | 3 +- .../silence-list/silence-list.component.ts | 5 +- .../breadcrumbs/breadcrumbs.component.html | 3 +- .../navigation/navigation.component.html | 11 +--- .../navigation/navigation.component.ts | 4 +- .../table-actions.component.html | 4 +- .../src/app/shared/models/cd-table-action.ts | 2 + 25 files changed, 195 insertions(+), 207 deletions(-) delete mode 100644 src/pybind/mgr/dashboard/frontend/e2e/cluster/alerts.e2e-spec.ts delete mode 100644 src/pybind/mgr/dashboard/frontend/e2e/cluster/alerts.po.ts rename src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/prometheus/{alert-list/alert-list.component.html => active-alert-list/active-alert-list.component.html} (84%) rename src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/prometheus/{alert-list/alert-list.component.scss => active-alert-list/active-alert-list.component.scss} (100%) rename src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/prometheus/{alert-list/alert-list.component.spec.ts => active-alert-list/active-alert-list.component.spec.ts} (69%) rename src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/prometheus/{alert-list/alert-list.component.ts => active-alert-list/active-alert-list.component.ts} (90%) create mode 100644 src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/prometheus/monitoring-list/monitoring-list.component.html rename src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/prometheus/{prometheus-tabs/prometheus-tabs.component.scss => monitoring-list/monitoring-list.component.scss} (100%) create mode 100644 src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/prometheus/monitoring-list/monitoring-list.component.spec.ts create mode 100644 src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/prometheus/monitoring-list/monitoring-list.component.ts delete mode 100644 src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/prometheus/prometheus-tabs/prometheus-tabs.component.html delete mode 100644 src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/prometheus/prometheus-tabs/prometheus-tabs.component.spec.ts delete mode 100644 src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/prometheus/prometheus-tabs/prometheus-tabs.component.ts diff --git a/src/pybind/mgr/dashboard/frontend/e2e/cluster/alerts.e2e-spec.ts b/src/pybind/mgr/dashboard/frontend/e2e/cluster/alerts.e2e-spec.ts deleted file mode 100644 index 51639d2fca7..00000000000 --- a/src/pybind/mgr/dashboard/frontend/e2e/cluster/alerts.e2e-spec.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { AlertsPageHelper } from './alerts.po'; - -describe('Alerts page', () => { - let alerts: AlertsPageHelper; - - beforeAll(() => { - alerts = new AlertsPageHelper(); - }); - - afterEach(async () => { - await AlertsPageHelper.checkConsole(); - }); - - describe('breadcrumb test', () => { - beforeAll(async () => { - await alerts.navigateTo(); - }); - - it('should open and show breadcrumb', async () => { - await alerts.waitTextToBePresent(alerts.getBreadcrumb(), 'Alerts'); - }); - }); -}); diff --git a/src/pybind/mgr/dashboard/frontend/e2e/cluster/alerts.po.ts b/src/pybind/mgr/dashboard/frontend/e2e/cluster/alerts.po.ts deleted file mode 100644 index 8a50662b26d..00000000000 --- a/src/pybind/mgr/dashboard/frontend/e2e/cluster/alerts.po.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { PageHelper } from '../page-helper.po'; - -export class AlertsPageHelper extends PageHelper { - pages = { index: '/#/alerts' }; -} diff --git a/src/pybind/mgr/dashboard/frontend/src/app/app-routing.module.ts b/src/pybind/mgr/dashboard/frontend/src/app/app-routing.module.ts index a483ba78bd6..2913b293dc3 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/app-routing.module.ts +++ b/src/pybind/mgr/dashboard/frontend/src/app/app-routing.module.ts @@ -16,9 +16,8 @@ import { MgrModuleListComponent } from './ceph/cluster/mgr-modules/mgr-module-li import { MonitorComponent } from './ceph/cluster/monitor/monitor.component'; import { OsdFormComponent } from './ceph/cluster/osd/osd-form/osd-form.component'; import { OsdListComponent } from './ceph/cluster/osd/osd-list/osd-list.component'; -import { AlertListComponent } from './ceph/cluster/prometheus/alert-list/alert-list.component'; +import { MonitoringListComponent } from './ceph/cluster/prometheus/monitoring-list/monitoring-list.component'; import { SilenceFormComponent } from './ceph/cluster/prometheus/silence-form/silence-form.component'; -import { SilenceListComponent } from './ceph/cluster/prometheus/silence-list/silence-list.component'; import { ServicesComponent } from './ceph/cluster/services/services.component'; import { DashboardComponent } from './ceph/dashboard/dashboard/dashboard.component'; import { Nfs501Component } from './ceph/nfs/nfs-501/nfs-501.component'; @@ -142,34 +141,31 @@ const routes: Routes = [ data: { breadcrumbs: 'Cluster/Logs' } }, { - path: 'alerts', - component: AlertListComponent, + path: 'monitoring', canActivate: [AuthGuardService], - data: { breadcrumbs: 'Cluster/Alerts' } - }, - { - path: 'silence', - canActivate: [AuthGuardService], - data: { breadcrumbs: 'Cluster/Silences' }, + data: { breadcrumbs: 'Cluster/Monitoring' }, children: [ - { path: '', component: SilenceListComponent }, { - path: URLVerbs.CREATE, + path: '', + component: MonitoringListComponent + }, + { + path: 'silence/' + URLVerbs.CREATE, component: SilenceFormComponent, - data: { breadcrumbs: ActionLabels.CREATE } + data: { breadcrumbs: `${ActionLabels.CREATE} Silence` } }, { - path: `${URLVerbs.CREATE}/:id`, + path: `silence/${URLVerbs.CREATE}/:id`, component: SilenceFormComponent, data: { breadcrumbs: ActionLabels.CREATE } }, { - path: `${URLVerbs.EDIT}/:id`, + path: `silence/${URLVerbs.EDIT}/:id`, component: SilenceFormComponent, data: { breadcrumbs: ActionLabels.EDIT } }, { - path: `${URLVerbs.RECREATE}/:id`, + path: `silence/${URLVerbs.RECREATE}/:id`, component: SilenceFormComponent, data: { breadcrumbs: ActionLabels.RECREATE } } diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/cluster.module.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/cluster.module.ts index 666b216698a..e3bae17c0ca 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/cluster.module.ts +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/cluster.module.ts @@ -42,8 +42,8 @@ import { OsdRecvSpeedModalComponent } from './osd/osd-recv-speed-modal/osd-recv- import { OsdReweightModalComponent } from './osd/osd-reweight-modal/osd-reweight-modal.component'; import { OsdScrubModalComponent } from './osd/osd-scrub-modal/osd-scrub-modal.component'; import { OsdSmartListComponent } from './osd/osd-smart-list/osd-smart-list.component'; -import { AlertListComponent } from './prometheus/alert-list/alert-list.component'; -import { PrometheusTabsComponent } from './prometheus/prometheus-tabs/prometheus-tabs.component'; +import { ActiveAlertListComponent } from './prometheus/active-alert-list/active-alert-list.component'; +import { MonitoringListComponent } from './prometheus/monitoring-list/monitoring-list.component'; import { RulesListComponent } from './prometheus/rules-list/rules-list.component'; import { SilenceFormComponent } from './prometheus/silence-form/silence-form.component'; import { SilenceListComponent } from './prometheus/silence-list/silence-list.component'; @@ -101,11 +101,10 @@ import { ServicesComponent } from './services/services.component'; LogsComponent, OsdRecvSpeedModalComponent, OsdPgScrubModalComponent, - AlertListComponent, + ActiveAlertListComponent, OsdRecvSpeedModalComponent, SilenceFormComponent, SilenceListComponent, - PrometheusTabsComponent, SilenceMatcherModalComponent, ServicesComponent, InventoryComponent, @@ -117,7 +116,8 @@ import { ServicesComponent } from './services/services.component'; OsdDevicesSelectionGroupsComponent, OsdCreationPreviewModalComponent, RulesListComponent, - AlertListComponent + ActiveAlertListComponent, + MonitoringListComponent ] }) export class ClusterModule {} diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/prometheus/alert-list/alert-list.component.html b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/prometheus/active-alert-list/active-alert-list.component.html similarity index 84% rename from src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/prometheus/alert-list/alert-list.component.html rename to src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/prometheus/active-alert-list/active-alert-list.component.html index 45c5a7ba62f..64a446c87fb 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/prometheus/alert-list/alert-list.component.html +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/prometheus/active-alert-list/active-alert-list.component.html @@ -1,11 +1,3 @@ - - -

All Alerts

- - -

Active Alerts

{ - let component: AlertListComponent; - let fixture: ComponentFixture; +describe('ActiveAlertListComponent', () => { + let component: ActiveAlertListComponent; + let fixture: ComponentFixture; configureTestBed({ imports: [ @@ -39,7 +39,7 @@ describe('AlertListComponent', () => { }); beforeEach(() => { - fixture = TestBed.createComponent(AlertListComponent); + fixture = TestBed.createComponent(ActiveAlertListComponent); component = fixture.componentInstance; }); @@ -57,39 +57,39 @@ describe('AlertListComponent', () => { expect(tableActions).toEqual({ 'create,update,delete': { - actions: ['Create silence'], + actions: ['Create Silence'], primary: { - multiple: 'Create silence', - executing: 'Create silence', - single: 'Create silence', - no: 'Create silence' + multiple: 'Create Silence', + executing: 'Create Silence', + single: 'Create Silence', + no: 'Create Silence' } }, 'create,update': { - actions: ['Create silence'], + actions: ['Create Silence'], primary: { - multiple: 'Create silence', - executing: 'Create silence', - single: 'Create silence', - no: 'Create silence' + multiple: 'Create Silence', + executing: 'Create Silence', + single: 'Create Silence', + no: 'Create Silence' } }, 'create,delete': { - actions: ['Create silence'], + actions: ['Create Silence'], primary: { - multiple: 'Create silence', - executing: 'Create silence', - single: 'Create silence', - no: 'Create silence' + multiple: 'Create Silence', + executing: 'Create Silence', + single: 'Create Silence', + no: 'Create Silence' } }, create: { - actions: ['Create silence'], + actions: ['Create Silence'], primary: { - multiple: 'Create silence', - executing: 'Create silence', - single: 'Create silence', - no: 'Create silence' + multiple: 'Create Silence', + executing: 'Create Silence', + single: 'Create Silence', + no: 'Create Silence' } }, 'update,delete': { diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/prometheus/alert-list/alert-list.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/prometheus/active-alert-list/active-alert-list.component.ts similarity index 90% rename from src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/prometheus/alert-list/alert-list.component.ts rename to src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/prometheus/active-alert-list/active-alert-list.component.ts index 2b68bae8749..2f09b1dcb94 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/prometheus/alert-list/alert-list.component.ts +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/prometheus/active-alert-list/active-alert-list.component.ts @@ -14,12 +14,12 @@ import { URLBuilderService } from '../../../../shared/services/url-builder.servi const BASE_URL = 'silence'; // as only silence actions can be used @Component({ - selector: 'cd-prometheus-list', + selector: 'cd-active-alert-list', providers: [{ provide: URLBuilderService, useValue: new URLBuilderService(BASE_URL) }], - templateUrl: './alert-list.component.html', - styleUrls: ['./alert-list.component.scss'] + templateUrl: './active-alert-list.component.html', + styleUrls: ['./active-alert-list.component.scss'] }) -export class AlertListComponent implements OnInit { +export class ActiveAlertListComponent implements OnInit { @ViewChild('externalLinkTpl', { static: true }) externalLinkTpl: TemplateRef; columns: CdTableColumn[]; @@ -49,8 +49,9 @@ export class AlertListComponent implements OnInit { disable: (selection: CdTableSelection) => !selection.hasSingleSelection || selection.first().cdExecuting, icon: Icons.add, - routerLink: () => this.urlBuilder.getCreateFrom(this.selection.first().fingerprint), - name: this.i18n('Create silence') + routerLink: () => + '/monitoring' + this.urlBuilder.getCreateFrom(this.selection.first().fingerprint), + name: this.i18n('Create Silence') } ]; } diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/prometheus/monitoring-list/monitoring-list.component.html b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/prometheus/monitoring-list/monitoring-list.component.html new file mode 100644 index 00000000000..55f571d8427 --- /dev/null +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/prometheus/monitoring-list/monitoring-list.component.html @@ -0,0 +1,20 @@ + + + + + + + + + + + diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/prometheus/prometheus-tabs/prometheus-tabs.component.scss b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/prometheus/monitoring-list/monitoring-list.component.scss similarity index 100% rename from src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/prometheus/prometheus-tabs/prometheus-tabs.component.scss rename to src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/prometheus/monitoring-list/monitoring-list.component.scss diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/prometheus/monitoring-list/monitoring-list.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/prometheus/monitoring-list/monitoring-list.component.spec.ts new file mode 100644 index 00000000000..bf0bf6c0567 --- /dev/null +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/prometheus/monitoring-list/monitoring-list.component.spec.ts @@ -0,0 +1,46 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { HttpClientTestingModule } from '@angular/common/http/testing'; + +import { ToastrModule } from 'ngx-toastr'; + +import { i18nProviders } from '../../../../../testing/unit-test-helper'; +import { AuthModule } from '../../../../core/auth/auth.module'; +import { CoreModule } from '../../../../core/core.module'; +import { CephfsModule } from '../../../cephfs/cephfs.module'; +import { DashboardModule } from '../../../dashboard/dashboard.module'; +import { NfsModule } from '../../../nfs/nfs.module'; +import { ClusterModule } from '../../cluster.module'; +import { MonitoringListComponent } from './monitoring-list.component'; + +describe('MonitoringListComponent', () => { + let component: MonitoringListComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + imports: [ + ClusterModule, + DashboardModule, + CephfsModule, + AuthModule, + NfsModule, + CoreModule, + ToastrModule.forRoot(), + HttpClientTestingModule + ], + declarations: [], + providers: [i18nProviders] + }).compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(MonitoringListComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/prometheus/monitoring-list/monitoring-list.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/prometheus/monitoring-list/monitoring-list.component.ts new file mode 100644 index 00000000000..f6f57a9b376 --- /dev/null +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/prometheus/monitoring-list/monitoring-list.component.ts @@ -0,0 +1,40 @@ +import { Component, OnInit, ViewChild } from '@angular/core'; +import { ActivatedRoute, Router } from '@angular/router'; + +import { TabDirective, TabsetComponent } from 'ngx-bootstrap/tabs'; + +import { PrometheusAlertService } from '../../../../shared/services/prometheus-alert.service'; + +@Component({ + selector: 'cd-monitoring-list', + templateUrl: './monitoring-list.component.html', + styleUrls: ['./monitoring-list.component.scss'] +}) +export class MonitoringListComponent implements OnInit { + @ViewChild('tabs', { static: true }) + tabs: TabsetComponent; + + constructor( + public prometheusAlertService: PrometheusAlertService, + private route: ActivatedRoute, + private router: Router + ) {} + + ngOnInit() { + // Activate tab according to given fragment + if (this.route.snapshot.fragment) { + const tab = this.tabs.tabs.find( + (t) => t.elementRef.nativeElement.id === this.route.snapshot.fragment + ); + if (tab) { + tab.active = true; + } + // Ensure fragment is not removed, so page can always be reloaded with the same tab open. + this.router.navigate([], { fragment: this.route.snapshot.fragment }); + } + } + + setFragment(element: TabDirective) { + this.router.navigate([], { fragment: element.id }); + } +} diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/prometheus/prometheus-tabs/prometheus-tabs.component.html b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/prometheus/prometheus-tabs/prometheus-tabs.component.html deleted file mode 100644 index b73a09ff4de..00000000000 --- a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/prometheus/prometheus-tabs/prometheus-tabs.component.html +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/prometheus/prometheus-tabs/prometheus-tabs.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/prometheus/prometheus-tabs/prometheus-tabs.component.spec.ts deleted file mode 100644 index 47760b549e4..00000000000 --- a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/prometheus/prometheus-tabs/prometheus-tabs.component.spec.ts +++ /dev/null @@ -1,47 +0,0 @@ -import { HttpClientTestingModule } from '@angular/common/http/testing'; -import { ComponentFixture, TestBed } from '@angular/core/testing'; -import { By } from '@angular/platform-browser'; -import { Router } from '@angular/router'; -import { RouterTestingModule } from '@angular/router/testing'; - -import { TabsModule } from 'ngx-bootstrap/tabs'; - -import { configureTestBed } from '../../../../../testing/unit-test-helper'; -import { PrometheusTabsComponent } from './prometheus-tabs.component'; - -describe('PrometheusTabsComponent', () => { - let component: PrometheusTabsComponent; - let fixture: ComponentFixture; - let router: Router; - - const selectTab = (index) => { - fixture.debugElement.queryAll(By.css('tab'))[index].triggerEventHandler('selectTab', null); - }; - - configureTestBed({ - declarations: [PrometheusTabsComponent], - imports: [RouterTestingModule, HttpClientTestingModule, TabsModule.forRoot()] - }); - - beforeEach(() => { - fixture = TestBed.createComponent(PrometheusTabsComponent); - component = fixture.componentInstance; - router = TestBed.get(Router); - spyOn(router, 'navigate').and.stub(); - fixture.detectChanges(); - }); - - it('should create', () => { - expect(component).toBeTruthy(); - }); - - it('should redirect to alert listing', () => { - selectTab(0); - expect(router.navigate).toHaveBeenCalledWith(['/alerts']); - }); - - it('should redirect to silence listing', () => { - selectTab(1); - expect(router.navigate).toHaveBeenCalledWith(['/silence']); - }); -}); diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/prometheus/prometheus-tabs/prometheus-tabs.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/prometheus/prometheus-tabs/prometheus-tabs.component.ts deleted file mode 100644 index 5675eb71002..00000000000 --- a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/prometheus/prometheus-tabs/prometheus-tabs.component.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { Component } from '@angular/core'; -import { Router } from '@angular/router'; - -@Component({ - selector: 'cd-prometheus-tabs', - templateUrl: './prometheus-tabs.component.html', - styleUrls: ['./prometheus-tabs.component.scss'] -}) -export class PrometheusTabsComponent { - url: string; - - constructor(private router: Router) { - this.url = this.router.url; - } - - navigateTo(url) { - this.router.navigate([url]); - } -} diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/prometheus/silence-form/silence-form.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/prometheus/silence-form/silence-form.component.spec.ts index cd338b4355d..73d5fd8a620 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/prometheus/silence-form/silence-form.component.spec.ts +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/prometheus/silence-form/silence-form.component.spec.ts @@ -45,7 +45,7 @@ describe('SilenceFormComponent', () => { let ifPrometheusSpy; // Helper let prometheus: PrometheusHelper; - let formH: FormHelper; + let formHelper: FormHelper; let fixtureH: FixtureHelper; let params; // Date mocking related @@ -86,10 +86,10 @@ describe('SilenceFormComponent', () => { const changeAction = (action: string) => { const modes = { - add: '/silence/add', - alertAdd: '/silence/add/someAlert', - recreate: '/silence/recreate/someExpiredId', - edit: '/silence/edit/someNotExpiredId' + add: '/monitoring/silence/add', + alertAdd: '/monitoring/silence/add/someAlert', + recreate: '/monitoring/silence/recreate/someExpiredId', + edit: '/monitoring/silence/edit/someNotExpiredId' }; Object.defineProperty(router, 'url', { value: modes[action] }); callInit(); @@ -138,7 +138,7 @@ describe('SilenceFormComponent', () => { fixtureH = new FixtureHelper(fixture); component = fixture.componentInstance; form = component.form; - formH = new FormHelper(form); + formHelper = new FormHelper(form); fixture.detectChanges(); }); @@ -333,7 +333,7 @@ describe('SilenceFormComponent', () => { it('should raise invalid start date error', fakeAsync(() => { changeStartDate('No valid date'); - formH.expectError('startsAt', 'bsDate'); + formHelper.expectError('startsAt', 'bsDate'); expect(form.getValue('startsAt').toString()).toBe('Invalid Date'); expect(form.getValue('endsAt')).toEqual(new Date('2022-02-22T02:00:00')); })); @@ -341,9 +341,9 @@ describe('SilenceFormComponent', () => { describe('on duration change', () => { it('changes end date if duration is changed', () => { - formH.setValue('duration', '15m'); + formHelper.setValue('duration', '15m'); expect(form.getValue('endsAt')).toEqual(new Date('2022-02-22T00:15')); - formH.setValue('duration', '5d 23h'); + formHelper.setValue('duration', '5d 23h'); expect(form.getValue('endsAt')).toEqual(new Date('2022-02-27T23:00')); }); }); @@ -363,7 +363,7 @@ describe('SilenceFormComponent', () => { it('should raise invalid end date error', fakeAsync(() => { changeEndDate('No valid date'); - formH.expectError('endsAt', 'bsDate'); + formHelper.expectError('endsAt', 'bsDate'); expect(form.getValue('endsAt').toString()).toBe('Invalid Date'); expect(form.getValue('startsAt')).toEqual(baseTime); })); @@ -371,20 +371,20 @@ describe('SilenceFormComponent', () => { }); it('should have a creator field', () => { - formH.expectValid('createdBy'); - formH.expectErrorChange('createdBy', '', 'required'); - formH.expectValidChange('createdBy', 'Mighty FSM'); + formHelper.expectValid('createdBy'); + formHelper.expectErrorChange('createdBy', '', 'required'); + formHelper.expectValidChange('createdBy', 'Mighty FSM'); }); it('should have a comment field', () => { - formH.expectError('comment', 'required'); - formH.expectValidChange('comment', 'A pretty long comment'); + formHelper.expectError('comment', 'required'); + formHelper.expectValidChange('comment', 'A pretty long comment'); }); it('should be a valid form if all inputs are filled and at least one matcher was added', () => { expect(form.valid).toBeFalsy(); - formH.expectValidChange('createdBy', 'Mighty FSM'); - formH.expectValidChange('comment', 'A pretty long comment'); + formHelper.expectValidChange('createdBy', 'Mighty FSM'); + formHelper.expectValidChange('comment', 'A pretty long comment'); addMatcher('job', 'someJob', false); expect(form.valid).toBeTruthy(); }); @@ -525,7 +525,7 @@ describe('SilenceFormComponent', () => { const fillAndSubmit = () => { ['createdBy', 'comment'].forEach((attr) => { - formH.setValue(attr, silence[attr]); + formHelper.setValue(attr, silence[attr]); }); silence.matchers.forEach((matcher) => addMatcher(matcher.name, matcher.value, matcher.isRegex) @@ -574,10 +574,10 @@ describe('SilenceFormComponent', () => { expect(router.navigate).not.toHaveBeenCalled(); }); - it('should route back to "/silence" on success', () => { + it('should route back to previous tab on success', () => { fillAndSubmit(); expect(form.valid).toBeTruthy(); - expect(router.navigate).toHaveBeenCalledWith(['/silence']); + expect(router.navigate).toHaveBeenCalledWith(['/monitoring'], { fragment: 'silences' }); }); it('should create a silence', () => { diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/prometheus/silence-form/silence-form.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/prometheus/silence-form/silence-form.component.ts index 8e984e90758..d5ef6b35e6f 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/prometheus/silence-form/silence-form.component.ts +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/prometheus/silence-form/silence-form.component.ts @@ -96,8 +96,8 @@ export class SilenceFormComponent { } private chooseMode() { - this.edit = this.router.url.startsWith('/silence/edit'); - this.recreate = this.router.url.startsWith('/silence/recreate'); + this.edit = this.router.url.startsWith('/monitoring/silence/edit'); + this.recreate = this.router.url.startsWith('/monitoring/silence/recreate'); if (this.edit) { this.action = this.actionLabels.EDIT; } else if (this.recreate) { @@ -294,7 +294,7 @@ export class SilenceFormComponent { } this.prometheusService.setSilence(this.getSubmitData()).subscribe( (resp) => { - this.router.navigate(['/silence']); + this.router.navigate(['/monitoring'], { fragment: 'silences' }); this.notificationService.show( NotificationType.success, this.getNotificationTile(resp.body['silenceId']), diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/prometheus/silence-list/silence-list.component.html b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/prometheus/silence-list/silence-list.component.html index 4d4f4d7b543..40dc8ffc8e5 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/prometheus/silence-list/silence-list.component.html +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/prometheus/silence-list/silence-list.component.html @@ -1,5 +1,3 @@ - - { @@ -37,7 +36,7 @@ describe('SilenceListComponent', () => { RouterTestingModule, HttpClientTestingModule ], - declarations: [SilenceListComponent, PrometheusTabsComponent], + declarations: [SilenceListComponent], providers: [i18nProviders] }); diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/prometheus/silence-list/silence-list.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/prometheus/silence-list/silence-list.component.ts index 50542a5a5ce..76de16a6b49 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/prometheus/silence-list/silence-list.component.ts +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/prometheus/silence-list/silence-list.component.ts @@ -24,7 +24,7 @@ import { AuthStorageService } from '../../../../shared/services/auth-storage.ser import { NotificationService } from '../../../../shared/services/notification.service'; import { URLBuilderService } from '../../../../shared/services/url-builder.service'; -const BASE_URL = 'silence'; +const BASE_URL = 'monitoring/silence'; @Component({ providers: [{ provide: URLBuilderService, useValue: new URLBuilderService(BASE_URL) }], @@ -65,6 +65,7 @@ export class SilenceListComponent { permission: 'create', icon: Icons.add, routerLink: () => this.urlBuilder.getCreate(), + preserveFragment: true, canBePrimary: (selection: CdTableSelection) => !selection.hasSingleSelection, name: this.actionLabels.CREATE }, @@ -79,6 +80,7 @@ export class SilenceListComponent { !selectionExpired(selection), icon: Icons.copy, routerLink: () => this.urlBuilder.getRecreate(this.selection.first().id), + preserveFragment: true, name: this.actionLabels.RECREATE }, { @@ -92,6 +94,7 @@ export class SilenceListComponent { (selection.first().cdExecuting && !selectionExpired(selection)) || selectionExpired(selection), routerLink: () => this.urlBuilder.getEdit(this.selection.first().id), + preserveFragment: true, name: this.actionLabels.EDIT }, { diff --git a/src/pybind/mgr/dashboard/frontend/src/app/core/navigation/breadcrumbs/breadcrumbs.component.html b/src/pybind/mgr/dashboard/frontend/src/app/core/navigation/breadcrumbs/breadcrumbs.component.html index 8b66ec42fcb..05232b7fa07 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/core/navigation/breadcrumbs/breadcrumbs.component.html +++ b/src/pybind/mgr/dashboard/frontend/src/app/core/navigation/breadcrumbs/breadcrumbs.component.html @@ -4,7 +4,8 @@ [ngClass]="{ 'active': last && finished }" class="breadcrumb-item"> {{ crumb.text }} + [routerLink]="crumb.path" + preserveFragment>{{ crumb.text }} {{ crumb.text }} diff --git a/src/pybind/mgr/dashboard/frontend/src/app/core/navigation/navigation/navigation.component.html b/src/pybind/mgr/dashboard/frontend/src/app/core/navigation/navigation/navigation.component.html index b49b33f0863..77b30500847 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/core/navigation/navigation/navigation.component.html +++ b/src/pybind/mgr/dashboard/frontend/src/app/core/navigation/navigation/navigation.component.html @@ -146,18 +146,11 @@ routerLink="/logs">Logs
  • Alerts -
  • -
  • - Silences + routerLink="/monitoring">Monitoring
  • diff --git a/src/pybind/mgr/dashboard/frontend/src/app/core/navigation/navigation/navigation.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/core/navigation/navigation/navigation.component.ts index 85154c3a7af..94313d5a561 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/core/navigation/navigation/navigation.component.ts +++ b/src/pybind/mgr/dashboard/frontend/src/app/core/navigation/navigation/navigation.component.ts @@ -41,7 +41,9 @@ export class NavigationComponent implements OnInit { } this.summaryData = data; }); - this.prometheusService.ifAlertmanagerConfigured(() => (this.prometheusConfigured = true)); + this.prometheusService.ifAlertmanagerConfigured(() => { + this.prometheusConfigured = true; + }); } blockHealthColor() { diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/datatable/table-actions/table-actions.component.html b/src/pybind/mgr/dashboard/frontend/src/app/shared/datatable/table-actions/table-actions.component.html index 28992932f52..1f20fc29f5a 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/shared/datatable/table-actions/table-actions.component.html +++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/datatable/table-actions/table-actions.component.html @@ -5,7 +5,8 @@ class="btn btn-{{btnColor}}" [ngClass]="{'disabled': disableSelectionAction(action)}" (click)="useClickAction(action)" - [routerLink]="useRouterLink(action)"> + [routerLink]="useRouterLink(action)" + [preserveFragment]="action.preserveFragment ? '' : null"> {{ action.name }} @@ -28,6 +29,7 @@ {{ action.name }} diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/models/cd-table-action.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/models/cd-table-action.ts index c5c6fab131e..ac8dcb61a98 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/shared/models/cd-table-action.ts +++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/models/cd-table-action.ts @@ -6,6 +6,8 @@ export class CdTableAction { // or none if it's not needed routerLink?: string | Function; + preserveFragment? = false; + // This is the function that will be triggered on a click event if defined click?: Function; -- 2.39.5