Skip to content

Commit

Permalink
[HXCS-1166] extend SnackBar to customize content appearance (#8379)
Browse files Browse the repository at this point in the history
* [HXCS-1166] add templateRef to SnackBarData interface

* [HXCS-1166] update SnackBarContentComponent

to be able to manage data.templateRef

* [HXCS-1166] add tests to NotificationService

* [HXCS-1166] fix lint

* [HXCS-1166] add documentation

* [HXCS-1166] follow PR advices

* [HXCS-1166] typos

* [HXCS-1166] update testrail id

---------

Co-authored-by: Adriano Costa <[email protected]>
  • Loading branch information
wideLandscape and Adriano Costa authored Mar 21, 2023
1 parent 0c4cc37 commit cfe1588
Show file tree
Hide file tree
Showing 11 changed files with 124 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,32 @@ <h1>Notification Service</h1>
<ul>
<li>Try setting custom message with unicode characters, for example: <strong>I ♥️ ADF</strong></li>
<li>Try setting custom i18n resource key, for example: <strong>APP_LAYOUT.NOTIFICATIONS</strong></li>
<li>Try setting a decorative icon, for example <strong>info</strong> or <strong>folder</strong></li>
<li>Try toggling the action button. Clicking the action within SnackBar should update the label under the toggle button.</li>
<li>All elements support <em>data-automation-id</em> attributes and can be automated.</li>
</ul>

<mat-form-field>
<input
matInput
placeholder="Message"
[(ngModel)]="message"
data-automation-id="notification-message">
</mat-form-field>
<div>
<mat-label class="adf-label">Message:</mat-label>
<mat-form-field>
<input
matInput
placeholder="Message"
[(ngModel)]="message"
data-automation-id="notification-message">
</mat-form-field>
</div>

<div>
<mat-label class="adf-label">Decorative icon:</mat-label>
<mat-form-field>
<input
matInput
placeholder="Decorative Icon"
[(ngModel)]="decorativeIcon"
data-automation-id="notification-icon">
</mat-form-field>
</div>

<div>
<mat-slide-toggle
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
.app-main-content {
padding: 10px;

.adf-label {
margin-right: 12px;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import { takeUntil } from 'rxjs/operators';
export class NotificationsComponent implements OnInit, OnDestroy {

message = 'I ♥️ ADF';
decorativeIcon = 'folder';
withAction = false;
actionOutput = '';
snackBarConfigObject = '';
Expand Down Expand Up @@ -111,6 +112,9 @@ export class NotificationsComponent implements OnInit, OnDestroy {
"duration": "${this.snackBarConfig.duration}",
"horizontalPosition": "${ this.snackBarConfig.horizontalPosition}",
"verticalPosition": "${ this.snackBarConfig.verticalPosition}"}`;

this.snackBarConfig.data = { decorativeIcon: this.decorativeIcon };

if (this.message) {
if (this.withAction) {
this.notificationService
Expand Down
26 changes: 26 additions & 0 deletions docs/core/services/notification.service.md
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,32 @@ export class MyComponent implements OnInit {
}
```

By providing a `decorativeIcon` property in the `SnackBarData`, it is possible to render a decorative
[`MaterialIcon`](https://material.angular.io/components/icon/overview#interactive-icons) to the left of the message.

```ts
import { NotificationService } from '@alfresco/adf-core';
import { MatSnackBarConfig } from '@angular/material/snackbar';

export class MyComponent implements OnInit {

snackBarConfig: MatSnackBarConfig = new MatSnackBarConfig();

constructor(private notificationService: NotificationService) {
}

ngOnInit() {
this.snackBarConfig.data = { decorativeIcon: 'folder' };
this.notificationService
.openSnackMessageAction('Do you want to report this issue?', 'send', snackBarConfig)
.afterDismissed()
.subscribe(() => {
console.log('The snack-bar was dismissed');
});
}
}
```

The default message duration is 5000 ms that is used only if you don't pass a custom duration in the parameters of openSnackMessageAction/openSnackMessage methods.
You can also change the default 5000 ms adding the following configuration in the app.config.json:

Expand Down
7 changes: 7 additions & 0 deletions e2e/core/notifications-component.e2e.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,13 @@ describe('Notifications Component', () => {
await expect(await notificationPage.snackbarPage.getSnackBarMessage()).toEqual('test');
});

it('[C694098] Should show a decorative icon when the message and the icon fields are not empty and button is clicked', async () => {
await notificationPage.enterMessageField('test');
await notificationPage.enterDecorativeIconField('folder');
await notificationPage.clickNotificationButton();
await expect(await notificationPage.snackbarPage.getSnackBarDecorativeIcon()).toEqual('folder');
});

it('[C279978] Should show notification with action when the message is not empty and button is clicked', async () => {
await notificationPage.enterMessageField('test');
await notificationPage.clickActionToggle();
Expand Down
5 changes: 5 additions & 0 deletions e2e/core/pages/notification.page.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ export class NotificationDemoPage {
snackbarPage = new SnackbarPage();

messageField = $('input[data-automation-id="notification-message"]');
decorativeIconField = $('input[data-automation-id="notification-icon"]');
durationField = $('input[data-automation-id="notification-duration"]');
actionToggle = $('mat-slide-toggle[data-automation-id="notification-action-toggle"]');
notificationSnackBar = $$('simple-snack-bar').first();
Expand Down Expand Up @@ -50,6 +51,10 @@ export class NotificationDemoPage {
await BrowserActions.clearSendKeys(this.messageField, text);
}

async enterDecorativeIconField(icon: string): Promise<void> {
await BrowserActions.clearSendKeys(this.decorativeIconField, icon);
}

async enterDurationField(time: number): Promise<void> {
await BrowserActions.clearSendKeys(this.durationField, time.toString());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import { TranslateModule } from '@ngx-translate/core';
providers: [NotificationService]
})
class ProvidesNotificationServiceComponent {

constructor(public notificationService: NotificationService) {

}
Expand Down Expand Up @@ -70,6 +71,22 @@ class ProvidesNotificationServiceComponent {
return this.notificationService.openSnackMessageAction('Test notification', 'TestWarn', matSnackBarConfig);
}

sendMessageWithDecorativeIcon() {
const notificationConfig = new MatSnackBarConfig();
notificationConfig.duration = 1000;
notificationConfig.data = {decorativeIcon: 'info'};

return this.notificationService.openSnackMessage('with decorative icon', notificationConfig);
}

sendMessageWithDecorativeIconAndAction() {
const notificationConfig = new MatSnackBarConfig();
notificationConfig.duration = 1000;
notificationConfig.data = { decorativeIcon: 'folder' };

return this.notificationService.openSnackMessageAction('with decorative icon', 'TestWarn', notificationConfig);
}

}

describe('NotificationService', () => {
Expand Down Expand Up @@ -197,4 +214,27 @@ describe('NotificationService', () => {

expect(document.querySelector('snack-bar-container')).not.toBeNull();
});

it('should open a message notification bar with a decorative icon', (done) => {
const promise = fixture.componentInstance.sendMessageWithDecorativeIcon();
promise.afterDismissed().subscribe(() => {
done();
});

fixture.detectChanges();

expect(document.querySelector('[data-automation-id="adf-snackbar-message-content"] mat-icon')).not.toBeNull();
});

it('should open a message notification bar with action and a decorative icon', (done) => {
const promise = fixture.componentInstance.sendMessageWithDecorativeIconAndAction();
promise.afterDismissed().subscribe(() => {
done();
});

fixture.detectChanges();

expect(document.querySelector('[data-automation-id="adf-snackbar-message-content"] mat-icon')).not.toBeNull();
});

});
1 change: 1 addition & 0 deletions lib/core/src/lib/snackbar-content/snack-bar-data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,5 @@ export interface SnackBarData {
message: string;
showAction?: boolean;
callActionOnIconClick?: boolean;
decorativeIcon?: string;
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
<p class="adf-snackbar-message-content" data-automation-id="adf-snackbar-message-content" aria-hidden="true">{{ data.message }}</p>
<p class="adf-snackbar-message-content" data-automation-id="adf-snackbar-message-content" aria-hidden="true">
<mat-icon *ngIf="data.decorativeIcon" data-automation-id="adf-snackbar-decorative-icon">{{ data.decorativeIcon }}</mat-icon>{{ data.message }}
</p>
<div *ngIf="data.showAction" class="adf-snackbar-message-content-action" aria-hidden="true">
<button mat-button (click)="snackBarRef.dismissWithAction()" *ngIf="data.actionLabel" class="adf-snackbar-message-content-action-button"
data-automation-id="adf-snackbar-message-content-action-button">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,13 @@
justify-content: space-between;

.adf-snackbar-message-content {
display: flex;
align-items: center;
margin: 0;

mat-icon {
margin-right: 8px;
}
}

.adf-snackbar-message-content-action {
Expand Down
6 changes: 6 additions & 0 deletions lib/testing/src/lib/protractor/core/pages/snackbar.page.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ export class SnackbarPage {
notificationSnackBar = $$(`[data-automation-id='adf-snackbar-message-content']`).first();
snackBarAction = $(`[data-automation-id='adf-snackbar-message-content-action-button']`);
snackBarContainerCss = $$('adf-snackbar-content');
decorativeIconSnackBar = $(`[data-automation-id='adf-snackbar-decorative-icon']`).first();

async waitForSnackBarToAppear(timeout = 5000) {
return BrowserVisibility.waitUntilElementIsVisible(this.snackBarContainerCss.first(), timeout,
Expand All @@ -45,6 +46,11 @@ export class SnackbarPage {
return this.snackBarAction.getText();
}

async getSnackBarDecorativeIcon(): Promise<string> {
await this.waitForSnackBarToAppear();
return this.decorativeIconSnackBar.getText();
}

async clickSnackBarAction(): Promise<void> {
await this.waitForSnackBarToAppear();
await BrowserActions.click(this.snackBarAction);
Expand Down

0 comments on commit cfe1588

Please sign in to comment.