Skip to content

Commit

Permalink
Merge pull request #2119 from abpframework/feat/theme-shared/custom-e…
Browse files Browse the repository at this point in the history
…rror

Feat/theme shared/custom error
  • Loading branch information
thediaval authored Nov 7, 2019
2 parents 5b78571 + 5809d1b commit fbc8c57
Show file tree
Hide file tree
Showing 14 changed files with 284 additions and 118 deletions.
2 changes: 2 additions & 0 deletions npm/ng-packs/packages/core/src/lib/models/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,4 +35,6 @@ export namespace Config {
key: string;
defaultValue: string;
}

export type LocalizationParam = string | LocalizationWithDefault;
}
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ export class UsersComponent implements OnInit {
}

save() {
if (!this.form.valid) return;
if (!this.form.valid || this.modalBusy) return;
this.modalBusy = true;

const { roleNames } = this.form.value;
Expand Down
18 changes: 12 additions & 6 deletions npm/ng-packs/packages/theme-shared/src/lib/abstracts/toaster.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { MessageService } from 'primeng/components/common/messageservice';
import { Observable, Subject } from 'rxjs';
import { Toaster } from '../models/toaster';
import { Config } from '@abp/ng.core';

export abstract class AbstractToaster<T = Toaster.Options> {
status$: Subject<Toaster.Status>;
Expand All @@ -11,23 +12,28 @@ export abstract class AbstractToaster<T = Toaster.Options> {

constructor(protected messageService: MessageService) {}

info(message: string, title: string, options?: T): Observable<Toaster.Status> {
info(message: Config.LocalizationParam, title: Config.LocalizationParam, options?: T): Observable<Toaster.Status> {
return this.show(message, title, 'info', options);
}

success(message: string, title: string, options?: T): Observable<Toaster.Status> {
success(message: Config.LocalizationParam, title: Config.LocalizationParam, options?: T): Observable<Toaster.Status> {
return this.show(message, title, 'success', options);
}

warn(message: string, title: string, options?: T): Observable<Toaster.Status> {
warn(message: Config.LocalizationParam, title: Config.LocalizationParam, options?: T): Observable<Toaster.Status> {
return this.show(message, title, 'warn', options);
}

error(message: string, title: string, options?: T): Observable<Toaster.Status> {
error(message: Config.LocalizationParam, title: Config.LocalizationParam, options?: T): Observable<Toaster.Status> {
return this.show(message, title, 'error', options);
}

protected show(message: string, title: string, severity: Toaster.Severity, options?: T): Observable<Toaster.Status> {
protected show(
message: Config.LocalizationParam,
title: Config.LocalizationParam,
severity: Toaster.Severity,
options?: T,
): Observable<Toaster.Status> {
this.messageService.clear(this.key);

this.messageService.add({
Expand All @@ -36,7 +42,7 @@ export abstract class AbstractToaster<T = Toaster.Options> {
summary: title || '',
...options,
key: this.key,
...(typeof (options || ({} as any)).sticky === 'undefined' && { sticky: this.sticky })
...(typeof (options || ({} as any)).sticky === 'undefined' && { sticky: this.sticky }),
});
this.status$ = new Subject<Toaster.Status>();
return this.status$;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { ABP } from '@abp/ng.core';
template: `
<button
#button
[attr.type]="buttonType || type"
[attr.type]="buttonType"
[ngClass]="buttonClass"
[disabled]="loading || disabled"
(click)="onClick($event)"
Expand All @@ -23,7 +23,7 @@ export class ButtonComponent implements OnInit {
buttonClass = 'btn btn-primary';

@Input()
buttonType; // TODO: Add initial value.
buttonType = 'button';

@Input()
iconClass: string;
Expand All @@ -49,11 +49,6 @@ export class ButtonComponent implements OnInit {
@ViewChild('button', { static: true })
buttonRef: ElementRef<HTMLButtonElement>;

/**
* @deprecated Use buttonType instead. To be deleted in v1
*/
@Input() type = 'button';

get icon(): string {
return `${this.loading ? 'fa fa-spinner fa-spin' : this.iconClass || 'd-none'}`;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ import { Toaster } from '../../models/toaster';
(click)="close(confirm)"
autofocus
>
<span>{{ message.yesText || 'AbpIdentity::Yes' | abpLocalization }}</span>
<span>{{ message.yesText || message.yesCopy || 'AbpIdentity::Yes' | abpLocalization }}</span>
</button>
</div>
</ng-template>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
<div id="abp-error" class="error">
<button id="abp-close-button" class="mr-3" type="button" class="close" (click)="destroy()">
<div #container id="abp-error" class="error">
<button id="abp-close-button" type="button" class="close mr-3" (click)="destroy()">
<span aria-hidden="true">&times;</span>
</button>
<div class="row centered">

<div *ngIf="!customComponent" class="row centered">
<div class="col-md-12">
<div class="error-template">
<h1>
{{ title | abpLocalization }}
</h1>
<h1>{{ statusText }} {{ title | abpLocalization }}</h1>
<div class="error-details">
{{ details | abpLocalization }}
</div>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,23 +1,65 @@
import { Component, Renderer2, ElementRef } from '@angular/core';
import { Config } from '@abp/ng.core';
import { Config, takeUntilDestroy } from '@abp/ng.core';
import {
AfterViewInit,
Component,
ComponentFactoryResolver,
ElementRef,
EmbeddedViewRef,
OnDestroy,
Type,
ViewChild,
} from '@angular/core';
import { fromEvent, Subject } from 'rxjs';
import { debounceTime, filter } from 'rxjs/operators';

@Component({
selector: 'abp-error',
templateUrl: './error.component.html',
styleUrls: ['error.component.scss'],
})
export class ErrorComponent {
title: string | Config.LocalizationWithDefault = 'Oops!';
export class ErrorComponent implements AfterViewInit, OnDestroy {
cfRes: ComponentFactoryResolver;

details: string | Config.LocalizationWithDefault = 'Sorry, an error has occured.';
status = 0;

renderer: Renderer2;
title: Config.LocalizationParam = 'Oops!';

elementRef: ElementRef;
details: Config.LocalizationParam = 'Sorry, an error has occured.';

host: any;
customComponent: Type<any> = null;

destroy$: Subject<void>;

@ViewChild('container', { static: false })
containerRef: ElementRef<HTMLDivElement>;

get statusText(): string {
return this.status ? `[${this.status}]` : '';
}

ngAfterViewInit() {
if (this.customComponent) {
const customComponentRef = this.cfRes.resolveComponentFactory(this.customComponent).create(null);
customComponentRef.instance.errorStatus = this.status;
this.containerRef.nativeElement.appendChild((customComponentRef.hostView as EmbeddedViewRef<any>).rootNodes[0]);
customComponentRef.changeDetectorRef.detectChanges();
}

fromEvent(document, 'keyup')
.pipe(
takeUntilDestroy(this),
debounceTime(150),
filter((key: KeyboardEvent) => key && key.key === 'Escape'),
)
.subscribe(() => {
this.destroy();
});
}

ngOnDestroy() {}

destroy() {
this.renderer.removeChild(this.host, this.elementRef.nativeElement);
this.destroy$.next();
this.destroy$.complete();
}
}
Loading

0 comments on commit fbc8c57

Please sign in to comment.