diff --git a/src/app/reports/common-models/chart-data.model.ts b/src/app/reports/common-models/chart-data.model.ts
new file mode 100644
index 000000000..d2a89616c
--- /dev/null
+++ b/src/app/reports/common-models/chart-data.model.ts
@@ -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]);
+ }
+
+}
diff --git a/src/app/reports/common-models/report-parameter.model.ts b/src/app/reports/common-models/report-parameter.model.ts
new file mode 100644
index 000000000..38bd53f1d
--- /dev/null
+++ b/src/app/reports/common-models/report-parameter.model.ts
@@ -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]}`;
+ }
+
+}
diff --git a/src/app/reports/common-models/select-option.model.ts b/src/app/reports/common-models/select-option.model.ts
new file mode 100644
index 000000000..d6520cc19
--- /dev/null
+++ b/src/app/reports/common-models/select-option.model.ts
@@ -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];
+ }
+}
diff --git a/src/app/reports/reports-routing.module.ts b/src/app/reports/reports-routing.module.ts
index e88e69c72..eab3d3994 100644
--- a/src/app/reports/reports-routing.module.ts
+++ b/src/app/reports/reports-routing.module.ts
@@ -10,9 +10,11 @@ import { extract } from '../core/i18n/i18n.service';
/** Custom Components */
import { ReportsComponent } from './reports.component';
+import { RunReportComponent } from './run-report/run-report.component';
/** Custom Resolvers */
import { ReportsResolver } from './reports.resolver';
+import { RunReportResolver } from './run-report/run-report.resolver';
/** Reports Routes */
const routes: Routes = [
@@ -34,6 +36,29 @@ const routes: Routes = [
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)],
exports: [RouterModule],
providers: [
- ReportsResolver
+ ReportsResolver,
+ RunReportResolver
]
})
export class ReportsRoutingModule { }
diff --git a/src/app/reports/reports.component.html b/src/app/reports/reports.component.html
index 616b2e6ef..77f1d602f 100644
--- a/src/app/reports/reports.component.html
+++ b/src/app/reports/reports.component.html
@@ -28,7 +28,7 @@
-
+
diff --git a/src/app/reports/reports.module.ts b/src/app/reports/reports.module.ts
index d4a27bc81..c1e649778 100644
--- a/src/app/reports/reports.module.ts
+++ b/src/app/reports/reports.module.ts
@@ -1,5 +1,6 @@
/** Angular Imports */
import { NgModule } from '@angular/core';
+import { DecimalPipe } from '@angular/common';
/** Custom Modules */
import { SharedModule } from '../shared/shared.module';
@@ -7,6 +8,10 @@ import { ReportsRoutingModule } from 'app/reports/reports-routing.module';
/** Custom Components */
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
@@ -18,6 +23,13 @@ import { ReportsComponent } from './reports.component';
SharedModule,
ReportsRoutingModule
],
- declarations: [ReportsComponent],
+ declarations: [
+ ReportsComponent,
+ RunReportComponent,
+ TableAndSmsComponent,
+ ChartComponent,
+ PentahoComponent
+ ],
+ providers: [ DecimalPipe ]
})
export class ReportsModule { }
diff --git a/src/app/reports/reports.service.ts b/src/app/reports/reports.service.ts
index b3acea4f2..4a80b17a4 100644
--- a/src/app/reports/reports.service.ts
+++ b/src/app/reports/reports.service.ts
@@ -4,6 +4,12 @@ import { HttpClient, HttpParams } from '@angular/common/http';
/** rxjs Imports */
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.
@@ -25,4 +31,82 @@ export class ReportsService {
return this.http.get('/reports');
}
+ /**
+ * @param {string} reportName Report name for which parameters are needed.
+ * @returns {Observable}
+ */
+ getReportParams(reportName: string): Observable {
+ 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}
+ */
+ getSelectOptions(inputString: string): Observable {
+ 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}
+ */
+ getPentahoParams(reportId: number): Observable {
+ 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}
+ */
+ getRunReportData(report: any, formData: object): Observable {
+ 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}
+ */
+ getChartRunReportData(report: any, formData: object): Observable {
+ 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}
+ */
+ getPentahoRunReportData(report: any, formData: object, tenantIdentifier: string, locale: string, dateFormat: string): Observable {
+ 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});
+ }
+
}
diff --git a/src/app/reports/run-report/chart/chart.component.html b/src/app/reports/run-report/chart/chart.component.html
new file mode 100644
index 000000000..ab16e0b74
--- /dev/null
+++ b/src/app/reports/run-report/chart/chart.component.html
@@ -0,0 +1,10 @@
+
+
+ Bar Chart
+ Pie Chart
+
+
+
+
+
+
diff --git a/src/app/reports/run-report/chart/chart.component.scss b/src/app/reports/run-report/chart/chart.component.scss
new file mode 100644
index 000000000..e69de29bb
diff --git a/src/app/reports/run-report/chart/chart.component.spec.ts b/src/app/reports/run-report/chart/chart.component.spec.ts
new file mode 100644
index 000000000..4bfa61135
--- /dev/null
+++ b/src/app/reports/run-report/chart/chart.component.spec.ts
@@ -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;
+
+ beforeEach(async(() => {
+ TestBed.configureTestingModule({
+ declarations: [ ChartComponent ]
+ })
+ .compileComponents();
+ }));
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(ChartComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/src/app/reports/run-report/chart/chart.component.ts b/src/app/reports/run-report/chart/chart.component.ts
new file mode 100644
index 000000000..661c69210
--- /dev/null
+++ b/src/app/reports/run-report/chart/chart.component.ts
@@ -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)`;
+ }
+
+}
diff --git a/src/app/reports/run-report/pentaho/pentaho.component.html b/src/app/reports/run-report/pentaho/pentaho.component.html
new file mode 100644
index 000000000..59244a56c
--- /dev/null
+++ b/src/app/reports/run-report/pentaho/pentaho.component.html
@@ -0,0 +1 @@
+
diff --git a/src/app/reports/run-report/pentaho/pentaho.component.scss b/src/app/reports/run-report/pentaho/pentaho.component.scss
new file mode 100644
index 000000000..e69de29bb
diff --git a/src/app/reports/run-report/pentaho/pentaho.component.spec.ts b/src/app/reports/run-report/pentaho/pentaho.component.spec.ts
new file mode 100644
index 000000000..2b84baca4
--- /dev/null
+++ b/src/app/reports/run-report/pentaho/pentaho.component.spec.ts
@@ -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;
+
+ beforeEach(async(() => {
+ TestBed.configureTestingModule({
+ declarations: [ PentahoComponent ]
+ })
+ .compileComponents();
+ }));
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(PentahoComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/src/app/reports/run-report/pentaho/pentaho.component.ts b/src/app/reports/run-report/pentaho/pentaho.component.ts
new file mode 100644
index 000000000..73e3765f1
--- /dev/null
+++ b/src/app/reports/run-report/pentaho/pentaho.component.ts
@@ -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;
+ });
+ }
+
+}
diff --git a/src/app/reports/run-report/run-report.component.html b/src/app/reports/run-report/run-report.component.html
new file mode 100644
index 000000000..27fa3ed18
--- /dev/null
+++ b/src/app/reports/run-report/run-report.component.html
@@ -0,0 +1,113 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/app/reports/run-report/run-report.component.scss b/src/app/reports/run-report/run-report.component.scss
new file mode 100644
index 000000000..57c04e49c
--- /dev/null
+++ b/src/app/reports/run-report/run-report.component.scss
@@ -0,0 +1,3 @@
+.input {
+ max-width: 37rem;
+}
diff --git a/src/app/reports/run-report/run-report.component.spec.ts b/src/app/reports/run-report/run-report.component.spec.ts
new file mode 100644
index 000000000..b6d4de470
--- /dev/null
+++ b/src/app/reports/run-report/run-report.component.spec.ts
@@ -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;
+
+ beforeEach(async(() => {
+ TestBed.configureTestingModule({
+ declarations: [ RunReportComponent ]
+ })
+ .compileComponents();
+ }));
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(RunReportComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/src/app/reports/run-report/run-report.component.ts b/src/app/reports/run-report/run-report.component.ts
new file mode 100644
index 000000000..123627f6e
--- /dev/null
+++ b/src/app/reports/run-report/run-report.component.ts
@@ -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;
+ }
+ }
+
+}
diff --git a/src/app/reports/run-report/run-report.resolver.ts b/src/app/reports/run-report/run-report.resolver.ts
new file mode 100644
index 000000000..07a18dd99
--- /dev/null
+++ b/src/app/reports/run-report/run-report.resolver.ts
@@ -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