From 1c02a94f59d31594a22ef4080bdc962538288587 Mon Sep 17 00:00:00 2001 From: Nizamudeen A Date: Tue, 19 Sep 2023 12:12:36 +0530 Subject: [PATCH] mgr/dashboard: fix the landing page layout issues We were following a row-col grid layout for the landing page. First row includes Details, Status and Capacity Second row for Inventory and Cluster Utilization So if one of the item in the first row increases, it pushes the entire second row downwards. To fix this, I made a col-row grid. First col has Details and Inventory in two rows. Second col has Status and Capacity as a col and Cluster Utilization as a single row Fixes: https://tracker.ceph.com/issues/62961 Signed-off-by: Nizamudeen A Co-authored-by: cloudbehl (cherry picked from commit 3f904b0a658e3759ef00fdd5a95f6ecf5ba76718) Conflicts: src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard-v3/dashboard/dashboard-v3.component.html - Accept the incoming change --- .../cypress/e2e/ui/dashboard-v3.e2e-spec.ts | 2 +- .../dashboard-pie.component.html | 2 +- .../dashboard/dashboard-v3.component.html | 563 +++++++++--------- .../dashboard/dashboard-v3.component.scss | 73 +-- .../dashboard/dashboard-v3.component.spec.ts | 10 +- .../dashboard/dashboard-v3.component.ts | 38 +- .../rgw-overview-dashboard.component.html | 5 +- .../components/card/card.component.html | 9 +- .../components/card/card.component.scss | 5 - .../shared/components/card/card.component.ts | 6 + .../src/app/shared/enum/health-icon.enum.ts | 6 + .../services/prometheus-alert.service.ts | 10 +- 12 files changed, 360 insertions(+), 369 deletions(-) diff --git a/src/pybind/mgr/dashboard/frontend/cypress/e2e/ui/dashboard-v3.e2e-spec.ts b/src/pybind/mgr/dashboard/frontend/cypress/e2e/ui/dashboard-v3.e2e-spec.ts index f6433aa3f07..3815011a185 100644 --- a/src/pybind/mgr/dashboard/frontend/cypress/e2e/ui/dashboard-v3.e2e-spec.ts +++ b/src/pybind/mgr/dashboard/frontend/cypress/e2e/ui/dashboard-v3.e2e-spec.ts @@ -39,7 +39,7 @@ describe('Dashboard-v3 Main Page', () => { it('should verify that cards exist on dashboard in proper order', () => { // Ensures that cards are all displayed on the dashboard tab while being in the proper // order, checks for card title and position via indexing into a list of all cards. - const order = ['Details', 'Status', 'Capacity', 'Inventory', 'Cluster Utilization']; + const order = ['Details', 'Inventory', 'Status', 'Capacity', 'Cluster Utilization']; for (let i = 0; i < order.length; i++) { dashboard.card(i).should('contain.text', order[i]); diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard-v3/dashboard-pie/dashboard-pie.component.html b/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard-v3/dashboard-pie/dashboard-pie.component.html index ba8176beab3..c013ab5404b 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard-v3/dashboard-pie/dashboard-pie.component.html +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard-v3/dashboard-pie/dashboard-pie.component.html @@ -1,4 +1,4 @@ -
+
-
- -
-
Cluster ID
-
{{ detailsCardData.fsid }}
-
Orchestrator
-
{{ detailsCardData.orchestrator || 'Orchestrator is not available' }}
-
Ceph version
-
{{ detailsCardData.cephVersion }}
-
Cluster API
-
- - {{ origin }}/api-docs - - -
- -
Telemetry Dashboard - - {{ telemetryEnabled ? 'Active' : 'Inactive' }} - -
+ +
+ + +
+ + + +
+
Cluster ID
+
{{ detailsCardData.fsid }}
+
Orchestrator
+
{{ detailsCardData.orchestrator || 'Orchestrator is not available' }}
+
Ceph version
+
{{ detailsCardData.cephVersion }}
+
Cluster API
- - {{ telemetryURL }} + + {{ origin }}/api-docs
- -
-
+ +
Telemetry Dashboard + + {{ telemetryEnabled ? 'Active' : 'Inactive' }} + +
+
+ + {{ telemetryURL }} + + +
+
+
+
- -
- - -
    -
  • - - {{ check.type }}: {{ check.summary.message }} -
  • -
-
- - Cluster - Cluster -
-
-
- Alerts - - + + +
+ +
  • + +
  • +
    + +
  • + +
  • +
    + +
  • + +
  • +
    + +
  • + +
  • +
    + +
  • + +
  • +
    + +
  • + +
  • +
    + +
  • + +
  • +
    + +
  • + +
  • +
    + +
  • + +
  • +
    +
    - + +
    +
    + +
    + + +
    + + +
      +
    • + + {{ check.type }}: {{ check.summary.message }} +
    • +
    +
    -
    - +
    + + Cluster + Cluster +
    +
    +
    + +
    +
    + +
    + +
    +
    +
    +
    +
    -
    -
    - -
    - -
    -
    +
    + + + + + +
    - - - - - - - - - -
    - -
    - - -
    - -
  • - -
  • -
    - -
  • - -
  • -
    - -
  • - -
  • -
    - -
  • - -
  • -
    - -
  • - -
  • -
    - -
  • - -
  • -
    - -
  • - -
  • -
    - -
  • - -
  • -
    - -
  • - -
  • -
    - -
    - - - - - - - - - - - - - - + +
    + +
    + + + + + + + + + + + + + + +
    +
    +
    -
    +
    - -
    + +
    -
    +
    - +
    -
    -
    +
    +
    {{ alert.labels.alertname }}
    -

    +

    -
    +
    diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard-v3/dashboard/dashboard-v3.component.scss b/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard-v3/dashboard/dashboard-v3.component.scss index 140f5f78fa4..5d558324319 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard-v3/dashboard/dashboard-v3.component.scss +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard-v3/dashboard/dashboard-v3.component.scss @@ -1,67 +1,38 @@ -.alerts { - height: 17rem; +.details { + font-size: larger; - div { - padding-top: 0; + dt { + margin-bottom: 0.3rem; } -} - -div { - padding-top: 20px; -} - -ngx-simplebar { - height: 18rem; -} - -hr { - margin-bottom: 2px; - margin-top: 2px; -} - -.position-right { - margin-left: auto; - order: 2; -} -.center-content { - align-items: center; - margin-top: 30px; - position: relative; + dd { + margin-bottom: 0.8rem; + } } -button.dropdown-toggle { - position: relative; - - &::after { - border: 0; - content: '\f054'; - font-family: 'ForkAwesome'; - font-size: 1rem; +.status { + .viewAlert { position: absolute; - right: 20px; - transition: transform 0.3s ease-in-out; + right: 2rem; + top: 2rem; } +} - &[aria-expanded='true']::after { - transform: rotate(90deg); +.alerts { + ngx-simplebar { + height: 13.5rem; + overflow-x: hidden; } - &:focus { - box-shadow: none; + .text-truncate { + -webkit-box-orient: vertical; /* stylelint-disable-line property-no-vendor-prefix */ + display: -webkit-box; /* stylelint-disable-line value-no-vendor-prefix */ + -webkit-line-clamp: 2; + white-space: normal; } } .list-group-item { border: 0; -} - -dt { - font-size: larger; - margin-bottom: 0.3rem; -} - -dd { - font-size: larger; - margin-bottom: 0.8rem; + font-size: 14px; } diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard-v3/dashboard/dashboard-v3.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard-v3/dashboard/dashboard-v3.component.spec.ts index c274a2f5406..60a30456ef7 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard-v3/dashboard/dashboard-v3.component.spec.ts +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard-v3/dashboard/dashboard-v3.component.spec.ts @@ -22,6 +22,7 @@ import { DashboardPieComponent } from '../dashboard-pie/dashboard-pie.component' import { PgSummaryPipe } from '../pg-summary.pipe'; import { DashboardV3Component } from './dashboard-v3.component'; import { OrchestratorService } from '~/app/shared/api/orchestrator.service'; +import { AlertClass } from '~/app/shared/enum/health-icon.enum'; export class SummaryServiceMock { summaryDataSource = new BehaviorSubject({ @@ -171,6 +172,8 @@ describe('Dashbord Component', () => { spyOn(TestBed.inject(PrometheusService), 'ifAlertmanagerConfigured').and.callFake((fn) => fn()); getAlertsSpy = spyOn(TestBed.inject(PrometheusService), 'getAlerts'); getAlertsSpy.and.returnValue(of(alertsPayload)); + component.prometheusAlertService.alerts = alertsPayload; + component.isAlertmanagerConfigured = true; }); it('should create', () => { @@ -240,7 +243,7 @@ describe('Dashbord Component', () => { it('should show the critical alerts window and its content', () => { const payload = _.cloneDeep(alertsPayload[0]); - component.toggleAlertsWindow('danger'); + component.toggleAlertsWindow(AlertClass[0]); fixture.detectChanges(); const cardTitle = fixture.debugElement.query(By.css('.tc_alerts h6.card-title')); @@ -251,7 +254,7 @@ describe('Dashbord Component', () => { it('should show the warning alerts window and its content', () => { const payload = _.cloneDeep(alertsPayload[2]); - component.toggleAlertsWindow('warning'); + component.toggleAlertsWindow(AlertClass.warning); fixture.detectChanges(); const cardTitle = fixture.debugElement.query(By.css('.tc_alerts h6.card-title')); @@ -261,8 +264,7 @@ describe('Dashbord Component', () => { }); it('should only show the pills when the alerts are not empty', () => { - spyOn(TestBed.inject(PrometheusAlertService), 'activeCriticalAlerts').and.returnValue(0); - spyOn(TestBed.inject(PrometheusAlertService), 'activeWarningAlerts').and.returnValue(0); + spyOn(TestBed.inject(PrometheusAlertService), 'alerts').and.returnValue(0); fixture.detectChanges(); const warningAlerts = fixture.debugElement.query(By.css('button[id=warningAlerts]')); diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard-v3/dashboard/dashboard-v3.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard-v3/dashboard/dashboard-v3.component.ts index cf2cb0b1974..7ec0cd4495b 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard-v3/dashboard/dashboard-v3.component.ts +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard-v3/dashboard/dashboard-v3.component.ts @@ -23,6 +23,7 @@ import { PrometheusListHelper } from '~/app/shared/helpers/prometheus-list-helpe import { PrometheusAlertService } from '~/app/shared/services/prometheus-alert.service'; import { OrchestratorService } from '~/app/shared/api/orchestrator.service'; import { MgrModuleService } from '~/app/shared/api/mgr-module.service'; +import { AlertClass } from '~/app/shared/enum/health-icon.enum'; @Component({ selector: 'cd-dashboard-v3', @@ -43,15 +44,13 @@ export class DashboardV3Component extends PrometheusListHelper implements OnInit prometheusAlerts$: Observable; icons = Icons; - showAlerts = false; flexHeight = true; simplebar = { - autoHide: false + autoHide: true }; - textClass: string; borderClass: string; alertType: string; - alerts: AlertmanagerAlert[]; + alertClass = AlertClass; healthData: any; categoryPgAmount: Record = {}; totalPgs = 0; @@ -115,23 +114,8 @@ export class DashboardV3Component extends PrometheusListHelper implements OnInit }); } - toggleAlertsWindow(type: string, isToggleButton: boolean = false) { - this.triggerPrometheusAlerts(); - if (isToggleButton) { - this.showAlerts = !this.showAlerts; - this.flexHeight = !this.flexHeight; - } else if ( - !this.showAlerts || - (this.alertType === type && type !== 'danger') || - (this.alertType !== 'warning' && type === 'danger') - ) { - this.showAlerts = !this.showAlerts; - this.flexHeight = !this.flexHeight; - } - - type === 'danger' ? (this.alertType = 'critical') : (this.alertType = type); - this.textClass = `text-${type}`; - this.borderClass = `border-${type}`; + toggleAlertsWindow(type: AlertClass) { + this.alertType === type ? (this.alertType = null) : (this.alertType = type); } getDetailsCardData() { @@ -160,14 +144,6 @@ export class DashboardV3Component extends PrometheusListHelper implements OnInit }); } - triggerPrometheusAlerts() { - this.prometheusService.ifAlertmanagerConfigured(() => { - this.prometheusService.getAlerts().subscribe((alerts) => { - this.alerts = alerts; - }); - }); - } - public getPrometheusData(selectedTime: any) { this.queriesResults = this.prometheusService.getPrometheusQueriesData( selectedTime, @@ -181,4 +157,8 @@ export class DashboardV3Component extends PrometheusListHelper implements OnInit this.telemetryEnabled = resp?.enabled; }); } + + trackByFn(index: any) { + return index; + } } diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-overview-dashboard/rgw-overview-dashboard.component.html b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-overview-dashboard/rgw-overview-dashboard.component.html index 7db871be4cf..f50a6e6c151 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-overview-dashboard/rgw-overview-dashboard.component.html +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-overview-dashboard/rgw-overview-dashboard.component.html @@ -154,7 +154,7 @@ @@ -163,7 +163,8 @@ [cardTitle]="title" i18n-title cardType="syncCards" - removeBorder="true" + bgColor="bg-color" + borderClass="border-0" class="col-sm-9 col-lg-6" [ngClass]="{ 'border-left': title === 'Data Sync' }" aria-label="Charts Card"> diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/components/card/card.component.html b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/card/card.component.html index ba258a285ed..deb408525de 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/shared/components/card/card.component.html +++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/card/card.component.html @@ -1,5 +1,5 @@
    + [ngClass]="{'border-0': removeBorder, 'bg-color': cardType === 'Sync Status Card', 'shadow': shadow, 'shadow-sm': !shadow && cardType !== 'syncCards', 'h-100': fullHeight}">

    {{ cardTitle }} @@ -13,7 +13,12 @@ class="text-center card-title"> {{ cardTitle }}

    -
    +
    +
    diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/components/card/card.component.scss b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/card/card.component.scss index fdf19a00ec6..e69de29bb2d 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/shared/components/card/card.component.scss +++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/card/card.component.scss @@ -1,5 +0,0 @@ -.card-body { - display: flex; - flex-direction: column; - justify-content: space-evenly; -} diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/components/card/card.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/card/card.component.ts index 9123b48fb37..55f1ba6ae93 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/shared/components/card/card.component.ts +++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/card/card.component.ts @@ -17,4 +17,10 @@ export class CardComponent { removeBorder = false; @Input() shadow = false; + @Input() + cardFooter = false; + @Input() + fullHeight = false; + @Input() + alignItemsCenter = false; } diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/enum/health-icon.enum.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/enum/health-icon.enum.ts index 7330a250bde..f741c396705 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/shared/enum/health-icon.enum.ts +++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/enum/health-icon.enum.ts @@ -3,3 +3,9 @@ export enum HealthIcon { HEALTH_WARN = 'fa fa-exclamation-triangle', HEALTH_OK = 'fa fa-check-circle' } + +export enum AlertClass { + critical = 'danger', + warning = 'warning', + info = 'info' +} diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/services/prometheus-alert.service.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/services/prometheus-alert.service.ts index f26b80629b9..be6c27da6e2 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/shared/services/prometheus-alert.service.ts +++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/services/prometheus-alert.service.ts @@ -64,23 +64,25 @@ export class PrometheusAlertService { this.notifyOnAlertChanges(alerts, this.alerts); } this.activeAlerts = _.reduce( - this.alerts, + alerts, (result, alert) => (alert.status.state === 'active' ? ++result : result), 0 ); this.activeCriticalAlerts = _.reduce( - this.alerts, + alerts, (result, alert) => alert.status.state === 'active' && alert.labels.severity === 'critical' ? ++result : result, 0 ); this.activeWarningAlerts = _.reduce( - this.alerts, + alerts, (result, alert) => alert.status.state === 'active' && alert.labels.severity === 'warning' ? ++result : result, 0 ); - this.alerts = alerts; + this.alerts = alerts.reverse().sort((a, b) => { + return a.labels.severity.localeCompare(b.labels.severity); + }); this.canAlertsBeNotified = true; } -- 2.39.5