diff --git a/projects/core/components/notification/notification.component.ts b/projects/core/components/notification/notification.component.ts index 0956d3e702a2..69834844eb07 100644 --- a/projects/core/components/notification/notification.component.ts +++ b/projects/core/components/notification/notification.component.ts @@ -8,8 +8,11 @@ import { Output, } from '@angular/core'; import {tuiDefaultProp} from '@taiga-ui/cdk'; -import {TuiNotification} from '@taiga-ui/core/enums'; -import {TUI_CLOSE_WORD} from '@taiga-ui/core/tokens'; +import { + NotificationTokenOptions, + TUI_CLOSE_WORD, + TUI_NOTIFICATION_OPTIONS, +} from '@taiga-ui/core/tokens'; import {Observable} from 'rxjs'; export const STATUS_ICON = { @@ -30,17 +33,21 @@ export class TuiNotificationComponent { @Input() @HostBinding('class._has-icon') @tuiDefaultProp() - hasIcon = true; + hasIcon = this.options.hasIcon; @Input() @HostBinding('attr.data-tui-host-status') @tuiDefaultProp() - status: 'info' | 'error' | 'warning' | 'success' = TuiNotification.Info; + status: 'info' | 'error' | 'warning' | 'success' = this.options.status; @Output() readonly close = new EventEmitter(); - constructor(@Inject(TUI_CLOSE_WORD) readonly closeWord$: Observable) {} + constructor( + @Inject(TUI_CLOSE_WORD) readonly closeWord$: Observable, + @Inject(TUI_NOTIFICATION_OPTIONS) + public readonly options: NotificationTokenOptions, + ) {} get icon(): string { return STATUS_ICON[this.status]; diff --git a/projects/core/components/notification/test/notification.component.spec.ts b/projects/core/components/notification/test/notification.component.spec.ts index 492f66e1e459..1a5c17420a46 100644 --- a/projects/core/components/notification/test/notification.component.spec.ts +++ b/projects/core/components/notification/test/notification.component.spec.ts @@ -1,6 +1,10 @@ import {Component, DebugElement, ViewChild} from '@angular/core'; import {ComponentFixture, TestBed} from '@angular/core/testing'; import {NoopAnimationsModule} from '@angular/platform-browser/animations'; +import { + TUI_NOTIFICATION_DEFAULT_OPTIONS, + TUI_NOTIFICATION_OPTIONS, +} from '@taiga-ui/core/tokens'; import {PageObject} from '@taiga-ui/testing'; import {configureTestSuite} from 'ng-bullet'; import {TuiNotification} from '../../../enums/notification'; @@ -106,3 +110,61 @@ describe('Notification', () => { }); }); }); + +describe('Notification with TUI_NOTIFICATION_OPTIONS', () => { + @Component({ + template: ` + Short simple informational message + `, + }) + class TestComponent { + @ViewChild(TuiNotificationComponent, {static: false}) + component: TuiNotificationComponent; + } + + const status = TuiNotification.Error; + const hasIcon = false; + + let fixture: ComponentFixture; + let testComponent: TestComponent; + let pageObject: PageObject; + + function getIcon(): DebugElement { + return pageObject.getByAutomationId('tui-notification__icon')!; + } + + configureTestSuite(() => { + TestBed.configureTestingModule({ + imports: [NoopAnimationsModule, TuiNotificationModule], + declarations: [TestComponent], + providers: [ + TuiSvgService, + { + provide: TUI_NOTIFICATION_OPTIONS, + useValue: { + ...TUI_NOTIFICATION_DEFAULT_OPTIONS, + status, + hasIcon, + }, + }, + ], + }); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(TestComponent); + pageObject = new PageObject(fixture); + testComponent = fixture.componentInstance; + fixture.detectChanges(); + }); + + describe('icon', () => { + it('chosen correctly depending on the status', () => { + expect(testComponent.component.icon).toBe(STATUS_ICON[status]); + }); + + it('when hasIcon = false is absent', () => { + expect(getIcon()).toBeNull(); + }); + }); +}); diff --git a/projects/core/interfaces/index.ts b/projects/core/interfaces/index.ts index 30d7a1beb15f..4839b1580534 100644 --- a/projects/core/interfaces/index.ts +++ b/projects/core/interfaces/index.ts @@ -8,3 +8,4 @@ export * from './icon-error'; export * from './number-format-settings'; export * from './value-content-context'; export * from './with-optional-min-max'; +export * from './notification-options'; diff --git a/projects/core/interfaces/notification-options.ts b/projects/core/interfaces/notification-options.ts new file mode 100644 index 000000000000..46c395fcb4e3 --- /dev/null +++ b/projects/core/interfaces/notification-options.ts @@ -0,0 +1,20 @@ +import {TuiContextWithImplicit} from '@taiga-ui/cdk'; +import {TuiNotification} from '@taiga-ui/core/enums'; +import {PolymorpheusContent} from '@tinkoff/ng-polymorpheus'; + +export type TuiNotificationAutoClose = + | boolean + | number + | ((status: TuiNotification) => number | boolean); + +export interface TuiNotificationOptions { + readonly label?: PolymorpheusContent>; + readonly status?: TuiNotification; + readonly hasIcon?: boolean; + readonly autoClose?: TuiNotificationAutoClose; + readonly hasCloseButton?: boolean; +} + +export interface TuiNotificationOptionsWithData extends TuiNotificationOptions { + readonly data: I; +} diff --git a/projects/core/modules/notifications/index.ts b/projects/core/modules/notifications/index.ts index fab37713c33d..e11701177b8a 100644 --- a/projects/core/modules/notifications/index.ts +++ b/projects/core/modules/notifications/index.ts @@ -3,6 +3,5 @@ export * from './notification-alert/notification-alert.module'; export * from './notification-alert/Notification-alert'; export * from './notifications-host/notifications-host.component'; export * from './notification-content-context'; -export * from './notification-options'; export * from './notifications.module'; export * from './notifications.service'; diff --git a/projects/core/modules/notifications/notification-alert/Notification-alert.ts b/projects/core/modules/notifications/notification-alert/Notification-alert.ts index 1f050e69ee6b..05c83c55303c 100644 --- a/projects/core/modules/notifications/notification-alert/Notification-alert.ts +++ b/projects/core/modules/notifications/notification-alert/Notification-alert.ts @@ -1,50 +1,38 @@ +import {TuiContextWithImplicit} from '@taiga-ui/cdk'; import {TuiNotification} from '@taiga-ui/core/enums'; -import {PolymorpheusContent} from '@tinkoff/ng-polymorpheus'; -import {Observer} from 'rxjs'; -import {TuiNotificationContentContext} from '../notification-content-context'; import { TuiNotificationOptions, TuiNotificationOptionsWithData, -} from '../notification-options'; +} from '@taiga-ui/core/interfaces'; +import {PolymorpheusContent} from '@tinkoff/ng-polymorpheus'; +import {Observer} from 'rxjs'; +import {TuiNotificationContentContext} from '../notification-content-context'; export class NotificationAlert { - readonly status: TuiNotification; + readonly status = this.options.status; - readonly hasIcon: boolean; + readonly hasIcon = this.options.hasIcon; readonly autoClose: boolean | number; - readonly hasCloseButton: boolean; + readonly hasCloseButton = this.options.hasCloseButton; - readonly label: string; + readonly label: PolymorpheusContent> = this + .options.label; readonly data!: I; - readonly observer: Observer; - - readonly content: PolymorpheusContent>; - constructor( - observer: Observer, - content: PolymorpheusContent>, - options: TuiNotificationOptions | TuiNotificationOptionsWithData, + readonly observer: Observer, + readonly content: PolymorpheusContent>, + private readonly options: Required< + TuiNotificationOptions | TuiNotificationOptionsWithData + >, ) { - const { - label = '', - status = TuiNotification.Info, - hasIcon = true, - autoClose = true, - hasCloseButton = true, - } = options; - - this.observer = observer; - this.content = content; - - this.label = label; - this.status = status; - this.hasIcon = hasIcon; - this.autoClose = autoClose; - this.hasCloseButton = hasCloseButton; + this.autoClose = + typeof this.options.autoClose === 'function' + ? this.options.autoClose(this.options.status) + : this.options.autoClose; if (options && this.withData(options)) { this.data = options.data; diff --git a/projects/core/modules/notifications/notification-alert/notification-alert.component.ts b/projects/core/modules/notifications/notification-alert/notification-alert.component.ts index 5da7d425cd2b..524e6d766809 100644 --- a/projects/core/modules/notifications/notification-alert/notification-alert.component.ts +++ b/projects/core/modules/notifications/notification-alert/notification-alert.component.ts @@ -7,6 +7,7 @@ import { OnInit, } from '@angular/core'; import {isNumber, TuiDestroyService, tuiPure} from '@taiga-ui/cdk'; +import {NotificationTokenOptions, TUI_NOTIFICATION_OPTIONS} from '@taiga-ui/core/tokens'; import {fromEvent, timer} from 'rxjs'; import {repeatWhen, takeUntil} from 'rxjs/operators'; import {TuiNotificationContentContext} from '../notification-content-context'; @@ -23,31 +24,25 @@ export const DEFAULT_ALERT_AUTOCLOSE_TIMEOUT = 3000; }) export class TuiNotificationAlertComponent implements OnInit { @Input() - item?: NotificationAlert; + item!: NotificationAlert; constructor( @Inject(ElementRef) private readonly elementRef: ElementRef, @Inject(TuiDestroyService) private readonly destroy$: TuiDestroyService, + @Inject(TUI_NOTIFICATION_OPTIONS) + public readonly options: NotificationTokenOptions, ) {} ngOnInit() { this.initAutoClose(); } - get safeItem(): NotificationAlert { - if (!this.item) { - throw new Error('Notification was created as undefined'); - } - - return this.item; - } - get context(): TuiNotificationContentContext { - return this.calculateContext(this.safeItem); + return this.calculateContext(this.item); } closeNotification() { - this.safeItem.observer.complete(); + this.item.observer.complete(); } @tuiPure @@ -75,13 +70,13 @@ export class TuiNotificationAlertComponent implements OnInit { } private initAutoClose() { - if (!this.safeItem.autoClose) { + if (!this.item.autoClose) { return; } timer( - isNumber(this.safeItem.autoClose) - ? this.safeItem.autoClose + isNumber(this.item.autoClose) + ? this.item.autoClose : DEFAULT_ALERT_AUTOCLOSE_TIMEOUT, ) .pipe( diff --git a/projects/core/modules/notifications/notification-alert/notification-alert.template.html b/projects/core/modules/notifications/notification-alert/notification-alert.template.html index 109da555ae5a..51697ba9100e 100644 --- a/projects/core/modules/notifications/notification-alert/notification-alert.template.html +++ b/projects/core/modules/notifications/notification-alert/notification-alert.template.html @@ -1,38 +1,42 @@
- +
diff --git a/projects/core/modules/notifications/notification-alert/test/notification-alert.component.spec.ts b/projects/core/modules/notifications/notification-alert/test/notification-alert.component.spec.ts index 2d811cae5d42..ea5e1a2d68b9 100644 --- a/projects/core/modules/notifications/notification-alert/test/notification-alert.component.spec.ts +++ b/projects/core/modules/notifications/notification-alert/test/notification-alert.component.spec.ts @@ -1,8 +1,21 @@ import {CommonModule} from '@angular/common'; import {Component, Inject, NgModule, ViewChild} from '@angular/core'; import {ComponentFixture, fakeAsync, TestBed, tick} from '@angular/core/testing'; +import { + TuiNotificationOptions, + TuiNotificationOptionsWithData, +} from '@taiga-ui/core/interfaces'; +import { + NotificationTokenOptions, + TUI_NOTIFICATION_DEFAULT_OPTIONS, + TUI_NOTIFICATION_OPTIONS, +} from '@taiga-ui/core/tokens'; import {PageObject} from '@taiga-ui/testing'; -import {POLYMORPHEUS_CONTEXT, PolymorpheusComponent} from '@tinkoff/ng-polymorpheus'; +import { + POLYMORPHEUS_CONTEXT, + PolymorpheusComponent, + PolymorpheusContent, +} from '@tinkoff/ng-polymorpheus'; import {TuiNotificationContentContext} from '../../notification-content-context'; import {NotificationAlert} from '../Notification-alert'; import {TuiNotificationAlertComponent} from '../notification-alert.component'; @@ -74,7 +87,24 @@ describe('NotificationAlertComponent', () => { @ViewChild(TuiNotificationAlertComponent, {static: true}) component: TuiNotificationAlertComponent; - alert = new NotificationAlert(observerMock, content, {label}); + constructor( + @Inject(TUI_NOTIFICATION_OPTIONS) + public readonly options: NotificationTokenOptions, + ) { + this.setAlert(content, {label}); + } + + alert: NotificationAlert; + + setAlert( + content: PolymorpheusContent>, + params: TuiNotificationOptions | TuiNotificationOptionsWithData, + ) { + this.alert = new NotificationAlert(observerMock, content, { + ...this.options, + ...params, + }); + } } beforeEach(() => { @@ -109,7 +139,7 @@ describe('NotificationAlertComponent', () => { describe('Display', () => { beforeEach(() => { - testComponent.alert = new NotificationAlert(observerMock, content, {label}); + testComponent.setAlert(content, {label}); fixture.detectChanges(); }); @@ -130,6 +160,35 @@ describe('NotificationAlertComponent', () => { }); }); + it('display | Use label from TUI_NOTIFICATION_OPTIONS', () => { + TestBed.resetTestingModule(); + TestBed.configureTestingModule({ + imports: [TuiNotificationAlertModule, AlertTestModule], + declarations: [TestComponent], + providers: [ + { + provide: TUI_NOTIFICATION_OPTIONS, + useValue: { + ...TUI_NOTIFICATION_DEFAULT_OPTIONS, + label, + }, + }, + ], + }); + fixture = TestBed.createComponent(TestComponent); + testComponent = fixture.componentInstance; + pageObject = new PageObject(fixture); + + testComponent.setAlert(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(); @@ -138,28 +197,98 @@ describe('NotificationAlertComponent', () => { expect(completeSpy).toHaveBeenCalled(); }); + it('close | Close the Alert after custom TUI_NOTIFICATION_OPTIONS autoClose timeout', fakeAsync(() => { + const customTimeoutMs = 100; + + TestBed.resetTestingModule(); + TestBed.configureTestingModule({ + imports: [TuiNotificationAlertModule, AlertTestModule], + declarations: [TestComponent], + providers: [ + { + provide: TUI_NOTIFICATION_OPTIONS, + useValue: { + ...TUI_NOTIFICATION_DEFAULT_OPTIONS, + autoClose: customTimeoutMs, + }, + }, + ], + }); + fixture = TestBed.createComponent(TestComponent); + testComponent = fixture.componentInstance; + + testComponent.setAlert(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_OPTIONS, + useValue: { + ...TUI_NOTIFICATION_DEFAULT_OPTIONS, + autoClose: customOptionsTimeoutMs, + }, + }, + ], + }); + fixture = TestBed.createComponent(TestComponent); + testComponent = fixture.componentInstance; + + testComponent.setAlert(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, - new PolymorpheusComponent(AlertConstructorMock), - {label, data, autoClose: customTimeoutMs}, - ); + testComponent.setAlert(new PolymorpheusComponent(AlertConstructorMock), { + label, + data, + autoClose: customTimeoutMs, + }); fixture.detectChanges(); expect(completeSpy).not.toHaveBeenCalled(); - tick(customTimeoutMs); + tick(customTimeoutMs / 2); + expect(completeSpy).not.toHaveBeenCalled(); + tick(customTimeoutMs / 2); expect(completeSpy).toHaveBeenCalled(); })); describe('processComponent | Alert with custom template', () => { beforeEach(() => { - testComponent.alert = new NotificationAlert( - observerMock, - new PolymorpheusComponent(AlertConstructorMock), - {label, data, autoClose: false}, - ); + testComponent.setAlert(new PolymorpheusComponent(AlertConstructorMock), { + label, + data, + autoClose: false, + }); fixture.detectChanges(); }); diff --git a/projects/core/modules/notifications/notification-content-context.ts b/projects/core/modules/notifications/notification-content-context.ts index f3b757579a14..b9089f1dd161 100644 --- a/projects/core/modules/notifications/notification-content-context.ts +++ b/projects/core/modules/notifications/notification-content-context.ts @@ -1,9 +1,10 @@ import {TuiContextWithImplicit} from '@taiga-ui/cdk'; import {TuiNotification} from '@taiga-ui/core/enums'; +import {PolymorpheusContent} from '@tinkoff/ng-polymorpheus'; export interface TuiNotificationContentContext extends TuiContextWithImplicit { - label: string; + label: PolymorpheusContent>; data: I; closeHook: () => void; emitHook: (data: O) => void; diff --git a/projects/core/modules/notifications/notification-options.ts b/projects/core/modules/notifications/notification-options.ts deleted file mode 100644 index 5d382df2204f..000000000000 --- a/projects/core/modules/notifications/notification-options.ts +++ /dev/null @@ -1,13 +0,0 @@ -import {TuiNotification} from '@taiga-ui/core/enums'; - -export interface TuiNotificationOptions { - readonly label?: string; - readonly status?: TuiNotification; - readonly hasIcon?: boolean; - readonly autoClose?: boolean | number; - readonly hasCloseButton?: boolean; -} - -export interface TuiNotificationOptionsWithData extends TuiNotificationOptions { - readonly data: I; -} diff --git a/projects/core/modules/notifications/notifications.service.ts b/projects/core/modules/notifications/notifications.service.ts index 1375557b563a..c893e378f5ab 100644 --- a/projects/core/modules/notifications/notifications.service.ts +++ b/projects/core/modules/notifications/notifications.service.ts @@ -1,13 +1,14 @@ -import {Injectable} from '@angular/core'; +import {Inject, Injectable} from '@angular/core'; import {tuiAssert} from '@taiga-ui/cdk'; +import { + TuiNotificationOptions, + TuiNotificationOptionsWithData, +} from '@taiga-ui/core/interfaces'; +import {NotificationTokenOptions, TUI_NOTIFICATION_OPTIONS} from '@taiga-ui/core/tokens'; import {PolymorpheusContent} from '@tinkoff/ng-polymorpheus'; import {BehaviorSubject, Observable, Observer} from 'rxjs'; import {NotificationAlert} from './notification-alert/Notification-alert'; import {TuiNotificationContentContext} from './notification-content-context'; -import { - TuiNotificationOptions, - TuiNotificationOptionsWithData, -} from './notification-options'; const NO_HOST = 'Notifications are disabled, enable support by adding TuiNotificationsModule to your main app module'; @@ -19,6 +20,11 @@ export class TuiNotificationsService { /** @internal */ readonly items$ = new BehaviorSubject>>([]); + constructor( + @Inject(TUI_NOTIFICATION_OPTIONS) + public readonly options: NotificationTokenOptions, + ) {} + show( content: PolymorpheusContent>, ): Observable; @@ -37,7 +43,10 @@ export class TuiNotificationsService { return new Observable((observer: Observer) => { tuiAssert.assert(!!this.items$.observers.length, NO_HOST); - const notification = new NotificationAlert(observer, content, options); + const notification = new NotificationAlert(observer, content, { + ...this.options, + ...options, + }); this.items$.next([...this.items$.value, notification]); diff --git a/projects/core/tokens/index.ts b/projects/core/tokens/index.ts index 68e3ac03c832..c2296c3f5c39 100644 --- a/projects/core/tokens/index.ts +++ b/projects/core/tokens/index.ts @@ -11,6 +11,7 @@ export * from './icons'; export * from './icons-path'; export * from './mode'; export * from './number-format'; +export * from './notification-options'; export * from './option-content'; export * from './sanitizer'; export * from './scroll-ref'; diff --git a/projects/core/tokens/notification-options.ts b/projects/core/tokens/notification-options.ts new file mode 100644 index 000000000000..965e09d2fc5e --- /dev/null +++ b/projects/core/tokens/notification-options.ts @@ -0,0 +1,29 @@ +import {InjectionToken} from '@angular/core'; +import {TuiContextWithImplicit} from '@taiga-ui/cdk'; +import {TuiNotification} from '@taiga-ui/core/enums'; +import {TuiNotificationAutoClose} from '@taiga-ui/core/interfaces'; +import {PolymorpheusContent} from '@tinkoff/ng-polymorpheus'; + +export interface NotificationTokenOptions { + readonly autoClose: TuiNotificationAutoClose; + readonly label: PolymorpheusContent>; + readonly status: TuiNotification; + readonly hasIcon: boolean; + readonly hasCloseButton: boolean; +} + +/** Default values for the notification options. */ +export const TUI_NOTIFICATION_DEFAULT_OPTIONS: NotificationTokenOptions = { + autoClose: true, + label: '', + status: TuiNotification.Info, + hasIcon: true, + hasCloseButton: true, +}; + +export const TUI_NOTIFICATION_OPTIONS = new InjectionToken( + 'Default parameters for notification alert component', + { + factory: () => TUI_NOTIFICATION_DEFAULT_OPTIONS, + }, +); diff --git a/projects/demo/src/modules/components/notification/examples/2/index.html b/projects/demo/src/modules/components/notification/examples/2/index.html new file mode 100644 index 000000000000..58d784e00cde --- /dev/null +++ b/projects/demo/src/modules/components/notification/examples/2/index.html @@ -0,0 +1,14 @@ +
+ + A short simple informative message. Works with token options + + + A short simple informative message. Works with token options + + + A short simple informative message. Works with token options + + + A short simple informative message. Works with token options + +
diff --git a/projects/demo/src/modules/components/notification/examples/2/index.less b/projects/demo/src/modules/components/notification/examples/2/index.less new file mode 100644 index 000000000000..b4eec35a90fc --- /dev/null +++ b/projects/demo/src/modules/components/notification/examples/2/index.less @@ -0,0 +1,3 @@ +.wrapper { + width: 28.75rem; +} diff --git a/projects/demo/src/modules/components/notification/examples/2/index.ts b/projects/demo/src/modules/components/notification/examples/2/index.ts new file mode 100644 index 000000000000..79e4d54b0a13 --- /dev/null +++ b/projects/demo/src/modules/components/notification/examples/2/index.ts @@ -0,0 +1,27 @@ +import {Component} from '@angular/core'; +import { + TUI_NOTIFICATION_DEFAULT_OPTIONS, + TUI_NOTIFICATION_OPTIONS, + TuiNotification, +} from '@taiga-ui/core'; +import {changeDetection} from '../../../../../change-detection-strategy'; +import {encapsulation} from '../../../../../view-encapsulation'; + +@Component({ + selector: 'tui-notification-example-2', + templateUrl: './index.html', + styleUrls: ['./index.less'], + changeDetection, + encapsulation, + providers: [ + { + provide: TUI_NOTIFICATION_OPTIONS, + useValue: { + ...TUI_NOTIFICATION_DEFAULT_OPTIONS, + status: TuiNotification.Error, + hasIcon: false, + }, + }, + ], +}) +export class TuiNotificationExample2 {} diff --git a/projects/demo/src/modules/components/notification/examples/import/define-options.txt b/projects/demo/src/modules/components/notification/examples/import/define-options.txt new file mode 100644 index 000000000000..7dd4c356c785 --- /dev/null +++ b/projects/demo/src/modules/components/notification/examples/import/define-options.txt @@ -0,0 +1,18 @@ +import { + TuiNotification, + TUI_NOTIFICATION_DEFAULT_OPTIONS, + TUI_NOTIFICATION_OPTIONS, +} from '@taiga-ui/core'; + +... + +@NgModule({ + providers: [{ + provide: TUI_NOTIFICATION_OPTIONS, + useValue: { + ...TUI_NOTIFICATION_DEFAULT_OPTIONS, + status: TuiNotification.Error, + hasIcon: false, + }, + }], +... diff --git a/projects/demo/src/modules/components/notification/notification.component.ts b/projects/demo/src/modules/components/notification/notification.component.ts index 7a73b0348cc0..06c70dacafd8 100644 --- a/projects/demo/src/modules/components/notification/notification.component.ts +++ b/projects/demo/src/modules/components/notification/notification.component.ts @@ -1,6 +1,10 @@ import {default as example1Html} from '!!raw-loader!./examples/1/index.html'; import {default as example1Ts} from '!!raw-loader!./examples/1/index.ts'; +import {default as example2Html} from '!!raw-loader!./examples/2/index.html'; +import {default as example2Ts} from '!!raw-loader!./examples/2/index.ts'; + +import {default as exampleDefineOptions} from '!!raw-loader!./examples/import/define-options.txt'; import {default as exampleImportModule} from '!!raw-loader!./examples/import/import-module.txt'; import {default as exampleInsertTemplate} from '!!raw-loader!./examples/import/insert-template.txt'; @@ -17,11 +21,16 @@ import {FrontEndExample} from '../../interfaces/front-end-example'; export class ExampleTuiNotificationComponent { readonly exampleImportModule = exampleImportModule; readonly exampleInsertTemplate = exampleInsertTemplate; + readonly exampleDefineOptions = exampleDefineOptions; readonly example1: FrontEndExample = { TypeScript: example1Ts, HTML: example1Html, }; + readonly example2: FrontEndExample = { + TypeScript: example2Ts, + HTML: example2Html, + }; hasIcon = true; diff --git a/projects/demo/src/modules/components/notification/notification.module.ts b/projects/demo/src/modules/components/notification/notification.module.ts index 8221d3ec3a7b..612554374182 100644 --- a/projects/demo/src/modules/components/notification/notification.module.ts +++ b/projects/demo/src/modules/components/notification/notification.module.ts @@ -5,6 +5,7 @@ import {RouterModule} from '@angular/router'; import {generateRoutes, TuiAddonDocModule} from '@taiga-ui/addon-doc'; import {TuiNotificationModule} from '@taiga-ui/core'; import {TuiNotificationExample1} from './examples/1'; +import {TuiNotificationExample2} from './examples/2'; import {ExampleTuiNotificationComponent} from './notification.component'; @NgModule({ @@ -16,7 +17,11 @@ import {ExampleTuiNotificationComponent} from './notification.component'; TuiAddonDocModule, RouterModule.forChild(generateRoutes(ExampleTuiNotificationComponent)), ], - declarations: [ExampleTuiNotificationComponent, TuiNotificationExample1], + declarations: [ + ExampleTuiNotificationComponent, + TuiNotificationExample1, + TuiNotificationExample2, + ], exports: [ExampleTuiNotificationComponent], }) export class ExampleTuiNotificationModule {} diff --git a/projects/demo/src/modules/components/notification/notification.template.html b/projects/demo/src/modules/components/notification/notification.template.html index 82b5f96faf3d..0e641d508344 100644 --- a/projects/demo/src/modules/components/notification/notification.template.html +++ b/projects/demo/src/modules/components/notification/notification.template.html @@ -13,6 +13,15 @@ > + + + +
@@ -79,6 +88,19 @@ [code]="exampleInsertTemplate" > + +
  • +

    + Optionally use the + TUI_NOTIFICATION_OPTIONS injection token to + override the default options. +

    + + +
  • diff --git a/projects/demo/src/modules/services/notifications/examples/5/alert-example-with-custom-label/alert-example-with-custom-label.component.ts b/projects/demo/src/modules/services/notifications/examples/5/alert-example-with-custom-label/alert-example-with-custom-label.component.ts new file mode 100644 index 000000000000..ab400d9949b8 --- /dev/null +++ b/projects/demo/src/modules/services/notifications/examples/5/alert-example-with-custom-label/alert-example-with-custom-label.component.ts @@ -0,0 +1,27 @@ +import {Component, Inject} from '@angular/core'; +import {TuiContextWithImplicit, tuiPure} from '@taiga-ui/cdk'; +import {TuiNotification, TuiNotificationContentContext} from '@taiga-ui/core'; +import {POLYMORPHEUS_CONTEXT, PolymorpheusContent} from '@tinkoff/ng-polymorpheus'; +import {changeDetection} from '../../../../../../change-detection-strategy'; + +@Component({ + selector: 'tui-notifications-service-example-with-custom-label', + templateUrl: './alert-example-with-custom-label.template.html', + changeDetection, +}) +export class AlertExampleWithCustomLabelComponent { + @tuiPure + get label(): PolymorpheusContent> { + return this.context.label; + } + + @tuiPure + get status(): TuiNotification { + return this.context.$implicit; + } + + constructor( + @Inject(POLYMORPHEUS_CONTEXT) + private readonly context: TuiNotificationContentContext, + ) {} +} diff --git a/projects/demo/src/modules/services/notifications/examples/5/alert-example-with-custom-label/alert-example-with-custom-label.module.ts b/projects/demo/src/modules/services/notifications/examples/5/alert-example-with-custom-label/alert-example-with-custom-label.module.ts new file mode 100644 index 000000000000..f1c5b95702fa --- /dev/null +++ b/projects/demo/src/modules/services/notifications/examples/5/alert-example-with-custom-label/alert-example-with-custom-label.module.ts @@ -0,0 +1,11 @@ +import {CommonModule} from '@angular/common'; +import {NgModule} from '@angular/core'; +import {PolymorpheusModule} from '@tinkoff/ng-polymorpheus'; +import {AlertExampleWithCustomLabelComponent} from './alert-example-with-custom-label.component'; + +@NgModule({ + imports: [CommonModule, PolymorpheusModule], + declarations: [AlertExampleWithCustomLabelComponent], + exports: [AlertExampleWithCustomLabelComponent], +}) +export class AlertExampleWithCustomLabelModule {} diff --git a/projects/demo/src/modules/services/notifications/examples/5/alert-example-with-custom-label/alert-example-with-custom-label.template.html b/projects/demo/src/modules/services/notifications/examples/5/alert-example-with-custom-label/alert-example-with-custom-label.template.html new file mode 100644 index 000000000000..1503a6f34058 --- /dev/null +++ b/projects/demo/src/modules/services/notifications/examples/5/alert-example-with-custom-label/alert-example-with-custom-label.template.html @@ -0,0 +1,7 @@ +

    Start content

    + +

    End content

    diff --git a/projects/demo/src/modules/services/notifications/examples/5/custom-label/custom-label.component.ts b/projects/demo/src/modules/services/notifications/examples/5/custom-label/custom-label.component.ts new file mode 100644 index 000000000000..f731fa9e3aa6 --- /dev/null +++ b/projects/demo/src/modules/services/notifications/examples/5/custom-label/custom-label.component.ts @@ -0,0 +1,10 @@ +import {Component} from '@angular/core'; +import {changeDetection} from '../../../../../../change-detection-strategy'; + +@Component({ + selector: 'tui-notifications-service-example-custom-label', + templateUrl: './custom-label.template.html', + styleUrls: ['./custom-label.style.less'], + changeDetection, +}) +export class CustomLabelComponent {} diff --git a/projects/demo/src/modules/services/notifications/examples/5/custom-label/custom-label.module.ts b/projects/demo/src/modules/services/notifications/examples/5/custom-label/custom-label.module.ts new file mode 100644 index 000000000000..3195a79cc883 --- /dev/null +++ b/projects/demo/src/modules/services/notifications/examples/5/custom-label/custom-label.module.ts @@ -0,0 +1,11 @@ +import {CommonModule} from '@angular/common'; +import {NgModule} from '@angular/core'; +import {TuiSvgModule} from '@taiga-ui/core'; +import {CustomLabelComponent} from './custom-label.component'; + +@NgModule({ + imports: [CommonModule, TuiSvgModule], + declarations: [CustomLabelComponent], + exports: [CustomLabelComponent], +}) +export class CustomLabelModule {} diff --git a/projects/demo/src/modules/services/notifications/examples/5/custom-label/custom-label.style.less b/projects/demo/src/modules/services/notifications/examples/5/custom-label/custom-label.style.less new file mode 100644 index 000000000000..802c4dbcb640 --- /dev/null +++ b/projects/demo/src/modules/services/notifications/examples/5/custom-label/custom-label.style.less @@ -0,0 +1,9 @@ +.label { + display: flex; + align-items: center; +} + +.text { + font-weight: normal; + font-style: italic; +} diff --git a/projects/demo/src/modules/services/notifications/examples/5/custom-label/custom-label.template.html b/projects/demo/src/modules/services/notifications/examples/5/custom-label/custom-label.template.html new file mode 100644 index 000000000000..c851e4cb5f00 --- /dev/null +++ b/projects/demo/src/modules/services/notifications/examples/5/custom-label/custom-label.template.html @@ -0,0 +1,4 @@ + diff --git a/projects/demo/src/modules/services/notifications/examples/5/index.html b/projects/demo/src/modules/services/notifications/examples/5/index.html new file mode 100644 index 000000000000..ab5192b699b9 --- /dev/null +++ b/projects/demo/src/modules/services/notifications/examples/5/index.html @@ -0,0 +1,12 @@ + + diff --git a/projects/demo/src/modules/services/notifications/examples/5/index.ts b/projects/demo/src/modules/services/notifications/examples/5/index.ts new file mode 100644 index 000000000000..27b8aa615734 --- /dev/null +++ b/projects/demo/src/modules/services/notifications/examples/5/index.ts @@ -0,0 +1,66 @@ +import {Component, Inject, Injector} from '@angular/core'; +import {Router} from '@angular/router'; +import {TuiNotification, TuiNotificationsService} from '@taiga-ui/core'; +import {PolymorpheusComponent} from '@tinkoff/ng-polymorpheus'; +import {Observable} from 'rxjs'; +import {takeUntil} from 'rxjs/operators'; +import {changeDetection} from '../../../../../change-detection-strategy'; +import {encapsulation} from '../../../../../view-encapsulation'; +import {AlertExampleWithCustomLabelComponent} from './alert-example-with-custom-label/alert-example-with-custom-label.component'; +import {CustomLabelComponent} from './custom-label/custom-label.component'; + +@Component({ + selector: 'tui-notifications-example-5', + templateUrl: './index.html', + changeDetection, + encapsulation, +}) +export class TuiNotificationsExampleComponent5 { + readonly notification: Observable; + readonly notificationWithCustomLabel: Observable; + + constructor( + @Inject(TuiNotificationsService) notificationsService: TuiNotificationsService, + @Inject(Router) router: Router, + @Inject(Injector) private injector: Injector, + ) { + this.notification = notificationsService + .show( + new PolymorpheusComponent( + AlertExampleWithCustomLabelComponent, + this.injector, + ), + { + label: ({$implicit}: any) => + $implicit === TuiNotification.Error + ? 'Error label from function' + : 'Info label from function', + status: TuiNotification.Info, + autoClose: false, + }, + ) + .pipe(takeUntil(router.events)); + + this.notificationWithCustomLabel = notificationsService + .show( + new PolymorpheusComponent( + AlertExampleWithCustomLabelComponent, + this.injector, + ), + { + label: new PolymorpheusComponent(CustomLabelComponent, this.injector), + status: TuiNotification.Warning, + autoClose: false, + }, + ) + .pipe(takeUntil(router.events)); + } + + showNotification() { + this.notification.subscribe(); + } + + showNotificationWithCustomLabel() { + this.notificationWithCustomLabel.subscribe(); + } +} diff --git a/projects/demo/src/modules/services/notifications/examples/import/define-options.txt b/projects/demo/src/modules/services/notifications/examples/import/define-options.txt new file mode 100644 index 000000000000..6421d9760625 --- /dev/null +++ b/projects/demo/src/modules/services/notifications/examples/import/define-options.txt @@ -0,0 +1,21 @@ +import { + TuiNotification, + TUI_NOTIFICATION_DEFAULT_OPTIONS, + TUI_NOTIFICATION_OPTIONS, +} from '@taiga-ui/core'; + +... + +@NgModule({ + providers: [{ + provide: TUI_NOTIFICATION_OPTIONS, + useValue: { + ...TUI_NOTIFICATION_DEFAULT_OPTIONS, + autocloseTimeout: 7000, + label: ({$implicit}: any) => ($implicit === TuiNotification.Error ? 'Error' : 'Info'), + status: TuiNotification.Error, + hasIcon: false, + hasCloseButton: false, + }, + }], +... diff --git a/projects/demo/src/modules/services/notifications/notifications.component.ts b/projects/demo/src/modules/services/notifications/notifications.component.ts index 99b0ea66d8a2..85e8d46404a0 100644 --- a/projects/demo/src/modules/services/notifications/notifications.component.ts +++ b/projects/demo/src/modules/services/notifications/notifications.component.ts @@ -17,7 +17,20 @@ import {default as example4AlertDataTemplate} from '!!raw-loader!./examples/4/al 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 example5CustomLabelComponent} from '!!raw-loader!./examples/5/custom-label/custom-label.component.ts'; +import {default as example5CustomLabelModule} from '!!raw-loader!./examples/5/custom-label/custom-label.module.ts'; +import {default as example5CustomLabelStyle} from '!!raw-loader!./examples/5/custom-label/custom-label.style.less'; +import {default as example5CustomLabelTemplate} from '!!raw-loader!./examples/5/custom-label/custom-label.template.html'; + +import {default as example5AlertExampleComponent} from '!!raw-loader!./examples/5/alert-example-with-custom-label/alert-example-with-custom-label.component.ts'; +import {default as example5AlertExampleModule} from '!!raw-loader!./examples/5/alert-example-with-custom-label/alert-example-with-custom-label.module.ts'; +import {default as example5AlertExampleTemplate} from '!!raw-loader!./examples/5/alert-example-with-custom-label/alert-example-with-custom-label.template.html'; + +import {default as example5Html} from '!!raw-loader!./examples/5/index.html'; +import {default as example5Ts} from '!!raw-loader!./examples/5/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'; @@ -49,6 +62,7 @@ export class ExampleTuiNotificationsComponent { readonly exampleCustomAlert = exampleCustomAlert; readonly exampleLazyModule = exampleLazyModule; readonly exampleModule = exampleModule; + readonly exampleDefineOptions = exampleDefineOptions; readonly example1: FrontEndExample = { TypeScript: example1Ts, @@ -77,6 +91,18 @@ export class ExampleTuiNotificationsComponent { 'alert-example-with-data/alert-example-with-data.module.ts': example4AlertDataModule, }; + readonly example5 = { + TypeScript: example5Ts, + HTML: example5Html, + 'custom-label/custom-label.module.ts': example5CustomLabelModule, + 'custom-label/custom-label.component.ts': example5CustomLabelComponent, + 'custom-label/custom-label.style.less': example5CustomLabelStyle, + 'custom-label/custom-label.template.html': example5CustomLabelTemplate, + 'alert-example-with-custom-label/alert-example-with-custom-label.module.ts': example5AlertExampleModule, + 'alert-example-with-custom-label/alert-example-with-custom-label.component.ts': example5AlertExampleComponent, + 'alert-example-with-custom-label/alert-example-with-custom-label.template.html': example5AlertExampleTemplate, + }; + data = 100; label = 'Heading'; diff --git a/projects/demo/src/modules/services/notifications/notifications.module.ts b/projects/demo/src/modules/services/notifications/notifications.module.ts index 9a18022a04e4..a1d676e87a04 100644 --- a/projects/demo/src/modules/services/notifications/notifications.module.ts +++ b/projects/demo/src/modules/services/notifications/notifications.module.ts @@ -10,9 +10,16 @@ import {PolymorpheusModule} from '@tinkoff/ng-polymorpheus'; import {TuiNotificationsExampleComponent1} from './examples/1'; import {TuiNotificationsExampleComponent2} from './examples/2'; import {TuiNotificationsExampleComponent3} from './examples/3'; +import {AlertExampleComponent} from './examples/3/alert-example/alert-example.component'; import {AlertExampleModule} from './examples/3/alert-example/alert-example.module'; import {TuiNotificationsExampleComponent4} from './examples/4'; +import {AlertExampleWithDataComponent} from './examples/4/alert-example-with-data/alert-example-with-data.component'; import {AlertExampleWithDataModule} from './examples/4/alert-example-with-data/alert-example-with-data.module'; +import {TuiNotificationsExampleComponent5} from './examples/5'; +import {AlertExampleWithCustomLabelComponent} from './examples/5/alert-example-with-custom-label/alert-example-with-custom-label.component'; +import {AlertExampleWithCustomLabelModule} from './examples/5/alert-example-with-custom-label/alert-example-with-custom-label.module'; +import {CustomLabelComponent} from './examples/5/custom-label/custom-label.component'; +import {CustomLabelModule} from './examples/5/custom-label/custom-label.module'; import {ExampleTuiNotificationsComponent} from './notifications.component'; @NgModule({ @@ -22,8 +29,10 @@ import {ExampleTuiNotificationsComponent} from './notifications.component'; TuiModeModule, TuiMoneyModule, PolymorpheusModule, + AlertExampleWithCustomLabelModule, AlertExampleWithDataModule, AlertExampleModule, + CustomLabelModule, TuiRadioListModule, TuiInputModule, TuiLinkModule, @@ -37,6 +46,13 @@ import {ExampleTuiNotificationsComponent} from './notifications.component'; TuiNotificationsExampleComponent2, TuiNotificationsExampleComponent3, TuiNotificationsExampleComponent4, + TuiNotificationsExampleComponent5, + ], + entryComponents: [ + AlertExampleComponent, + AlertExampleWithDataComponent, + AlertExampleWithCustomLabelComponent, + CustomLabelComponent, ], exports: [ExampleTuiNotificationsComponent], }) diff --git a/projects/demo/src/modules/services/notifications/notifications.template.html b/projects/demo/src/modules/services/notifications/notifications.template.html index b72b80d27a64..f04f4f44d4da 100644 --- a/projects/demo/src/modules/services/notifications/notifications.template.html +++ b/projects/demo/src/modules/services/notifications/notifications.template.html @@ -39,6 +39,15 @@ > + + + + @@ -190,7 +199,10 @@
        $implicit: TuiNotification;
    -
        label: string;
    +
    +     label: + PolymorpheusContent<TuiContextWithImplicit<TuiNotification>>; +
        data: I;
        closeHook: () => void; @@ -259,6 +271,19 @@ [code]="exampleLazyModule" > + +
  • +

    + Optionally use the + TUI_NOTIFICATION_OPTIONS injection token to + override the default options (works only in app.module.ts). +

    + + +