+++ /dev/null
-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');
- });
- });
-});
+++ /dev/null
-import { PageHelper } from '../page-helper.po';
-
-export class AlertsPageHelper extends PageHelper {
- pages = { index: '/#/alerts' };
-}
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';
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 }
}
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';
LogsComponent,
OsdRecvSpeedModalComponent,
OsdPgScrubModalComponent,
- AlertListComponent,
+ ActiveAlertListComponent,
OsdRecvSpeedModalComponent,
SilenceFormComponent,
SilenceListComponent,
- PrometheusTabsComponent,
SilenceMatcherModalComponent,
ServicesComponent,
InventoryComponent,
OsdDevicesSelectionGroupsComponent,
OsdCreationPreviewModalComponent,
RulesListComponent,
- AlertListComponent
+ ActiveAlertListComponent,
+ MonitoringListComponent
]
})
export class ClusterModule {}
--- /dev/null
+<cd-table [data]="prometheusAlertService.alerts"
+ [columns]="columns"
+ identifier="fingerprint"
+ [forceIdentifier]="true"
+ [customCss]="customCss"
+ selectionType="single"
+ (updateSelection)="updateSelection($event)">
+ <cd-table-actions class="table-actions"
+ [permission]="permission"
+ [selection]="selection"
+ [tableActions]="tableActions">
+ </cd-table-actions>
+ <tabset cdTableDetail
+ *ngIf="selection.hasSingleSelection">
+ <tab i18n-heading
+ heading="Details">
+ <cd-table-key-value [renderObjects]="true"
+ [hideEmpty]="true"
+ [appendParentKey]="false"
+ [data]="selection.first()"
+ [customCss]="customCss"
+ [autoReload]="false">
+ </cd-table-key-value>
+ </tab>
+ </tabset>
+</cd-table>
+
+<ng-template #externalLinkTpl
+ let-row="row"
+ let-value="value">
+ <a [href]="value"
+ target="_blank"><i [ngClass]="[icons.lineChart]"></i> Source</a>
+</ng-template>
--- /dev/null
+import { HttpClientTestingModule } from '@angular/common/http/testing';
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { RouterTestingModule } from '@angular/router/testing';
+
+import { TabsModule } from 'ngx-bootstrap/tabs';
+import { ToastrModule } from 'ngx-toastr';
+
+import {
+ configureTestBed,
+ i18nProviders,
+ PermissionHelper
+} from '../../../../../testing/unit-test-helper';
+import { CoreModule } from '../../../../core/core.module';
+import { TableActionsComponent } from '../../../../shared/datatable/table-actions/table-actions.component';
+import { SharedModule } from '../../../../shared/shared.module';
+import { CephModule } from '../../../ceph.module';
+import { DashboardModule } from '../../../dashboard/dashboard.module';
+import { ClusterModule } from '../../cluster.module';
+import { ActiveAlertListComponent } from './active-alert-list.component';
+
+describe('ActiveAlertListComponent', () => {
+ let component: ActiveAlertListComponent;
+ let fixture: ComponentFixture<ActiveAlertListComponent>;
+
+ configureTestBed({
+ imports: [
+ HttpClientTestingModule,
+ TabsModule.forRoot(),
+ RouterTestingModule,
+ ToastrModule.forRoot(),
+ SharedModule,
+ ClusterModule,
+ DashboardModule,
+ CephModule,
+ CoreModule
+ ],
+ declarations: [],
+ providers: [i18nProviders]
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(ActiveAlertListComponent);
+ component = fixture.componentInstance;
+ });
+
+ it('should create', () => {
+ fixture.detectChanges();
+ expect(component).toBeTruthy();
+ });
+
+ it('should test all TableActions combinations', () => {
+ component.ngOnInit();
+ const permissionHelper: PermissionHelper = new PermissionHelper(component.permission);
+ const tableActions: TableActionsComponent = permissionHelper.setPermissionsAndGetActions(
+ component.tableActions
+ );
+
+ expect(tableActions).toEqual({
+ 'create,update,delete': {
+ actions: ['Create Silence'],
+ primary: {
+ multiple: 'Create Silence',
+ executing: 'Create Silence',
+ single: 'Create Silence',
+ no: 'Create Silence'
+ }
+ },
+ 'create,update': {
+ actions: ['Create Silence'],
+ primary: {
+ multiple: 'Create Silence',
+ executing: 'Create Silence',
+ single: 'Create Silence',
+ no: 'Create Silence'
+ }
+ },
+ 'create,delete': {
+ actions: ['Create Silence'],
+ primary: {
+ multiple: 'Create Silence',
+ executing: 'Create Silence',
+ single: 'Create Silence',
+ no: 'Create Silence'
+ }
+ },
+ create: {
+ actions: ['Create Silence'],
+ primary: {
+ multiple: 'Create Silence',
+ executing: 'Create Silence',
+ single: 'Create Silence',
+ no: 'Create Silence'
+ }
+ },
+ 'update,delete': {
+ actions: [],
+ primary: { multiple: '', executing: '', single: '', no: '' }
+ },
+ update: { actions: [], primary: { multiple: '', executing: '', single: '', no: '' } },
+ delete: { actions: [], primary: { multiple: '', executing: '', single: '', no: '' } },
+ 'no-permissions': {
+ actions: [],
+ primary: { multiple: '', executing: '', single: '', no: '' }
+ }
+ });
+ });
+});
--- /dev/null
+import { Component, OnInit, TemplateRef, ViewChild } from '@angular/core';
+import { I18n } from '@ngx-translate/i18n-polyfill';
+import { CellTemplate } from '../../../../shared/enum/cell-template.enum';
+import { Icons } from '../../../../shared/enum/icons.enum';
+import { CdTableAction } from '../../../../shared/models/cd-table-action';
+import { CdTableColumn } from '../../../../shared/models/cd-table-column';
+import { CdTableSelection } from '../../../../shared/models/cd-table-selection';
+import { Permission } from '../../../../shared/models/permissions';
+import { CdDatePipe } from '../../../../shared/pipes/cd-date.pipe';
+import { AuthStorageService } from '../../../../shared/services/auth-storage.service';
+import { PrometheusAlertService } from '../../../../shared/services/prometheus-alert.service';
+import { URLBuilderService } from '../../../../shared/services/url-builder.service';
+
+const BASE_URL = 'silence'; // as only silence actions can be used
+
+@Component({
+ selector: 'cd-active-alert-list',
+ providers: [{ provide: URLBuilderService, useValue: new URLBuilderService(BASE_URL) }],
+ templateUrl: './active-alert-list.component.html',
+ styleUrls: ['./active-alert-list.component.scss']
+})
+export class ActiveAlertListComponent implements OnInit {
+ @ViewChild('externalLinkTpl', { static: true })
+ externalLinkTpl: TemplateRef<any>;
+ columns: CdTableColumn[];
+ tableActions: CdTableAction[];
+ permission: Permission;
+ selection = new CdTableSelection();
+ icons = Icons;
+ customCss = {
+ 'badge badge-danger': 'active',
+ 'badge badge-warning': 'unprocessed',
+ 'badge badge-info': 'suppressed'
+ };
+
+ constructor(
+ // NotificationsComponent will refresh all alerts every 5s (No need to do it here as well)
+ private authStorageService: AuthStorageService,
+ public prometheusAlertService: PrometheusAlertService,
+ private urlBuilder: URLBuilderService,
+ private i18n: I18n,
+ private cdDatePipe: CdDatePipe
+ ) {
+ this.permission = this.authStorageService.getPermissions().prometheus;
+ this.tableActions = [
+ {
+ permission: 'create',
+ canBePrimary: (selection: CdTableSelection) => selection.hasSingleSelection,
+ disable: (selection: CdTableSelection) =>
+ !selection.hasSingleSelection || selection.first().cdExecuting,
+ icon: Icons.add,
+ routerLink: () =>
+ '/monitoring' + this.urlBuilder.getCreateFrom(this.selection.first().fingerprint),
+ name: this.i18n('Create Silence')
+ }
+ ];
+ }
+
+ ngOnInit() {
+ this.columns = [
+ {
+ name: this.i18n('Name'),
+ prop: 'labels.alertname',
+ flexGrow: 2
+ },
+ {
+ name: this.i18n('Job'),
+ prop: 'labels.job',
+ flexGrow: 2
+ },
+ {
+ name: this.i18n('Severity'),
+ prop: 'labels.severity'
+ },
+ {
+ name: this.i18n('State'),
+ prop: 'status.state',
+ cellTransformation: CellTemplate.classAdding
+ },
+ {
+ name: this.i18n('Started'),
+ prop: 'startsAt',
+ pipe: this.cdDatePipe
+ },
+ {
+ name: this.i18n('URL'),
+ prop: 'generatorURL',
+ sortable: false,
+ cellTemplate: this.externalLinkTpl
+ }
+ ];
+ }
+
+ updateSelection(selection: CdTableSelection) {
+ this.selection = selection;
+ }
+}
+++ /dev/null
-<cd-prometheus-tabs></cd-prometheus-tabs>
-
-<h3 class="cd-header"
- i18n>All Alerts</h3>
-<cd-rules-list [data]="prometheusAlertService.rules"></cd-rules-list>
-
-<h3 class="cd-header"
- i18n>Active Alerts</h3>
-<cd-table [data]="prometheusAlertService.alerts"
- [columns]="columns"
- identifier="fingerprint"
- [forceIdentifier]="true"
- [customCss]="customCss"
- selectionType="single"
- (updateSelection)="updateSelection($event)">
- <cd-table-actions class="table-actions"
- [permission]="permission"
- [selection]="selection"
- [tableActions]="tableActions">
- </cd-table-actions>
- <tabset cdTableDetail
- *ngIf="selection.hasSingleSelection">
- <tab i18n-heading
- heading="Details">
- <cd-table-key-value [renderObjects]="true"
- [hideEmpty]="true"
- [appendParentKey]="false"
- [data]="selection.first()"
- [customCss]="customCss"
- [autoReload]="false">
- </cd-table-key-value>
- </tab>
- </tabset>
-</cd-table>
-
-<ng-template #externalLinkTpl
- let-row="row"
- let-value="value">
- <a [href]="value"
- target="_blank"><i [ngClass]="[icons.lineChart]"></i> Source</a>
-</ng-template>
+++ /dev/null
-import { HttpClientTestingModule } from '@angular/common/http/testing';
-import { ComponentFixture, TestBed } from '@angular/core/testing';
-import { RouterTestingModule } from '@angular/router/testing';
-
-import { TabsModule } from 'ngx-bootstrap/tabs';
-import { ToastrModule } from 'ngx-toastr';
-
-import {
- configureTestBed,
- i18nProviders,
- PermissionHelper
-} from '../../../../../testing/unit-test-helper';
-import { CoreModule } from '../../../../core/core.module';
-import { TableActionsComponent } from '../../../../shared/datatable/table-actions/table-actions.component';
-import { SharedModule } from '../../../../shared/shared.module';
-import { CephModule } from '../../../ceph.module';
-import { DashboardModule } from '../../../dashboard/dashboard.module';
-import { ClusterModule } from '../../cluster.module';
-import { AlertListComponent } from './alert-list.component';
-
-describe('AlertListComponent', () => {
- let component: AlertListComponent;
- let fixture: ComponentFixture<AlertListComponent>;
-
- configureTestBed({
- imports: [
- HttpClientTestingModule,
- TabsModule.forRoot(),
- RouterTestingModule,
- ToastrModule.forRoot(),
- SharedModule,
- ClusterModule,
- DashboardModule,
- CephModule,
- CoreModule
- ],
- declarations: [],
- providers: [i18nProviders]
- });
-
- beforeEach(() => {
- fixture = TestBed.createComponent(AlertListComponent);
- component = fixture.componentInstance;
- });
-
- it('should create', () => {
- fixture.detectChanges();
- expect(component).toBeTruthy();
- });
-
- it('should test all TableActions combinations', () => {
- component.ngOnInit();
- const permissionHelper: PermissionHelper = new PermissionHelper(component.permission);
- const tableActions: TableActionsComponent = permissionHelper.setPermissionsAndGetActions(
- component.tableActions
- );
-
- expect(tableActions).toEqual({
- 'create,update,delete': {
- actions: ['Create silence'],
- primary: {
- multiple: 'Create silence',
- executing: 'Create silence',
- single: 'Create silence',
- no: 'Create silence'
- }
- },
- 'create,update': {
- actions: ['Create silence'],
- primary: {
- multiple: 'Create silence',
- executing: 'Create silence',
- single: 'Create silence',
- no: 'Create silence'
- }
- },
- 'create,delete': {
- actions: ['Create silence'],
- primary: {
- multiple: 'Create silence',
- executing: 'Create silence',
- single: 'Create silence',
- no: 'Create silence'
- }
- },
- create: {
- actions: ['Create silence'],
- primary: {
- multiple: 'Create silence',
- executing: 'Create silence',
- single: 'Create silence',
- no: 'Create silence'
- }
- },
- 'update,delete': {
- actions: [],
- primary: { multiple: '', executing: '', single: '', no: '' }
- },
- update: { actions: [], primary: { multiple: '', executing: '', single: '', no: '' } },
- delete: { actions: [], primary: { multiple: '', executing: '', single: '', no: '' } },
- 'no-permissions': {
- actions: [],
- primary: { multiple: '', executing: '', single: '', no: '' }
- }
- });
- });
-});
+++ /dev/null
-import { Component, OnInit, TemplateRef, ViewChild } from '@angular/core';
-import { I18n } from '@ngx-translate/i18n-polyfill';
-import { CellTemplate } from '../../../../shared/enum/cell-template.enum';
-import { Icons } from '../../../../shared/enum/icons.enum';
-import { CdTableAction } from '../../../../shared/models/cd-table-action';
-import { CdTableColumn } from '../../../../shared/models/cd-table-column';
-import { CdTableSelection } from '../../../../shared/models/cd-table-selection';
-import { Permission } from '../../../../shared/models/permissions';
-import { CdDatePipe } from '../../../../shared/pipes/cd-date.pipe';
-import { AuthStorageService } from '../../../../shared/services/auth-storage.service';
-import { PrometheusAlertService } from '../../../../shared/services/prometheus-alert.service';
-import { URLBuilderService } from '../../../../shared/services/url-builder.service';
-
-const BASE_URL = 'silence'; // as only silence actions can be used
-
-@Component({
- selector: 'cd-prometheus-list',
- providers: [{ provide: URLBuilderService, useValue: new URLBuilderService(BASE_URL) }],
- templateUrl: './alert-list.component.html',
- styleUrls: ['./alert-list.component.scss']
-})
-export class AlertListComponent implements OnInit {
- @ViewChild('externalLinkTpl', { static: true })
- externalLinkTpl: TemplateRef<any>;
- columns: CdTableColumn[];
- tableActions: CdTableAction[];
- permission: Permission;
- selection = new CdTableSelection();
- icons = Icons;
- customCss = {
- 'badge badge-danger': 'active',
- 'badge badge-warning': 'unprocessed',
- 'badge badge-info': 'suppressed'
- };
-
- constructor(
- // NotificationsComponent will refresh all alerts every 5s (No need to do it here as well)
- private authStorageService: AuthStorageService,
- public prometheusAlertService: PrometheusAlertService,
- private urlBuilder: URLBuilderService,
- private i18n: I18n,
- private cdDatePipe: CdDatePipe
- ) {
- this.permission = this.authStorageService.getPermissions().prometheus;
- this.tableActions = [
- {
- permission: 'create',
- canBePrimary: (selection: CdTableSelection) => selection.hasSingleSelection,
- disable: (selection: CdTableSelection) =>
- !selection.hasSingleSelection || selection.first().cdExecuting,
- icon: Icons.add,
- routerLink: () => this.urlBuilder.getCreateFrom(this.selection.first().fingerprint),
- name: this.i18n('Create silence')
- }
- ];
- }
-
- ngOnInit() {
- this.columns = [
- {
- name: this.i18n('Name'),
- prop: 'labels.alertname',
- flexGrow: 2
- },
- {
- name: this.i18n('Job'),
- prop: 'labels.job',
- flexGrow: 2
- },
- {
- name: this.i18n('Severity'),
- prop: 'labels.severity'
- },
- {
- name: this.i18n('State'),
- prop: 'status.state',
- cellTransformation: CellTemplate.classAdding
- },
- {
- name: this.i18n('Started'),
- prop: 'startsAt',
- pipe: this.cdDatePipe
- },
- {
- name: this.i18n('URL'),
- prop: 'generatorURL',
- sortable: false,
- cellTemplate: this.externalLinkTpl
- }
- ];
- }
-
- updateSelection(selection: CdTableSelection) {
- this.selection = selection;
- }
-}
--- /dev/null
+<tabset #tabs>
+ <tab id="active-alerts"
+ heading="Active Alerts"
+ (selectTab)="setFragment($event)"
+ i18n-heading>
+ <cd-active-alert-list></cd-active-alert-list>
+ </tab>
+ <tab id="all-alerts"
+ heading="All Alerts"
+ (selectTab)="setFragment($event)"
+ i18n-heading>
+ <cd-rules-list [data]="prometheusAlertService.rules"></cd-rules-list>
+ </tab>
+ <tab id="silences"
+ heading="Silences"
+ (selectTab)="setFragment($event)"
+ i18n-heading>
+ <cd-silences-list></cd-silences-list>
+ </tab>
+</tabset>
--- /dev/null
+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<MonitoringListComponent>;
+
+ 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();
+ });
+});
--- /dev/null
+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 });
+ }
+}
+++ /dev/null
-<tabset>
- <tab heading="Alerts"
- i18n-heading
- [active]="url === '/alerts'"
- (selectTab)="navigateTo('/alerts')">
- </tab>
- <tab heading="Silences"
- i18n-heading
- [active]="url === '/silence'"
- (selectTab)="navigateTo('/silence')">
- </tab>
-</tabset>
-
+++ /dev/null
-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<PrometheusTabsComponent>;
- 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']);
- });
-});
+++ /dev/null
-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]);
- }
-}
let ifPrometheusSpy;
// Helper
let prometheus: PrometheusHelper;
- let formH: FormHelper;
+ let formHelper: FormHelper;
let fixtureH: FixtureHelper;
let params;
// Date mocking related
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();
fixtureH = new FixtureHelper(fixture);
component = fixture.componentInstance;
form = component.form;
- formH = new FormHelper(form);
+ formHelper = new FormHelper(form);
fixture.detectChanges();
});
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'));
}));
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'));
});
});
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);
}));
});
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();
});
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)
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', () => {
}
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) {
}
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']),
-<cd-prometheus-tabs></cd-prometheus-tabs>
-
<cd-table [data]="silences"
[columns]="columns"
[forceIdentifier]="true"
import { NotificationType } from '../../../../shared/enum/notification-type.enum';
import { NotificationService } from '../../../../shared/services/notification.service';
import { SharedModule } from '../../../../shared/shared.module';
-import { PrometheusTabsComponent } from '../prometheus-tabs/prometheus-tabs.component';
import { SilenceListComponent } from './silence-list.component';
describe('SilenceListComponent', () => {
RouterTestingModule,
HttpClientTestingModule
],
- declarations: [SilenceListComponent, PrometheusTabsComponent],
+ declarations: [SilenceListComponent],
providers: [i18nProviders]
});
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) }],
permission: 'create',
icon: Icons.add,
routerLink: () => this.urlBuilder.getCreate(),
+ preserveFragment: true,
canBePrimary: (selection: CdTableSelection) => !selection.hasSingleSelection,
name: this.actionLabels.CREATE
},
!selectionExpired(selection),
icon: Icons.copy,
routerLink: () => this.urlBuilder.getRecreate(this.selection.first().id),
+ preserveFragment: true,
name: this.actionLabels.RECREATE
},
{
(selection.first().cdExecuting && !selectionExpired(selection)) ||
selectionExpired(selection),
routerLink: () => this.urlBuilder.getEdit(this.selection.first().id),
+ preserveFragment: true,
name: this.actionLabels.EDIT
},
{
[ngClass]="{ 'active': last && finished }"
class="breadcrumb-item">
<a *ngIf="!last && crumb.path !== null"
- [routerLink]="crumb.path">{{ crumb.text }}</a>
+ [routerLink]="crumb.path"
+ preserveFragment>{{ crumb.text }}</a>
<span *ngIf="last || crumb.path === null">{{ crumb.text }}</span>
</li>
</ol>
routerLink="/logs">Logs</a>
</li>
<li routerLinkActive="active"
- class="tc_submenuitem tc_submenuitem_prometheus"
+ class="tc_submenuitem tc_submenuitem_monitoring"
*ngIf="prometheusConfigured && permissions.prometheus.read">
<a i18n
class="dropdown-item"
- routerLink="/alerts">Alerts</a>
- </li>
- <li routerLinkActive="active"
- class="tc_submenuitem tc_submenuitem_prometheus"
- *ngIf="prometheusConfigured && permissions.prometheus.read">
- <a i18n
- class="dropdown-item"
- routerLink="/silence">Silences</a>
+ routerLink="/monitoring">Monitoring</a>
</li>
</ul>
</li>
}
this.summaryData = data;
});
- this.prometheusService.ifAlertmanagerConfigured(() => (this.prometheusConfigured = true));
+ this.prometheusService.ifAlertmanagerConfigured(() => {
+ this.prometheusConfigured = true;
+ });
}
blockHealthColor() {
class="btn btn-{{btnColor}}"
[ngClass]="{'disabled': disableSelectionAction(action)}"
(click)="useClickAction(action)"
- [routerLink]="useRouterLink(action)">
+ [routerLink]="useRouterLink(action)"
+ [preserveFragment]="action.preserveFragment ? '' : null">
<i [ngClass]="[action.icon]"></i><span>{{ action.name }}</span>
</button>
</ng-container>
<a class="dropdown-item"
(click)="useClickAction(action)"
[routerLink]="useRouterLink(action)"
+ [preserveFragment]="action.preserveFragment ? '' : null"
[ngClass]="{'disabled': disableSelectionAction(action)}">
<i [ngClass]="[action.icon]"></i><span>{{ action.name }}</span>
</a>
// 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;