Browse Source

Merge pull request #2261 from abpframework/refactor/general

General refactor for Angular
pull/2267/head
Mehmet Erim 7 years ago
committed by GitHub
parent
commit
ff1788d258
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 1
      npm/ng-packs/packages/core/src/lib/core.module.ts
  2. 67
      npm/ng-packs/packages/core/src/lib/directives/permission.directive.ts
  3. 12
      npm/ng-packs/packages/core/src/lib/guards/permission.guard.ts
  4. 39
      npm/ng-packs/packages/core/src/lib/tests/permission.directive.spec.ts
  5. 18
      npm/ng-packs/packages/core/src/lib/tests/permission.guard.spec.ts
  6. 13
      npm/ng-packs/packages/core/src/lib/utils/date-extensions.ts
  7. 8
      npm/ng-packs/packages/identity/src/lib/components/roles/roles.component.html
  8. 8
      npm/ng-packs/packages/identity/src/lib/components/users/users.component.html
  9. 10
      npm/ng-packs/packages/tenant-management/src/lib/components/tenants/tenants.component.html
  10. 8
      npm/ng-packs/packages/tenant-management/src/lib/components/tenants/tenants.component.ts
  11. 8
      npm/ng-packs/packages/theme-basic/src/lib/components/application-layout/application-layout.component.html
  12. 2
      npm/ng-packs/packages/theme-shared/src/lib/components/http-error-wrapper/http-error-wrapper.component.html
  13. 1
      npm/ng-packs/packages/theme-shared/src/lib/components/http-error-wrapper/http-error-wrapper.component.scss
  14. 21
      npm/ng-packs/packages/theme-shared/src/lib/components/http-error-wrapper/http-error-wrapper.component.ts
  15. 8
      npm/ng-packs/packages/theme-shared/src/lib/handlers/error.handler.ts
  16. 8
      npm/ng-packs/packages/theme-shared/src/lib/tests/error.component.spec.ts
  17. 14
      npm/ng-packs/packages/theme-shared/src/lib/tests/error.handler.spec.ts
  18. 6
      npm/ng-packs/packages/theme-shared/src/lib/theme-shared.module.ts

1
npm/ng-packs/packages/core/src/lib/core.module.ts

@ -28,6 +28,7 @@ import { ConfigState } from './states/config.state';
import { ProfileState } from './states/profile.state'; import { ProfileState } from './states/profile.state';
import { SessionState } from './states/session.state'; import { SessionState } from './states/session.state';
import { getInitialData, localeInitializer } from './utils/initial-utils'; import { getInitialData, localeInitializer } from './utils/initial-utils';
import './utils/date-extensions';
@NgModule({ @NgModule({
imports: [ imports: [

67
npm/ng-packs/packages/core/src/lib/directives/permission.directive.ts

@ -1,31 +1,68 @@
import { Directive, ElementRef, Input, OnDestroy, OnInit, Optional, Renderer2 } from '@angular/core'; import {
Directive,
ElementRef,
Input,
OnDestroy,
OnInit,
Renderer2,
ViewContainerRef,
TemplateRef,
Optional,
SimpleChanges,
OnChanges,
} from '@angular/core';
import { Store } from '@ngxs/store'; import { Store } from '@ngxs/store';
import { ConfigState } from '../states'; import { ConfigState } from '../states';
import { takeUntilDestroy } from '../utils'; import { takeUntilDestroy } from '../utils';
import { Subscription } from 'rxjs';
@Directive({ @Directive({
selector: '[abpPermission]', selector: '[abpPermission]',
}) })
export class PermissionDirective implements OnInit, OnDestroy { export class PermissionDirective implements OnInit, OnDestroy, OnChanges {
@Input('abpPermission') condition: string; @Input('abpPermission') condition: string;
constructor(@Optional() private elRef: ElementRef, private renderer: Renderer2, private store: Store) {} subscription: Subscription;
constructor(
private elRef: ElementRef,
private renderer: Renderer2,
private store: Store,
@Optional() private templateRef: TemplateRef<any>,
private vcRef: ViewContainerRef,
) {}
private check() {
if (this.subscription) {
this.subscription.unsubscribe();
}
this.subscription = this.store
.select(ConfigState.getGrantedPolicy(this.condition))
.pipe(takeUntilDestroy(this))
.subscribe(isGranted => {
if (this.templateRef && isGranted) {
this.vcRef.clear();
this.vcRef.createEmbeddedView(this.templateRef);
} 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);
}
});
}
ngOnInit() { ngOnInit() {
if (this.condition) { if (this.templateRef && !this.condition) {
this.store this.vcRef.createEmbeddedView(this.templateRef);
.select(ConfigState.getGrantedPolicy(this.condition))
.pipe(takeUntilDestroy(this))
.subscribe(isGranted => {
if (!isGranted) {
this.renderer.removeChild(
(this.elRef.nativeElement as HTMLElement).parentElement,
this.elRef.nativeElement,
);
}
});
} }
} }
ngOnDestroy(): void {} ngOnDestroy(): void {}
ngOnChanges({ condition }: SimpleChanges) {
if ((condition || { currentValue: null }).currentValue) {
this.check();
}
}
} }

12
npm/ng-packs/packages/core/src/lib/guards/permission.guard.ts

@ -1,5 +1,5 @@
import { Injectable } from '@angular/core'; import { Injectable } from '@angular/core';
import { ActivatedRouteSnapshot, CanActivate } from '@angular/router'; import { ActivatedRouteSnapshot, CanActivate, RouterStateSnapshot } from '@angular/router';
import { Store } from '@ngxs/store'; import { Store } from '@ngxs/store';
import { Observable } from 'rxjs'; import { Observable } from 'rxjs';
import { tap } from 'rxjs/operators'; import { tap } from 'rxjs/operators';
@ -13,8 +13,14 @@ import { ConfigState } from '../states';
export class PermissionGuard implements CanActivate { export class PermissionGuard implements CanActivate {
constructor(private store: Store) {} constructor(private store: Store) {}
canActivate({ data }: ActivatedRouteSnapshot): Observable<boolean> { canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean> {
const resource = snq(() => data.routes.requiredPolicy) || (data.requiredPolicy as string); let resource = snq(() => route.data.routes.requiredPolicy) || snq(() => route.data.requiredPolicy as string);
if (!resource) {
resource = snq(
() => route.routeConfig.children.find(child => state.url.indexOf(child.path) > -1).data.requiredPolicy,
);
}
return this.store.select(ConfigState.getGrantedPolicy(resource)).pipe( return this.store.select(ConfigState.getGrantedPolicy(resource)).pipe(
tap(access => { tap(access => {
if (!access) { if (!access) {

39
npm/ng-packs/packages/core/src/lib/tests/permission.directive.spec.ts

@ -43,4 +43,43 @@ describe('PermissionDirective', () => {
expect(spy.mock.calls).toHaveLength(0); expect(spy.mock.calls).toHaveLength(0);
}); });
}); });
describe('structural', () => {
beforeEach(() => {
spectator = createDirective(
'<div id="test-element" *abpPermission="condition">Testing Permission Directive</div>',
{ hostProps: { condition: '' } },
);
directive = spectator.directive;
});
it('should be created', () => {
expect(directive).toBeTruthy();
});
it('should remove the element from DOM', () => {
expect(spectator.query('#test-element')).toBeTruthy();
expect(spectator.directive.subscription).toBeUndefined();
spectator.setHostInput({ condition: 'test' });
expect(spectator.directive.subscription).toBeTruthy();
grantedPolicy$.next(true);
expect(spectator.query('#test-element')).toBeTruthy();
grantedPolicy$.next(false);
expect(spectator.query('#test-element')).toBeFalsy();
grantedPolicy$.next(true);
grantedPolicy$.next(true);
expect(spectator.queryAll('#test-element')).toHaveLength(1);
});
describe('#subscription', () => {
it('should call the unsubscribe', () => {
const spy = jest.fn(() => {});
spectator.setHostInput({ condition: 'test' });
spectator.directive.subscription.unsubscribe = spy;
spectator.setHostInput({ condition: 'test2' });
expect(spy).toHaveBeenCalled();
});
});
});
}); });

18
npm/ng-packs/packages/core/src/lib/tests/permission.guard.spec.ts

@ -23,7 +23,7 @@ describe('PermissionGuard', () => {
it('should return true when the grantedPolicy is true', done => { it('should return true when the grantedPolicy is true', done => {
store.select.andReturn(of(true)); store.select.andReturn(of(true));
const spy = jest.spyOn(store, 'dispatch'); const spy = jest.spyOn(store, 'dispatch');
guard.canActivate({ data: { requiredPolicy: '' } } as any).subscribe(res => { guard.canActivate({ data: { requiredPolicy: 'test' } } as any, null).subscribe(res => {
expect(res).toBe(true); expect(res).toBe(true);
expect(spy.mock.calls).toHaveLength(0); expect(spy.mock.calls).toHaveLength(0);
done(); done();
@ -33,11 +33,25 @@ describe('PermissionGuard', () => {
it('should return false and dispatch RestOccurError when the grantedPolicy is false', done => { it('should return false and dispatch RestOccurError when the grantedPolicy is false', done => {
store.select.andReturn(of(false)); store.select.andReturn(of(false));
const spy = jest.spyOn(store, 'dispatch'); const spy = jest.spyOn(store, 'dispatch');
guard.canActivate({ data: { requiredPolicy: '' } } as any).subscribe(res => { guard.canActivate({ data: { requiredPolicy: 'test' } } as any, null).subscribe(res => {
expect(res).toBe(false); expect(res).toBe(false);
expect(spy.mock.calls[0][0] instanceof RestOccurError).toBeTruthy(); expect(spy.mock.calls[0][0] instanceof RestOccurError).toBeTruthy();
expect((spy.mock.calls[0][0] as RestOccurError).payload).toEqual({ status: 403 }); expect((spy.mock.calls[0][0] as RestOccurError).payload).toEqual({ status: 403 });
done(); done();
}); });
}); });
it('should find the requiredPolicy from child route', done => {
store.select.andReturn(of(false));
const spy = jest.spyOn(store, 'select');
guard
.canActivate(
{ data: {}, routeConfig: { children: [{ path: 'test', data: { requiredPolicy: 'TestPolicy' } }] } } as any,
{ url: 'test' } as any,
)
.subscribe(() => {
expect(spy.mock.calls[0][0]({ auth: { grantedPolicies: { TestPolicy: true } } })).toBe(true);
done();
});
});
}); });

13
npm/ng-packs/packages/core/src/lib/utils/date-extensions.ts

@ -0,0 +1,13 @@
export {};
declare global {
interface Date {
toLocalISOString(): string;
}
}
Date.prototype.toLocalISOString = function(this: Date): string {
const timezoneOffset = this.getTimezoneOffset();
return new Date(this.getTime() - timezoneOffset * 60000).toISOString();
};

8
npm/ng-packs/packages/identity/src/lib/components/roles/roles.component.html

@ -6,7 +6,7 @@
</div> </div>
<div class="text-right col col-md-6"> <div class="text-right col col-md-6">
<button <button
[abpPermission]="'AbpIdentity.Roles.Create'" *abpPermission="'AbpIdentity.Roles.Create'"
id="create-role" id="create-role"
class="btn btn-primary" class="btn btn-primary"
type="button" type="button"
@ -73,18 +73,18 @@
<i class="fa fa-cog mr-1"></i>{{ 'AbpIdentity::Actions' | abpLocalization }} <i class="fa fa-cog mr-1"></i>{{ 'AbpIdentity::Actions' | abpLocalization }}
</button> </button>
<div ngbDropdownMenu> <div ngbDropdownMenu>
<button [abpPermission]="'AbpIdentity.Roles.Update'" ngbDropdownItem (click)="edit(data.id)"> <button *abpPermission="'AbpIdentity.Roles.Update'" ngbDropdownItem (click)="edit(data.id)">
{{ 'AbpIdentity::Edit' | abpLocalization }} {{ 'AbpIdentity::Edit' | abpLocalization }}
</button> </button>
<button <button
[abpPermission]="'AbpIdentity.Roles.ManagePermissions'" *abpPermission="'AbpIdentity.Roles.ManagePermissions'"
ngbDropdownItem ngbDropdownItem
(click)="providerKey = data.name; visiblePermissions = true" (click)="providerKey = data.name; visiblePermissions = true"
> >
{{ 'AbpIdentity::Permissions' | abpLocalization }} {{ 'AbpIdentity::Permissions' | abpLocalization }}
</button> </button>
<button <button
[abpPermission]="'AbpIdentity.Roles.Delete'" *abpPermission="'AbpIdentity.Roles.Delete'"
ngbDropdownItem ngbDropdownItem
(click)="delete(data.id, data.name)" (click)="delete(data.id, data.name)"
> >

8
npm/ng-packs/packages/identity/src/lib/components/users/users.component.html

@ -6,7 +6,7 @@
</div> </div>
<div class="text-right col col-md-6"> <div class="text-right col col-md-6">
<button <button
[abpPermission]="'AbpIdentity.Users.Create'" *abpPermission="'AbpIdentity.Users.Create'"
id="create-role" id="create-role"
class="btn btn-primary" class="btn btn-primary"
type="button" type="button"
@ -86,18 +86,18 @@
<i class="fa fa-cog mr-1"></i>{{ 'AbpIdentity::Actions' | abpLocalization }} <i class="fa fa-cog mr-1"></i>{{ 'AbpIdentity::Actions' | abpLocalization }}
</button> </button>
<div ngbDropdownMenu> <div ngbDropdownMenu>
<button [abpPermission]="'AbpIdentity.Users.Update'" ngbDropdownItem (click)="edit(data.id)"> <button *abpPermission="'AbpIdentity.Users.Update'" ngbDropdownItem (click)="edit(data.id)">
{{ 'AbpIdentity::Edit' | abpLocalization }} {{ 'AbpIdentity::Edit' | abpLocalization }}
</button> </button>
<button <button
[abpPermission]="'AbpIdentity.Users.ManagePermissions'" *abpPermission="'AbpIdentity.Users.ManagePermissions'"
ngbDropdownItem ngbDropdownItem
(click)="providerKey = data.id; visiblePermissions = true" (click)="providerKey = data.id; visiblePermissions = true"
> >
{{ 'AbpIdentity::Permissions' | abpLocalization }} {{ 'AbpIdentity::Permissions' | abpLocalization }}
</button> </button>
<button <button
[abpPermission]="'AbpIdentity.Users.Delete'" *abpPermission="'AbpIdentity.Users.Delete'"
ngbDropdownItem ngbDropdownItem
(click)="delete(data.id, data.userName)" (click)="delete(data.id, data.userName)"
> >

10
npm/ng-packs/packages/tenant-management/src/lib/components/tenants/tenants.component.html

@ -6,7 +6,7 @@
</div> </div>
<div class="text-right col col-md-6"> <div class="text-right col col-md-6">
<button <button
[abpPermission]="'AbpTenantManagement.Tenants.Create'" *abpPermission="'AbpTenantManagement.Tenants.Create'"
id="create-tenants" id="create-tenants"
class="btn btn-primary" class="btn btn-primary"
type="button" type="button"
@ -79,28 +79,28 @@
</button> </button>
<div ngbDropdownMenu> <div ngbDropdownMenu>
<button <button
[abpPermission]="'AbpTenantManagement.Tenants.Update'" *abpPermission="'AbpTenantManagement.Tenants.Update'"
ngbDropdownItem ngbDropdownItem
(click)="editTenant(data.id)" (click)="editTenant(data.id)"
> >
{{ 'AbpTenantManagement::Edit' | abpLocalization }} {{ 'AbpTenantManagement::Edit' | abpLocalization }}
</button> </button>
<button <button
[abpPermission]="'AbpTenantManagement.Tenants.ManageConnectionStrings'" *abpPermission="'AbpTenantManagement.Tenants.ManageConnectionStrings'"
ngbDropdownItem ngbDropdownItem
(click)="onEditConnectionString(data.id)" (click)="onEditConnectionString(data.id)"
> >
{{ 'AbpTenantManagement::Permission:ManageConnectionStrings' | abpLocalization }} {{ 'AbpTenantManagement::Permission:ManageConnectionStrings' | abpLocalization }}
</button> </button>
<button <button
[abpPermission]="'AbpTenantManagement.Tenants.ManageFeatures'" *abpPermission="'AbpTenantManagement.Tenants.ManageFeatures'"
ngbDropdownItem ngbDropdownItem
(click)="providerKey = data.id; visibleFeatures = true" (click)="providerKey = data.id; visibleFeatures = true"
> >
{{ 'AbpTenantManagement::Permission:ManageFeatures' | abpLocalization }} {{ 'AbpTenantManagement::Permission:ManageFeatures' | abpLocalization }}
</button> </button>
<button <button
[abpPermission]="'AbpTenantManagement.Tenants.Delete'" *abpPermission="'AbpTenantManagement.Tenants.Delete'"
ngbDropdownItem ngbDropdownItem
(click)="delete(data.id, data.name)" (click)="delete(data.id, data.name)"
> >

8
npm/ng-packs/packages/tenant-management/src/lib/components/tenants/tenants.component.ts

@ -77,9 +77,13 @@ export class TenantsComponent implements OnInit {
get isDisabledSaveButton(): boolean { get isDisabledSaveButton(): boolean {
if (!this.selectedModalContent) return false; if (!this.selectedModalContent) return false;
if (this.selectedModalContent.type === 'saveConnStr' && this.defaultConnectionStringForm.invalid) { if (
this.selectedModalContent.type === 'saveConnStr' &&
this.defaultConnectionStringForm &&
this.defaultConnectionStringForm.invalid
) {
return true; return true;
} else if (this.selectedModalContent.type === 'saveTenant' && this.tenantForm.invalid) { } else if (this.selectedModalContent.type === 'saveTenant' && this.tenantForm && this.tenantForm.invalid) {
return true; return true;
} else { } else {
return false; return false;

8
npm/ng-packs/packages/theme-basic/src/lib/components/application-layout/application-layout.component.html

@ -32,7 +32,7 @@
</ng-container> </ng-container>
<ng-template #defaultLink let-route> <ng-template #defaultLink let-route>
<li class="nav-item" [abpPermission]="route.requiredPolicy"> <li class="nav-item" *abpPermission="route.requiredPolicy">
<a class="nav-link" [routerLink]="[route.url]" <a class="nav-link" [routerLink]="[route.url]"
><i *ngIf="route.iconClass" [ngClass]="route.iconClass"></i> {{ route.name | abpLocalization }}</a ><i *ngIf="route.iconClass" [ngClass]="route.iconClass"></i> {{ route.name | abpLocalization }}</a
> >
@ -42,7 +42,7 @@
<ng-template #dropdownLink let-route> <ng-template #dropdownLink let-route>
<li <li
#navbarRootDropdown #navbarRootDropdown
[abpPermission]="route.requiredPolicy" *abpPermission="route.requiredPolicy"
[abpVisibility]="routeContainer" [abpVisibility]="routeContainer"
class="nav-item dropdown" class="nav-item dropdown"
display="static" display="static"
@ -86,7 +86,7 @@
</ng-template> </ng-template>
<ng-template #defaultChild let-child> <ng-template #defaultChild let-child>
<div class="dropdown-submenu" [abpPermission]="child.requiredPolicy"> <div class="dropdown-submenu" *abpPermission="child.requiredPolicy">
<a class="dropdown-item" [routerLink]="[child.url]"> <a class="dropdown-item" [routerLink]="[child.url]">
<i *ngIf="child.iconClass" [ngClass]="child.iconClass"></i> <i *ngIf="child.iconClass" [ngClass]="child.iconClass"></i>
{{ child.name | abpLocalization }}</a {{ child.name | abpLocalization }}</a
@ -103,7 +103,7 @@
[display]="isDropdownChildDynamic ? 'dynamic' : 'static'" [display]="isDropdownChildDynamic ? 'dynamic' : 'static'"
placement="right-top" placement="right-top"
[autoClose]="true" [autoClose]="true"
[abpPermission]="child.requiredPolicy" *abpPermission="child.requiredPolicy"
(openChange)="openChange($event, childrenContainer)" (openChange)="openChange($event, childrenContainer)"
> >
<div ngbDropdownToggle [class.dropdown-toggle]="false"> <div ngbDropdownToggle [class.dropdown-toggle]="false">

2
npm/ng-packs/packages/theme-shared/src/lib/components/error/error.component.html → npm/ng-packs/packages/theme-shared/src/lib/components/http-error-wrapper/http-error-wrapper.component.html

@ -1,4 +1,4 @@
<div #container id="abp-error" class="error"> <div #container id="abp-http-error-container" class="error" [style.backgroundColor]="backgroundColor">
<button *ngIf="!hideCloseIcon" id="abp-close-button" type="button" class="close mr-2" (click)="destroy()"> <button *ngIf="!hideCloseIcon" id="abp-close-button" type="button" class="close mr-2" (click)="destroy()">
<span aria-hidden="true">&times;</span> <span aria-hidden="true">&times;</span>
</button> </button>

1
npm/ng-packs/packages/theme-shared/src/lib/components/error/error.component.scss → npm/ng-packs/packages/theme-shared/src/lib/components/http-error-wrapper/http-error-wrapper.component.scss

@ -1,7 +1,6 @@
.error { .error {
position: fixed; position: fixed;
top: 0; top: 0;
background-color: #fff;
width: 100vw; width: 100vw;
height: 100vh; height: 100vh;
z-index: 999999; z-index: 999999;

21
npm/ng-packs/packages/theme-shared/src/lib/components/error/error.component.ts → npm/ng-packs/packages/theme-shared/src/lib/components/http-error-wrapper/http-error-wrapper.component.ts

@ -1,25 +1,27 @@
import { Config, takeUntilDestroy } from '@abp/ng.core'; import { Config, takeUntilDestroy } from '@abp/ng.core';
import { import {
AfterViewInit, AfterViewInit,
ApplicationRef,
Component, Component,
ComponentFactoryResolver, ComponentFactoryResolver,
ElementRef, ElementRef,
EmbeddedViewRef, EmbeddedViewRef,
Injector,
OnDestroy, OnDestroy,
OnInit,
Type, Type,
ViewChild, ViewChild,
ApplicationRef,
Injector,
} from '@angular/core'; } from '@angular/core';
import { fromEvent, Subject } from 'rxjs'; import { fromEvent, Subject } from 'rxjs';
import { debounceTime, filter } from 'rxjs/operators'; import { debounceTime, filter } from 'rxjs/operators';
import snq from 'snq';
@Component({ @Component({
selector: 'abp-error', selector: 'abp-http-error-wrapper',
templateUrl: './error.component.html', templateUrl: './http-error-wrapper.component.html',
styleUrls: ['error.component.scss'], styleUrls: ['http-error-wrapper.component.scss'],
}) })
export class ErrorComponent implements AfterViewInit, OnDestroy { export class HttpErrorWrapperComponent implements AfterViewInit, OnDestroy, OnInit {
appRef: ApplicationRef; appRef: ApplicationRef;
cfRes: ComponentFactoryResolver; cfRes: ComponentFactoryResolver;
@ -38,6 +40,8 @@ export class ErrorComponent implements AfterViewInit, OnDestroy {
hideCloseIcon = false; hideCloseIcon = false;
backgroundColor: string;
@ViewChild('container', { static: false }) @ViewChild('container', { static: false })
containerRef: ElementRef<HTMLDivElement>; containerRef: ElementRef<HTMLDivElement>;
@ -45,6 +49,11 @@ export class ErrorComponent implements AfterViewInit, OnDestroy {
return this.status ? `[${this.status}]` : ''; return this.status ? `[${this.status}]` : '';
} }
ngOnInit() {
this.backgroundColor =
snq(() => window.getComputedStyle(document.body).getPropertyValue('background-color')) || '#fff';
}
ngAfterViewInit() { ngAfterViewInit() {
if (this.customComponent) { if (this.customComponent) {
const customComponentRef = this.cfRes.resolveComponentFactory(this.customComponent).create(this.injector); const customComponentRef = this.cfRes.resolveComponentFactory(this.customComponent).create(this.injector);

8
npm/ng-packs/packages/theme-shared/src/lib/handlers/error.handler.ts

@ -15,7 +15,7 @@ import { Navigate, RouterError, RouterState, RouterDataResolved } from '@ngxs/ro
import { Actions, ofActionSuccessful, Store } from '@ngxs/store'; import { Actions, ofActionSuccessful, Store } from '@ngxs/store';
import { Observable, Subject } from 'rxjs'; import { Observable, Subject } from 'rxjs';
import snq from 'snq'; import snq from 'snq';
import { ErrorComponent } from '../components/error/error.component'; import { HttpErrorWrapperComponent } from '../components/http-error-wrapper/http-error-wrapper.component';
import { HttpErrorConfig, ErrorScreenErrorCodes } from '../models/common'; import { HttpErrorConfig, ErrorScreenErrorCodes } from '../models/common';
import { Toaster } from '../models/toaster'; import { Toaster } from '../models/toaster';
import { ConfirmationService } from '../services/confirmation.service'; import { ConfirmationService } from '../services/confirmation.service';
@ -45,7 +45,7 @@ export const DEFAULT_ERROR_MESSAGES = {
@Injectable({ providedIn: 'root' }) @Injectable({ providedIn: 'root' })
export class ErrorHandler { export class ErrorHandler {
componentRef: ComponentRef<ErrorComponent>; componentRef: ComponentRef<HttpErrorWrapperComponent>;
constructor( constructor(
private actions: Actions, private actions: Actions,
@ -196,11 +196,11 @@ export class ErrorHandler {
); );
} }
createErrorComponent(instance: Partial<ErrorComponent>) { createErrorComponent(instance: Partial<HttpErrorWrapperComponent>) {
const renderer = this.rendererFactory.createRenderer(null, null); const renderer = this.rendererFactory.createRenderer(null, null);
const host = renderer.selectRootElement(document.body, true); const host = renderer.selectRootElement(document.body, true);
this.componentRef = this.cfRes.resolveComponentFactory(ErrorComponent).create(this.injector); this.componentRef = this.cfRes.resolveComponentFactory(HttpErrorWrapperComponent).create(this.injector);
for (const key in this.componentRef.instance) { for (const key in this.componentRef.instance) {
if (this.componentRef.instance.hasOwnProperty(key)) { if (this.componentRef.instance.hasOwnProperty(key)) {

8
npm/ng-packs/packages/theme-shared/src/lib/tests/error.component.spec.ts

@ -1,14 +1,14 @@
import { SpectatorHost, createHostFactory } from '@ngneat/spectator/jest'; import { SpectatorHost, createHostFactory } from '@ngneat/spectator/jest';
import { ErrorComponent } from '../components/error/error.component'; import { HttpErrorWrapperComponent } from '../components/http-error-wrapper/http-error-wrapper.component';
import { LocalizationPipe } from '@abp/ng.core'; import { LocalizationPipe } from '@abp/ng.core';
import { Store } from '@ngxs/store'; import { Store } from '@ngxs/store';
import { Renderer2, ElementRef } from '@angular/core'; import { Renderer2, ElementRef } from '@angular/core';
import { Subject } from 'rxjs'; import { Subject } from 'rxjs';
describe('ErrorComponent', () => { describe('ErrorComponent', () => {
let spectator: SpectatorHost<ErrorComponent>; let spectator: SpectatorHost<HttpErrorWrapperComponent>;
const createHost = createHostFactory({ const createHost = createHostFactory({
component: ErrorComponent, component: HttpErrorWrapperComponent,
declarations: [LocalizationPipe], declarations: [LocalizationPipe],
mocks: [Store], mocks: [Store],
providers: [ providers: [
@ -18,7 +18,7 @@ describe('ErrorComponent', () => {
}); });
beforeEach(() => { beforeEach(() => {
spectator = createHost('<abp-error></abp-error>'); spectator = createHost('<abp-http-error-wrapper></abp-http-error-wrapper>');
spectator.component.destroy$ = new Subject(); spectator.component.destroy$ = new Subject();
}); });

14
npm/ng-packs/packages/theme-shared/src/lib/tests/error.handler.spec.ts

@ -22,14 +22,17 @@ describe('ErrorHandler', () => {
component: DummyComponent, component: DummyComponent,
imports: [CoreModule, ThemeSharedModule.forRoot(), NgxsModule.forRoot([])], imports: [CoreModule, ThemeSharedModule.forRoot(), NgxsModule.forRoot([])],
stubsEnabled: false, stubsEnabled: false,
routes: [{ path: '', component: DummyComponent }, { path: 'account/login', component: RouterOutletComponent }], routes: [
{ path: '', component: DummyComponent },
{ path: 'account/login', component: RouterOutletComponent },
],
}); });
beforeEach(() => { beforeEach(() => {
spectator = createComponent(); spectator = createComponent();
store = spectator.get(Store); store = spectator.get(Store);
const abpError = document.querySelector('abp-error'); const abpError = document.querySelector('abp-http-error-wrapper');
if (abpError) document.body.removeChild(abpError); if (abpError) document.body.removeChild(abpError);
}); });
@ -133,14 +136,17 @@ describe('ErrorHandler with custom error component', () => {
ErrorModule, ErrorModule,
], ],
stubsEnabled: false, stubsEnabled: false,
routes: [{ path: '', component: DummyComponent }, { path: 'account/login', component: RouterOutletComponent }], routes: [
{ path: '', component: DummyComponent },
{ path: 'account/login', component: RouterOutletComponent },
],
}); });
beforeEach(() => { beforeEach(() => {
spectator = createComponent(); spectator = createComponent();
store = spectator.get(Store); store = spectator.get(Store);
const abpError = document.querySelector('abp-error'); const abpError = document.querySelector('abp-http-error-wrapper');
if (abpError) document.body.removeChild(abpError); if (abpError) document.body.removeChild(abpError);
}); });

6
npm/ng-packs/packages/theme-shared/src/lib/theme-shared.module.ts

@ -8,7 +8,7 @@ import { BreadcrumbComponent } from './components/breadcrumb/breadcrumb.componen
import { ButtonComponent } from './components/button/button.component'; import { ButtonComponent } from './components/button/button.component';
import { ChartComponent } from './components/chart/chart.component'; import { ChartComponent } from './components/chart/chart.component';
import { ConfirmationComponent } from './components/confirmation/confirmation.component'; import { ConfirmationComponent } from './components/confirmation/confirmation.component';
import { ErrorComponent } from './components/error/error.component'; import { HttpErrorWrapperComponent } from './components/http-error-wrapper/http-error-wrapper.component';
import { LoaderBarComponent } from './components/loader-bar/loader-bar.component'; import { LoaderBarComponent } from './components/loader-bar/loader-bar.component';
import { ModalComponent } from './components/modal/modal.component'; import { ModalComponent } from './components/modal/modal.component';
import { SortOrderIconComponent } from './components/sort-order-icon/sort-order-icon.component'; import { SortOrderIconComponent } from './components/sort-order-icon/sort-order-icon.component';
@ -42,7 +42,7 @@ export function appendScript(injector: Injector) {
ButtonComponent, ButtonComponent,
ChartComponent, ChartComponent,
ConfirmationComponent, ConfirmationComponent,
ErrorComponent, HttpErrorWrapperComponent,
LoaderBarComponent, LoaderBarComponent,
ModalComponent, ModalComponent,
TableEmptyMessageComponent, TableEmptyMessageComponent,
@ -63,7 +63,7 @@ export function appendScript(injector: Injector) {
TableSortDirective, TableSortDirective,
], ],
providers: [DatePipe], providers: [DatePipe],
entryComponents: [ErrorComponent], entryComponents: [HttpErrorWrapperComponent],
}) })
export class ThemeSharedModule { export class ThemeSharedModule {
constructor(private errorHandler: ErrorHandler) {} constructor(private errorHandler: ErrorHandler) {}

Loading…
Cancel
Save