Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding constants to theme-shared module for error messages by status code #19421

Merged
merged 6 commits into from
Mar 28, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion npm/ng-packs/apps/dev-app/src/app/app-routing.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,4 +31,4 @@ const routes: Routes = [
imports: [RouterModule.forRoot(routes, {})],
exports: [RouterModule],
})
export class AppRoutingModule { }
export class AppRoutingModule {}
Original file line number Diff line number Diff line change
Expand Up @@ -4,32 +4,28 @@
class="error"
[style.backgroundColor]="backgroundColor"
>
<button
*ngIf="!hideCloseIcon"
id="abp-close-button"
type="button"
class="btn-close me-2"
(click)="destroy()"
></button>
@if (!hideCloseIcon) {
<button id="abp-close-button" type="button" class="btn-close me-2" (click)="destroy()"></button>
}

<div *ngIf="!customComponent" class="row centered">
<div class="col-md-12">
<div class="error-template">
<h1>{{ statusText }} {{ title | abpLocalization }}</h1>
<div class="error-details">
{{ details | abpLocalization }}
</div>
<div class="error-actions">
<a
*ngIf="isHomeShow"
(click)="destroy()"
routerLink="/"
class="btn btn-primary btn-md mt-2"
><span class="glyphicon glyphicon-home"></span>
{{ { key: '::Menu:Home', defaultValue: 'Home' } | abpLocalization }}
</a>
@if (!customComponent) {
<div class="row centered">
<div class="col-md-12">
<div class="error-template">
<h1>{{ statusText }} {{ title | abpLocalization }}</h1>
<div class="error-details">
{{ details | abpLocalization }}
</div>
<div class="error-actions">
@if (isHomeShow) {
<a (click)="goHome()" class="btn btn-primary btn-md mt-2"
><span class="glyphicon glyphicon-home"></span>
{{ { key: '::Menu:Home', defaultValue: 'Home' } | abpLocalization }}
</a>
}
</div>
</div>
</div>
</div>
</div>
}
</div>
Original file line number Diff line number Diff line change
@@ -1,38 +1,40 @@
import {
ApplicationRef,
Component,
Injector,
inject,
OnInit,
ComponentFactoryResolver,
ElementRef,
EmbeddedViewRef,
Type,
ViewChild,
AfterViewInit,
OnDestroy,
createComponent,
EnvironmentInjector,
DestroyRef,
} from '@angular/core';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
import { DOCUMENT } from '@angular/common';
import { Router } from '@angular/router';
import { fromEvent, Subject } from 'rxjs';
import { debounceTime, filter } from 'rxjs/operators';
import { LocalizationParam, SubscriptionService } from '@abp/ng.core';
import { LocalizationParam } from '@abp/ng.core';
import { ErrorScreenErrorCodes } from '../../models';

@Component({
selector: 'abp-http-error-wrapper',
templateUrl: './http-error-wrapper.component.html',
styleUrls: ['http-error-wrapper.component.scss'],
providers: [SubscriptionService],
})
export class HttpErrorWrapperComponent implements OnInit, AfterViewInit, OnDestroy {
protected readonly destroyRef = inject(DestroyRef);
protected readonly document = inject(DOCUMENT);
protected readonly window = this.document.defaultView;
protected readonly router = inject(Router);

appRef!: ApplicationRef;

cfRes!: ComponentFactoryResolver;

injector!: Injector;
environmentInjector!: EnvironmentInjector;

status: ErrorScreenErrorCodes = 0;

Expand All @@ -57,21 +59,23 @@ export class HttpErrorWrapperComponent implements OnInit, AfterViewInit, OnDestr
return this.status ? `[${this.status}]` : '';
}

constructor(private subscription: SubscriptionService) {}

ngOnInit(): void {
this.backgroundColor =
this.window.getComputedStyle(this.document.body)?.getPropertyValue('background-color') || '#fff';
const computedStyle = this.window.getComputedStyle(this.document.body);
const backgroundColor = computedStyle?.getPropertyValue('background-color');
this.backgroundColor = backgroundColor || '#fff';
}

ngAfterViewInit(): void {
if (this.customComponent) {
const customComponentRef = this.cfRes
.resolveComponentFactory(this.customComponent)
.create(this.injector);
const customComponentRef = createComponent(this.customComponent, {
environmentInjector: this.environmentInjector,
});

customComponentRef.instance.errorStatus = this.status;
customComponentRef.instance.destroy$ = this.destroy$;

this.appRef.attachView(customComponentRef.hostView);

if (this.containerRef) {
this.containerRef.nativeElement.appendChild(
(customComponentRef.hostView as EmbeddedViewRef<any>).rootNodes[0],
Expand All @@ -80,19 +84,26 @@ export class HttpErrorWrapperComponent implements OnInit, AfterViewInit, OnDestr
customComponentRef.changeDetectorRef.detectChanges();
}

const keyup$ = fromEvent<KeyboardEvent>(this.document, 'keyup').pipe(
debounceTime(150),
filter((key: KeyboardEvent) => key && key.key === 'Escape'),
);
this.subscription.addOne(keyup$, () => this.destroy());
fromEvent<KeyboardEvent>(this.document, 'keyup')
.pipe(
debounceTime(150),
filter((key: KeyboardEvent) => key && key.key === 'Escape'),
takeUntilDestroyed(this.destroyRef),
)
.subscribe(() => this.destroy());
}

ngOnDestroy(): void {
goHome(): void {
this.router.navigateByUrl('/', { onSameUrlNavigation: 'reload' });
this.destroy();
}

destroy(): void {
this.destroy$.next();
this.destroy$.complete();
}

ngOnDestroy(): void {
this.destroy();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -51,3 +51,17 @@ export const CUSTOM_HTTP_ERROR_HANDLER_PRIORITY = Object.freeze({
high: 9,
veryHigh: 99,
});

export const HTTP_ERROR_STATUS = {
'401': 'AbpUi::401Message',
'403': 'AbpUi::403Message',
'404': 'AbpUi::404Message',
'500': 'AbpUi::500Message',
};

export const HTTP_ERROR_DETAIL = {
'401': 'AbpUi::DefaultErrorMessage401Detail',
'403': 'AbpUi::DefaultErrorMessage403Detail',
'404': 'AbpUi::DefaultErrorMessage404Detail',
'500': 'AbpUi::DefaultErrorMessage',
};
4 changes: 4 additions & 0 deletions npm/ng-packs/packages/theme-shared/src/lib/constants/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export * from './validation';
export * from './default-errors';
export * from './styles';
export * from './scripts';
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import {
ApplicationRef,
ComponentFactoryResolver,
ComponentRef,
createComponent,
EmbeddedViewRef,
EnvironmentInjector,
inject,
Injectable,
Injector,
Expand All @@ -21,9 +22,9 @@ import { ErrorScreenErrorCodes } from '../models/common';
export class CreateErrorComponentService {
protected readonly document = inject(DOCUMENT);
protected readonly rendererFactory = inject(RendererFactory2);
protected readonly cfRes = inject(ComponentFactoryResolver);
protected readonly routerEvents = inject(RouterEvents);
protected readonly injector = inject(Injector);
protected readonly envInjector = inject(EnvironmentInjector);
protected readonly httpErrorConfig = inject(HTTP_ERROR_CONFIG);

componentRef: ComponentRef<HttpErrorWrapperComponent> | null = null;
Expand Down Expand Up @@ -65,9 +66,9 @@ export class CreateErrorComponentService {
const hostElement = this.getErrorHostElement();
const host = renderer.selectRootElement(hostElement, true);

this.componentRef = this.cfRes
.resolveComponentFactory(HttpErrorWrapperComponent)
.create(this.injector);
this.componentRef = createComponent(HttpErrorWrapperComponent, {
environmentInjector: this.envInjector,
});

for (const key in instance) {
/* istanbul ignore else */
Expand All @@ -80,9 +81,8 @@ export class CreateErrorComponentService {
const appRef = this.injector.get(ApplicationRef);

if (this.canCreateCustomError(instance.status as ErrorScreenErrorCodes)) {
this.componentRef.instance.cfRes = this.cfRes;
this.componentRef.instance.appRef = appRef;
this.componentRef.instance.injector = this.injector;
this.componentRef.instance.environmentInjector = this.envInjector;
this.componentRef.instance.customComponent = this.httpErrorConfig.errorScreen?.component;
}

Expand All @@ -91,6 +91,7 @@ export class CreateErrorComponentService {

const destroy$ = new Subject<void>();
this.componentRef.instance.destroy$ = destroy$;

destroy$.subscribe(() => {
this.componentRef?.destroy();
this.componentRef = null;
Expand Down
5 changes: 2 additions & 3 deletions npm/ng-packs/packages/theme-shared/src/public-api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,9 @@
* Public API Surface of theme-shared
*/

export * from './lib/adapters'
export * from './lib/adapters';
export * from './lib/animations';
export * from './lib/components';
export * from './lib/constants/validation';
export * from './lib/constants/default-errors';
export * from './lib/directives';
export * from './lib/enums';
export * from './lib/handlers';
Expand All @@ -16,3 +14,4 @@ export * from './lib/services';
export * from './lib/theme-shared.module';
export * from './lib/tokens';
export * from './lib/utils';
export * from './lib/constants';
Loading