From: Afreen Misbah Date: Tue, 13 Jan 2026 17:26:34 +0000 (+0530) Subject: mgr/dashboard: Add new landing page component X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=c83576707e4037cc92bfeb475aa998e10fbe1f15;p=ceph.git mgr/dashboard: Add new landing page component Fixes https://tracker.ceph.com/issues/74409 - flagged by DASHBOARD fetaure flag - added tests - added layout for overview page - dropped using get API which is getting polled freqently for perf Signed-off-by: Afreen Misbah (cherry picked from commit 9a07fbf6e2848025124458faee6db953f6d91a2b) Conflicts: src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard/dashboard.module.ts src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard/dashboard/dashboard.component.html src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard/dashboard/dashboard.component.ts src/pybind/mgr/dashboard/frontend/src/app/shared/services/feature-toggles.service.ts --- diff --git a/src/pybind/mgr/dashboard/frontend/.nx/cache/terminalOutputs/10501135011127341749 b/src/pybind/mgr/dashboard/frontend/.nx/cache/terminalOutputs/10501135011127341749 new file mode 100644 index 00000000000..00c12264752 --- /dev/null +++ b/src/pybind/mgr/dashboard/frontend/.nx/cache/terminalOutputs/10501135011127341749 @@ -0,0 +1,5 @@ + +Linting "ceph-dashboard"... + +All files pass linting. + diff --git a/src/pybind/mgr/dashboard/frontend/.nx/cache/terminalOutputs/12707214466441736553 b/src/pybind/mgr/dashboard/frontend/.nx/cache/terminalOutputs/12707214466441736553 new file mode 100644 index 00000000000..00c12264752 --- /dev/null +++ b/src/pybind/mgr/dashboard/frontend/.nx/cache/terminalOutputs/12707214466441736553 @@ -0,0 +1,5 @@ + +Linting "ceph-dashboard"... + +All files pass linting. + diff --git a/src/pybind/mgr/dashboard/frontend/.nx/cache/terminalOutputs/13106400625475788256 b/src/pybind/mgr/dashboard/frontend/.nx/cache/terminalOutputs/13106400625475788256 new file mode 100644 index 00000000000..00c12264752 --- /dev/null +++ b/src/pybind/mgr/dashboard/frontend/.nx/cache/terminalOutputs/13106400625475788256 @@ -0,0 +1,5 @@ + +Linting "ceph-dashboard"... + +All files pass linting. + diff --git a/src/pybind/mgr/dashboard/frontend/.nx/cache/terminalOutputs/13685585831439463788 b/src/pybind/mgr/dashboard/frontend/.nx/cache/terminalOutputs/13685585831439463788 new file mode 100644 index 00000000000..00c12264752 --- /dev/null +++ b/src/pybind/mgr/dashboard/frontend/.nx/cache/terminalOutputs/13685585831439463788 @@ -0,0 +1,5 @@ + +Linting "ceph-dashboard"... + +All files pass linting. + diff --git a/src/pybind/mgr/dashboard/frontend/.nx/cache/terminalOutputs/1758954290910463637 b/src/pybind/mgr/dashboard/frontend/.nx/cache/terminalOutputs/1758954290910463637 new file mode 100644 index 00000000000..00c12264752 --- /dev/null +++ b/src/pybind/mgr/dashboard/frontend/.nx/cache/terminalOutputs/1758954290910463637 @@ -0,0 +1,5 @@ + +Linting "ceph-dashboard"... + +All files pass linting. + diff --git a/src/pybind/mgr/dashboard/frontend/.nx/cache/terminalOutputs/2801012194694874285 b/src/pybind/mgr/dashboard/frontend/.nx/cache/terminalOutputs/2801012194694874285 new file mode 100644 index 00000000000..00c12264752 --- /dev/null +++ b/src/pybind/mgr/dashboard/frontend/.nx/cache/terminalOutputs/2801012194694874285 @@ -0,0 +1,5 @@ + +Linting "ceph-dashboard"... + +All files pass linting. + diff --git a/src/pybind/mgr/dashboard/frontend/.nx/cache/terminalOutputs/4379954223956111510 b/src/pybind/mgr/dashboard/frontend/.nx/cache/terminalOutputs/4379954223956111510 new file mode 100644 index 00000000000..00c12264752 --- /dev/null +++ b/src/pybind/mgr/dashboard/frontend/.nx/cache/terminalOutputs/4379954223956111510 @@ -0,0 +1,5 @@ + +Linting "ceph-dashboard"... + +All files pass linting. + diff --git a/src/pybind/mgr/dashboard/frontend/.nx/cache/terminalOutputs/5698680818973360491 b/src/pybind/mgr/dashboard/frontend/.nx/cache/terminalOutputs/5698680818973360491 new file mode 100644 index 00000000000..00c12264752 --- /dev/null +++ b/src/pybind/mgr/dashboard/frontend/.nx/cache/terminalOutputs/5698680818973360491 @@ -0,0 +1,5 @@ + +Linting "ceph-dashboard"... + +All files pass linting. + diff --git a/src/pybind/mgr/dashboard/frontend/.nx/cache/terminalOutputs/6554461255961944329 b/src/pybind/mgr/dashboard/frontend/.nx/cache/terminalOutputs/6554461255961944329 new file mode 100644 index 00000000000..00c12264752 --- /dev/null +++ b/src/pybind/mgr/dashboard/frontend/.nx/cache/terminalOutputs/6554461255961944329 @@ -0,0 +1,5 @@ + +Linting "ceph-dashboard"... + +All files pass linting. + diff --git a/src/pybind/mgr/dashboard/frontend/.nx/cache/terminalOutputs/7234210859985966681 b/src/pybind/mgr/dashboard/frontend/.nx/cache/terminalOutputs/7234210859985966681 new file mode 100644 index 00000000000..00c12264752 --- /dev/null +++ b/src/pybind/mgr/dashboard/frontend/.nx/cache/terminalOutputs/7234210859985966681 @@ -0,0 +1,5 @@ + +Linting "ceph-dashboard"... + +All files pass linting. + diff --git a/src/pybind/mgr/dashboard/frontend/.nx/cache/terminalOutputs/741499322021383751 b/src/pybind/mgr/dashboard/frontend/.nx/cache/terminalOutputs/741499322021383751 new file mode 100644 index 00000000000..00c12264752 --- /dev/null +++ b/src/pybind/mgr/dashboard/frontend/.nx/cache/terminalOutputs/741499322021383751 @@ -0,0 +1,5 @@ + +Linting "ceph-dashboard"... + +All files pass linting. + diff --git a/src/pybind/mgr/dashboard/frontend/.nx/cache/terminalOutputs/9919571031428218619 b/src/pybind/mgr/dashboard/frontend/.nx/cache/terminalOutputs/9919571031428218619 new file mode 100644 index 00000000000..00c12264752 --- /dev/null +++ b/src/pybind/mgr/dashboard/frontend/.nx/cache/terminalOutputs/9919571031428218619 @@ -0,0 +1,5 @@ + +Linting "ceph-dashboard"... + +All files pass linting. + diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard/dashboard/dashboard.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard/dashboard/dashboard.component.spec.ts index 9c20e4438f1..d3b4f5e8bb9 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard/dashboard/dashboard.component.spec.ts +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard/dashboard/dashboard.component.spec.ts @@ -1,6 +1,7 @@ import { HttpClientTestingModule } from '@angular/common/http/testing'; import { NO_ERRORS_SCHEMA } from '@angular/core'; import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { By } from '@angular/platform-browser'; import { NgbNavModule } from '@ng-bootstrap/ng-bootstrap'; import { FeatureTogglesService } from '~/app/shared/services/feature-toggles.service'; @@ -11,6 +12,7 @@ import { DashboardComponent } from './dashboard.component'; describe('DashboardComponent', () => { let component: DashboardComponent; let fixture: ComponentFixture; + let featureTogglesService: FeatureTogglesService; configureTestBed({ imports: [NgbNavModule, HttpClientTestingModule], @@ -20,12 +22,70 @@ describe('DashboardComponent', () => { }); beforeEach(() => { + featureTogglesService = TestBed.inject(FeatureTogglesService); fixture = TestBed.createComponent(DashboardComponent); component = fixture.componentInstance; - fixture.detectChanges(); }); it('should create', () => { + spyOn(featureTogglesService, 'isFeatureEnabled').and.returnValue(true); + + fixture.detectChanges(); expect(component).toBeTruthy(); }); + + it('should call featureTogglesService.isFeatureEnabled() on initialization', () => { + const spy = spyOn(featureTogglesService, 'isFeatureEnabled').and.returnValue(true); + fixture.detectChanges(); + expect(spy).toHaveBeenCalled(); + expect(spy).toHaveBeenCalledWith('dashboard'); + }); + + it('should set useDeprecated based on feature toggle', () => { + spyOn(featureTogglesService, 'isFeatureEnabled').and.returnValue(true); + fixture.detectChanges(); + expect(component.useDeprecated).toBe(true); + }); + + describe('when dashboard feature is enabled (new dashboard)', () => { + beforeEach(() => { + spyOn(featureTogglesService, 'isFeatureEnabled').and.returnValue(true); + fixture.detectChanges(); + }); + + it('should show cd-dashboard-v3 in template when dashboard feature is enabled', () => { + const overviewElement = fixture.debugElement.query(By.css('[data-testid="cd-overview"]')); + const dashboardV3Element = fixture.debugElement.query( + By.css('[data-testid="cd-dashboard-v3"]') + ); + + expect(overviewElement).toBeNull(); + expect(dashboardV3Element).toBeTruthy(); + }); + + it('should set useDeprecated to false when feature is enabled', () => { + expect(component.useDeprecated).toBe(true); + }); + }); + + describe('when dashboard feature is disabled (old dashboard)', () => { + beforeEach(() => { + spyOn(featureTogglesService, 'isFeatureEnabled').and.returnValue(false); + fixture.detectChanges(); + }); + + it('should show cd-overview in template when dashboard feature is disabled', () => { + const overviewElement = fixture.debugElement.query(By.css('[data-testid="cd-overview"]')); + const dashboardV3Element = fixture.debugElement.query( + By.css('[data-testid="cd-dashboard-v3"]') + ); + + expect(overviewElement).toBeTruthy(); + expect(dashboardV3Element).toBeNull(); + }); + + it('should set useDeprecated to true when feature is disabled', () => { + expect(component.useDeprecated).toBe(false); + }); + }); }); 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 new file mode 100644 index 00000000000..d736a3df24b --- /dev/null +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/overview/overview.component.html @@ -0,0 +1,36 @@ +
+
+
+ Health card +
+
+ Alerts card +
+
+
+
+ Storage card +
+
+ Docs card +
+
+
+
+ Performance card +
+
+
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/overview/overview.component.scss b/src/pybind/mgr/dashboard/frontend/src/app/ceph/overview/overview.component.scss new file mode 100644 index 00000000000..a84b2ba119c --- /dev/null +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/overview/overview.component.scss @@ -0,0 +1,8 @@ +.overview { + margin-top: var(--cds-spacing-05); + margin-bottom: var(--cds-spacing-05); +} + +.overview-row { + margin-bottom: var(--cds-spacing-05); +} diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/overview/overview.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/overview/overview.component.spec.ts new file mode 100644 index 00000000000..2774459b713 --- /dev/null +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/overview/overview.component.spec.ts @@ -0,0 +1,22 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { OverviewComponent } from './overview.component'; + +describe('OverviewComponent', () => { + let component: OverviewComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + imports: [OverviewComponent] + }).compileComponents(); + + fixture = TestBed.createComponent(OverviewComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); 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 new file mode 100644 index 00000000000..4ba2a899556 --- /dev/null +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/overview/overview.component.ts @@ -0,0 +1,11 @@ +import { Component } from '@angular/core'; +import { GridModule, TilesModule } from 'carbon-components-angular'; + +@Component({ + selector: 'cd-overview', + imports: [GridModule, TilesModule], + standalone: true, + templateUrl: './overview.component.html', + styleUrl: './overview.component.scss' +}) +export class OverviewComponent {} diff --git a/src/pybind/mgr/dashboard/plugins/feature_toggles.py b/src/pybind/mgr/dashboard/plugins/feature_toggles.py index 63b1d762c34..6ff3931bd14 100644 --- a/src/pybind/mgr/dashboard/plugins/feature_toggles.py +++ b/src/pybind/mgr/dashboard/plugins/feature_toggles.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- from enum import Enum -from typing import Dict, List, Optional, Set, no_type_check +from typing import Dict, List, Optional, Set import cherrypy from mgr_module import CLICommand, Option @@ -115,7 +115,6 @@ class FeatureToggles(I.CanMgr, I.Setupable, I.HasOptions, return ret, '\n'.join(msg), '' return {'handle_command': cmd} - @no_type_check # https://github.com/python/mypy/issues/7806 def _get_feature_from_request(self, request): try: return self.Controller2Feature[ @@ -124,7 +123,6 @@ class FeatureToggles(I.CanMgr, I.Setupable, I.HasOptions, return None @ttl_cache(ttl=CACHE_TTL, maxsize=CACHE_MAX_SIZE) - @no_type_check # https://github.com/python/mypy/issues/7806 def _is_feature_enabled(self, feature): return self.mgr.get_module_option(self.OPTION_FMT.format(feature))