Skip to content

Commit

Permalink
fix(core): implement review notes
Browse files Browse the repository at this point in the history
  • Loading branch information
KarimovDev committed Sep 27, 2021
1 parent a01fe73 commit 9a5c12a
Show file tree
Hide file tree
Showing 5 changed files with 93 additions and 106 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
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';
Expand All @@ -9,15 +7,15 @@ import {
} from '../notification-options';

export class NotificationAlert<O, I> {
readonly status?: TuiNotification;
readonly status = this.options.status;

readonly hasIcon?: boolean;
readonly hasIcon = this.options.hasIcon;

readonly autoClose?: boolean | number;
readonly autoClose = this.options.autoClose;

readonly hasCloseButton?: boolean;
readonly hasCloseButton = this.options.hasCloseButton;

readonly label?: PolymorpheusContent<TuiContextWithImplicit<TuiNotification>>;
readonly label = this.options.label;

readonly data!: I;

Expand All @@ -28,19 +26,13 @@ export class NotificationAlert<O, I> {
constructor(
observer: Observer<O>,
content: PolymorpheusContent<TuiNotificationContentContext<O, I>>,
options: TuiNotificationOptions | TuiNotificationOptionsWithData<I>,
private readonly options: Required<
TuiNotificationOptions | TuiNotificationOptionsWithData<I>
>,
) {
const {label, status, hasIcon, autoClose, hasCloseButton} = options;

this.observer = observer;
this.content = content;

this.label = label;
this.status = status;
this.hasIcon = hasIcon;
this.autoClose = autoClose;
this.hasCloseButton = hasCloseButton;

if (options && this.withData(options)) {
this.data = options.data;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,8 @@ import {
Input,
OnInit,
} from '@angular/core';
import {
isNumber,
TuiContextWithImplicit,
TuiDestroyService,
tuiPure,
} from '@taiga-ui/cdk';
import {TuiNotification} from '@taiga-ui/core/enums';
import {isNumber, TuiDestroyService, tuiPure} from '@taiga-ui/cdk';
import {NotificationTokenOptions, TUI_NOTIFICATION_OPTIONS} from '@taiga-ui/core/tokens';
import {PolymorpheusContent} from '@tinkoff/ng-polymorpheus';
import {fromEvent, timer} from 'rxjs';
import {repeatWhen, takeUntil} from 'rxjs/operators';
import {TuiNotificationContentContext} from '../notification-content-context';
Expand All @@ -31,7 +24,7 @@ export const DEFAULT_ALERT_AUTOCLOSE_TIMEOUT = 3000;
})
export class TuiNotificationAlertComponent<O, I> implements OnInit {
@Input()
item?: NotificationAlert<O, I>;
item!: NotificationAlert<O, I>;

constructor(
@Inject(ElementRef) private readonly elementRef: ElementRef<HTMLElement>,
Expand All @@ -44,57 +37,25 @@ export class TuiNotificationAlertComponent<O, I> implements OnInit {
this.initAutoClose();
}

get safeItem(): NotificationAlert<O, I> {
if (!this.item) {
throw new Error('Notification was created as undefined');
}

return this.item;
}

get context(): TuiNotificationContentContext<O, I> {
return this.calculateContext(this.safeItem);
}

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

@tuiPure
get hasCloseButton(): boolean {
return this.safeItem.hasCloseButton ?? this.options.hasCloseButton;
}

@tuiPure
get status(): TuiNotification {
return this.safeItem.status ?? this.options.status;
}

@tuiPure
get hasIcon(): boolean {
return this.safeItem.hasIcon ?? this.options.hasIcon;
}

@tuiPure
get autoClose(): boolean | number {
return this.safeItem.autoClose ?? this.options.autoClose;
return this.calculateContext(this.item);
}

closeNotification() {
this.safeItem.observer.complete();
this.item.observer.complete();
}

@tuiPure
private calculateContext({
status,
data,
label,
observer,
}: NotificationAlert<O, I>): TuiNotificationContentContext<O, I> {
return {
$implicit: status || this.options.status,
$implicit: status,
data: data,
label: this.label,
label: label,
closeHook: () => {
observer.complete();
},
Expand All @@ -109,11 +70,15 @@ export class TuiNotificationAlertComponent<O, I> implements OnInit {
}

private initAutoClose() {
if (!this.autoClose) {
if (!this.item.autoClose) {
return;
}

timer(isNumber(this.autoClose) ? this.autoClose : DEFAULT_ALERT_AUTOCLOSE_TIMEOUT)
timer(
isNumber(this.item.autoClose)
? this.item.autoClose
: DEFAULT_ALERT_AUTOCLOSE_TIMEOUT,
)
.pipe(
takeUntil(fromEvent(this.elementRef.nativeElement, 'mouseenter')),
repeatWhen(() => fromEvent(this.elementRef.nativeElement, 'mouseleave')),
Expand Down
Original file line number Diff line number Diff line change
@@ -1,42 +1,42 @@
<tui-notification
*ngIf="hasCloseButton else noClose"
*ngIf="item.hasCloseButton else noClose"
[status]="status"
[hasIcon]="hasIcon"
(close)="closeNotification()"
>
<label
*ngIf="label"
*ngIf="item.label"
polymorpheus-outlet
[content]="label"
[context]="context"
automation-id="tui-notification-alert__heading"
class="heading"
[content]="item.label"
[context]="context"
>
</label>
<div
polymorpheus-outlet
automation-id="tui-notification-alert__content"
class="content"
[content]="safeItem.content"
[content]="item.content"
[context]="context"
></div>
</tui-notification>
<ng-template #noClose>
<tui-notification [status]="status" [hasIcon]="hasIcon">
<tui-notification [status]="item.status" [hasIcon]="item.hasIcon">
<label
*ngIf="label"
*ngIf="item.label"
polymorpheus-outlet
[content]="label"
[context]="context"
automation-id="tui-notification-alert__heading"
class="heading"
[content]="item.label"
[context]="context"
>
</label>
<div
polymorpheus-outlet
automation-id="tui-notification-alert__content"
class="content"
[content]="safeItem.content"
[content]="item.content"
[context]="context"
></div>
</tui-notification>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,19 @@ import {ComponentFixture, fakeAsync, TestBed, tick} from '@angular/core/testing'
import {
TUI_NOTIFICATION_DEFAULT_OPTIONS,
TUI_NOTIFICATION_OPTIONS,
NotificationTokenOptions,
} 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 {
TuiNotificationOptions,
TuiNotificationOptionsWithData,
} from '../../notification-options';
import {NotificationAlert} from '../Notification-alert';
import {TuiNotificationAlertComponent} from '../notification-alert.component';
import {TuiNotificationAlertModule} from '../notification-alert.module';
Expand Down Expand Up @@ -78,7 +87,24 @@ describe('NotificationAlertComponent', () => {
@ViewChild(TuiNotificationAlertComponent, {static: true})
component: TuiNotificationAlertComponent<string, string>;

alert = new NotificationAlert(observerMock, content, {label});
constructor(
@Inject(TUI_NOTIFICATION_OPTIONS)
public readonly options: NotificationTokenOptions,
) {
this.setAlert(content, {label});
}

alert: NotificationAlert<string, string>;

setAlert(
content: PolymorpheusContent<TuiNotificationContentContext<string, string>>,
params: TuiNotificationOptions | TuiNotificationOptionsWithData<string>,
) {
this.alert = new NotificationAlert(observerMock, content, {
...this.options,
...params,
});
}
}

beforeEach(() => {
Expand All @@ -103,17 +129,17 @@ describe('NotificationAlertComponent', () => {
});

it('Default status', () => {
expect(component.status).toBe('info');
expect(component.item!.status).toBe('info');
});

it('Default autoclose', () => {
expect(component.autoClose).toBe(true);
expect(component.item!.autoClose).toBe(true);
});
});

describe('Display', () => {
beforeEach(() => {
testComponent.alert = new NotificationAlert(observerMock, content, {label});
testComponent.setAlert(content, {label});
fixture.detectChanges();
});

Expand Down Expand Up @@ -153,11 +179,7 @@ describe('NotificationAlertComponent', () => {
testComponent = fixture.componentInstance;
pageObject = new PageObject(fixture);

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

expect(
Expand Down Expand Up @@ -195,11 +217,10 @@ describe('NotificationAlertComponent', () => {
fixture = TestBed.createComponent(TestComponent);
testComponent = fixture.componentInstance;

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

expect(completeSpy).not.toHaveBeenCalled();
Expand Down Expand Up @@ -230,11 +251,11 @@ describe('NotificationAlertComponent', () => {
fixture = TestBed.createComponent(TestComponent);
testComponent = fixture.componentInstance;

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();
Expand All @@ -247,11 +268,11 @@ describe('NotificationAlertComponent', () => {
it('close | Close the Alert after custom autoClose timeout', fakeAsync(() => {
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();
Expand All @@ -263,11 +284,11 @@ describe('NotificationAlertComponent', () => {

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

Expand Down
13 changes: 11 additions & 2 deletions projects/core/modules/notifications/notifications.service.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import {Injectable} from '@angular/core';
import {Inject, Injectable} from '@angular/core';
import {tuiAssert} from '@taiga-ui/cdk';
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';
Expand All @@ -19,6 +20,11 @@ export class TuiNotificationsService {
/** @internal */
readonly items$ = new BehaviorSubject<ReadonlyArray<NotificationAlert<any, any>>>([]);

constructor(
@Inject(TUI_NOTIFICATION_OPTIONS)
public readonly options: NotificationTokenOptions,
) {}

show<O = void>(
content: PolymorpheusContent<TuiNotificationContentContext<O>>,
): Observable<O>;
Expand All @@ -37,7 +43,10 @@ export class TuiNotificationsService {
return new Observable((observer: Observer<O>) => {
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]);

Expand Down

0 comments on commit 9a5c12a

Please sign in to comment.