angular/projects/researchdatabox/report/src/app/report.component.ts
Report Component
Author: Shilo B
selector | report |
styleUrls | ./report.component.scss |
templateUrl | ./report.component.html |
Properties |
|
Methods |
|
constructor(loggerService: LoggerService, reportService: ReportService, configService: ConfigService, translationService: TranslationService, elementRef: ElementRef)
|
||||||||||||||||||
Parameters :
|
Public Async filter | ||||||
filter(event?: any)
|
||||||
Parameters :
Returns :
any
|
getCurrentPage |
getCurrentPage()
|
Returns :
ReportResultDto
|
Public getDownloadCSVUrl |
getDownloadCSVUrl()
|
Returns :
string
|
Public getLuxonDateFromJs |
getLuxonDateFromJs(srcDate: Date, tz: string, mode: string)
|
Returns :
any
|
Public getParams |
getParams()
|
Returns :
any
|
Async gotoPage | ||||||
gotoPage(pageNum: number)
|
||||||
Parameters :
Returns :
Promise<RecordPageDto>
|
Public Async headerSortChanged |
headerSortChanged(event: any, data: any)
|
Returns :
any
|
Protected Async initComponent |
initComponent()
|
Inherited from
BaseComponent
|
Defined in
BaseComponent:77
|
Returns :
Promise<void>
|
Public Async recordTableAction |
recordTableAction(event: any, data: any, actionName: string)
|
Returns :
any
|
getInitSubject |
getInitSubject()
|
Inherited from
BaseComponent
|
Defined in
BaseComponent:71
|
For those interested in the init from RXJS-land. Note that it returns a BehaviorSubject instance, and will have an initial value of false, so process the return value as needed.
Returns :
Subject<any>
|
isInitializing |
isInitializing()
|
Inherited from
BaseComponent
|
Defined in
BaseComponent:95
|
Main flag to indicate the init status
Returns :
boolean
|
ngOnInit |
ngOnInit()
|
Inherited from
BaseComponent
|
Defined in
BaseComponent:50
|
Returns :
void
|
Async waitForDeps |
waitForDeps()
|
Inherited from
BaseComponent
|
Defined in
BaseComponent:78
|
Wait for dependencies to initialise
Returns :
Promise<any>
|
Async waitForInit |
waitForInit()
|
Inherited from
BaseComponent
|
Defined in
BaseComponent:89
|
For those interested in the init from the Promise-land
Returns :
Promise<any>
|
appName |
Type : string
|
Default value : 'report'
|
dateParamTz |
Type : string
|
Default value : 'utc'
|
datePickerOpts |
Type : any
|
datePickerPlaceHolder |
Type : string
|
Default value : ''
|
filterParams |
Type : any
|
Default value : {}
|
initTracker |
Type : any
|
Default value : { reportLoaded: false, resultsReturned: false }
|
optTemplateData |
Type : any
|
Default value : {}
|
paginationMaxSize |
Type : number
|
Default value : 10
|
recordsPerPage |
Type : number
|
Default value : 10
|
report |
Type : ReportDto
|
Default value : null as any
|
reportName |
Type : string
|
Default value : ''
|
reportParams |
Type : any
|
Default value : {}
|
reportResult |
Type : ReportResultDto
|
Default value : null as any
|
tableHeaders |
Type : RecordPropViewMetaDto[]
|
Default value : null as any
|
Protected brandingAndPortalUrl |
Type : string
|
Default value : ''
|
Inherited from
BaseComponent
|
Defined in
BaseComponent:42
|
Private filterFn |
Default value : function(initStat: boolean) { return initStat; }
|
Inherited from
BaseComponent
|
Defined in
BaseComponent:40
|
Protected initDependencies |
Type : Initable[]
|
Default value : []
|
Inherited from
BaseComponent
|
Defined in
BaseComponent:39
|
Protected initSubject |
Type : BehaviorSubject<any>
|
Default value : new BehaviorSubject(false)
|
Inherited from
BaseComponent
|
Defined in
BaseComponent:38
|
Protected isReady |
Type : boolean
|
Default value : false
|
Inherited from
BaseComponent
|
Defined in
BaseComponent:37
|
import { Component, Inject, ElementRef } from '@angular/core';
import { ConfigService, LoggerService, TranslationService, ReportService, BaseComponent } from '@researchdatabox/portal-ng-common';
import { RecordSource } from '@researchdatabox/portal-ng-common';
import { RecordPropViewMetaDto, ReportDto, ReportResultDto, RecordPageDto } from '@researchdatabox/sails-ng-common';
import { isEmpty as _isEmpty, set as _set, map as _map } from 'lodash-es';
import { DateTime } from 'luxon';
/**
* Report Component
*
* Author: <a href='https://github.com/shilob' target='_blank'>Shilo B</a>
*/
@Component({
selector: 'report',
templateUrl: './report.component.html',
styleUrls: ['./report.component.scss']
})
export class ReportComponent extends BaseComponent implements RecordSource {
datePickerPlaceHolder: string = '';
datePickerOpts: any;
filterParams: any = {};
initTracker: any = { reportLoaded: false, resultsReturned: false };
report: ReportDto = null as any;
reportResult: ReportResultDto = null as any;
tableHeaders: RecordPropViewMetaDto[] = null as any;
appName:string = 'report';
optTemplateData:any = {};
reportName: string = '';
reportParams: any = {};
recordsPerPage: number = 10;
paginationMaxSize: number = 10;
// See https://moment.github.io/luxon/docs/manual/zones.html#specifying-a-zone
dateParamTz: string = 'utc';
constructor(
@Inject(LoggerService) private loggerService: LoggerService,
@Inject(ReportService) protected reportService: ReportService,
@Inject(ConfigService) private configService: ConfigService,
@Inject(TranslationService) private translationService: TranslationService,
@Inject(ElementRef) elementRef: ElementRef
) {
super();
this.initDependencies = [this.translationService, this.reportService];
this.reportName = elementRef.nativeElement.getAttribute('reportName');
this.loggerService.debug(`'${this.appName} - ${this.reportName}' waiting for deps to init...`);
}
getCurrentPage() {
return this.reportResult;
}
async gotoPage(pageNum: number): Promise<RecordPageDto> {
this.initTracker.resultsReturned = false;
this.reportResult = await this.reportService.getReportResult(this.reportName, pageNum, this.getParams(), this.recordsPerPage);
this.initTracker.resultsReturned = true;
return this.reportResult;
}
protected async initComponent(): Promise<void> {
const sysConfig = await this.configService.getConfig();
const defaultDatePickerOpts = { dateInputFormat: 'DD/MM/YYYY', containerClass: 'theme-dark-blue' };
const defaultDatePickerPlaceHolder = 'dd/mm/yyyy';
this.datePickerOpts = ConfigService._getAppConfigProperty(sysConfig, this.appName, 'datePickerOpts', defaultDatePickerOpts);
this.datePickerPlaceHolder = ConfigService._getAppConfigProperty(sysConfig, this.appName, 'datePickerPlaceHolder', defaultDatePickerPlaceHolder);
this.brandingAndPortalUrl = this.reportService.brandingAndPortalUrl;
_set(this.optTemplateData, 'brandingAndPortalUrl', this.brandingAndPortalUrl);
this.recordsPerPage = ConfigService._getAppConfigProperty(sysConfig, this.appName, 'recordsPerPage', this.recordsPerPage);
this.dateParamTz = ConfigService._getAppConfigProperty(sysConfig, this.appName, 'dateParamTz', this.dateParamTz);
this.paginationMaxSize = ConfigService._getAppConfigProperty(sysConfig, this.appName, 'paginationMaxSize', this.paginationMaxSize);
this.report = await this.reportService.getReportConfig(this.reportName);
this.tableHeaders = this.report.columns;
this.initTracker.reportLoaded = true;
this.gotoPage(1);
this.loggerService.debug(`'${this.appName}' ready!`);
}
public async filter(event?: any) {
await this.gotoPage(1);
}
public getDownloadCSVUrl() {
let url = `${this.brandingAndPortalUrl}/admin/downloadReportCSV?name=${this.reportName}`;
let params = this.getParams();
for(var key in params) {
url=url+'&'+key+"="+params[key];
}
return url;
}
public getLuxonDateFromJs(srcDate: Date, tz: string, mode: string) {
if (mode == 'floor') {
srcDate.setHours(0, 0, 0, 0);
} else if (mode == 'ceil') {
srcDate.setHours(23, 59, 59, 999);
}
return DateTime.fromJSDate(srcDate, {zone: tz});
}
public getParams() {
var params:any = {};
for(let filter of this.report.filter) {
if (filter.type == 'date-range') {
const fromDateJs = this.filterParams[filter.paramName + "_fromDate"];
const toDateJs = this.filterParams[filter.paramName + "_toDate"];
var fromDate = fromDateJs ? this.getLuxonDateFromJs(fromDateJs, this.dateParamTz, 'floor') : null;
var toDate = toDateJs ? this.getLuxonDateFromJs(toDateJs, this.dateParamTz, 'ceil') : null;
if (fromDate != null) {
params[filter.paramName + "_fromDate"] = fromDate.toISO();
}
if (toDate != null) {
params[filter.paramName + "_toDate"] = toDate.toISO();
}
} else {
let paramValue = this.filterParams[filter.paramName];
if(!_isEmpty(paramValue)) {
params[filter.paramName] = paramValue;
}
}
}
return params;
}
public async recordTableAction(event: any, data: any, actionName: string) {
console.log('recordTableAction', arguments);
}
public async headerSortChanged(event: any, data: any) {
console.log('headerSortChanged', arguments);
}
}
<ng-container *ngIf="isReady">
<!-- The report title -->
<div class="row">
<div class="col-xs-12">
<h1 class="text-center" *ngIf="report && report.title">
{{ report.title }}
</h1>
</div>
</div>
<!-- Render the report's filter UI elements -->
<div class="row" *ngIf="report && report.filter != null">
<div class="panel panel-default">
<div class="panel-body">
<div class="row">
<div class="text-center h4-header mb-2">
{{ 'report-filters-heading' | i18next }}
</div>
</div>
<ng-container *ngFor="let filter of report.filter">
<!-- Text filter -->
<div *ngIf="filter.type == 'text'" class="row">
<div class="col-md-2"></div>
<div class="col-xs-2">
<label [for]="filter.paramName">{{filter.message}}</label>
</div>
<div class="col-xs-6">
<input [id]="filter.paramName" type="text" class="form-control" [(ngModel)]="filterParams[ filter['paramName']]">
</div>
<div class="col-md-2"></div>
</div>
<!-- Date filter -->
<div *ngIf="filter.type == 'date-range'" class="row">
<div class="col-md-2"></div>
<div class="col-12 col-sm-2 col-md-2">
<label [for]="filter.paramName" class="report-filter-date-range-label">{{filter.message}}</label>
</div>
<div class="col-12 col-sm-3 col-md-3">
<div class="form-group">
<label class="control-label mr-2">{{ 'report-filter-date-from' | i18next }}</label>
<input type="text" [id]="filter.paramName + '_fromDate'"
[bsConfig] = "datePickerOpts"
[placeholder] = "datePickerPlaceHolder"
[(ngModel)]="filterParams[ filter['paramName'] + '_fromDate']"
bsDatepicker />
</div>
</div>
<div class="col-12 col-sm-3 col-md-3">
<div class="form-group">
<label class="control-label mr-2">{{ 'report-filter-date-to' | i18next }}</label>
<input type="text" [id]="filter.paramName + '_toDate'"
[bsConfig] = "datePickerOpts"
[placeholder] = "datePickerPlaceHolder"
[(ngModel)]="filterParams[ filter['paramName'] + '_toDate']"
bsDatepicker />
</div>
</div>
<div class="col-md-2"></div>
</div>
</ng-container>
<div class="row">
<div class="col-xs-2"></div>
<div class="col-xs-8" style="text-align:right; padding-top:15px;">
<a class="btn btn-large btn-primary" (click)="filter()">
<span class="glyphicon glyphicon-search"></span>
{{ 'report-filter-button' | i18next }}
</a>
</div>
</div>
</div>
</div>
</div>
<!-- Result overview -->
<div class="row" *ngIf="initTracker && initTracker.resultsReturned">
<div class="col-xs-2">
<span *ngIf="initTracker.resultsReturned == false">
<span class="fa fa-spinner fa-spin fa-fw"></span>
{{ 'report-retrieving-results' | i18next }}
</span>
<span *ngIf="initTracker.resultsReturned == true"
[innerHTML]='"report-results-returned" | i18next: {count: reportResult.total }'>
</span>
</div>
<div class="col-xs-8"></div>
<div class="col-xs-2">
<a class="btn btn-large btn-primary" [attr.href]='getDownloadCSVUrl()'>
<span class="glyphicon glyphicon-download"></span>
{{ 'report-csv-download' | i18next }}
</a>
</div>
</div>
<!-- Result details -->
<record-table [columnConfig]="tableHeaders" [dataSource]="this" [optTemplateData]="optTemplateData" [paginationItemsPerPage]="recordsPerPage" [paginationMaxSize]="paginationMaxSize">
</record-table>
</ng-container>
./report.component.scss
.report-filter-date-range-label
{
margin-top: 10px;
}