From bb52430eb31f7eaa8c8546718cc177ada349c4bb Mon Sep 17 00:00:00 2001 From: Naman Munet Date: Fri, 27 Jun 2025 14:00:42 +0530 Subject: [PATCH] mgr/dashboard: add support for inline-tip notification https://tracker.ceph.com/issues/71870 Signed-off-by: Naman Munet --- .../shared/components/components.module.ts | 29 ++++++--- .../inline-message.component.html | 46 +++++++++++++++ .../inline-message.component.scss | 42 +++++++++++++ .../inline-message.component.spec.ts | 59 +++++++++++++++++++ .../inline-message.component.ts | 36 +++++++++++ .../src/app/shared/enum/icons.enum.ts | 1 + .../frontend/src/styles/_carbon-defaults.scss | 6 +- 7 files changed, 211 insertions(+), 8 deletions(-) create mode 100644 src/pybind/mgr/dashboard/frontend/src/app/shared/components/inline-message/inline-message.component.html create mode 100644 src/pybind/mgr/dashboard/frontend/src/app/shared/components/inline-message/inline-message.component.scss create mode 100644 src/pybind/mgr/dashboard/frontend/src/app/shared/components/inline-message/inline-message.component.spec.ts create mode 100644 src/pybind/mgr/dashboard/frontend/src/app/shared/components/inline-message/inline-message.component.ts 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 868a09b7af1..b22124cebfd 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 @@ -36,7 +36,8 @@ import { SelectModule, ComboBoxModule, ProgressIndicatorModule, - PanelModule + PanelModule, + LayoutModule } from 'carbon-components-angular'; import EditIcon from '@carbon/icons/es/edit/20'; import CodeIcon from '@carbon/icons/es/code/16'; @@ -83,13 +84,16 @@ import { FormAdvancedFieldsetComponent } from './form-advanced-fieldset/form-adv import { UpgradableComponent } from './upgradable/upgradable.component'; import { ProgressComponent } from './progress/progress.component'; import { SidePanelComponent } from './side-panel/side-panel.component'; +import { ChartsModule } from '@carbon/charts-angular'; +import { InlineMessageComponent } from './inline-message/inline-message.component'; +import { IconComponent } from './icon/icon.component'; // Icons import InfoIcon from '@carbon/icons/es/information/16'; import CopyIcon from '@carbon/icons/es/copy/32'; import downloadIcon from '@carbon/icons/es/download/16'; -import { ChartsModule } from '@carbon/charts-angular'; -import { IconComponent } from './icon/icon.component'; +import IdeaIcon from '@carbon/icons/es/idea/20'; +import CloseIcon from '@carbon/icons/es/close/16'; @NgModule({ imports: [ @@ -130,7 +134,8 @@ import { IconComponent } from './icon/icon.component'; ProgressIndicatorModule, BaseChartDirective, PanelModule, - ChartsModule + ChartsModule, + LayoutModule ], declarations: [ SparklineComponent, @@ -174,7 +179,8 @@ import { IconComponent } from './icon/icon.component'; UpgradableComponent, ProgressComponent, SidePanelComponent, - IconComponent + IconComponent, + InlineMessageComponent ], providers: [provideCharts(withDefaultRegisterables())], exports: [ @@ -215,11 +221,20 @@ import { IconComponent } from './icon/icon.component'; UpgradableComponent, ProgressComponent, SidePanelComponent, - IconComponent + IconComponent, + InlineMessageComponent ] }) export class ComponentsModule { constructor(private iconService: IconService) { - this.iconService.registerAll([InfoIcon, CopyIcon, EditIcon, CodeIcon, downloadIcon]); + this.iconService.registerAll([ + InfoIcon, + CopyIcon, + EditIcon, + CodeIcon, + downloadIcon, + IdeaIcon, + CloseIcon + ]); } } diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/components/inline-message/inline-message.component.html b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/inline-message/inline-message.component.html new file mode 100644 index 00000000000..d6fba56b49e --- /dev/null +++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/inline-message/inline-message.component.html @@ -0,0 +1,46 @@ +@if (!isDismissed) { +
+
+ + + +
+ +
+ + +
+ @if (title) { +

{{ title }}

+ } + +
+ +
+ @if (collapsible) { + + } +
+
+
+} diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/components/inline-message/inline-message.component.scss b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/inline-message/inline-message.component.scss new file mode 100644 index 00000000000..7afc990188e --- /dev/null +++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/inline-message/inline-message.component.scss @@ -0,0 +1,42 @@ +@use '@carbon/colors'; +@use '@carbon/themes'; +@use './src/styles/vendor/variables' as vv; +@use '@carbon/layout'; + +.inline-tip-container { + position: relative; + background: linear-gradient(90deg, colors.$blue-90, colors.$purple-70); + color: vv.$white; + padding: layout.$spacing-05; + + .inline-tip-body-content { + width: 80%; + + .btn-toggle { + margin-top: layout.$spacing-05; + color: themes.$link-inverse-hover; + + &:hover { + color: themes.$link-inverse-active; + } + } + } +} + +.close-btn-position { + position: absolute; + top: 0; + right: 0; + + .close-btn { + padding: 0; + + svg { + fill: themes.$icon-on-color; + } + } +} + +.inline-tip-bg-color:hover { + background-color: #7f3ae7; +} diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/components/inline-message/inline-message.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/inline-message/inline-message.component.spec.ts new file mode 100644 index 00000000000..a12590eed31 --- /dev/null +++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/inline-message/inline-message.component.spec.ts @@ -0,0 +1,59 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { InlineMessageComponent } from './inline-message.component'; +import { ButtonModule, IconModule, LayoutModule } from 'carbon-components-angular'; + +describe('InlineMessageComponent', () => { + let component: InlineMessageComponent; + let fixture: ComponentFixture; + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [InlineMessageComponent], + imports: [LayoutModule, IconModule, ButtonModule] + }).compileComponents(); + + fixture = TestBed.createComponent(InlineMessageComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); + + it('should have default values for inputs', () => { + expect(component.collapsible).toBe(false); + expect(component.title).toBe(''); + expect(component.onClose).toBeDefined(); + }); + + it('should set collapsible input', () => { + component.collapsible = true; + expect(component.collapsible).toBe(true); + }); + + it('should set title input', () => { + component.title = 'Test Title'; + expect(component.title).toBe('Test Title'); + }); + + it('should call onClose and set isDismissed to true when Close is called', () => { + const onCloseSpy = jasmine.createSpy('onClose'); + component.onClose = onCloseSpy; + component.isDismissed = false; + component.close(); + expect(component.isDismissed).toBe(true); + expect(onCloseSpy).toHaveBeenCalled(); + }); + + it('should toggle isTruncated when toggleContent is called', () => { + component.isTruncated = false; + component.toggleContent(); + expect(component.isTruncated).toBe(true); + component.toggleContent(); + expect(component.isTruncated).toBe(false); + }); + + it('should have icons property set to Icons enum', () => { + expect(component.icons).toBeDefined(); + }); +}); diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/components/inline-message/inline-message.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/inline-message/inline-message.component.ts new file mode 100644 index 00000000000..aa15a77217d --- /dev/null +++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/inline-message/inline-message.component.ts @@ -0,0 +1,36 @@ +import { Component, Input } from '@angular/core'; +import { Icons } from '../../enum/icons.enum'; + +@Component({ + selector: 'cd-inline-message', + templateUrl: './inline-message.component.html', + styleUrl: './inline-message.component.scss' +}) +export class InlineMessageComponent { + // collapsible when true will show read more/read less button + @Input() + collapsible = false; + // title to show in the message + + @Input() + title = ''; + + // callback function to execute onclose + @Input() + onClose?: () => void = () => {}; + + isTruncated = false; + icons = Icons; + isDismissed = false; + + close() { + this.isDismissed = true; + if (this.onClose) { + this.onClose(); + } + } + + toggleContent() { + this.isTruncated = !this.isTruncated; + } +} diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/enum/icons.enum.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/enum/icons.enum.ts index 8c86a302f18..f1895743c79 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/shared/enum/icons.enum.ts +++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/enum/icons.enum.ts @@ -83,6 +83,7 @@ export enum Icons { launch = 'launch', parentChild = 'parent-child', dataTable = 'data-table', + idea = 'idea', /* Icons for special effect */ size16 = '16', size20 = '20', diff --git a/src/pybind/mgr/dashboard/frontend/src/styles/_carbon-defaults.scss b/src/pybind/mgr/dashboard/frontend/src/styles/_carbon-defaults.scss index 7bc6e6c0079..b1ba3d9ec47 100644 --- a/src/pybind/mgr/dashboard/frontend/src/styles/_carbon-defaults.scss +++ b/src/pybind/mgr/dashboard/frontend/src/styles/_carbon-defaults.scss @@ -31,6 +31,7 @@ ); @use '@carbon/styles'; @use '@carbon/type'; +@use '@carbon/styles/scss/utilities/text-truncate' as textTruncate; /****************************************** Custom theme @@ -40,7 +41,6 @@ Custom theme /****************************************** Datatable ******************************************/ - :root { @include type.type-classes(); } @@ -212,3 +212,7 @@ Tabs .cds-mb-4 { margin-bottom: layout.$spacing-02; } + +.cds--text-truncate--end { + @include textTruncate.text-truncate-end; +} -- 2.39.5