From a6a77b8561f1bf1015194163612b7ea616ca9ad7 Mon Sep 17 00:00:00 2001 From: davidcanonieto Date: Fri, 6 Jul 2018 16:19:20 +0200 Subject: [PATCH] [ADF-3286] Snackbar now supports custom configuration (#3549) * [ADF-3286] Snackbar now supports custom configuration * [ADF-3286] Trailing whitespace removed * [ADF-3286] Tests added * [ADF-3286] Improved tests * [ADF-3286] Documentation added * [ADF-3286] Logic improved * [ADF-3286] Styling error fixed * [ADF-3286] Broken tests fixed * [ADF-3286] Broken tests fixed --- .../notifications.component.html | 45 ++++++++++ .../notifications/notifications.component.ts | 85 ++++++++++++++++++- docs/core/notification.service.md | 33 +++++-- .../services/notification.service.spec.ts | 70 ++++++++++++++- lib/core/services/notification.service.ts | 32 ++++--- 5 files changed, 243 insertions(+), 22 deletions(-) diff --git a/demo-shell/src/app/components/notifications/notifications.component.html b/demo-shell/src/app/components/notifications/notifications.component.html index f643ce970a..bd05e755eb 100644 --- a/demo-shell/src/app/components/notifications/notifications.component.html +++ b/demo-shell/src/app/components/notifications/notifications.component.html @@ -31,5 +31,50 @@
{{ actionOutput }}
+ + + + +

Custom Configuration

+
+
+ + +
+ + + + + + + {{ direction.title }} + + + + + + + + + + {{ horizontalPosition.title }} + + + + + + {{ verticalPosition.title }} + + + + +
+ + + +
+
diff --git a/demo-shell/src/app/components/notifications/notifications.component.ts b/demo-shell/src/app/components/notifications/notifications.component.ts index d476fbc652..8eb1a43eb2 100644 --- a/demo-shell/src/app/components/notifications/notifications.component.ts +++ b/demo-shell/src/app/components/notifications/notifications.component.ts @@ -15,20 +15,83 @@ * limitations under the License. */ -import { Component } from '@angular/core'; +import { Component, OnInit } from '@angular/core'; import { NotificationService } from '@alfresco/adf-core'; +import { MatSnackBarConfig } from '@angular/material'; +import { FormBuilder, FormGroup, FormControl } from '@angular/forms'; @Component({ templateUrl: './notifications.component.html', styleUrls: ['./notifications.component.scss'] }) -export class NotificationsComponent { +export class NotificationsComponent implements OnInit { message = 'I ♥️ ADF'; withAction = false; actionOutput = ''; - constructor(private notificationService: NotificationService) {} + configForm: FormGroup; + + snackBarConfig: MatSnackBarConfig = new MatSnackBarConfig(); + + directions = [ + {value: 'ltr', title: 'Left to right'}, + {value: 'rtl', title: 'Right to left'} + ]; + + horizontalPositions = [ + {value: 'start', title: 'Start'}, + {value: 'center', title: 'Center'}, + {value: 'end', title: 'End'}, + {value: 'left', title: 'Left'}, + {value: 'right', title: 'Right'} + ]; + + verticalPositions = [ + {value: 'top', title: 'Top'}, + {value: 'bottom', title: 'Bottom'} + ]; + + constructor(private notificationService: NotificationService, + private formBuilder: FormBuilder) { } + + ngOnInit() { + this.configForm = this.formBuilder.group({ + announcementMessage: new FormControl(''), + direction: new FormControl(''), + horizontalPosition: new FormControl(''), + verticalPosition: new FormControl(''), + duration: new FormControl('') + }); + + this.configForm.valueChanges + .subscribe(configFormValues => + this.setSnackBarConfig(configFormValues) + ); + + } + + setSnackBarConfig(configFormValues: any) { + + if (configFormValues.announcementMessage) { + this.snackBarConfig.announcementMessage = configFormValues.announcementMessage; + } + if (configFormValues.direction) { + this.snackBarConfig.direction = configFormValues.direction; + + } + if (configFormValues.duration) { + this.snackBarConfig.duration = configFormValues.duration; + + } + if (configFormValues.horizontalPosition) { + this.snackBarConfig.horizontalPosition = configFormValues.horizontalPosition; + } + if (configFormValues.verticalPosition) { + this.snackBarConfig.verticalPosition = configFormValues.verticalPosition; + } + + } send() { this.actionOutput = ''; @@ -44,4 +107,20 @@ export class NotificationsComponent { } } } + + sendCustomConfig() { + this.actionOutput = ''; + console.log(this.snackBarConfig); + + if (this.message) { + if (this.withAction) { + this.notificationService + .openSnackMessageAction(this.message, 'Some action', this.snackBarConfig ) + .onAction() + .subscribe(() => this.actionOutput = 'Action clicked'); + } else { + this.notificationService.openSnackMessage(this.message, this.snackBarConfig); + } + } + } } diff --git a/docs/core/notification.service.md b/docs/core/notification.service.md index 68bf2ab6f4..a9ebb8a0b7 100644 --- a/docs/core/notification.service.md +++ b/docs/core/notification.service.md @@ -14,16 +14,17 @@ Shows a notification message with optional feedback. ### Methods -- **openSnackMessage**(message: `string` = `null`, millisecondsDuration?: `number` = `null`): [`MatSnackBarRef`](https://material.angular.io/components/snack-bar/overview)``
+- **openSnackMessage**(message: `string` = `null`, config?: `number` | [`MatSnackBarConfig`](https://v5.material.angular.io/components/snack-bar/api#MatSnackBarConfig) = `null`): [`MatSnackBarRef`](https://material.angular.io/components/snack-bar/overview)``
Opens a SnackBar notification to show a message. - _message:_ `string` - The message (or resource key) to show. - - _millisecondsDuration:_ `number` - (Optional) Time before notification disappears after being shown - - **Returns** [`MatSnackBarRef`](https://material.angular.io/components/snack-bar/overview)`` - Information/control object for the SnackBar -- **openSnackMessageAction**(message: `string` = `null`, action: `string` = `null`, millisecondsDuration?: `number` = `null`): [`MatSnackBarRef`](https://material.angular.io/components/snack-bar/overview)``
+ - _config:_ `number` - (Optional) Time before notification disappears after being shown or [`MatSnackBarConfig`](https://v5.material.angular.io/components/snack-bar/api#MatSnackBarConfig) object to fully customize SnackBar + - **Returns** [`MatSnackBarRef`](https://material.angular.io/components/snack-bar/overview)`` - Information/control object for the SnackBar +
+- **openSnackMessageAction**(message: `string` = `null`, action: `string` = `null`, config?: `number` | [`MatSnackBarConfig`](https://v5.material.angular.io/components/snack-bar/api#MatSnackBarConfig) = `null`): [`MatSnackBarRef`](https://material.angular.io/components/snack-bar/overview)``
Opens a SnackBar notification with a message and a response button. - _message:_ `string` - The message (or resource key) to show. - _action:_ `string` - Caption for the response button - - _millisecondsDuration:_ `number` - (Optional) Time before the notification disappears (unless the button is clicked) + - _config:_ `number` - (Optional) Time before notification disappears after being shown or [`MatSnackBarConfig`](https://v5.material.angular.io/components/snack-bar/api#MatSnackBarConfig) object to fully customize SnackBar - **Returns** [`MatSnackBarRef`](https://material.angular.io/components/snack-bar/overview)`` - Information/control object for the SnackBar ## Details @@ -68,3 +69,25 @@ export class MyComponent implements OnInit { } } ``` + +```ts +import { NotificationService } from '@alfresco/adf-core'; +import { MatSnackBarConfig } from '@angular/material'; + +export class MyComponent implements OnInit { + + snackBarConfig: MatSnackBarConfig = new MatSnackBarConfig(); + + constructor(private notificationService: NotificationService) { + } + + ngOnInit() { + this.notificationService + .openSnackMessageAction('Do you want to report this issue?', 'send', snackBarConfig) + .afterDismissed() + .subscribe(() => { + console.log('The snack-bar was dismissed'); + }); + } +} +``` diff --git a/lib/core/services/notification.service.spec.ts b/lib/core/services/notification.service.spec.ts index 877efb9ff7..2ad736e4b4 100644 --- a/lib/core/services/notification.service.spec.ts +++ b/lib/core/services/notification.service.spec.ts @@ -20,7 +20,7 @@ import { OVERLAY_PROVIDERS, OverlayModule } from '@angular/cdk/overlay'; import { Component } from '@angular/core'; import { async, ComponentFixture, TestBed } from '@angular/core/testing'; -import { MatSnackBar, MatSnackBarModule } from '@angular/material'; +import { MatSnackBar, MatSnackBarModule, MatSnackBarConfig } from '@angular/material'; import { NoopAnimationsModule } from '@angular/platform-browser/animations'; import { NotificationService } from './notification.service'; import { TranslationMock } from '../mock/translation.service.mock'; @@ -35,13 +35,33 @@ class ProvidesNotificationServiceComponent { } + sendMessageWithoutConfig() { + let promise = this.notificationService.openSnackMessage('Test notification'); + return promise; + } + sendMessage() { - let promise = this.notificationService.openSnackMessage('Test notification', 5000); + let promise = this.notificationService.openSnackMessage('Test notification', 1000); + return promise; + } + + sendCustomMessage() { + let promise = this.notificationService.openSnackMessage('Test notification', new MatSnackBarConfig()); + return promise; + } + + sendMessageActionWithoutConfig() { + let promise = this.notificationService.openSnackMessageAction('Test notification', 'TestWarn'); return promise; } sendMessageAction() { - let promise = this.notificationService.openSnackMessageAction('Test notification', 'TestWarn', 5000); + let promise = this.notificationService.openSnackMessageAction('Test notification', 'TestWarn', 1000); + return promise; + } + + sendCustomMessageAction() { + let promise = this.notificationService.openSnackMessageAction('Test notification', 'TestWarn', new MatSnackBarConfig()); return promise; } @@ -99,6 +119,28 @@ describe('NotificationService', () => { expect(document.querySelector('snack-bar-container')).not.toBeNull(); }); + it('should open a message notification bar without custom configuration', (done) => { + let promise = fixture.componentInstance.sendMessageWithoutConfig(); + promise.afterDismissed().subscribe(() => { + done(); + }); + + fixture.detectChanges(); + + expect(document.querySelector('snack-bar-container')).not.toBeNull(); + }); + + it('should open a message notification bar with custom configuration', async((done) => { + let promise = fixture.componentInstance.sendCustomMessage(); + promise.afterDismissed().subscribe(() => { + done(); + }); + + fixture.detectChanges(); + + expect(document.querySelector('snack-bar-container')).not.toBeNull(); + })); + it('should open a message notification bar with action', (done) => { let promise = fixture.componentInstance.sendMessageAction(); promise.afterDismissed().subscribe(() => { @@ -110,4 +152,26 @@ describe('NotificationService', () => { expect(document.querySelector('snack-bar-container')).not.toBeNull(); }); + it('should open a message notification bar with action and custom configuration', async((done) => { + let promise = fixture.componentInstance.sendCustomMessageAction(); + promise.afterDismissed().subscribe(() => { + done(); + }); + + fixture.detectChanges(); + + expect(document.querySelector('snack-bar-container')).not.toBeNull(); + })); + + it('should open a message notification bar with action and no custom configuration', (done) => { + let promise = fixture.componentInstance.sendMessageActionWithoutConfig(); + promise.afterDismissed().subscribe(() => { + done(); + }); + + fixture.detectChanges(); + + expect(document.querySelector('snack-bar-container')).not.toBeNull(); + }); + }); diff --git a/lib/core/services/notification.service.ts b/lib/core/services/notification.service.ts index 9479a862b0..4ac339b0cf 100644 --- a/lib/core/services/notification.service.ts +++ b/lib/core/services/notification.service.ts @@ -16,7 +16,7 @@ */ import { Injectable } from '@angular/core'; -import { MatSnackBar, MatSnackBarRef } from '@angular/material'; +import { MatSnackBar, MatSnackBarRef, MatSnackBarConfig } from '@angular/material'; import { TranslationService } from './translation.service'; @Injectable() @@ -31,29 +31,39 @@ export class NotificationService { /** * Opens a SnackBar notification to show a message. * @param message The message (or resource key) to show. - * @param millisecondsDuration Time before notification disappears after being shown + * @param config Time before notification disappears after being shown or MatSnackBarConfig object * @returns Information/control object for the SnackBar */ - openSnackMessage(message: string, millisecondsDuration?: number): MatSnackBarRef { + openSnackMessage(message: string, config: number | MatSnackBarConfig = NotificationService.DEFAULT_DURATION_MESSAGE): MatSnackBarRef { + const translatedMessage = this.translationService.instant(message); - return this.snackBar.open(translatedMessage, null, { - duration: millisecondsDuration || NotificationService.DEFAULT_DURATION_MESSAGE - }); + if (typeof config === 'number') { + config = { + duration: config + }; + } + + return this.snackBar.open(translatedMessage, null, config); } /** * Opens a SnackBar notification with a message and a response button. * @param message The message (or resource key) to show. * @param action Caption for the response button - * @param millisecondsDuration Time before the notification disappears (unless the button is clicked) + * @param config Time before notification disappears after being shown or MatSnackBarConfig object * @returns Information/control object for the SnackBar */ - openSnackMessageAction(message: string, action: string, millisecondsDuration?: number): MatSnackBarRef { + openSnackMessageAction(message: string, action: string, config: number | MatSnackBarConfig = NotificationService.DEFAULT_DURATION_MESSAGE): MatSnackBarRef { + const translatedMessage = this.translationService.instant(message); - return this.snackBar.open(translatedMessage, action, { - duration: millisecondsDuration || NotificationService.DEFAULT_DURATION_MESSAGE - }); + if (typeof config === 'number') { + config = { + duration: config + }; + } + + return this.snackBar.open(translatedMessage, action, config); } }