From: Afreen Misbah Date: Tue, 13 Jan 2026 20:47:40 +0000 (+0530) Subject: mgr/dashboard: Add productive card component X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=aa2216d8d5e728b7ed7637e190a93717e86c8dc6;p=ceph.git mgr/dashboard: Add productive card component - add generic productive card component - based on carbon design system - there are two versions of card - with shadow(tinted affect) and without. - applies gray10 theme which is decided by new designs. Fixes https://tracker.ceph.com/issues/74450 Signed-off-by: Afreen Misbah --- diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard-v3/dashboard/dashboard-v3.component.html b/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard-v3/dashboard/dashboard-v3.component.html index bc3bc26a682..2e74622998d 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard-v3/dashboard/dashboard-v3.component.html +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard-v3/dashboard/dashboard-v3.component.html @@ -1,15 +1,10 @@
- -
- - - -
+
+ +
Cluster ID
{{ detailsCardData.fsid }}
Orchestrator
@@ -23,7 +18,7 @@
- {{ origin }}/api-docs + {{ origin }}/api-docs
@@ -57,7 +52,7 @@
- +
{ it('should render all cards', () => { fixture.detectChanges(); const dashboardCards = fixture.debugElement.nativeElement.querySelectorAll('cd-card'); - expect(dashboardCards.length).toBe(5); + expect(dashboardCards.length).toBe(4); }); it('should get corresponding data into detailsCardData', () => { diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard/dashboard.module.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard/dashboard.module.ts index 0e400e01994..32588db56c1 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard/dashboard.module.ts +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard/dashboard.module.ts @@ -12,8 +12,14 @@ import { CephSharedModule } from '../shared/ceph-shared.module'; import { FeedbackComponent } from '../shared/feedback/feedback.component'; import { DashboardComponent } from './dashboard/dashboard.component'; import { HealthPieComponent } from './health-pie/health-pie.component'; -import { InputModule, ModalModule, SelectModule, ToggletipModule } from 'carbon-components-angular'; import { OverviewComponent } from '../overview/overview.component'; +import { + InputModule, + ModalModule, + SelectModule, + ThemeModule, + ToggletipModule +} from 'carbon-components-angular'; @NgModule({ imports: [ @@ -30,7 +36,8 @@ import { OverviewComponent } from '../overview/overview.component'; ModalModule, InputModule, SelectModule, - OverviewComponent + OverviewComponent, + ThemeModule ], exports: [OverviewComponent], declarations: [DashboardComponent, HealthPieComponent, FeedbackComponent], diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/components/components.module.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/components.module.ts index 12d70e741f9..947c80aece0 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/shared/components/components.module.ts +++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/components.module.ts @@ -42,7 +42,8 @@ import { PopoverModule, InlineLoadingModule, TagModule, - LinkModule + LinkModule, + LayerModule } from 'carbon-components-angular'; import EditIcon from '@carbon/icons/es/edit/20'; import CodeIcon from '@carbon/icons/es/code/16'; @@ -102,6 +103,7 @@ import downloadIcon from '@carbon/icons/es/download/16'; import IdeaIcon from '@carbon/icons/es/idea/20'; import CloseIcon from '@carbon/icons/es/close/16'; import { TearsheetStepComponent } from './tearsheet-step/tearsheet-step.component'; +import { ProductiveCardComponent } from './productive-card/productive-card.component'; @NgModule({ imports: [ @@ -148,7 +150,8 @@ import { TearsheetStepComponent } from './tearsheet-step/tearsheet-step.componen PopoverModule, InlineLoadingModule, TagModule, - LinkModule + LinkModule, + LayerModule ], declarations: [ SparklineComponent, @@ -196,7 +199,8 @@ import { TearsheetStepComponent } from './tearsheet-step/tearsheet-step.componen DetailsCardComponent, ToastComponent, TearsheetComponent, - TearsheetStepComponent + TearsheetStepComponent, + ProductiveCardComponent ], providers: [provideCharts(withDefaultRegisterables())], exports: [ @@ -241,7 +245,8 @@ import { TearsheetStepComponent } from './tearsheet-step/tearsheet-step.componen DetailsCardComponent, ToastComponent, TearsheetComponent, - TearsheetStepComponent + TearsheetStepComponent, + ProductiveCardComponent ] }) export class ComponentsModule { 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 new file mode 100644 index 00000000000..67a4cbfaee4 --- /dev/null +++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/productive-card/productive-card.component.html @@ -0,0 +1,31 @@ + +
+

+ {{title}} +

+ @if(headerActionTemplate) { +
+ +
+ } +
+
+ +
+ @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 new file mode 100644 index 00000000000..cbfd1402f95 --- /dev/null +++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/productive-card/productive-card.component.scss @@ -0,0 +1,48 @@ +@use '@carbon/colors'; + +.productive-card { + margin: 0; + padding: 0; + + &-header { + margin: 0; + padding: var(--cds-spacing-05); + + &-title { + margin: 0; + } + + &-actions { + margin: 0; + } + } + + &-section { + margin: 0; + padding: var(--cds-spacing-05); + padding-top: 0; + + &--footer { + padding-bottom: 0; + } + } + + &-footer { + height: var(--cds-spacing-08); + padding: var(--cds-spacing-05); + } + + &--shadow { + background-color: var(--cds-layer); + position: relative; + overflow: hidden; // ensures proper edge fade + background-image: + // cyan left edge + radial-gradient(120% 60% at -15% 100%, rgba(colors.$cyan-60, 0.13) 0%, transparent 65%), + // cyan right edge + radial-gradient(120% 60% at 115% 100%, rgba(colors.$cyan-60, 0.1) 0%, transparent 65%), + // pink center + radial-gradient(120% 60% at 50% 100%, rgba(colors.$magenta-60, 0.11) 0%, transparent 70%); + box-shadow: var(--cds-ai-drop-shadow), inset 0 0 0 1px var(--cds-ai-inner-shadow); + } +} diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/components/productive-card/productive-card.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/productive-card/productive-card.component.spec.ts new file mode 100644 index 00000000000..0fe568b44db --- /dev/null +++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/productive-card/productive-card.component.spec.ts @@ -0,0 +1,24 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ProductiveCardComponent } from './productive-card.component'; +import { GridModule, LayerModule, TilesModule } from 'carbon-components-angular'; + +describe('ProductiveCardComponent', () => { + let component: ProductiveCardComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ProductiveCardComponent], + imports: [GridModule, LayerModule, TilesModule] + }).compileComponents(); + + fixture = TestBed.createComponent(ProductiveCardComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); 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 new file mode 100644 index 00000000000..7047a1a3c68 --- /dev/null +++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/productive-card/productive-card.component.ts @@ -0,0 +1,38 @@ +import { Component, ContentChild, Input, TemplateRef } from '@angular/core'; + +/** + * A generic productive card component. + * + * @example + * + * ... + * ... + *

My card body content

+ *
+ */ +@Component({ + selector: 'cd-productive-card', + standalone: false, + templateUrl: './productive-card.component.html', + styleUrl: './productive-card.component.scss' +}) +export class ProductiveCardComponent { + /* Card Title */ + @Input() title!: string; + + /* Optional: Applies a tinted-colored background to card */ + @Input() applyShadow: boolean = false; + + /* Optional: Header action template, appears alongwith title in top-right corner */ + @ContentChild('headerAction', { + read: TemplateRef + }) + headerActionTemplate?: TemplateRef; + + /* Optional: Footer template , otherwise no footer will be used for card.*/ + @ContentChild('footer', { + read: TemplateRef + }) + footerTemplate?: TemplateRef; +}