Skip to content

Commit

Permalink
feat(notification-alert): allow configuration of default options
Browse files Browse the repository at this point in the history
  • Loading branch information
Dima Karimov committed Aug 21, 2021
1 parent b5af611 commit c28f3fe
Show file tree
Hide file tree
Showing 8 changed files with 210 additions and 18 deletions.
1 change: 1 addition & 0 deletions projects/core/modules/notifications/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
export * from './notification-alert/notification-alert.component';
export * from './notification-alert/notification-alert.module';
export * from './notification-alert/Notification-alert';
export * from './notification-alert/notification-alert-options';
export * from './notifications-host/notifications-host.component';
export * from './notification-content-context';
export * from './notification-options';
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import {InjectionToken} from '@angular/core';
import {TuiContextWithImplicit} from '@taiga-ui/cdk';
import {PolymorpheusContent} from '@tinkoff/ng-polymorpheus';
import {TuiNotification} from '../../../enums/notification';

export interface NotificationAlertOptions {
readonly autoClose: boolean | number;
readonly label: PolymorpheusContent<TuiContextWithImplicit<TuiNotification>>;
}

/** Default values for the toggle options. */
export const TUI_NOTIFICATION_ALERT_DEFAULT_OPTIONS: NotificationAlertOptions = {
autoClose: 3000,
label: '',
};

export const TUI_NOTIFICATION_ALERT_OPTIONS = new InjectionToken<NotificationAlertOptions>(
'Default parameters for notification alert component',
{
factory: () => TUI_NOTIFICATION_ALERT_DEFAULT_OPTIONS,
},
);
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,22 @@ import {
Input,
OnInit,
} from '@angular/core';
import {isNumber, TuiDestroyService, tuiPure} from '@taiga-ui/cdk';
import {
isNumber,
TuiContextWithImplicit,
TuiDestroyService,
tuiPure,
} from '@taiga-ui/cdk';
import {PolymorpheusContent} from '@tinkoff/ng-polymorpheus';
import {fromEvent, timer} from 'rxjs';
import {repeatWhen, takeUntil} from 'rxjs/operators';
import {TuiNotification} from '../../../enums/notification';
import {TuiNotificationContentContext} from '../notification-content-context';
import {NotificationAlert} from './Notification-alert';
import {
NotificationAlertOptions,
TUI_NOTIFICATION_ALERT_OPTIONS,
} from './notification-alert-options';

export const DEFAULT_ALERT_AUTOCLOSE_TIMEOUT = 3000;

Expand All @@ -28,6 +39,8 @@ export class TuiNotificationAlertComponent<O, I> implements OnInit {
constructor(
@Inject(ElementRef) private readonly elementRef: ElementRef<HTMLElement>,
@Inject(TuiDestroyService) private readonly destroy$: TuiDestroyService,
@Inject(TUI_NOTIFICATION_ALERT_OPTIONS)
public readonly options: NotificationAlertOptions,
) {}

ngOnInit() {
Expand All @@ -46,6 +59,10 @@ export class TuiNotificationAlertComponent<O, I> implements OnInit {
return this.calculateContext(this.safeItem);
}

get label(): PolymorpheusContent<TuiContextWithImplicit<TuiNotification>> {
return this.safeItem.label || this.options.label;
}

closeNotification() {
this.safeItem.observer.complete();
}
Expand Down Expand Up @@ -75,13 +92,15 @@ export class TuiNotificationAlertComponent<O, I> implements OnInit {
}

private initAutoClose() {
if (!this.safeItem.autoClose) {
if (!this.safeItem.autoClose || !this.options.autoClose) {
return;
}

timer(
isNumber(this.safeItem.autoClose)
? this.safeItem.autoClose
: isNumber(this.options.autoClose)
? this.options.autoClose
: DEFAULT_ALERT_AUTOCLOSE_TIMEOUT,
)
.pipe(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,17 @@
[hasIcon]="safeItem.hasIcon"
(close)="closeNotification()"
>
<label
*ngIf="safeItem.label"
automation-id="tui-notification-alert__heading"
class="heading"
>
{{safeItem.label}}
</label>
<span polymorpheus-outlet [content]="label" [context]="context">
<ng-template let-label>
<label
*ngIf="label"
automation-id="tui-notification-alert__heading"
class="heading"
>
{{label}}
</label>
</ng-template>
</span>
<div
polymorpheus-outlet
automation-id="tui-notification-alert__content"
Expand All @@ -21,13 +25,17 @@
</tui-notification>
<ng-template #noClose>
<tui-notification [status]="safeItem.status" [hasIcon]="safeItem.hasIcon">
<label
*ngIf="safeItem.label"
automation-id="tui-notification-alert__heading"
class="heading"
>
{{safeItem.label}}
</label>
<span polymorpheus-outlet [content]="label" [context]="context">
<ng-template let-label>
<label
*ngIf="label"
automation-id="tui-notification-alert__heading"
class="heading"
>
{{label}}
</label>
</ng-template>
</span>
<div
polymorpheus-outlet
automation-id="tui-notification-alert__content"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@ import {PageObject} from '@taiga-ui/testing';
import {POLYMORPHEUS_CONTEXT, PolymorpheusComponent} from '@tinkoff/ng-polymorpheus';
import {TuiNotificationContentContext} from '../../notification-content-context';
import {NotificationAlert} from '../Notification-alert';
import {
TUI_NOTIFICATION_ALERT_DEFAULT_OPTIONS,
TUI_NOTIFICATION_ALERT_OPTIONS,
} from '../notification-alert-options';
import {TuiNotificationAlertComponent} from '../notification-alert.component';
import {TuiNotificationAlertModule} from '../notification-alert.module';

Expand Down Expand Up @@ -130,6 +134,39 @@ describe('NotificationAlertComponent', () => {
});
});

it('display | Use label from TUI_NOTIFICATION_ALERT_OPTIONS', () => {
TestBed.resetTestingModule();
TestBed.configureTestingModule({
imports: [TuiNotificationAlertModule, AlertTestModule],
declarations: [TestComponent],
providers: [
{
provide: TUI_NOTIFICATION_ALERT_OPTIONS,
useValue: {
...TUI_NOTIFICATION_ALERT_DEFAULT_OPTIONS,
label,
},
},
],
});
fixture = TestBed.createComponent(TestComponent);
testComponent = fixture.componentInstance;
pageObject = new PageObject(fixture);

testComponent.alert = new NotificationAlert(
observerMock,
new PolymorpheusComponent(AlertConstructorMock),
{data},
);
fixture.detectChanges();

expect(
pageObject
.getByAutomationId(`${testContext.prefix}heading`)!
.nativeElement.textContent.trim(),
).toBe(label);
});

it('close | Close the Alert and notify the observer', () => {
fixture.detectChanges();
component.closeNotification();
Expand All @@ -138,8 +175,77 @@ describe('NotificationAlertComponent', () => {
expect(completeSpy).toHaveBeenCalled();
});

it('close | Close the Alert after custom TUI_NOTIFICATION_ALERT_OPTIONS autoClose timeout', fakeAsync(() => {
const customTimeoutMs = 100;

TestBed.resetTestingModule();
TestBed.configureTestingModule({
imports: [TuiNotificationAlertModule, AlertTestModule],
declarations: [TestComponent],
providers: [
{
provide: TUI_NOTIFICATION_ALERT_OPTIONS,
useValue: {
...TUI_NOTIFICATION_ALERT_DEFAULT_OPTIONS,
autoClose: customTimeoutMs,
},
},
],
});
fixture = TestBed.createComponent(TestComponent);
testComponent = fixture.componentInstance;

testComponent.alert = new NotificationAlert(
observerMock,
new PolymorpheusComponent(AlertConstructorMock),
{label, data},
);
fixture.detectChanges();

expect(completeSpy).not.toHaveBeenCalled();
tick(customTimeoutMs / 2);
expect(completeSpy).not.toHaveBeenCalled();
tick(customTimeoutMs / 2);
expect(completeSpy).toHaveBeenCalled();
}));

it('close | Use autoClose timeout from NotificationAlert params', fakeAsync(() => {
const customOptionsTimeoutMs = 100;
const customTimeoutMs = 300;

TestBed.resetTestingModule();
TestBed.configureTestingModule({
imports: [TuiNotificationAlertModule, AlertTestModule],
declarations: [TestComponent],
providers: [
{
provide: TUI_NOTIFICATION_ALERT_OPTIONS,
useValue: {
...TUI_NOTIFICATION_ALERT_DEFAULT_OPTIONS,
autoClose: customOptionsTimeoutMs,
},
},
],
});
fixture = TestBed.createComponent(TestComponent);
testComponent = fixture.componentInstance;

testComponent.alert = new NotificationAlert(
observerMock,
new PolymorpheusComponent(AlertConstructorMock),
{label, data, autoClose: customTimeoutMs},
);
fixture.detectChanges();

expect(completeSpy).not.toHaveBeenCalled();
tick(customTimeoutMs / 2);
expect(completeSpy).not.toHaveBeenCalled();
tick(customTimeoutMs / 2);
expect(completeSpy).toHaveBeenCalled();
}));

it('close | Close the Alert after custom autoClose timeout', fakeAsync(() => {
const customTimeoutMs = 1000;
const customTimeoutMs = 500;

testComponent.alert = new NotificationAlert(
observerMock,
Expand All @@ -149,7 +255,9 @@ describe('NotificationAlertComponent', () => {
fixture.detectChanges();

expect(completeSpy).not.toHaveBeenCalled();
tick(customTimeoutMs);
tick(customTimeoutMs / 2);
expect(completeSpy).not.toHaveBeenCalled();
tick(customTimeoutMs / 2);
expect(completeSpy).toHaveBeenCalled();
}));

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import {
TuiNotification,
TUI_NOTIFICATION_ALERT_DEFAULT_OPTIONS,
TUI_NOTIFICATION_ALERT_OPTIONS,
} from '@taiga-ui/core';

...

@NgModule({
providers: [{
provide: TUI_NOTIFICATION_ALERT_OPTIONS,
useValue: {
...TUI_NOTIFICATION_ALERT_DEFAULT_OPTIONS,
autocloseTimeout: 7000,
label: ({$implicit}: any) => ($implicit === TuiNotification.Error ? 'Error' : 'Info')
},
}],
...
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {default as example4Html} from '!!raw-loader!./examples/4/index.html';
import {default as example4Ts} from '!!raw-loader!./examples/4/index.ts';

import {default as exampleCustomAlert} from '!!raw-loader!./examples/import/custom-alert.txt';
import {default as exampleDefineOptions} from '!!raw-loader!./examples/import/define-options.txt';
import {default as exampleImportModuleComponent} from '!!raw-loader!./examples/import/import-module-component.txt';
import {default as exampleLazyModule} from '!!raw-loader!./examples/import/lazy-module.txt';
import {default as exampleModule} from '!!raw-loader!./examples/import/module.txt';
Expand Down Expand Up @@ -42,6 +43,7 @@ export class ExampleTuiNotificationsComponent {
readonly exampleCustomAlert = exampleCustomAlert;
readonly exampleLazyModule = exampleLazyModule;
readonly exampleModule = exampleModule;
readonly exampleDefineOptions = exampleDefineOptions;

readonly example1: FrontEndExample = {
TypeScript: example1Ts,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,20 @@
[code]="exampleLazyModule"
></tui-doc-code>
</li>

<li>
<p i18n>
Optionally use the
<code>TUI_NOTIFICATION_ALERT_OPTIONS</code> injection token
to override the default options (works only in
app.module.ts).
</p>

<tui-doc-code
filename="app.module.ts"
[code]="exampleDefineOptions"
></tui-doc-code>
</li>
</ol>
</ng-template>
</tui-doc-page>

0 comments on commit c28f3fe

Please sign in to comment.