@@ -0,0 +1,16 @@
|
|||||||
|
/** Chart Data Model */
|
||||||
|
export class ChartData {
|
||||||
|
|
||||||
|
keysLabel: string;
|
||||||
|
valuesLabel: string;
|
||||||
|
keys: string[];
|
||||||
|
values: number[];
|
||||||
|
|
||||||
|
constructor(response: any) {
|
||||||
|
this.keysLabel = response.columnHeaders[0].columnName;
|
||||||
|
this.valuesLabel = response.columnHeaders[1].columnName;
|
||||||
|
this.keys = response.data.map((object: any) => object.row[0]);
|
||||||
|
this.values = response.data.map((object: any) => object.row[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
/** Report Parameter Model */
|
||||||
|
export class ReportParameter {
|
||||||
|
|
||||||
|
name: string;
|
||||||
|
variable: string;
|
||||||
|
label: string;
|
||||||
|
displayType: string;
|
||||||
|
formatType: string;
|
||||||
|
defaultVal: any;
|
||||||
|
selectOne: any;
|
||||||
|
selectAll: any;
|
||||||
|
parentParameterName: string;
|
||||||
|
inputName: string;
|
||||||
|
selectOptions: any[] = [];
|
||||||
|
childParameter: any;
|
||||||
|
pentahoName: any;
|
||||||
|
|
||||||
|
constructor(options: any[]) {
|
||||||
|
this.name = options[0];
|
||||||
|
this.variable = options[1];
|
||||||
|
this.label = options[2];
|
||||||
|
this.displayType = options[3];
|
||||||
|
this.formatType = options[4];
|
||||||
|
this.defaultVal = options[5];
|
||||||
|
this.selectOne = options[6];
|
||||||
|
this.selectAll = options[7];
|
||||||
|
this.parentParameterName = options[8];
|
||||||
|
this.inputName = `R_${options[1]}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
/** Select Option model */
|
||||||
|
export class SelectOption {
|
||||||
|
|
||||||
|
id: number;
|
||||||
|
name: string;
|
||||||
|
|
||||||
|
constructor(options: any[]) {
|
||||||
|
this.id = options[0],
|
||||||
|
this.name = options[1];
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -10,9 +10,11 @@ import { extract } from '../core/i18n/i18n.service';
|
|||||||
|
|
||||||
/** Custom Components */
|
/** Custom Components */
|
||||||
import { ReportsComponent } from './reports.component';
|
import { ReportsComponent } from './reports.component';
|
||||||
|
import { RunReportComponent } from './run-report/run-report.component';
|
||||||
|
|
||||||
/** Custom Resolvers */
|
/** Custom Resolvers */
|
||||||
import { ReportsResolver } from './reports.resolver';
|
import { ReportsResolver } from './reports.resolver';
|
||||||
|
import { RunReportResolver } from './run-report/run-report.resolver';
|
||||||
|
|
||||||
/** Reports Routes */
|
/** Reports Routes */
|
||||||
const routes: Routes = [
|
const routes: Routes = [
|
||||||
@@ -34,6 +36,29 @@ const routes: Routes = [
|
|||||||
component: ReportsComponent,
|
component: ReportsComponent,
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'run-report',
|
||||||
|
data: { title: extract('Reports'), breadcrumb: 'Reports' },
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
path: '',
|
||||||
|
redirectTo: '/reports', pathMatch: 'full'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: ':report-name/:report-type/:report-id',
|
||||||
|
data: { title: extract('Run Report'), routeParamBreadcrumb: 'report-name' },
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
path: '',
|
||||||
|
component: RunReportComponent,
|
||||||
|
resolve: {
|
||||||
|
params: RunReportResolver
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
])
|
])
|
||||||
];
|
];
|
||||||
@@ -47,7 +72,8 @@ const routes: Routes = [
|
|||||||
imports: [RouterModule.forChild(routes)],
|
imports: [RouterModule.forChild(routes)],
|
||||||
exports: [RouterModule],
|
exports: [RouterModule],
|
||||||
providers: [
|
providers: [
|
||||||
ReportsResolver
|
ReportsResolver,
|
||||||
|
RunReportResolver
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
export class ReportsRoutingModule { }
|
export class ReportsRoutingModule { }
|
||||||
|
|||||||
@@ -28,7 +28,7 @@
|
|||||||
|
|
||||||
|
|
||||||
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
|
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
|
||||||
<tr mat-row *matRowDef="let row; columns: displayedColumns;" class="select-row"></tr>
|
<tr mat-row *matRowDef="let row; columns: displayedColumns;" class="select-row" [routerLink]="['/run-report', row.reportName, row.reportType, row.id]"></tr>
|
||||||
|
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
/** Angular Imports */
|
/** Angular Imports */
|
||||||
import { NgModule } from '@angular/core';
|
import { NgModule } from '@angular/core';
|
||||||
|
import { DecimalPipe } from '@angular/common';
|
||||||
|
|
||||||
/** Custom Modules */
|
/** Custom Modules */
|
||||||
import { SharedModule } from '../shared/shared.module';
|
import { SharedModule } from '../shared/shared.module';
|
||||||
@@ -7,6 +8,10 @@ import { ReportsRoutingModule } from 'app/reports/reports-routing.module';
|
|||||||
|
|
||||||
/** Custom Components */
|
/** Custom Components */
|
||||||
import { ReportsComponent } from './reports.component';
|
import { ReportsComponent } from './reports.component';
|
||||||
|
import { RunReportComponent } from './run-report/run-report.component';
|
||||||
|
import { TableAndSmsComponent } from './run-report/table-and-sms/table-and-sms.component';
|
||||||
|
import { ChartComponent } from './run-report/chart/chart.component';
|
||||||
|
import { PentahoComponent } from './run-report/pentaho/pentaho.component';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reports Module
|
* Reports Module
|
||||||
@@ -18,6 +23,13 @@ import { ReportsComponent } from './reports.component';
|
|||||||
SharedModule,
|
SharedModule,
|
||||||
ReportsRoutingModule
|
ReportsRoutingModule
|
||||||
],
|
],
|
||||||
declarations: [ReportsComponent],
|
declarations: [
|
||||||
|
ReportsComponent,
|
||||||
|
RunReportComponent,
|
||||||
|
TableAndSmsComponent,
|
||||||
|
ChartComponent,
|
||||||
|
PentahoComponent
|
||||||
|
],
|
||||||
|
providers: [ DecimalPipe ]
|
||||||
})
|
})
|
||||||
export class ReportsModule { }
|
export class ReportsModule { }
|
||||||
|
|||||||
@@ -4,6 +4,12 @@ import { HttpClient, HttpParams } from '@angular/common/http';
|
|||||||
|
|
||||||
/** rxjs Imports */
|
/** rxjs Imports */
|
||||||
import { Observable } from 'rxjs';
|
import { Observable } from 'rxjs';
|
||||||
|
import { map } from 'rxjs/operators';
|
||||||
|
|
||||||
|
/** Custom Models */
|
||||||
|
import { ReportParameter } from './common-models/report-parameter.model';
|
||||||
|
import { SelectOption } from './common-models/select-option.model';
|
||||||
|
import { ChartData } from './common-models/chart-data.model';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reports service.
|
* Reports service.
|
||||||
@@ -25,4 +31,82 @@ export class ReportsService {
|
|||||||
return this.http.get('/reports');
|
return this.http.get('/reports');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} reportName Report name for which parameters are needed.
|
||||||
|
* @returns {Observable<ReportParameter[]>}
|
||||||
|
*/
|
||||||
|
getReportParams(reportName: string): Observable<ReportParameter[]> {
|
||||||
|
const httpParams = new HttpParams()
|
||||||
|
.set('R_reportListing', `'${reportName}'`)
|
||||||
|
.set('parameterType', 'true');
|
||||||
|
return this.http.get(`/runreports/FullParameterList`, {params: httpParams})
|
||||||
|
.pipe(map((response: any) => response.data.map((entry: any) => new ReportParameter(entry.row)) ));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} inputString URL substring containing object details.
|
||||||
|
* @returns {Observable<SelectOption[]>}
|
||||||
|
*/
|
||||||
|
getSelectOptions(inputString: string): Observable<SelectOption[]> {
|
||||||
|
const httpParams = new HttpParams().set('parameterType', 'true');
|
||||||
|
return this.http.get(`/runreports/${inputString}`, {params: httpParams})
|
||||||
|
.pipe(map((response: any) => response.data.map((entry: any) => new SelectOption(entry.row)) ));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {number} reportId Report id for which pentaho parameters are needed.
|
||||||
|
* @returns {Observable<any>}
|
||||||
|
*/
|
||||||
|
getPentahoParams(reportId: number): Observable<any> {
|
||||||
|
const httpParams = new HttpParams().set('fields', 'reportParameters');
|
||||||
|
return this.http.get(`/reports/${reportId}`, {params: httpParams})
|
||||||
|
.pipe(map((response: any) => response.reportParameters));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Run Report Data for Table and SMS.
|
||||||
|
* @param {any} report report object containing 'id', 'name' & 'type' attributes.
|
||||||
|
* @param {object} formData Form Data.
|
||||||
|
* @returns {Observable<any>}
|
||||||
|
*/
|
||||||
|
getRunReportData(report: any, formData: object): Observable<any> {
|
||||||
|
let httpParams = new HttpParams();
|
||||||
|
for (const [key, value] of Object.entries(formData)) {
|
||||||
|
httpParams = httpParams.set(key, value);
|
||||||
|
}
|
||||||
|
return this.http.get(`/runreports/${report.name}`, {params: httpParams});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Run Report Data for Charts.
|
||||||
|
* @param {any} report report object containing 'id', 'name' & 'type' attributes.
|
||||||
|
* @param {object} formData Form Data.
|
||||||
|
* @returns {Observable<ChartData>}
|
||||||
|
*/
|
||||||
|
getChartRunReportData(report: any, formData: object): Observable<ChartData> {
|
||||||
|
let httpParams = new HttpParams();
|
||||||
|
for (const [key, value] of Object.entries(formData)) {
|
||||||
|
httpParams = httpParams.set(key, value);
|
||||||
|
}
|
||||||
|
return this.http.get(`/runreports/${report.name}`, {params: httpParams})
|
||||||
|
.pipe(map((response: any) => new ChartData(response)));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Run Report Data for Pentaho.
|
||||||
|
* @param {any} report report object containing 'id', 'name' & 'type' attributes.
|
||||||
|
* @param {object} formData Form Data.
|
||||||
|
* @returns {Observable<any>}
|
||||||
|
*/
|
||||||
|
getPentahoRunReportData(report: any, formData: object, tenantIdentifier: string, locale: string, dateFormat: string): Observable<any> {
|
||||||
|
let httpParams = new HttpParams()
|
||||||
|
.set('tenantIdentifier', tenantIdentifier)
|
||||||
|
.set('locale', locale)
|
||||||
|
.set('dateFormat', dateFormat);
|
||||||
|
for (const [key, value] of Object.entries(formData)) {
|
||||||
|
httpParams = httpParams.set(key, value);
|
||||||
|
}
|
||||||
|
return this.http.get(`/runreports/${report.name}`, {responseType: 'arraybuffer', observe: 'response', params: httpParams});
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,10 @@
|
|||||||
|
<div class="m-b-20" fxLayoutAlign="end">
|
||||||
|
<mat-button-toggle-group aria-label="Select Chart Type">
|
||||||
|
<mat-button-toggle value="Bar" (click) = "setBarChart(inputData)">Bar Chart</mat-button-toggle>
|
||||||
|
<mat-button-toggle value="Pie" (click) = "setPieChart(inputData)">Pie Chart</mat-button-toggle>
|
||||||
|
</mat-button-toggle-group>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div [ngStyle]="{'display': (hideOutput) ? 'none' : 'block'}">
|
||||||
|
<canvas id="output"></canvas>
|
||||||
|
</div>
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { ChartComponent } from './chart.component';
|
||||||
|
|
||||||
|
describe('ChartComponent', () => {
|
||||||
|
let component: ChartComponent;
|
||||||
|
let fixture: ComponentFixture<ChartComponent>;
|
||||||
|
|
||||||
|
beforeEach(async(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
declarations: [ ChartComponent ]
|
||||||
|
})
|
||||||
|
.compileComponents();
|
||||||
|
}));
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
fixture = TestBed.createComponent(ChartComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -0,0 +1,139 @@
|
|||||||
|
/** Angular Imports */
|
||||||
|
import { Component, OnChanges, Input } from '@angular/core';
|
||||||
|
|
||||||
|
/** Custom Services */
|
||||||
|
import { ReportsService } from '../../reports.service';
|
||||||
|
|
||||||
|
/** Custom Models */
|
||||||
|
import { ChartData } from '../../common-models/chart-data.model';
|
||||||
|
|
||||||
|
/** Charting Imports */
|
||||||
|
import Chart from 'chart.js';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Chart Component
|
||||||
|
*/
|
||||||
|
@Component({
|
||||||
|
selector: 'mifosx-chart',
|
||||||
|
templateUrl: './chart.component.html',
|
||||||
|
styleUrls: ['./chart.component.scss' ]
|
||||||
|
})
|
||||||
|
export class ChartComponent implements OnChanges {
|
||||||
|
|
||||||
|
/** Run Report Data */
|
||||||
|
@Input() dataObject: any;
|
||||||
|
|
||||||
|
/** chart data object */
|
||||||
|
chart: any;
|
||||||
|
/** substitute for resolver */
|
||||||
|
hideOutput = true;
|
||||||
|
/** Data object for witching charts in view. */
|
||||||
|
inputData: ChartData;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {ReportsService} reportsService Reports Service
|
||||||
|
*/
|
||||||
|
constructor(private reportsService: ReportsService) { }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetches run report data post changes in run report form.
|
||||||
|
*/
|
||||||
|
ngOnChanges() {
|
||||||
|
this.getRunReportData();
|
||||||
|
}
|
||||||
|
|
||||||
|
getRunReportData() {
|
||||||
|
this.reportsService.getChartRunReportData(this.dataObject.reportData, this.dataObject.formData)
|
||||||
|
.subscribe((response: ChartData) => {
|
||||||
|
this.inputData = response;
|
||||||
|
this.setPieChart(this.inputData);
|
||||||
|
this.hideOutput = false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates instance of chart.js pie chart.
|
||||||
|
* Refer: https://www.chartjs.org/docs/latest/charts/doughnut.html for configuration details.
|
||||||
|
*/
|
||||||
|
setPieChart(inputData: ChartData) {
|
||||||
|
if (this.chart) {
|
||||||
|
this.chart.destroy();
|
||||||
|
}
|
||||||
|
this.chart = new Chart('output', {
|
||||||
|
type: 'pie',
|
||||||
|
data: {
|
||||||
|
labels: inputData.keys,
|
||||||
|
datasets: [{
|
||||||
|
label: inputData.valuesLabel,
|
||||||
|
data: inputData.values,
|
||||||
|
backgroundColor: this.randomColorArray(inputData.values.length)
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
options: {
|
||||||
|
title: {
|
||||||
|
display: true,
|
||||||
|
text: inputData.keysLabel
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates instance of chart.js bar chart.
|
||||||
|
* Refer: https://www.chartjs.org/docs/latest/charts/bar.html for configuration details.
|
||||||
|
*/
|
||||||
|
setBarChart(inputData: ChartData) {
|
||||||
|
if (this.chart) {
|
||||||
|
this.chart.destroy();
|
||||||
|
}
|
||||||
|
this.chart = new Chart('output', {
|
||||||
|
type: 'bar',
|
||||||
|
data: {
|
||||||
|
labels: inputData.keys,
|
||||||
|
datasets: [{
|
||||||
|
label: inputData.valuesLabel,
|
||||||
|
data: inputData.values,
|
||||||
|
backgroundColor: this.randomColorArray(inputData.values.length)
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
options: {
|
||||||
|
legend: { display: false },
|
||||||
|
scales: {
|
||||||
|
xAxes: [{
|
||||||
|
scaleLabel: {
|
||||||
|
display: true,
|
||||||
|
labelString: inputData.keysLabel
|
||||||
|
},
|
||||||
|
ticks: {
|
||||||
|
beginAtZero: true
|
||||||
|
}
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates bar/pie-slice colors array for dynamic charts.
|
||||||
|
* @param {number} length Length of dataset array.
|
||||||
|
*/
|
||||||
|
randomColorArray(length: number) {
|
||||||
|
const colorArray: any[] = [];
|
||||||
|
while (length--) {
|
||||||
|
const color = this.randomColor();
|
||||||
|
colorArray.push(color);
|
||||||
|
}
|
||||||
|
return colorArray;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a random rgb color.
|
||||||
|
*/
|
||||||
|
randomColor() {
|
||||||
|
const r = Math.floor(Math.random() * 255);
|
||||||
|
const g = Math.floor(Math.random() * 255);
|
||||||
|
const b = Math.floor(Math.random() * 255);
|
||||||
|
return `rgb(${r},${g},${b},0.6)`;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
<iframe *ngIf = "!hideOutput" [src]="pentahoUrl" frameborder="0" width=100% height="750px;"></iframe>
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { PentahoComponent } from './pentaho.component';
|
||||||
|
|
||||||
|
describe('PentahoComponent', () => {
|
||||||
|
let component: PentahoComponent;
|
||||||
|
let fixture: ComponentFixture<PentahoComponent>;
|
||||||
|
|
||||||
|
beforeEach(async(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
declarations: [ PentahoComponent ]
|
||||||
|
})
|
||||||
|
.compileComponents();
|
||||||
|
}));
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
fixture = TestBed.createComponent(PentahoComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -0,0 +1,52 @@
|
|||||||
|
/** Angular Imports */
|
||||||
|
import { Component, OnChanges, Input } from '@angular/core';
|
||||||
|
import { DomSanitizer } from '@angular/platform-browser';
|
||||||
|
|
||||||
|
/** Custom Services */
|
||||||
|
import { ReportsService } from '../../reports.service';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pentaho Component
|
||||||
|
*/
|
||||||
|
@Component({
|
||||||
|
selector: 'mifosx-pentaho',
|
||||||
|
templateUrl: './pentaho.component.html',
|
||||||
|
styleUrls: ['./pentaho.component.scss']
|
||||||
|
})
|
||||||
|
export class PentahoComponent implements OnChanges {
|
||||||
|
|
||||||
|
/** Run Report Data */
|
||||||
|
@Input() dataObject: any;
|
||||||
|
|
||||||
|
/** substitute for resolver */
|
||||||
|
hideOutput = true;
|
||||||
|
/** trusted resource url for pentaho output */
|
||||||
|
pentahoUrl: any;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {DomSanitizer} sanitizer DOM Sanitizer
|
||||||
|
* @param {ReportsService} reportsService Reports Service
|
||||||
|
*/
|
||||||
|
constructor(private sanitizer: DomSanitizer,
|
||||||
|
private reportsService: ReportsService) { }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetches run report data post changes in run report form.
|
||||||
|
*/
|
||||||
|
ngOnChanges() {
|
||||||
|
this.hideOutput = true;
|
||||||
|
this.getRunReportData();
|
||||||
|
}
|
||||||
|
|
||||||
|
getRunReportData() {
|
||||||
|
this.reportsService.getPentahoRunReportData(this.dataObject.reportData, this.dataObject.formData, 'default', 'en', 'dd MMMM yyyy')
|
||||||
|
.subscribe( (res: any) => {
|
||||||
|
const contentType = res.headers.get('Content-Type');
|
||||||
|
const file = new Blob([res.body], {type: contentType});
|
||||||
|
const filecontent = URL.createObjectURL(file);
|
||||||
|
this.pentahoUrl = this.sanitizer.bypassSecurityTrustResourceUrl(filecontent);
|
||||||
|
this.hideOutput = false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,113 @@
|
|||||||
|
<div class="container input">
|
||||||
|
|
||||||
|
<mat-card *ngIf="!isCollapsed">
|
||||||
|
|
||||||
|
<form [formGroup]="ReportForm" (ngSubmit)="run()">
|
||||||
|
|
||||||
|
<mat-card-content>
|
||||||
|
|
||||||
|
<div fxLayout="column" *ngFor="let param of paramData">
|
||||||
|
|
||||||
|
<div [ngSwitch]="param.displayType">
|
||||||
|
|
||||||
|
<div *ngIf="ReportForm.contains(param.name)">
|
||||||
|
<mat-form-field fxFlex="100%" *ngSwitchCase="'text'">
|
||||||
|
<mat-label>{{param.label}}</mat-label>
|
||||||
|
<input matInput required [formControlName]="param.name">
|
||||||
|
<mat-error *ngIf="ReportForm.controls[param.name].hasError('required')">
|
||||||
|
{{param.label}} is <strong>required</strong>
|
||||||
|
</mat-error>
|
||||||
|
</mat-form-field>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div *ngIf="ReportForm.contains(param.name)">
|
||||||
|
<mat-form-field fxFlex="100%" *ngSwitchCase="'date'">
|
||||||
|
<mat-label>{{param.label}}</mat-label>
|
||||||
|
<input matInput [min]="minDate" [max]="maxDate" [matDatepicker]="runReportDatePicker" required [formControlName]="param.name">
|
||||||
|
<mat-datepicker-toggle matSuffix [for]="runReportDatePicker"></mat-datepicker-toggle>
|
||||||
|
<mat-datepicker #runReportDatePicker></mat-datepicker>
|
||||||
|
<mat-error *ngIf="ReportForm.controls[param.name].hasError('required')">
|
||||||
|
{{param.label}} is <strong>required</strong>
|
||||||
|
</mat-error>
|
||||||
|
</mat-form-field>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div *ngIf="ReportForm.contains(param.name) ">
|
||||||
|
<mat-form-field fxFlex="100%" *ngSwitchCase="'select'" >
|
||||||
|
<mat-label>{{param.label}}</mat-label>
|
||||||
|
<mat-select required [formControlName]="param.name">
|
||||||
|
<mat-option *ngFor="let option of param.selectOptions" [value]="option" >
|
||||||
|
{{option.name}}
|
||||||
|
</mat-option>
|
||||||
|
</mat-select>
|
||||||
|
<mat-error *ngIf="ReportForm.controls[param.name].hasError('required')">
|
||||||
|
{{param.label}} is <strong>required</strong>
|
||||||
|
</mat-error>
|
||||||
|
</mat-form-field>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<mat-form-field fxFlex="100%">
|
||||||
|
<mat-label>Decimal Places</mat-label>
|
||||||
|
<mat-select [formControl]="decimalChoice">
|
||||||
|
<mat-option value="0">0</mat-option>
|
||||||
|
<mat-option value="1">1</mat-option>
|
||||||
|
<mat-option value="2">2</mat-option>
|
||||||
|
<mat-option value="3">3</mat-option>
|
||||||
|
<mat-option value="4">4</mat-option>
|
||||||
|
</mat-select>
|
||||||
|
</mat-form-field>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div *ngIf="report.type === 'Pentaho' && ReportForm.contains('outputType')">
|
||||||
|
<mat-form-field fxFlex="100%">
|
||||||
|
<mat-label>Output Type</mat-label>
|
||||||
|
<mat-select formControlName="outputType" value="HTML">
|
||||||
|
<mat-option value="HTML">Normal format</mat-option>
|
||||||
|
<mat-option value="XLS">Excel format</mat-option>
|
||||||
|
<mat-option value="XLSX">Excel 2007 format</mat-option>
|
||||||
|
<mat-option value="CSV">CSV format</mat-option>
|
||||||
|
<mat-option value="PDF">PDF format</mat-option>
|
||||||
|
</mat-select>
|
||||||
|
</mat-form-field>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</mat-card-content>
|
||||||
|
|
||||||
|
<mat-card-actions fxLayout="row" fxLayout.xs="column" fxLayoutAlign="center" fxLayoutGap="5px">
|
||||||
|
<button type="button" mat-raised-button [routerLink]="['/reports']">Cancel</button>
|
||||||
|
<button mat-raised-button color="primary" [disabled]="!ReportForm.valid">
|
||||||
|
<fa-icon icon="cogs"></fa-icon>
|
||||||
|
Run Report
|
||||||
|
</button>
|
||||||
|
</mat-card-actions>
|
||||||
|
|
||||||
|
</form>
|
||||||
|
|
||||||
|
</mat-card>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="container output" *ngIf="isCollapsed">
|
||||||
|
|
||||||
|
<mat-card>
|
||||||
|
|
||||||
|
<div class="m-b-20">
|
||||||
|
<button mat-raised-button color="primary" (click)="isCollapsed = false">
|
||||||
|
Parameters
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<mifosx-table-and-sms *ngIf="!hideTable"[dataObject]="dataObject"></mifosx-table-and-sms>
|
||||||
|
<mifosx-chart *ngIf="!hideChart" [dataObject]="dataObject"></mifosx-chart>
|
||||||
|
<mifosx-pentaho *ngIf="!hidePentaho" [dataObject]="dataObject"></mifosx-pentaho>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</mat-card>
|
||||||
|
|
||||||
|
</div>
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
.input {
|
||||||
|
max-width: 37rem;
|
||||||
|
}
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { RunReportComponent } from './run-report.component';
|
||||||
|
|
||||||
|
describe('RunReportComponent', () => {
|
||||||
|
let component: RunReportComponent;
|
||||||
|
let fixture: ComponentFixture<RunReportComponent>;
|
||||||
|
|
||||||
|
beforeEach(async(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
declarations: [ RunReportComponent ]
|
||||||
|
})
|
||||||
|
.compileComponents();
|
||||||
|
}));
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
fixture = TestBed.createComponent(RunReportComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -0,0 +1,201 @@
|
|||||||
|
/** Angular Imports */
|
||||||
|
import { Component, OnInit } from '@angular/core';
|
||||||
|
import { ActivatedRoute } from '@angular/router';
|
||||||
|
import { FormControl, FormGroup, Validators } from '@angular/forms';
|
||||||
|
import { DatePipe } from '@angular/common';
|
||||||
|
|
||||||
|
/** Custom Services */
|
||||||
|
import { ReportsService } from '../reports.service';
|
||||||
|
|
||||||
|
/** Custom Models */
|
||||||
|
import { ReportParameter } from '../common-models/report-parameter.model';
|
||||||
|
import { SelectOption } from '../common-models/select-option.model';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Run report component.
|
||||||
|
*/
|
||||||
|
@Component({
|
||||||
|
selector: 'mifosx-run-report',
|
||||||
|
templateUrl: './run-report.component.html',
|
||||||
|
styleUrls: ['./run-report.component.scss']
|
||||||
|
})
|
||||||
|
export class RunReportComponent implements OnInit {
|
||||||
|
|
||||||
|
/** Minimum date allowed. */
|
||||||
|
minDate = new Date(2000, 0, 1);
|
||||||
|
/** Maximum date allowed. */
|
||||||
|
maxDate = new Date();
|
||||||
|
/** Contains report specifications i.e: name, type and id */
|
||||||
|
report: any = {};
|
||||||
|
/** Formatted data post labeling of report parameters fetched from API */
|
||||||
|
paramData: any = [];
|
||||||
|
/** Array of all parent parameters */
|
||||||
|
parentParameters: any[] = [];
|
||||||
|
/** Parameter data to configure pentaho output */
|
||||||
|
pentahoReportParameters: any[] = [];
|
||||||
|
/** Data to be passed on to component selectors */
|
||||||
|
dataObject: any;
|
||||||
|
/** Initializes new form group 'ReportForm */
|
||||||
|
ReportForm = new FormGroup({});
|
||||||
|
/** Static Form control for decimal places in output */
|
||||||
|
decimalChoice = new FormControl();
|
||||||
|
/** Toggles Report form */
|
||||||
|
isCollapsed = false;
|
||||||
|
/** Toggles Table output. */
|
||||||
|
hideTable = true;
|
||||||
|
/** Toggles Chart output */
|
||||||
|
hideChart = true;
|
||||||
|
/** Toggles Pentaho output */
|
||||||
|
hidePentaho = true;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetches report specifications from route params and retrieves report parameters data from `resolve`.
|
||||||
|
* @param {ActivatedRoute} route ActivatedRoute.
|
||||||
|
* @param {DomSanitizer} sanitizer DomSanitizer.
|
||||||
|
* @param {ReportsService} reportsService ReportsService
|
||||||
|
* @param {DatePipe} datePipe Date Pipe
|
||||||
|
*/
|
||||||
|
constructor(private route: ActivatedRoute,
|
||||||
|
private reportsService: ReportsService,
|
||||||
|
private datePipe: DatePipe) {
|
||||||
|
this.report.name = this.route.snapshot.params['report-name'];
|
||||||
|
this.report.type = this.route.snapshot.params['report-type'];
|
||||||
|
this.report.id = this.route.snapshot.params['report-id'];
|
||||||
|
this.route.data.subscribe((data: any) => {
|
||||||
|
this.paramData = data.params;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates and sets the run report form.
|
||||||
|
*/
|
||||||
|
ngOnInit() {
|
||||||
|
this.createRunReportForm();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Establishes form controls for Report Parameter's name attribute,
|
||||||
|
* Fetches dropdown options and builds child dependencies.
|
||||||
|
*/
|
||||||
|
createRunReportForm() {
|
||||||
|
this.paramData.forEach(
|
||||||
|
(param: any) => {
|
||||||
|
if (!param.parentParameterName) {
|
||||||
|
this.ReportForm.addControl(param.name, new FormControl('', Validators.required));
|
||||||
|
if (param.displayType === 'select') {
|
||||||
|
this.fetchSelectOptions(param, param.name);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
const parent: ReportParameter = this.paramData
|
||||||
|
.find((entry: any) => entry.name === param.parentParameterName);
|
||||||
|
parent.childParameter = param;
|
||||||
|
this.parentParameters.push(parent);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (this.report.type === 'Pentaho') {
|
||||||
|
this.ReportForm.addControl('outputType', new FormControl(''));
|
||||||
|
this.mapPentahoParams();
|
||||||
|
}
|
||||||
|
this.decimalChoice.patchValue('0');
|
||||||
|
this.setChildControls();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetches Select Dropdown options for param type "Select".
|
||||||
|
* @param {ReportParameter} param Parameter for which dropdown options are required.
|
||||||
|
* @param {string} inputstring url substring for API call.
|
||||||
|
*/
|
||||||
|
fetchSelectOptions(param: ReportParameter, inputstring: string) {
|
||||||
|
this.reportsService.getSelectOptions(inputstring).subscribe((options: SelectOption[]) => {
|
||||||
|
param.selectOptions = options;
|
||||||
|
if (param.selectAll === 'Y') {
|
||||||
|
param.selectOptions.push({id: '-1', name: 'All'});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Maps pentaho specific names to form-control names.
|
||||||
|
*/
|
||||||
|
mapPentahoParams() {
|
||||||
|
this.reportsService.getPentahoParams(this.report.id).subscribe((data: any) => {
|
||||||
|
data.forEach((entry: any) => {
|
||||||
|
const param: ReportParameter = this.paramData
|
||||||
|
.find((_entry: any) => _entry.name === entry.parameterName);
|
||||||
|
param.pentahoName = `R_${entry.reportParameterName}`;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Subscribes to changes in parent parameters value, builds child parameter vis-a-vis parent's value.
|
||||||
|
*/
|
||||||
|
setChildControls() {
|
||||||
|
this.parentParameters.forEach((param: ReportParameter) => {
|
||||||
|
this.ReportForm.get(param.name).valueChanges.subscribe((option: any) => {
|
||||||
|
this.ReportForm.addControl(param.childParameter.name, new FormControl('', Validators.required));
|
||||||
|
if (param.childParameter.displayType === 'select') {
|
||||||
|
const inputstring = `${param.childParameter.name}?${param.inputName}=${option.id}`;
|
||||||
|
this.fetchSelectOptions(param.childParameter, inputstring);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Formats user response and readies it for utilization by run report function.
|
||||||
|
* @param {any} response Object containing formcontrol values.
|
||||||
|
*/
|
||||||
|
formatUserResponse(response: any) {
|
||||||
|
const formattedResponse: any = {};
|
||||||
|
let newKey: string;
|
||||||
|
for (const [key, value] of Object.entries(response)) {
|
||||||
|
if (key === 'outputType') {
|
||||||
|
formattedResponse['output-type'] = value;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
const param: ReportParameter = this.paramData
|
||||||
|
.find((_entry: any) => _entry.name === key);
|
||||||
|
newKey = this.report.type === 'Pentaho' ? param.pentahoName : param.inputName;
|
||||||
|
switch (param.displayType) {
|
||||||
|
case 'text':
|
||||||
|
formattedResponse[newKey] = value;
|
||||||
|
break;
|
||||||
|
case 'select':
|
||||||
|
formattedResponse[newKey] = value['id'];
|
||||||
|
break;
|
||||||
|
case 'date':
|
||||||
|
const dateFormat = 'yyyy-MM-dd';
|
||||||
|
formattedResponse[newKey] = this.datePipe.transform(value, dateFormat);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return formattedResponse;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Core run report functionality.
|
||||||
|
*/
|
||||||
|
run() {
|
||||||
|
this.isCollapsed = true;
|
||||||
|
const userResponse = this.formatUserResponse(this.ReportForm.value);
|
||||||
|
this.dataObject = {
|
||||||
|
formData: userResponse,
|
||||||
|
reportData: this.report,
|
||||||
|
decimalChoice: this.decimalChoice.value
|
||||||
|
};
|
||||||
|
switch (this.report.type) {
|
||||||
|
case 'SMS':
|
||||||
|
case 'Table':
|
||||||
|
this.hideTable = false;
|
||||||
|
break;
|
||||||
|
case 'Chart':
|
||||||
|
this.hideChart = false;
|
||||||
|
break;
|
||||||
|
case 'Pentaho':
|
||||||
|
this.hidePentaho = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
/** Angular Imports */
|
||||||
|
import { Injectable } from '@angular/core';
|
||||||
|
import { Resolve, ActivatedRouteSnapshot } from '@angular/router';
|
||||||
|
|
||||||
|
/** rxjs Imports */
|
||||||
|
import { Observable } from 'rxjs';
|
||||||
|
|
||||||
|
/** Custom Services */
|
||||||
|
import { ReportsService } from '../reports.service';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reports data resolver.
|
||||||
|
*/
|
||||||
|
@Injectable()
|
||||||
|
export class RunReportResolver implements Resolve<Object> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {ReportsService} reportsService Reports service.
|
||||||
|
*/
|
||||||
|
constructor(private reportsService: ReportsService) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the reports data.
|
||||||
|
* @returns {Observable<any>}
|
||||||
|
*/
|
||||||
|
resolve(route: ActivatedRouteSnapshot): Observable<any> {
|
||||||
|
return this.reportsService.getReportParams(route.params['report-name']);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
<div *ngIf = "!hideOutput">
|
||||||
|
|
||||||
|
<div class="m-b-10" *ngIf = "dataObject.reportData.type === 'Table'" fxLayoutAlign="end">
|
||||||
|
<button mat-raised-button color="primary" (click)="downloadCSV()" >
|
||||||
|
Export CSV
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="table-output">
|
||||||
|
<table mat-table [dataSource]="dataSource">
|
||||||
|
<div *ngFor= "let column of displayedColumns index as i">
|
||||||
|
<ng-container [matColumnDef]="column">
|
||||||
|
<th mat-header-cell *matHeaderCellDef>{{column}}</th>
|
||||||
|
<td mat-cell *matCellDef="let param" >
|
||||||
|
<span *ngIf="isDecimal(i)">{{toDecimal(param.row[i])}}</span>
|
||||||
|
<span *ngIf="!isDecimal(i)">{{param.row[i]}}</span>
|
||||||
|
</td>
|
||||||
|
</ng-container>
|
||||||
|
</div>
|
||||||
|
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
|
||||||
|
<tr mat-row *matRowDef="let row; columns: displayedColumns;" class="select-row" ></tr>
|
||||||
|
</table>
|
||||||
|
<mat-paginator [pageSizeOptions]="[10, 25, 50, 100]" showFirstLastButtons></mat-paginator>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
.table-output {
|
||||||
|
overflow: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.select-row:hover {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mat-header-cell, .mat-cell {
|
||||||
|
min-width: 150px;
|
||||||
|
margin-left: 5px;
|
||||||
|
margin-right: 5px;
|
||||||
|
}
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { TableAndSmsComponent } from './table-and-sms.component';
|
||||||
|
|
||||||
|
describe('TableAndSmsComponent', () => {
|
||||||
|
let component: TableAndSmsComponent;
|
||||||
|
let fixture: ComponentFixture<TableAndSmsComponent>;
|
||||||
|
|
||||||
|
beforeEach(async(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
declarations: [ TableAndSmsComponent ]
|
||||||
|
})
|
||||||
|
.compileComponents();
|
||||||
|
}));
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
fixture = TestBed.createComponent(TableAndSmsComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -0,0 +1,110 @@
|
|||||||
|
/** Angular Imports */
|
||||||
|
import { Component, Input, ViewChild, OnChanges } from '@angular/core';
|
||||||
|
import { MatPaginator, MatTableDataSource} from '@angular/material';
|
||||||
|
import { DecimalPipe } from '@angular/common';
|
||||||
|
|
||||||
|
/** Custom Servies */
|
||||||
|
import { ReportsService } from '../../reports.service';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Table and SMS Component
|
||||||
|
*/
|
||||||
|
@Component({
|
||||||
|
selector: 'mifosx-table-and-sms',
|
||||||
|
templateUrl: './table-and-sms.component.html',
|
||||||
|
styleUrls: ['./table-and-sms.component.scss']
|
||||||
|
})
|
||||||
|
export class TableAndSmsComponent implements OnChanges {
|
||||||
|
|
||||||
|
/** Run Report Data */
|
||||||
|
@Input() dataObject: any;
|
||||||
|
|
||||||
|
/** Columns to be displayed in mat-table */
|
||||||
|
displayedColumns: string[] = [];
|
||||||
|
/** Data source for run-report table. */
|
||||||
|
dataSource = new MatTableDataSource();
|
||||||
|
/** Maps column name to type */
|
||||||
|
columnTypes: any[] = [];
|
||||||
|
/** substitute for resolver */
|
||||||
|
hideOutput = true;
|
||||||
|
/** Data to be converted into CSV file */
|
||||||
|
csvData: any;
|
||||||
|
|
||||||
|
/** Paginator for run-report table. */
|
||||||
|
@ViewChild(MatPaginator) paginator: MatPaginator;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {ReportsService} reportsService Reports Service
|
||||||
|
* @param {DecimalPipe} decimalPipe Decimal Pipe
|
||||||
|
*/
|
||||||
|
constructor(private reportsService: ReportsService,
|
||||||
|
private decimalPipe: DecimalPipe ) { }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetches run report data post changes in run report form.
|
||||||
|
*/
|
||||||
|
ngOnChanges() {
|
||||||
|
this.hideOutput = true;
|
||||||
|
this.columnTypes = [];
|
||||||
|
this.displayedColumns = [];
|
||||||
|
this.getRunReportData();
|
||||||
|
}
|
||||||
|
|
||||||
|
getRunReportData() {
|
||||||
|
this.reportsService.getRunReportData(this.dataObject.reportData, this.dataObject.formData)
|
||||||
|
.subscribe( (res: any) => {
|
||||||
|
this.csvData = res.data;
|
||||||
|
this.setOutputTable(res.data);
|
||||||
|
res.columnHeaders.forEach((header: any) => {
|
||||||
|
this.columnTypes.push(header.columnDisplayType);
|
||||||
|
this.displayedColumns.push(header.columnName);
|
||||||
|
});
|
||||||
|
this.hideOutput = false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets up a dynamic Mat Table.
|
||||||
|
* @param {any} data Mat Table data
|
||||||
|
*/
|
||||||
|
setOutputTable(data: any) {
|
||||||
|
this.dataSource = new MatTableDataSource(data);
|
||||||
|
setTimeout(() => {
|
||||||
|
this.dataSource.paginator = this.paginator;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates the CSV file dynamically for run report data.
|
||||||
|
*/
|
||||||
|
downloadCSV() {
|
||||||
|
const headers = this.displayedColumns;
|
||||||
|
let csv = this.csvData.map((object: any) => object.row.join());
|
||||||
|
csv.unshift(`data:text/csv;charset=utf-8,${headers.join()}`);
|
||||||
|
csv = csv.join('\r\n');
|
||||||
|
const link = document.createElement('a');
|
||||||
|
link.setAttribute('href', encodeURI(csv));
|
||||||
|
link.setAttribute('download', `${this.dataObject.reportData.name}.csv`);
|
||||||
|
document.body.appendChild(link);
|
||||||
|
link.click();
|
||||||
|
document.body.removeChild(link);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns number formatted as per user's decimal choice.
|
||||||
|
* @param {number} value Value to be formatted as per decimal choice.
|
||||||
|
*/
|
||||||
|
toDecimal(value: number) {
|
||||||
|
const decimalChoice = this.dataObject.decimalChoice;
|
||||||
|
return this.decimalPipe.transform(value, `1.${decimalChoice}-${decimalChoice}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks the weather Mat-Table column has decimal display type.
|
||||||
|
* @param {number} index Index of column.
|
||||||
|
*/
|
||||||
|
isDecimal(index: number) {
|
||||||
|
return this.columnTypes[index] === 'DECIMAL';
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
Vendored
+2
@@ -10,3 +10,5 @@ declare var module: NodeModule;
|
|||||||
interface NodeModule {
|
interface NodeModule {
|
||||||
id: string;
|
id: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
declare module 'chart.js';
|
||||||
|
|||||||
Reference in New Issue
Block a user