Skip to content

Commit 36ac178

Browse files
authored
Merge pull request ceph#64225 from rhcs-dashboard/inline-tip-notification
mgr/dashboard: add support for inline-tip notification Reviewed-by: Afreen Misbah <[email protected]> Reviewed-by: Nizamudeen A <[email protected]>
2 parents 9f08c1f + bb52430 commit 36ac178

File tree

7 files changed

+211
-8
lines changed

7 files changed

+211
-8
lines changed

src/pybind/mgr/dashboard/frontend/src/app/shared/components/components.module.ts

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,8 @@ import {
3636
SelectModule,
3737
ComboBoxModule,
3838
ProgressIndicatorModule,
39-
PanelModule
39+
PanelModule,
40+
LayoutModule
4041
} from 'carbon-components-angular';
4142
import EditIcon from '@carbon/icons/es/edit/20';
4243
import CodeIcon from '@carbon/icons/es/code/16';
@@ -83,13 +84,16 @@ import { FormAdvancedFieldsetComponent } from './form-advanced-fieldset/form-adv
8384
import { UpgradableComponent } from './upgradable/upgradable.component';
8485
import { ProgressComponent } from './progress/progress.component';
8586
import { SidePanelComponent } from './side-panel/side-panel.component';
87+
import { ChartsModule } from '@carbon/charts-angular';
88+
import { InlineMessageComponent } from './inline-message/inline-message.component';
89+
import { IconComponent } from './icon/icon.component';
8690

8791
// Icons
8892
import InfoIcon from '@carbon/icons/es/information/16';
8993
import CopyIcon from '@carbon/icons/es/copy/32';
9094
import downloadIcon from '@carbon/icons/es/download/16';
91-
import { ChartsModule } from '@carbon/charts-angular';
92-
import { IconComponent } from './icon/icon.component';
95+
import IdeaIcon from '@carbon/icons/es/idea/20';
96+
import CloseIcon from '@carbon/icons/es/close/16';
9397

9498
@NgModule({
9599
imports: [
@@ -130,7 +134,8 @@ import { IconComponent } from './icon/icon.component';
130134
ProgressIndicatorModule,
131135
BaseChartDirective,
132136
PanelModule,
133-
ChartsModule
137+
ChartsModule,
138+
LayoutModule
134139
],
135140
declarations: [
136141
SparklineComponent,
@@ -174,7 +179,8 @@ import { IconComponent } from './icon/icon.component';
174179
UpgradableComponent,
175180
ProgressComponent,
176181
SidePanelComponent,
177-
IconComponent
182+
IconComponent,
183+
InlineMessageComponent
178184
],
179185
providers: [provideCharts(withDefaultRegisterables())],
180186
exports: [
@@ -215,11 +221,20 @@ import { IconComponent } from './icon/icon.component';
215221
UpgradableComponent,
216222
ProgressComponent,
217223
SidePanelComponent,
218-
IconComponent
224+
IconComponent,
225+
InlineMessageComponent
219226
]
220227
})
221228
export class ComponentsModule {
222229
constructor(private iconService: IconService) {
223-
this.iconService.registerAll([InfoIcon, CopyIcon, EditIcon, CodeIcon, downloadIcon]);
230+
this.iconService.registerAll([
231+
InfoIcon,
232+
CopyIcon,
233+
EditIcon,
234+
CodeIcon,
235+
downloadIcon,
236+
IdeaIcon,
237+
CloseIcon
238+
]);
224239
}
225240
}
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
@if (!isDismissed) {
2+
<div class="inline-tip-container"
3+
[cdsStack]="'horizontal'"
4+
[gap]="4">
5+
<div class="close-btn-position">
6+
<cds-icon-button class="close-btn inline-tip-bg-color"
7+
type="button"
8+
kind="ghost"
9+
size="sm"
10+
description="Close"
11+
i18n-description
12+
(click)="close()">
13+
<svg [size]="icons.size16"
14+
[cdsIcon]="icons.destroy"></svg>
15+
</cds-icon-button>
16+
</div>
17+
18+
<div class="inline-tip-body"
19+
[cdsStack]="'horizontal'"
20+
[gap]="4">
21+
<svg [cdsIcon]="icons.idea"
22+
[size]="icons.size20"></svg>
23+
24+
<div [cdsStack]="'vertical'"
25+
[gap]="1"
26+
class="inline-tip-body-content">
27+
@if (title) {
28+
<h1 class="cds--type-heading-compact-01">{{ title }}</h1>
29+
}
30+
31+
<div class="cds--type-body-compact-01"
32+
[class.cds--text-truncate--end]="isTruncated">
33+
<ng-content></ng-content>
34+
</div>
35+
@if (collapsible) {
36+
<button class="inline-tip-bg-color btn-toggle"
37+
cdsButton="ghost"
38+
size="md"
39+
(click)="toggleContent()">
40+
<span i18n>{{ isTruncated ? 'Read more' : 'Read less' }}</span>
41+
</button>
42+
}
43+
</div>
44+
</div>
45+
</div>
46+
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
@use '@carbon/colors';
2+
@use '@carbon/themes';
3+
@use './src/styles/vendor/variables' as vv;
4+
@use '@carbon/layout';
5+
6+
.inline-tip-container {
7+
position: relative;
8+
background: linear-gradient(90deg, colors.$blue-90, colors.$purple-70);
9+
color: vv.$white;
10+
padding: layout.$spacing-05;
11+
12+
.inline-tip-body-content {
13+
width: 80%;
14+
15+
.btn-toggle {
16+
margin-top: layout.$spacing-05;
17+
color: themes.$link-inverse-hover;
18+
19+
&:hover {
20+
color: themes.$link-inverse-active;
21+
}
22+
}
23+
}
24+
}
25+
26+
.close-btn-position {
27+
position: absolute;
28+
top: 0;
29+
right: 0;
30+
31+
.close-btn {
32+
padding: 0;
33+
34+
svg {
35+
fill: themes.$icon-on-color;
36+
}
37+
}
38+
}
39+
40+
.inline-tip-bg-color:hover {
41+
background-color: #7f3ae7;
42+
}
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
import { ComponentFixture, TestBed } from '@angular/core/testing';
2+
import { InlineMessageComponent } from './inline-message.component';
3+
import { ButtonModule, IconModule, LayoutModule } from 'carbon-components-angular';
4+
5+
describe('InlineMessageComponent', () => {
6+
let component: InlineMessageComponent;
7+
let fixture: ComponentFixture<InlineMessageComponent>;
8+
beforeEach(async () => {
9+
await TestBed.configureTestingModule({
10+
declarations: [InlineMessageComponent],
11+
imports: [LayoutModule, IconModule, ButtonModule]
12+
}).compileComponents();
13+
14+
fixture = TestBed.createComponent(InlineMessageComponent);
15+
component = fixture.componentInstance;
16+
fixture.detectChanges();
17+
});
18+
19+
it('should create', () => {
20+
expect(component).toBeTruthy();
21+
});
22+
23+
it('should have default values for inputs', () => {
24+
expect(component.collapsible).toBe(false);
25+
expect(component.title).toBe('');
26+
expect(component.onClose).toBeDefined();
27+
});
28+
29+
it('should set collapsible input', () => {
30+
component.collapsible = true;
31+
expect(component.collapsible).toBe(true);
32+
});
33+
34+
it('should set title input', () => {
35+
component.title = 'Test Title';
36+
expect(component.title).toBe('Test Title');
37+
});
38+
39+
it('should call onClose and set isDismissed to true when Close is called', () => {
40+
const onCloseSpy = jasmine.createSpy('onClose');
41+
component.onClose = onCloseSpy;
42+
component.isDismissed = false;
43+
component.close();
44+
expect(component.isDismissed).toBe(true);
45+
expect(onCloseSpy).toHaveBeenCalled();
46+
});
47+
48+
it('should toggle isTruncated when toggleContent is called', () => {
49+
component.isTruncated = false;
50+
component.toggleContent();
51+
expect(component.isTruncated).toBe(true);
52+
component.toggleContent();
53+
expect(component.isTruncated).toBe(false);
54+
});
55+
56+
it('should have icons property set to Icons enum', () => {
57+
expect(component.icons).toBeDefined();
58+
});
59+
});
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import { Component, Input } from '@angular/core';
2+
import { Icons } from '../../enum/icons.enum';
3+
4+
@Component({
5+
selector: 'cd-inline-message',
6+
templateUrl: './inline-message.component.html',
7+
styleUrl: './inline-message.component.scss'
8+
})
9+
export class InlineMessageComponent {
10+
// collapsible when true will show read more/read less button
11+
@Input()
12+
collapsible = false;
13+
// title to show in the message
14+
15+
@Input()
16+
title = '';
17+
18+
// callback function to execute onclose
19+
@Input()
20+
onClose?: () => void = () => {};
21+
22+
isTruncated = false;
23+
icons = Icons;
24+
isDismissed = false;
25+
26+
close() {
27+
this.isDismissed = true;
28+
if (this.onClose) {
29+
this.onClose();
30+
}
31+
}
32+
33+
toggleContent() {
34+
this.isTruncated = !this.isTruncated;
35+
}
36+
}

src/pybind/mgr/dashboard/frontend/src/app/shared/enum/icons.enum.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ export enum Icons {
8383
launch = 'launch',
8484
parentChild = 'parent-child',
8585
dataTable = 'data-table',
86+
idea = 'idea',
8687
/* Icons for special effect */
8788
size16 = '16',
8889
size20 = '20',

src/pybind/mgr/dashboard/frontend/src/styles/_carbon-defaults.scss

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
);
3232
@use '@carbon/styles';
3333
@use '@carbon/type';
34+
@use '@carbon/styles/scss/utilities/text-truncate' as textTruncate;
3435

3536
/******************************************
3637
Custom theme
@@ -40,7 +41,6 @@ Custom theme
4041
/******************************************
4142
Datatable
4243
******************************************/
43-
4444
:root {
4545
@include type.type-classes();
4646
}
@@ -212,3 +212,7 @@ Tabs
212212
.cds-mb-4 {
213213
margin-bottom: layout.$spacing-02;
214214
}
215+
216+
.cds--text-truncate--end {
217+
@include textTruncate.text-truncate-end;
218+
}

0 commit comments

Comments
 (0)