diff --git a/npm/ng-packs/packages/theme-shared/src/lib/components/chart/chart.component.html b/npm/ng-packs/packages/theme-shared/src/lib/components/chart/chart.component.html new file mode 100644 index 0000000000..211614c90d --- /dev/null +++ b/npm/ng-packs/packages/theme-shared/src/lib/components/chart/chart.component.html @@ -0,0 +1,11 @@ +
+ +
diff --git a/npm/ng-packs/packages/theme-shared/src/lib/components/chart/chart.component.ts b/npm/ng-packs/packages/theme-shared/src/lib/components/chart/chart.component.ts new file mode 100644 index 0000000000..2c8b7d0fb4 --- /dev/null +++ b/npm/ng-packs/packages/theme-shared/src/lib/components/chart/chart.component.ts @@ -0,0 +1,118 @@ +import { AfterViewInit, Component, ElementRef, EventEmitter, Input, OnDestroy, Output } from '@angular/core'; +import { BehaviorSubject } from 'rxjs'; +declare const Chart: any; + +@Component({ + selector: 'abp-chart', + templateUrl: './chart.component.html', +}) +export class ChartComponent implements AfterViewInit, OnDestroy { + @Input() type: string; + + @Input() options: any = {}; + + @Input() plugins: any[] = []; + + @Input() width: string; + + @Input() height: string; + + @Input() responsive: boolean = true; + + @Output() onDataSelect: EventEmitter = new EventEmitter(); + + @Output() initialized = new BehaviorSubject(this); + + private _initialized: boolean; + + _data: any; + + chart: any; + + constructor(public el: ElementRef) {} + + @Input() get data(): any { + return this._data; + } + + set data(val: any) { + this._data = val; + this.reinit(); + } + + get canvas() { + return this.el.nativeElement.children[0].children[0]; + } + + get base64Image() { + return this.chart.toBase64Image(); + } + + ngAfterViewInit() { + try { + Chart; + } catch (error) { + console.error(`Chart is not found. Import the Chart from app.module like shown below: + import('chart.js'); + `); + return; + } + + this.initChart(); + this._initialized = true; + } + + onCanvasClick = event => { + if (this.chart) { + let element = this.chart.getElementAtEvent(event); + let dataset = this.chart.getDatasetAtEvent(event); + if (element && element[0] && dataset) { + this.onDataSelect.emit({ originalEvent: event, element: element[0], dataset: dataset }); + } + } + }; + + initChart = () => { + let opts = this.options || {}; + opts.responsive = this.responsive; + + // allows chart to resize in responsive mode + if (opts.responsive && (this.height || this.width)) { + opts.maintainAspectRatio = false; + } + + this.chart = new Chart(this.el.nativeElement.children[0].children[0], { + type: this.type, + data: this.data, + options: this.options, + plugins: this.plugins, + }); + }; + + generateLegend = () => { + if (this.chart) { + return this.chart.generateLegend(); + } + }; + + refresh = () => { + if (this.chart) { + this.chart.update(); + } + }; + + reinit = () => { + if (this.chart) { + this.chart.destroy(); + this.initChart(); + } + }; + + ngOnDestroy() { + if (this.chart) { + this.chart.destroy(); + this._initialized = false; + this.chart = null; + } + } +} diff --git a/npm/ng-packs/packages/theme-shared/src/lib/components/index.ts b/npm/ng-packs/packages/theme-shared/src/lib/components/index.ts index 9665c263e5..e4bcb47597 100644 --- a/npm/ng-packs/packages/theme-shared/src/lib/components/index.ts +++ b/npm/ng-packs/packages/theme-shared/src/lib/components/index.ts @@ -1,6 +1,7 @@ -export * from './button/button.component'; export * from './breadcrumb/breadcrumb.component'; +export * from './button/button.component'; export * from './change-password/change-password.component'; +export * from './chart/chart.component'; export * from './confirmation/confirmation.component'; export * from './loader-bar/loader-bar.component'; export * from './modal/modal.component'; diff --git a/npm/ng-packs/packages/theme-shared/src/lib/models/index.ts b/npm/ng-packs/packages/theme-shared/src/lib/models/index.ts index da311b86be..e42b6ccfa5 100644 --- a/npm/ng-packs/packages/theme-shared/src/lib/models/index.ts +++ b/npm/ng-packs/packages/theme-shared/src/lib/models/index.ts @@ -1,3 +1,4 @@ export * from './confirmation'; -export * from './toaster'; export * from './setting-management'; +export * from './statistics'; +export * from './toaster'; diff --git a/npm/ng-packs/packages/theme-shared/src/lib/models/statistics.ts b/npm/ng-packs/packages/theme-shared/src/lib/models/statistics.ts new file mode 100644 index 0000000000..65bd5dfa8f --- /dev/null +++ b/npm/ng-packs/packages/theme-shared/src/lib/models/statistics.ts @@ -0,0 +1,14 @@ +export namespace Statistics { + export interface Response { + data: Data; + } + + export interface Data { + [key: string]: number; + } + + export interface Filter { + startDate: string | Date; + endDate: string | Date; + } +} diff --git a/npm/ng-packs/packages/theme-shared/src/lib/theme-shared.module.ts b/npm/ng-packs/packages/theme-shared/src/lib/theme-shared.module.ts index 49269b59d9..0933a607d2 100644 --- a/npm/ng-packs/packages/theme-shared/src/lib/theme-shared.module.ts +++ b/npm/ng-packs/packages/theme-shared/src/lib/theme-shared.module.ts @@ -17,27 +17,24 @@ import { ValidationErrorComponent } from './components/errors/validation-error.c import { ChangePasswordComponent } from './components/change-password/change-password.component'; import { ProfileComponent } from './components/profile/profile.component'; import { BreadcrumbComponent } from './components/breadcrumb/breadcrumb.component'; +import { ChartComponent } from './components/chart/chart.component'; -export function appendScript(styles) { - const higher = (injector: Injector) => { - const fn = function() { - const lazyLoadService: LazyLoadService = injector.get(LazyLoadService); +export function appendScript(injector: Injector) { + const fn = function() { + const lazyLoadService: LazyLoadService = injector.get(LazyLoadService); - return forkJoin( - lazyLoadService.load( - null, - 'style', - styles, - 'head', - 'afterbegin', - ) /* lazyLoadService.load(null, 'script', scripts) */, - ).pipe(take(1)); - }; - - return fn; + return forkJoin( + lazyLoadService.load( + null, + 'style', + styles, + 'head', + 'afterbegin', + ) /* lazyLoadService.load(null, 'script', scripts) */, + ).pipe(take(1)); }; - return higher; + return fn; } @NgModule({ @@ -59,26 +56,28 @@ export function appendScript(styles) { }), ], declarations: [ + BreadcrumbComponent, ButtonComponent, + ChangePasswordComponent, + ChartComponent, ConfirmationComponent, - ToastComponent, - ModalComponent, ErrorComponent, LoaderBarComponent, - ValidationErrorComponent, - ChangePasswordComponent, + ModalComponent, ProfileComponent, - BreadcrumbComponent, + ToastComponent, + ValidationErrorComponent, ], exports: [ + BreadcrumbComponent, ButtonComponent, + ChangePasswordComponent, + ChartComponent, ConfirmationComponent, - ToastComponent, - ModalComponent, LoaderBarComponent, - ChangePasswordComponent, + ModalComponent, ProfileComponent, - BreadcrumbComponent, + ToastComponent, ], entryComponents: [ErrorComponent, ValidationErrorComponent], }) @@ -91,7 +90,7 @@ export class ThemeSharedModule { provide: APP_INITIALIZER, multi: true, deps: [Injector, ErrorHandler], - useFactory: appendScript(styles), + useFactory: appendScript, }, { provide: MessageService, useClass: MessageService }, ],