From 263ca92f8eae5af812d1fb88ffa26c3a952884bd Mon Sep 17 00:00:00 2001 From: Afreen Misbah Date: Sun, 8 Feb 2026 21:10:45 +0530 Subject: [PATCH] mgr/dashboard: Add storage card to overview page Fixes https://tracker.ceph.com/issues/73318 Signed-off-by: Afreen Misbah --- .../ceph/dashboard-v3/dashboard-v3.module.ts | 4 +- .../app/ceph/overview/overview.component.html | 9 +- .../app/ceph/overview/overview.component.ts | 3 +- .../overview-storage-card.component.html | 43 +++++++++ .../overview-storage-card.component.scss | 33 +++++++ .../overview-storage-card.component.spec.ts | 22 +++++ .../overview-storage-card.component.ts | 92 +++++++++++++++++++ .../productive-card.component.html | 30 +++--- .../productive-card.component.scss | 15 ++- .../productive-card.component.ts | 5 +- 10 files changed, 223 insertions(+), 33 deletions(-) create mode 100644 src/pybind/mgr/dashboard/frontend/src/app/ceph/overview/storage-card/overview-storage-card.component.html create mode 100644 src/pybind/mgr/dashboard/frontend/src/app/ceph/overview/storage-card/overview-storage-card.component.scss create mode 100644 src/pybind/mgr/dashboard/frontend/src/app/ceph/overview/storage-card/overview-storage-card.component.spec.ts create mode 100644 src/pybind/mgr/dashboard/frontend/src/app/ceph/overview/storage-card/overview-storage-card.component.ts diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard-v3/dashboard-v3.module.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard-v3/dashboard-v3.module.ts index 363c9b68edd..257215413b4 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard-v3/dashboard-v3.module.ts +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard-v3/dashboard-v3.module.ts @@ -15,6 +15,7 @@ import { DashboardTimeSelectorComponent } from './dashboard-time-selector/dashbo import { DashboardV3Component } from './dashboard/dashboard-v3.component'; import { PgSummaryPipe } from './pg-summary.pipe'; import { InlineLoadingModule, ToggletipModule, TagModule } from 'carbon-components-angular'; +import { ProductiveCardComponent } from '~/app/shared/components/productive-card/productive-card.component'; @NgModule({ imports: [ @@ -30,7 +31,8 @@ import { InlineLoadingModule, ToggletipModule, TagModule } from 'carbon-componen BaseChartDirective, ToggletipModule, InlineLoadingModule, - TagModule + TagModule, + ProductiveCardComponent ], declarations: [ DashboardV3Component, diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/overview/overview.component.html b/src/pybind/mgr/dashboard/frontend/src/app/ceph/overview/overview.component.html index 70d5d3908a1..30b7fa30cd0 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/ceph/overview/overview.component.html +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/overview/overview.component.html @@ -20,13 +20,8 @@ [narrow]="true">
- Storage card -
-
- Docs card + [columnNumbers]="{lg: 16}"> +
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/overview/overview.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/overview/overview.component.ts index 4ba2a899556..09d97324fd1 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/ceph/overview/overview.component.ts +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/overview/overview.component.ts @@ -1,9 +1,10 @@ import { Component } from '@angular/core'; import { GridModule, TilesModule } from 'carbon-components-angular'; +import { OverviewStorageCardComponent } from './storage-card/overview-storage-card.component'; @Component({ selector: 'cd-overview', - imports: [GridModule, TilesModule], + imports: [GridModule, TilesModule, OverviewStorageCardComponent], standalone: true, templateUrl: './overview.component.html', styleUrl: './overview.component.scss' diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/overview/storage-card/overview-storage-card.component.html b/src/pybind/mgr/dashboard/frontend/src/app/ceph/overview/storage-card/overview-storage-card.component.html new file mode 100644 index 00000000000..556f08e7d19 --- /dev/null +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/overview/storage-card/overview-storage-card.component.html @@ -0,0 +1,43 @@ + + + + + + +
+
+ 200{{' '}} + TB of 1300 TB used +
+ + + Raw capacity + + +
+ +
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/overview/storage-card/overview-storage-card.component.scss b/src/pybind/mgr/dashboard/frontend/src/app/ceph/overview/storage-card/overview-storage-card.component.scss new file mode 100644 index 00000000000..f1ab45e4b27 --- /dev/null +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/overview/storage-card/overview-storage-card.component.scss @@ -0,0 +1,33 @@ +.overview-storage-card { + // Hiding the native chart title + &-chart { + .meter-title { + height: 0 !important; + display: none !important; + } + + .spacer { + height: 0 !important; + display: none !important; + } + } + + &-chart-header { + display: flex; + justify-content: space-between; + } + + &-dropdown { + display: flex; + justify-content: flex-end; + align-items: flex-end; + + .cds--label { + padding-right: var(--cds-spacing-03); + } + + .cds--dropdown { + flex: 0 0 35%; + } + } +} diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/overview/storage-card/overview-storage-card.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/overview/storage-card/overview-storage-card.component.spec.ts new file mode 100644 index 00000000000..ebfa6cccca5 --- /dev/null +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/overview/storage-card/overview-storage-card.component.spec.ts @@ -0,0 +1,22 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { OverviewStorageCardComponent } from './overview-storage-card.component'; + +describe('OverviewStorageCardComponent', () => { + let component: OverviewStorageCardComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + imports: [OverviewStorageCardComponent] + }).compileComponents(); + + fixture = TestBed.createComponent(OverviewStorageCardComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/overview/storage-card/overview-storage-card.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/overview/storage-card/overview-storage-card.component.ts new file mode 100644 index 00000000000..1db7cb7917f --- /dev/null +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/overview/storage-card/overview-storage-card.component.ts @@ -0,0 +1,92 @@ +import { Component, ViewEncapsulation } from '@angular/core'; +import { + CheckboxModule, + DropdownModule, + GridModule, + TilesModule, + TooltipModule +} from 'carbon-components-angular'; +import { ProductiveCardComponent } from '~/app/shared/components/productive-card/productive-card.component'; +import { MeterChartComponent, MeterChartOptions } from '@carbon/charts-angular'; + +const StorageType = { + ALL: $localize`All`, + BLOCK: $localize`Block`, + FILE: $localize`File`, + OBJECT: $localize`Object` +}; + +@Component({ + selector: 'cd-overview-storage-card', + imports: [ + GridModule, + TilesModule, + ProductiveCardComponent, + MeterChartComponent, + CheckboxModule, + DropdownModule, + TooltipModule + ], + standalone: true, + templateUrl: './overview-storage-card.component.html', + styleUrl: './overview-storage-card.component.scss', + encapsulation: ViewEncapsulation.None +}) +export class OverviewStorageCardComponent { + options: MeterChartOptions = { + height: '45px', + meter: { + proportional: { + total: 2000, + unit: 'GB', + breakdownFormatter: (_e) => null, + totalFormatter: (_e) => null + } + }, + toolbar: { + enabled: false + }, + color: { + pairing: { + option: 2 + } + }, + canvasZoom: { + enabled: false + } + }; + allData = [ + { + group: StorageType.BLOCK, + value: 202 + }, + { + group: StorageType.FILE, + value: 654 + }, + { + group: StorageType.OBJECT, + value: 120 + } + ]; + dropdownItems = [ + { content: StorageType.ALL }, + { content: StorageType.BLOCK }, + { content: StorageType.FILE }, + { content: StorageType.OBJECT } + ]; + isRawCapacity: boolean = true; + selectedStorageType: string = StorageType.ALL; + displayData = this.allData; + + toggleRawCapacity(isChecked: boolean) { + this.isRawCapacity = isChecked; + } + + onStorageTypeSelect(selected: { item: { content: string; selected: true } }) { + this.selectedStorageType = selected?.item?.content; + if (this.selectedStorageType === StorageType.ALL) { + this.displayData = this.allData; + } else this.displayData = this.allData.filter((d) => d.group === this.selectedStorageType); + } +} diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/components/productive-card/productive-card.component.html b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/productive-card/productive-card.component.html index 67a4cbfaee4..aa328a0ab44 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/shared/components/productive-card/productive-card.component.html +++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/productive-card/productive-card.component.html @@ -3,27 +3,27 @@ [cdsLayer]="0">
-

- {{title}} -

- @if(headerActionTemplate) { -
- -
- } +
+
+

{{title}}

+
+ @if(!!headerActionTemplate) { +
+ +
+ } +
- @if(footerTemplate) { + @if(!!footerTemplate) { diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/components/productive-card/productive-card.component.scss b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/productive-card/productive-card.component.scss index cbfd1402f95..d550c32f7ca 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/shared/components/productive-card/productive-card.component.scss +++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/productive-card/productive-card.component.scss @@ -5,16 +5,15 @@ padding: 0; &-header { - margin: 0; - padding: var(--cds-spacing-05); + padding-inline: var(--cds-spacing-05); + } - &-title { - margin: 0; - } + &-header-row { + padding: var(--cds-spacing-05); + } - &-actions { - margin: 0; - } + &-header-actions { + padding-right: 0; } &-section { diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/components/productive-card/productive-card.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/productive-card/productive-card.component.ts index 7047a1a3c68..aba50e37af7 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/shared/components/productive-card/productive-card.component.ts +++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/productive-card/productive-card.component.ts @@ -1,4 +1,6 @@ +import { CommonModule } from '@angular/common'; import { Component, ContentChild, Input, TemplateRef } from '@angular/core'; +import { GridModule, LayerModule, TilesModule } from 'carbon-components-angular'; /** * A generic productive card component. @@ -13,7 +15,8 @@ import { Component, ContentChild, Input, TemplateRef } from '@angular/core'; */ @Component({ selector: 'cd-productive-card', - standalone: false, + imports: [GridModule, TilesModule, CommonModule, LayerModule], + standalone: true, templateUrl: './productive-card.component.html', styleUrl: './productive-card.component.scss' }) -- 2.47.3