mirror of https://github.com/abpframework/abp.git
5 changed files with 163 additions and 100 deletions
@ -0,0 +1,45 @@ |
|||||
|
export const DEFAULT_ERROR_MESSAGES = { |
||||
|
defaultError: { |
||||
|
title: 'An error has occurred!', |
||||
|
details: 'Error detail not sent by server.', |
||||
|
}, |
||||
|
defaultError401: { |
||||
|
title: 'You are not authenticated!', |
||||
|
details: 'You should be authenticated (sign in) in order to perform this operation.', |
||||
|
}, |
||||
|
defaultError403: { |
||||
|
title: 'You are not authorized!', |
||||
|
details: 'You are not allowed to perform this operation.', |
||||
|
}, |
||||
|
defaultError404: { |
||||
|
title: 'Resource not found!', |
||||
|
details: 'The resource requested could not found on the server.', |
||||
|
}, |
||||
|
defaultError500: { |
||||
|
title: 'Internal server error', |
||||
|
details: 'Error detail not sent by server.', |
||||
|
}, |
||||
|
}; |
||||
|
|
||||
|
export const DEFAULT_ERROR_LOCALIZATIONS = { |
||||
|
defaultError: { |
||||
|
title: 'AbpUi::DefaultErrorMessage', |
||||
|
details: 'AbpUi::DefaultErrorMessageDetail', |
||||
|
}, |
||||
|
defaultError401: { |
||||
|
title: 'AbpUi::DefaultErrorMessage401', |
||||
|
details: 'AbpUi::DefaultErrorMessage401Detail', |
||||
|
}, |
||||
|
defaultError403: { |
||||
|
title: 'AbpUi::DefaultErrorMessage403', |
||||
|
details: 'AbpUi::DefaultErrorMessage403Detail', |
||||
|
}, |
||||
|
defaultError404: { |
||||
|
title: 'AbpUi::DefaultErrorMessage404', |
||||
|
details: 'AbpUi::DefaultErrorMessage404Detail', |
||||
|
}, |
||||
|
defaultError500: { |
||||
|
title: 'AbpUi::500Message', |
||||
|
details: 'AbpUi::DefaultErrorMessage', |
||||
|
}, |
||||
|
}; |
||||
@ -0,0 +1,18 @@ |
|||||
|
import { inject, Injectable } from '@angular/core'; |
||||
|
import { ErrorScreenErrorCodes } from '../models/common'; |
||||
|
import { HTTP_ERROR_CONFIG } from '@abp/ng.theme.shared'; |
||||
|
|
||||
|
@Injectable({ |
||||
|
providedIn: 'root', |
||||
|
}) |
||||
|
export class CanCreateCustomErrorService { |
||||
|
private httpErrorConfig = inject(HTTP_ERROR_CONFIG); |
||||
|
|
||||
|
execute(status: ErrorScreenErrorCodes): boolean { |
||||
|
return !!( |
||||
|
this.httpErrorConfig?.errorScreen?.component && |
||||
|
this.httpErrorConfig?.errorScreen?.forWhichErrors && |
||||
|
this.httpErrorConfig?.errorScreen?.forWhichErrors.indexOf(status) > -1 |
||||
|
); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,89 @@ |
|||||
|
import { |
||||
|
ApplicationRef, |
||||
|
ComponentFactoryResolver, |
||||
|
ComponentRef, |
||||
|
EmbeddedViewRef, |
||||
|
inject, |
||||
|
Injectable, |
||||
|
Injector, |
||||
|
RendererFactory2, |
||||
|
} from '@angular/core'; |
||||
|
import { |
||||
|
ErrorScreenErrorCodes, |
||||
|
HTTP_ERROR_CONFIG, |
||||
|
HttpErrorWrapperComponent, |
||||
|
} from '@abp/ng.theme.shared'; |
||||
|
import { Subject } from 'rxjs'; |
||||
|
import { ResolveEnd } from '@angular/router'; |
||||
|
import { filter } from 'rxjs/operators'; |
||||
|
import { RouterEvents } from '@abp/ng.core'; |
||||
|
import { CanCreateCustomErrorService } from './can-create-custom-error.service'; |
||||
|
|
||||
|
@Injectable({ providedIn: 'root' }) |
||||
|
export class CreateErrorComponentService { |
||||
|
protected rendererFactory = inject(RendererFactory2); |
||||
|
protected cfRes = inject(ComponentFactoryResolver); |
||||
|
private routerEvents = inject(RouterEvents); |
||||
|
private injector = inject(Injector); |
||||
|
private canCreateCustomErrorService = inject(CanCreateCustomErrorService); |
||||
|
private httpErrorConfig = inject(HTTP_ERROR_CONFIG); |
||||
|
|
||||
|
componentRef: ComponentRef<HttpErrorWrapperComponent> | null = null; |
||||
|
|
||||
|
protected getErrorHostElement() { |
||||
|
return document.body; |
||||
|
} |
||||
|
|
||||
|
constructor() { |
||||
|
this.listenToRouterDataResolved(); |
||||
|
} |
||||
|
protected listenToRouterDataResolved() { |
||||
|
this.routerEvents |
||||
|
.getEvents(ResolveEnd) |
||||
|
.pipe(filter(() => !!this.componentRef)) |
||||
|
.subscribe(() => { |
||||
|
this.componentRef?.destroy(); |
||||
|
this.componentRef = null; |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
private isCloseIconHidden() { |
||||
|
return !!this.httpErrorConfig.errorScreen?.hideCloseIcon; |
||||
|
} |
||||
|
execute(instance: Partial<HttpErrorWrapperComponent>) { |
||||
|
const renderer = this.rendererFactory.createRenderer(null, null); |
||||
|
const hostElement = this.getErrorHostElement(); |
||||
|
const host = renderer.selectRootElement(hostElement, true); |
||||
|
|
||||
|
this.componentRef = this.cfRes |
||||
|
.resolveComponentFactory(HttpErrorWrapperComponent) |
||||
|
.create(this.injector); |
||||
|
|
||||
|
for (const key in instance) { |
||||
|
/* istanbul ignore else */ |
||||
|
if (Object.prototype.hasOwnProperty.call(this.componentRef.instance, key)) { |
||||
|
(this.componentRef.instance as any)[key] = (instance as any)[key]; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
this.componentRef.instance.hideCloseIcon = this.isCloseIconHidden(); |
||||
|
const appRef = this.injector.get(ApplicationRef); |
||||
|
|
||||
|
if (this.canCreateCustomErrorService.execute(instance.status as ErrorScreenErrorCodes)) { |
||||
|
this.componentRef.instance.cfRes = this.cfRes; |
||||
|
this.componentRef.instance.appRef = appRef; |
||||
|
this.componentRef.instance.injector = this.injector; |
||||
|
this.componentRef.instance.customComponent = this.httpErrorConfig.errorScreen?.component; |
||||
|
} |
||||
|
|
||||
|
appRef.attachView(this.componentRef.hostView); |
||||
|
renderer.appendChild(host, (this.componentRef.hostView as EmbeddedViewRef<any>).rootNodes[0]); |
||||
|
|
||||
|
const destroy$ = new Subject<void>(); |
||||
|
this.componentRef.instance.destroy$ = destroy$; |
||||
|
destroy$.subscribe(() => { |
||||
|
this.componentRef?.destroy(); |
||||
|
this.componentRef = null; |
||||
|
}); |
||||
|
} |
||||
|
} |
||||
Loading…
Reference in new issue