Merge pull request #4849 from abpframework/fix/4818

Implemented the SubscriptionService
pull/4857/head
Erol Arkat 5 years ago committed by GitHub
commit 57fb35247c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -1,21 +1,18 @@
import { ConfigState, takeUntilDestroy } from '@abp/ng.core';
import { Component, Input, OnDestroy, OnInit, TemplateRef } from '@angular/core';
import { ConfigState, SubscriptionService } from '@abp/ng.core';
import { Component, Input, OnInit, TemplateRef } from '@angular/core';
import { Select, Store } from '@ngxs/store';
import { Observable } from 'rxjs';
import { Account } from '../../models/account';
import { eAccountComponents } from '../../enums/components';
import { Account } from '../../models/account';
@Component({
selector: 'abp-auth-wrapper',
templateUrl: './auth-wrapper.component.html',
exportAs: 'abpAuthWrapper',
providers: [SubscriptionService],
})
export class AuthWrapperComponent
implements
Account.AuthWrapperComponentInputs,
Account.AuthWrapperComponentOutputs,
OnInit,
OnDestroy {
implements Account.AuthWrapperComponentInputs, Account.AuthWrapperComponentOutputs, OnInit {
@Input()
readonly mainContentRef: TemplateRef<any>;
@ -29,18 +26,16 @@ export class AuthWrapperComponent
tenantBoxKey = eAccountComponents.TenantBox;
constructor(private store: Store) {}
constructor(private store: Store, private subscription: SubscriptionService) {}
ngOnInit() {
this.store
.select(ConfigState.getSetting('Abp.Account.EnableLocalLogin'))
.pipe(takeUntilDestroy(this))
.subscribe(value => {
this.subscription.addOne(
this.store.select(ConfigState.getSetting('Abp.Account.EnableLocalLogin')),
value => {
if (value) {
this.enableLocalLogin = value.toLowerCase() !== 'false';
}
});
},
);
}
ngOnDestroy() {}
}

@ -1,4 +1,4 @@
import { Component, Injector, OnDestroy, Optional, SkipSelf, Type } from '@angular/core';
import { Component, Injector, Optional, SkipSelf, Type } from '@angular/core';
import { ActivatedRoute, NavigationEnd, Router } from '@angular/router';
import { Store } from '@ngxs/store';
import { eLayoutType } from '../enums/common';
@ -6,9 +6,9 @@ import { ABP } from '../models';
import { ReplaceableComponents } from '../models/replaceable-components';
import { LocalizationService } from '../services/localization.service';
import { RoutesService } from '../services/routes.service';
import { SubscriptionService } from '../services/subscription.service';
import { ReplaceableComponentsState } from '../states/replaceable-components.state';
import { findRoute, getRoutePath } from '../utils/route-utils';
import { takeUntilDestroy } from '../utils/rxjs-utils';
import { TreeNode } from '../utils/tree-utils';
@Component({
@ -20,8 +20,9 @@ import { TreeNode } from '../utils/tree-utils';
><ng-container *ngIf="isLayoutVisible" [ngComponentOutlet]="layout"></ng-container
></ng-template>
`,
providers: [SubscriptionService],
})
export class DynamicLayoutComponent implements OnDestroy {
export class DynamicLayoutComponent {
layout: Type<any>;
// TODO: Consider a shared enum (eThemeSharedComponents) for known layouts
@ -37,6 +38,7 @@ export class DynamicLayoutComponent implements OnDestroy {
injector: Injector,
private localizationService: LocalizationService,
private store: Store,
private subscription: SubscriptionService,
@Optional() @SkipSelf() dynamicLayoutComponent: DynamicLayoutComponent,
) {
if (dynamicLayoutComponent) return;
@ -44,7 +46,7 @@ export class DynamicLayoutComponent implements OnDestroy {
const router = injector.get(Router);
const routes = injector.get(RoutesService);
router.events.pipe(takeUntilDestroy(this)).subscribe(event => {
this.subscription.addOne(router.events, event => {
if (event instanceof NavigationEnd) {
let expectedLayout = (route.snapshot.data || {}).layout;
@ -73,7 +75,7 @@ export class DynamicLayoutComponent implements OnDestroy {
}
private listenToLanguageChange() {
this.localizationService.languageChange.pipe(takeUntilDestroy(this)).subscribe(() => {
this.subscription.addOne(this.localizationService.languageChange, () => {
this.isLayoutVisible = false;
setTimeout(() => (this.isLayoutVisible = true), 0);
});
@ -82,6 +84,4 @@ export class DynamicLayoutComponent implements OnDestroy {
private getComponent(key: string): ReplaceableComponents.ReplaceableComponent {
return this.store.selectSnapshot(ReplaceableComponentsState.getComponent(key));
}
ngOnDestroy() {}
}

@ -1,39 +1,45 @@
import { Component, OnDestroy, OnInit, Type } from '@angular/core';
import { Component, OnInit, Type } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { Store } from '@ngxs/store';
import { distinctUntilChanged } from 'rxjs/operators';
import { ABP } from '../models/common';
import { ReplaceableComponents } from '../models/replaceable-components';
import { SubscriptionService } from '../services/subscription.service';
import { ReplaceableComponentsState } from '../states/replaceable-components.state';
import { takeUntilDestroy } from '../utils/rxjs-utils';
@Component({
selector: 'abp-replaceable-route-container',
template: `
<ng-container *ngComponentOutlet="externalComponent || defaultComponent"></ng-container>
`,
providers: [SubscriptionService],
})
export class ReplaceableRouteContainerComponent implements OnInit, OnDestroy {
export class ReplaceableRouteContainerComponent implements OnInit {
defaultComponent: Type<any>;
componentKey: string;
externalComponent: Type<any>;
constructor(private route: ActivatedRoute, private store: Store) {}
constructor(
private route: ActivatedRoute,
private store: Store,
private subscription: SubscriptionService,
) {}
ngOnInit() {
this.defaultComponent = this.route.snapshot.data.replaceableComponent.defaultComponent;
this.componentKey = (this.route.snapshot.data
.replaceableComponent as ReplaceableComponents.RouteData).key;
this.store
const component$ = this.store
.select(ReplaceableComponentsState.getComponent(this.componentKey))
.pipe(takeUntilDestroy(this), distinctUntilChanged())
.subscribe((res = {} as ReplaceableComponents.ReplaceableComponent) => {
.pipe(distinctUntilChanged());
this.subscription.addOne(
component$,
(res = {} as ReplaceableComponents.ReplaceableComponent) => {
this.externalComponent = res.component;
});
},
);
}
ngOnDestroy() {}
}

@ -1,34 +1,25 @@
import {
Directive,
ElementRef,
EventEmitter,
Input,
OnDestroy,
OnInit,
Output,
} from '@angular/core';
import { takeUntilDestroy } from '../utils/rxjs-utils';
import { Directive, ElementRef, EventEmitter, Input, OnInit, Output } from '@angular/core';
import { fromEvent } from 'rxjs';
import { debounceTime } from 'rxjs/operators';
import { SubscriptionService } from '../services/subscription.service';
@Directive({
// tslint:disable-next-line: directive-selector
selector: '[input.debounce]',
providers: [SubscriptionService],
})
export class InputEventDebounceDirective implements OnInit, OnDestroy {
export class InputEventDebounceDirective implements OnInit {
@Input() debounce = 300;
@Output('input.debounce') readonly debounceEvent = new EventEmitter<Event>();
constructor(private el: ElementRef) {}
constructor(private el: ElementRef, private subscription: SubscriptionService) {}
ngOnInit(): void {
fromEvent(this.el.nativeElement, 'input')
.pipe(debounceTime(this.debounce), takeUntilDestroy(this))
.subscribe((event: Event) => {
this.debounceEvent.emit(event);
});
}
const input$ = fromEvent(this.el.nativeElement, 'input').pipe(debounceTime(this.debounce));
ngOnDestroy(): void {}
this.subscription.addOne(input$, (event: Event) => {
this.debounceEvent.emit(event);
});
}
}

@ -4,7 +4,6 @@ import {
ElementRef,
EventEmitter,
Input,
OnDestroy,
OnInit,
Output,
Self,
@ -12,15 +11,16 @@ import {
import { FormControl, FormGroup, FormGroupDirective } from '@angular/forms';
import { fromEvent } from 'rxjs';
import { debounceTime, filter } from 'rxjs/operators';
import { takeUntilDestroy } from '../utils';
import { SubscriptionService } from '../services/subscription.service';
type Controls = { [key: string]: FormControl } | FormGroup[];
@Directive({
// tslint:disable-next-line: directive-selector
selector: 'form[ngSubmit][formGroup]',
providers: [SubscriptionService],
})
export class FormSubmitDirective implements OnInit, OnDestroy {
export class FormSubmitDirective implements OnInit {
@Input()
debounce = 200;
@ -35,30 +35,30 @@ export class FormSubmitDirective implements OnInit, OnDestroy {
@Self() private formGroupDirective: FormGroupDirective,
private host: ElementRef<HTMLFormElement>,
private cdRef: ChangeDetectorRef,
private subscription: SubscriptionService,
) {}
ngOnInit() {
this.formGroupDirective.ngSubmit.pipe(takeUntilDestroy(this)).subscribe(() => {
this.subscription.addOne(this.formGroupDirective.ngSubmit, () => {
this.markAsDirty();
this.executedNgSubmit = true;
});
fromEvent(this.host.nativeElement as HTMLElement, 'keyup')
.pipe(
debounceTime(this.debounce),
filter((key: KeyboardEvent) => key && key.key === 'Enter'),
takeUntilDestroy(this),
)
.subscribe(() => {
if (!this.executedNgSubmit) {
this.host.nativeElement.dispatchEvent(new Event('submit', { bubbles: true, cancelable: true }));
}
const keyup$ = fromEvent(this.host.nativeElement as HTMLElement, 'keyup').pipe(
debounceTime(this.debounce),
filter((key: KeyboardEvent) => key && key.key === 'Enter'),
);
this.executedNgSubmit = false;
});
}
this.subscription.addOne(keyup$, () => {
if (!this.executedNgSubmit) {
this.host.nativeElement.dispatchEvent(
new Event('submit', { bubbles: true, cancelable: true }),
);
}
ngOnDestroy(): void {}
this.executedNgSubmit = false;
});
}
markAsDirty() {
const { form } = this.formGroupDirective;

@ -2,19 +2,18 @@ import {
Directive,
ElementRef,
Input,
OnChanges,
OnDestroy,
OnInit,
Renderer2,
ViewContainerRef,
TemplateRef,
Optional,
Renderer2,
SimpleChanges,
OnChanges,
TemplateRef,
ViewContainerRef,
} from '@angular/core';
import { Store } from '@ngxs/store';
import { ConfigState } from '../states';
import { takeUntilDestroy } from '../utils';
import { Subscription } from 'rxjs';
import { ConfigState } from '../states';
@Directive({
selector: '[abpPermission]',
@ -39,7 +38,6 @@ export class PermissionDirective implements OnInit, OnDestroy, OnChanges {
this.subscription = this.store
.select(ConfigState.getGrantedPolicy(this.condition))
.pipe(takeUntilDestroy(this))
.subscribe(isGranted => {
if (this.templateRef && isGranted) {
this.vcRef.clear();
@ -47,7 +45,10 @@ export class PermissionDirective implements OnInit, OnDestroy, OnChanges {
} else if (this.templateRef && !isGranted) {
this.vcRef.clear();
} else if (!isGranted && !this.templateRef) {
this.renderer.removeChild((this.elRef.nativeElement as HTMLElement).parentElement, this.elRef.nativeElement);
this.renderer.removeChild(
(this.elRef.nativeElement as HTMLElement).parentElement,
this.elRef.nativeElement,
);
}
});
}
@ -58,7 +59,9 @@ export class PermissionDirective implements OnInit, OnDestroy, OnChanges {
}
}
ngOnDestroy(): void {}
ngOnDestroy(): void {
if (this.subscription) this.subscription.unsubscribe();
}
ngOnChanges({ condition }: SimpleChanges) {
if ((condition || { currentValue: null }).currentValue) {

@ -4,7 +4,6 @@ import {
Injector,
Input,
OnChanges,
OnDestroy,
OnInit,
SimpleChanges,
TemplateRef,
@ -12,17 +11,17 @@ import {
ViewContainerRef,
} from '@angular/core';
import { Store } from '@ngxs/store';
import compare from 'just-compare';
import { Subscription } from 'rxjs';
import { filter } from 'rxjs/operators';
import snq from 'snq';
import { ABP } from '../models/common';
import { ReplaceableComponents } from '../models/replaceable-components';
import { SubscriptionService } from '../services/subscription.service';
import { ReplaceableComponentsState } from '../states/replaceable-components.state';
import { takeUntilDestroy } from '../utils/rxjs-utils';
import compare from 'just-compare';
import snq from 'snq';
@Directive({ selector: '[abpReplaceableTemplate]' })
export class ReplaceableTemplateDirective implements OnInit, OnDestroy, OnChanges {
@Directive({ selector: '[abpReplaceableTemplate]', providers: [SubscriptionService] })
export class ReplaceableTemplateDirective implements OnInit, OnChanges {
@Input('abpReplaceableTemplate')
data: ReplaceableComponents.ReplaceableTemplateDirectiveInput<any, any>;
@ -47,6 +46,7 @@ export class ReplaceableTemplateDirective implements OnInit, OnDestroy, OnChange
private cfRes: ComponentFactoryResolver,
private vcRef: ViewContainerRef,
private store: Store,
private subscription: SubscriptionService,
) {
this.context = {
initTemplate: ref => {
@ -58,16 +58,18 @@ export class ReplaceableTemplateDirective implements OnInit, OnDestroy, OnChange
}
ngOnInit() {
this.store
const component$ = this.store
.select(ReplaceableComponentsState.getComponent(this.data.componentKey))
.pipe(
filter(
(res = {} as ReplaceableComponents.ReplaceableComponent) =>
!this.initialized || !compare(res.component, this.externalComponent),
),
takeUntilDestroy(this),
)
.subscribe((res = {} as ReplaceableComponents.ReplaceableComponent) => {
);
this.subscription.addOne(
component$,
(res = {} as ReplaceableComponents.ReplaceableComponent) => {
this.vcRef.clear();
this.externalComponent = res.component;
if (this.defaultComponentRef) {
@ -90,7 +92,8 @@ export class ReplaceableTemplateDirective implements OnInit, OnDestroy, OnChange
}
this.initialized = true;
});
},
);
}
ngOnChanges(changes: SimpleChanges) {
@ -99,8 +102,6 @@ export class ReplaceableTemplateDirective implements OnInit, OnDestroy, OnChange
}
}
ngOnDestroy() {}
setDefaultComponentInputs() {
if (!this.defaultComponentRef || (!this.data.inputs && !this.data.outputs)) return;

@ -1,24 +1,21 @@
import { Directive, ElementRef, EventEmitter, OnInit, Output, OnDestroy } from '@angular/core';
import { Directive, ElementRef, EventEmitter, OnInit, Output } from '@angular/core';
import { fromEvent } from 'rxjs';
import { takeUntilDestroy } from '../utils/rxjs-utils';
import { SubscriptionService } from '../services/subscription.service';
@Directive({
// tslint:disable-next-line: directive-selector
selector: '[click.stop]',
providers: [SubscriptionService],
})
export class StopPropagationDirective implements OnInit, OnDestroy {
export class StopPropagationDirective implements OnInit {
@Output('click.stop') readonly stopPropEvent = new EventEmitter<MouseEvent>();
constructor(private el: ElementRef) {}
constructor(private el: ElementRef, private subscription: SubscriptionService) {}
ngOnInit(): void {
fromEvent(this.el.nativeElement, 'click')
.pipe(takeUntilDestroy(this))
.subscribe((event: MouseEvent) => {
event.stopPropagation();
this.stopPropEvent.emit(event);
});
this.subscription.addOne(fromEvent(this.el.nativeElement, 'click'), (event: MouseEvent) => {
event.stopPropagation();
this.stopPropEvent.emit(event);
});
}
ngOnDestroy(): void {}
}

@ -1,10 +1,17 @@
import { Inject, Injectable, OnDestroy, Optional } from '@angular/core';
import { BehaviorSubject, Observable, of, ReplaySubject } from 'rxjs';
import { catchError, debounceTime, filter, shareReplay, switchMap, tap } from 'rxjs/operators';
import { BehaviorSubject, Observable, of, ReplaySubject, Subject } from 'rxjs';
import {
catchError,
debounceTime,
filter,
shareReplay,
switchMap,
takeUntil,
tap,
} from 'rxjs/operators';
import { ABP } from '../models/common';
import { PagedResultDto } from '../models/dtos';
import { LIST_QUERY_DEBOUNCE_TIME } from '../tokens/list.token';
import { takeUntilDestroy } from '../utils/rxjs-utils';
@Injectable()
export class ListService<QueryParamsType = ABP.PageQueryParams> implements OnDestroy {
@ -65,6 +72,8 @@ export class ListService<QueryParamsType = ABP.PageQueryParams> implements OnDes
private _isLoading$ = new BehaviorSubject(false);
private destroy$ = new Subject();
get isLoading$(): Observable<boolean> {
return this._isLoading$.asObservable();
}
@ -92,11 +101,13 @@ export class ListService<QueryParamsType = ABP.PageQueryParams> implements OnDes
filter(Boolean),
tap(() => this._isLoading$.next(false)),
shareReplay({ bufferSize: 1, refCount: true }),
takeUntilDestroy(this),
takeUntil(this.destroy$),
);
}
ngOnDestroy() {}
ngOnDestroy() {
this.destroy$.next();
}
}
export type QueryStreamCreatorCallback<T, QueryParamsType = ABP.PageQueryParams> = (

@ -1,10 +1,9 @@
import { Injectable, OnDestroy } from '@angular/core';
import { Actions, ofActionSuccessful, Store } from '@ngxs/store';
import { BehaviorSubject, Observable } from 'rxjs';
import { BehaviorSubject, Observable, Subscription } from 'rxjs';
import { GetAppConfiguration } from '../actions/config.actions';
import { ABP } from '../models/common';
import { ConfigState } from '../states/config.state';
import { takeUntilDestroy } from '../utils/rxjs-utils';
import { pushValueTo } from '../utils/array-utils';
import { BaseTreeNode, createTreeFromList, TreeNode } from '../utils/tree-utils';
@ -129,6 +128,7 @@ export abstract class AbstractTreeService<T extends object> {
@Injectable()
export abstract class AbstractNavTreeService<T extends ABP.Nav> extends AbstractTreeService<T>
implements OnDestroy {
private subscription: Subscription;
readonly id = 'name';
readonly parentId = 'parentName';
readonly hide = (item: T) => item.invisible || !this.isGranted(item);
@ -142,8 +142,8 @@ export abstract class AbstractNavTreeService<T extends ABP.Nav> extends Abstract
constructor(protected actions: Actions, protected store: Store) {
super();
this.actions
.pipe(takeUntilDestroy(this), ofActionSuccessful(GetAppConfiguration))
this.subscription = this.actions
.pipe(ofActionSuccessful(GetAppConfiguration))
.subscribe(() => this.refresh());
}
@ -162,7 +162,9 @@ export abstract class AbstractNavTreeService<T extends ABP.Nav> extends Abstract
}
/* istanbul ignore next */
ngOnDestroy() {}
ngOnDestroy() {
this.subscription.unsubscribe();
}
}
@Injectable({ providedIn: 'root' })

@ -1,3 +1,4 @@
// tslint:disable: max-line-length
import { Observable, Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
@ -5,13 +6,16 @@ function isFunction(value) {
return typeof value === 'function';
}
/**
* @deprecated no longer working, please use SubscriptionService (https://docs.abp.io/en/abp/latest/UI/Angular/Subscription-Service) instead.
*/
export const takeUntilDestroy = (componentInstance, destroyMethodName = 'ngOnDestroy') => <T>(
source: Observable<T>
source: Observable<T>,
) => {
const originalDestroy = componentInstance[destroyMethodName];
if (isFunction(originalDestroy) === false) {
throw new Error(
`${componentInstance.constructor.name} is using untilDestroyed but doesn't implement ${destroyMethodName}`
`${componentInstance.constructor.name} is using untilDestroyed but doesn't implement ${destroyMethodName}`,
);
}
if (!componentInstance['__takeUntilDestroy']) {

@ -1,4 +1,4 @@
import { eLayoutType, takeUntilDestroy } from '@abp/ng.core';
import { eLayoutType, SubscriptionService } from '@abp/ng.core';
import { collapseWithMargin, slideFromBottom } from '@abp/ng.theme.shared';
import { AfterViewInit, Component, OnDestroy } from '@angular/core';
import { fromEvent } from 'rxjs';
@ -9,6 +9,7 @@ import { eThemeBasicComponents } from '../../enums/components';
selector: 'abp-layout-application',
templateUrl: './application-layout.component.html',
animations: [slideFromBottom, collapseWithMargin],
providers: [SubscriptionService],
})
export class ApplicationLayoutComponent implements AfterViewInit, OnDestroy {
// required for dynamic component
@ -24,6 +25,8 @@ export class ApplicationLayoutComponent implements AfterViewInit, OnDestroy {
navItemsComponentKey = eThemeBasicComponents.NavItems;
constructor(private subscription: SubscriptionService) {}
private checkWindowWidth() {
setTimeout(() => {
if (window.innerWidth < 992) {
@ -43,11 +46,8 @@ export class ApplicationLayoutComponent implements AfterViewInit, OnDestroy {
ngAfterViewInit() {
this.checkWindowWidth();
fromEvent(window, 'resize')
.pipe(takeUntilDestroy(this), debounceTime(150))
.subscribe(() => {
this.checkWindowWidth();
});
const resize$ = fromEvent(window, 'resize').pipe(debounceTime(150));
this.subscription.addOne(resize$, () => this.checkWindowWidth());
}
ngOnDestroy() {}

@ -1,11 +1,5 @@
import { ABP, getRoutePath, RoutesService, takeUntilDestroy, TreeNode } from '@abp/ng.core';
import {
ChangeDetectionStrategy,
ChangeDetectorRef,
Component,
OnDestroy,
OnInit,
} from '@angular/core';
import { ABP, getRoutePath, RoutesService, TreeNode, SubscriptionService } from '@abp/ng.core';
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, OnInit } from '@angular/core';
import { NavigationEnd, Router } from '@angular/router';
import { filter, map, startWith } from 'rxjs/operators';
import { eThemeSharedRouteNames } from '../../enums';
@ -14,28 +8,27 @@ import { eThemeSharedRouteNames } from '../../enums';
selector: 'abp-breadcrumb',
templateUrl: './breadcrumb.component.html',
changeDetection: ChangeDetectionStrategy.OnPush,
providers: [SubscriptionService],
})
export class BreadcrumbComponent implements OnDestroy, OnInit {
export class BreadcrumbComponent implements OnInit {
segments: Partial<ABP.Route>[] = [];
constructor(
public readonly cdRef: ChangeDetectorRef,
private router: Router,
private routes: RoutesService,
private subscription: SubscriptionService,
) {}
ngOnDestroy() {}
ngOnInit(): void {
this.router.events
.pipe(
takeUntilDestroy(this),
this.subscription.addOne(
this.router.events.pipe(
filter<NavigationEnd>(event => event instanceof NavigationEnd),
// tslint:disable-next-line:deprecation
startWith(null),
map(() => this.routes.search({ path: getRoutePath(this.router) })),
)
.subscribe(route => {
),
route => {
this.segments = [];
if (route) {
let node = { parent: route } as TreeNode<ABP.Route>;
@ -48,7 +41,8 @@ export class BreadcrumbComponent implements OnDestroy, OnInit {
this.cdRef.detectChanges();
}
});
},
);
}
}

@ -1,4 +1,4 @@
import { Config, takeUntilDestroy } from '@abp/ng.core';
import { Config, SubscriptionService } from '@abp/ng.core';
import {
AfterViewInit,
ApplicationRef,
@ -20,6 +20,7 @@ import snq from 'snq';
selector: 'abp-http-error-wrapper',
templateUrl: './http-error-wrapper.component.html',
styleUrls: ['http-error-wrapper.component.scss'],
providers: [SubscriptionService],
})
export class HttpErrorWrapperComponent implements AfterViewInit, OnDestroy, OnInit {
appRef: ApplicationRef;
@ -51,6 +52,8 @@ export class HttpErrorWrapperComponent implements AfterViewInit, OnDestroy, OnIn
return this.status ? `[${this.status}]` : '';
}
constructor(private subscription: SubscriptionService) {}
ngOnInit() {
this.backgroundColor =
snq(() => window.getComputedStyle(document.body).getPropertyValue('background-color')) ||
@ -71,15 +74,11 @@ export class HttpErrorWrapperComponent implements AfterViewInit, OnDestroy, OnIn
customComponentRef.changeDetectorRef.detectChanges();
}
fromEvent(document, 'keyup')
.pipe(
takeUntilDestroy(this),
debounceTime(150),
filter((key: KeyboardEvent) => key && key.key === 'Escape'),
)
.subscribe(() => {
this.destroy();
});
const keyup$ = fromEvent(document, 'keyup').pipe(
debounceTime(150),
filter((key: KeyboardEvent) => key && key.key === 'Escape'),
);
this.subscription.addOne(keyup$, () => this.destroy());
}
ngOnDestroy() {}

@ -1,7 +1,6 @@
import { StartLoader, StopLoader } from '@abp/ng.core';
import { StartLoader, StopLoader, SubscriptionService } from '@abp/ng.core';
import { ChangeDetectorRef, Component, Input, OnDestroy, OnInit } from '@angular/core';
import { NavigationEnd, NavigationError, NavigationStart, Router } from '@angular/router';
import { takeUntilDestroy } from '@ngx-validate/core';
import { Actions, ofActionSuccessful } from '@ngxs/store';
import { Subscription, timer } from 'rxjs';
import { filter } from 'rxjs/operators';
@ -22,6 +21,7 @@ import { filter } from 'rxjs/operators';
</div>
`,
styleUrls: ['./loader-bar.component.scss'],
providers: [SubscriptionService],
})
export class LoaderBarComponent implements OnDestroy, OnInit {
protected _isLoading: boolean;
@ -77,36 +77,38 @@ export class LoaderBarComponent implements OnDestroy, OnInit {
return `0 0 10px rgba(${this.color}, 0.5)`;
}
constructor(private actions: Actions, private router: Router, private cdRef: ChangeDetectorRef) {}
constructor(
private actions: Actions,
private router: Router,
private cdRef: ChangeDetectorRef,
private subscription: SubscriptionService,
) {}
private subscribeToLoadActions() {
this.actions
.pipe(
ofActionSuccessful(StartLoader, StopLoader),
filter(this.filter),
takeUntilDestroy(this),
)
.subscribe(action => {
this.subscription.addOne(
this.actions.pipe(ofActionSuccessful(StartLoader, StopLoader), filter(this.filter)),
action => {
if (action instanceof StartLoader) this.startLoading();
else this.stopLoading();
});
},
);
}
private subscribeToRouterEvents() {
this.router.events
.pipe(
this.subscription.addOne(
this.router.events.pipe(
filter(
event =>
event instanceof NavigationStart ||
event instanceof NavigationEnd ||
event instanceof NavigationError,
),
takeUntilDestroy(this),
)
.subscribe(event => {
),
event => {
if (event instanceof NavigationStart) this.startLoading();
else this.stopLoading();
});
},
);
}
ngOnInit() {

@ -1,4 +1,4 @@
import { takeUntilDestroy } from '@abp/ng.core';
import { SubscriptionService } from '@abp/ng.core';
import {
Component,
ContentChild,
@ -27,7 +27,7 @@ export type ModalSize = 'sm' | 'md' | 'lg' | 'xl';
templateUrl: './modal.component.html',
animations: [fadeAnimation],
styleUrls: ['./modal.component.scss'],
providers: [ModalService],
providers: [ModalService, SubscriptionService],
})
export class ModalComponent implements OnDestroy {
@Input()
@ -60,11 +60,11 @@ export class ModalComponent implements OnDestroy {
@ContentChild(ButtonComponent, { static: false, read: ButtonComponent })
abpSubmit: ButtonComponent;
@ContentChild('abpHeader', {static: false}) abpHeader: TemplateRef<any>;
@ContentChild('abpHeader', { static: false }) abpHeader: TemplateRef<any>;
@ContentChild('abpBody', {static: false}) abpBody: TemplateRef<any>;
@ContentChild('abpBody', { static: false }) abpBody: TemplateRef<any>;
@ContentChild('abpFooter', {static: false}) abpFooter: TemplateRef<any>;
@ContentChild('abpFooter', { static: false }) abpFooter: TemplateRef<any>;
@ContentChild('abpClose', { static: false, read: ElementRef })
abpClose: ElementRef<any>;
@ -103,14 +103,15 @@ export class ModalComponent implements OnDestroy {
private renderer: Renderer2,
private confirmationService: ConfirmationService,
private modalService: ModalService,
private subscription: SubscriptionService,
) {
this.initToggleStream();
}
private initToggleStream() {
this.toggle$
.pipe(takeUntilDestroy(this), debounceTime(0), distinctUntilChanged())
.subscribe(value => this.toggle(value));
this.subscription.addOne(this.toggle$.pipe(debounceTime(0), distinctUntilChanged()), value =>
this.toggle(value),
);
}
private toggle(value: boolean) {

@ -1,9 +1,15 @@
import { Router, RouteReuseStrategy, NavigationStart, NavigationEnd, NavigationError } from '@angular/router';
import {
Router,
RouteReuseStrategy,
NavigationStart,
NavigationEnd,
NavigationError,
} from '@angular/router';
import { createHostFactory, SpectatorHost, SpyObject } from '@ngneat/spectator/jest';
import { Actions, NgxsModule, Store } from '@ngxs/store';
import { Subject, Subscription, Observable, Subscriber, timer } from 'rxjs';
import { LoaderBarComponent } from '../components/loader-bar/loader-bar.component';
import { StartLoader, StopLoader } from '@abp/ng.core';
import { StartLoader, StopLoader, SubscriptionService } from '@abp/ng.core';
import { HttpRequest } from '@angular/common/http';
describe('LoaderBarComponent', () => {
@ -16,6 +22,7 @@ describe('LoaderBarComponent', () => {
mocks: [Router],
imports: [NgxsModule.forRoot()],
detectChanges: false,
providers: [SubscriptionService],
});
beforeEach(() => {

Loading…
Cancel
Save