[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
This commit is contained in:
davidcanonieto
2018-07-06 16:19:20 +02:00
committed by Eugenio Romano
parent 495f9937fe
commit a6a77b8561
5 changed files with 243 additions and 22 deletions

View File

@@ -31,5 +31,50 @@
<div data-automation-id="notification-action-output">
{{ actionOutput }}
</div>
<mat-accordion>
<mat-expansion-panel>
<mat-expansion-panel-header>
<mat-panel-title>
<h3>Custom Configuration</h3>
</mat-panel-title>
</mat-expansion-panel-header>
<form [formGroup]="configForm">
<mat-form-field>
<input matInput class="form-control" formControlName="announcementMessage" placeholder="Announcement Message" >
</mat-form-field>
<mat-form-field>
<mat-select class="form-control" formControlName="direction" placeholder="Direction">
<mat-option *ngFor="let direction of directions" [value]="direction.value">
{{ direction.title }}
</mat-option>
</mat-select>
</mat-form-field>
<mat-form-field>
<input matInput type="number" class="form-control" formControlName="duration" placeholder="Duration" >
</mat-form-field>
<mat-form-field>
<mat-select class="form-control" formControlName="horizontalPosition" placeholder="Horizontal Position">
<mat-option *ngFor="let horizontalPosition of horizontalPositions" [value]="horizontalPosition.value">
{{ horizontalPosition.title }}
</mat-option>
</mat-select>
</mat-form-field>
<mat-form-field>
<mat-select class="form-control" formControlName="verticalPosition" placeholder="Vertical Position">
<mat-option *ngFor="let verticalPosition of verticalPositions" [value]="verticalPosition.value">{{ verticalPosition.title }}</mat-option>
</mat-select>
</mat-form-field>
</form>
<button mat-icon-button (click)="sendCustomConfig()">
<mat-icon>send</mat-icon>
</button>
</mat-expansion-panel>
</mat-accordion>
</div>

View File

@@ -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);
}
}
}
}

View File

@@ -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)`<any>`<br/>
- **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)`<any>`<br/>
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)`<any>` - 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)`<any>`<br/>
- _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)`<any>` - Information/control object for the SnackBar
<br/>
- **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)`<any>`<br/>
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)`<any>` - 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');
});
}
}
```

View File

@@ -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();
});
});

View File

@@ -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<any> {
openSnackMessage(message: string, config: number | MatSnackBarConfig = NotificationService.DEFAULT_DURATION_MESSAGE): MatSnackBarRef<any> {
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<any> {
openSnackMessageAction(message: string, action: string, config: number | MatSnackBarConfig = NotificationService.DEFAULT_DURATION_MESSAGE): MatSnackBarRef<any> {
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);
}
}