diff --git a/lib/insights/src/lib/analytics-process/components/analytics-report-parameters.component.spec.ts b/lib/insights/src/lib/analytics-process/components/analytics-report-parameters.component.spec.ts index 3f051ec9062..f2eef61b738 100644 --- a/lib/insights/src/lib/analytics-process/components/analytics-report-parameters.component.spec.ts +++ b/lib/insights/src/lib/analytics-process/components/analytics-report-parameters.component.spec.ts @@ -19,7 +19,7 @@ import { SimpleChange } from '@angular/core'; import { ComponentFixture, fakeAsync, TestBed } from '@angular/core/testing'; import { ReportParametersModel } from '../../diagram/models/report/report-parameters.model'; import * as analyticParamsMock from '../../mock'; -import { AnalyticsReportParametersComponent } from '../components/analytics-report-parameters.component'; +import { AnalyticsReportParametersComponent, ReportFormValues } from '../components/analytics-report-parameters.component'; import { InsightsTestingModule } from '../../testing/insights.testing.module'; import { AnalyticsService } from '../services/analytics.service'; import { of } from 'rxjs'; @@ -61,7 +61,7 @@ describe('AnalyticsReportParametersComponent', () => { it('Should initialize the Report form with a Form Group ', async () => { const fakeReportParam = new ReportParametersModel(analyticParamsMock.reportDefParamTask); - await component.successReportParams.subscribe(() => { + component.successReportParams.subscribe(() => { fixture.detectChanges(); expect(component.reportForm.get('taskGroup')).toBeDefined(); expect(component.reportForm.get('taskGroup').get('taskName')).toBeDefined(); @@ -70,7 +70,7 @@ describe('AnalyticsReportParametersComponent', () => { }); it('Should render a dropdown with all the status when the definition parameter type is \'status\' ', async () => { - await component.successReportParams.subscribe(() => { + component.successReportParams.subscribe(() => { fixture.detectChanges(); const dropDown: any = element.querySelector('#select-status'); expect(element.querySelector('h4').textContent.trim()).toEqual('Fake Task overview status'); @@ -94,7 +94,7 @@ describe('AnalyticsReportParametersComponent', () => { }); it('Should render a number with the default value when the definition parameter type is \'integer\' ', async () => { - await component.successReportParams.subscribe(() => { + component.successReportParams.subscribe(() => { fixture.detectChanges(); const numberElement: any = element.querySelector('#slowProcessInstanceInteger'); expect(numberElement.value).toEqual('10'); @@ -112,7 +112,7 @@ describe('AnalyticsReportParametersComponent', () => { }); it('Should render a duration component when the definition parameter type is "duration"', async () => { - await component.successReportParams.subscribe(() => { + component.successReportParams.subscribe(() => { fixture.detectChanges(); fixture.whenStable().then(() => { const numberElement: any = element.querySelector('#duration'); @@ -147,12 +147,12 @@ describe('AnalyticsReportParametersComponent', () => { expect(res.processDefinitionId).toEqual('FakeProcess:1:22'); expect(res.taskName).toEqual('FakeTaskName'); expect(res.duration).toEqual(22); - expect(res.dateRangeInterval).toEqual(120); + expect(res.dateRangeInterval).toEqual('120'); expect(res.slowProcessInstanceInteger).toEqual(2); expect(res.typeFiltering).toEqual(true); }); - const values: any = { + const values: ReportFormValues = { dateRange: { startDate: '2016-09-01', endDate: '2016-10-05' }, @@ -169,10 +169,10 @@ describe('AnalyticsReportParametersComponent', () => { duration: 22 }, dateIntervalGroup: { - dateRangeInterval: 120 + dateRangeInterval: '120' }, processInstanceGroup: { - slowProcessInstanceInteger: 2 + slowProcessInstanceInteger: '2' }, typeFilteringGroup: { typeFiltering: true @@ -183,7 +183,7 @@ describe('AnalyticsReportParametersComponent', () => { }); it('Should render a checkbox with the value true when the definition parameter type is \'boolean\' ', async () => { - await component.successReportParams.subscribe(() => { + component.successReportParams.subscribe(() => { fixture.detectChanges(); const checkElement: any = element.querySelector('#typeFiltering-input'); expect(checkElement.checked).toBeTruthy(); @@ -201,7 +201,7 @@ describe('AnalyticsReportParametersComponent', () => { }); it('Should render a date range components when the definition parameter type is \'dateRange\' ', async () => { - await component.successReportParams.subscribe(() => { + component.successReportParams.subscribe(() => { const dateElement: any = element.querySelector('adf-date-range-widget'); expect(dateElement).toBeDefined(); }); @@ -219,7 +219,7 @@ describe('AnalyticsReportParametersComponent', () => { }); it('Should render a dropdown with all the RangeInterval when the definition parameter type is \'dateRangeInterval\' ', async () => { - await component.successReportParams.subscribe(() => { + component.successReportParams.subscribe(() => { fixture.detectChanges(); const dropDown: any = element.querySelector('#select-dateRangeInterval'); expect(dropDown).toBeDefined(); @@ -244,7 +244,7 @@ describe('AnalyticsReportParametersComponent', () => { it('Should render a dropdown with all the process definition when the definition parameter type is \'processDefinition\' and the' + ' reportId change', async () => { - await component.successParamOpt.subscribe(() => { + component.successParamOpt.subscribe(() => { fixture.detectChanges(); const dropDown: any = element.querySelector('#select-processDefinitionId'); expect(dropDown).toBeDefined(); @@ -276,7 +276,7 @@ describe('AnalyticsReportParametersComponent', () => { it('Should render a dropdown with all the process definition when the definition parameter type is \'processDefinition\' and the' + ' appId change', async () => { - await component.successParamOpt.subscribe(() => { + component.successParamOpt.subscribe(() => { fixture.detectChanges(); const dropDown: any = element.querySelector('#select-processDefinitionId'); expect(dropDown).toBeDefined(); @@ -347,7 +347,7 @@ describe('AnalyticsReportParametersComponent', () => { }); it('Should emit an error with a 404 response when the options response is not found', async () => { - await component.error.subscribe((err) => { + component.error.subscribe((err) => { expect(err).toBeDefined(); }); @@ -370,7 +370,7 @@ describe('AnalyticsReportParametersComponent', () => { }); it('Should emit an error with a 404 response when the report parameters response is not found', async () => { - await component.error.subscribe((err) => { + component.error.subscribe((err) => { expect(err).toBeDefined(); }); @@ -386,7 +386,7 @@ describe('AnalyticsReportParametersComponent', () => { }); it('Should convert a string in number', () => { - const numberConvert = component.convertNumber('2'); + const numberConvert = component.parseNumber('2'); expect(numberConvert).toEqual(2); }); diff --git a/lib/insights/src/lib/analytics-process/components/analytics-report-parameters.component.ts b/lib/insights/src/lib/analytics-process/components/analytics-report-parameters.component.ts index 875d29e4b56..899b97ad185 100644 --- a/lib/insights/src/lib/analytics-process/components/analytics-report-parameters.component.ts +++ b/lib/insights/src/lib/analytics-process/components/analytics-report-parameters.component.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -import { DownloadService, LogService } from '@alfresco/adf-core'; +import { AdfDateFnsAdapter, DownloadService, LogService } from '@alfresco/adf-core'; import { AfterContentChecked, Component, @@ -29,10 +29,8 @@ import { ViewChild, ViewEncapsulation } from '@angular/core'; -import { UntypedFormBuilder, UntypedFormControl, UntypedFormGroup, Validators } from '@angular/forms'; +import { FormBuilder, FormControl, FormGroup, Validators } from '@angular/forms'; import { MatDialog } from '@angular/material/dialog'; -import moment from 'moment'; -import { ParameterValueModel } from '../../diagram/models/report/parameter-value.model'; import { ReportParameterDetailsModel } from '../../diagram/models/report/report-parameter-details.model'; import { ReportParametersModel } from '../../diagram/models/report/report-parameters.model'; import { ReportQuery } from '../../diagram/models/report/report-query.model'; @@ -42,6 +40,62 @@ import { takeUntil } from 'rxjs/operators'; const FORMAT_DATE_ACTIVITI = 'YYYY-MM-DD'; +export interface ReportFormProps { + taskGroup?: FormGroup<{ + taskName: FormControl; + }>; + processDefGroup?: FormGroup<{ + processDefinitionId: FormControl; + }>; + dateIntervalGroup?: FormGroup<{ + dateRangeInterval: FormControl; + }>; + dateRange?: FormGroup<{ + startDate?: FormControl; + endDate?: FormControl; + }>; + statusGroup?: FormGroup<{ + status: FormControl; + }>; + typeFilteringGroup?: FormGroup<{ + typeFiltering: FormControl; + }>; + durationGroup?: FormGroup<{ + duration: FormControl; + }>; + processInstanceGroup?: FormGroup<{ + slowProcessInstanceInteger: FormControl; + }>; +} + +export interface ReportFormValues { + taskGroup?: { + taskName?: string; + }; + processDefGroup?: { + processDefinitionId?: string; + }; + dateIntervalGroup?: { + dateRangeInterval?: string; + }; + dateRange?: { + startDate?: string; + endDate?: string; + }; + statusGroup?: { + status?: string; + }; + typeFilteringGroup?: { + typeFiltering?: boolean; + }; + durationGroup?: { + duration?: number; + }; + processInstanceGroup?: { + slowProcessInstanceInteger?: string; + }; +} + @Component({ selector: 'adf-analytics-report-parameters', templateUrl: './analytics-report-parameters.component.html', @@ -63,7 +117,7 @@ export class AnalyticsReportParametersComponent implements OnInit, OnChanges, On /** success. */ @Output() - success = new EventEmitter(); + success = new EventEmitter(); /** error. */ @Output() @@ -88,12 +142,12 @@ export class AnalyticsReportParametersComponent implements OnInit, OnChanges, On @ViewChild('reportNameDialog') reportNameDialog: any; - onDropdownChanged = new EventEmitter(); + onDropdownChanged = new EventEmitter(); successReportParams = new EventEmitter(); successParamOpt = new EventEmitter(); reportParameters: ReportParametersModel; - reportForm: UntypedFormGroup; + reportForm: FormGroup; action: string; isEditable: boolean = false; reportName: string; @@ -105,10 +159,11 @@ export class AnalyticsReportParametersComponent implements OnInit, OnChanges, On constructor( private analyticsService: AnalyticsService, - private formBuilder: UntypedFormBuilder, + private formBuilder: FormBuilder, private logService: LogService, private downloadService: DownloadService, - private dialog: MatDialog + private dialog: MatDialog, + private dateAdapter: AdfDateFnsAdapter ) {} ngOnInit() { @@ -152,7 +207,7 @@ export class AnalyticsReportParametersComponent implements OnInit, OnChanges, On if (this.reportParameters.hasParameters()) { this.successReportParams.emit(res); } else { - this.reportForm = this.formBuilder.group({}); + this.reportForm = this.formBuilder.group({}); this.success.emit(); } }, @@ -162,18 +217,18 @@ export class AnalyticsReportParametersComponent implements OnInit, OnChanges, On ); } - onProcessDefinitionChanges(field: any) { + onProcessDefinitionChanges(field: ReportParameterDetailsModel) { if (field.value) { this.onDropdownChanged.emit(field); } } - public submit(values: any) { + public submit(values: ReportFormValues) { this.reportParamQuery = this.convertFormValuesToReportParamQuery(values); this.success.emit(this.reportParamQuery); } - onValueChanged(values: any) { + onValueChanged(values: ReportFormValues) { this.formValueChanged.emit(values); if (this.reportForm?.valid) { this.submit(values); @@ -186,23 +241,20 @@ export class AnalyticsReportParametersComponent implements OnInit, OnChanges, On } } - convertMomentDate(date: string) { - return moment(date, FORMAT_DATE_ACTIVITI, true).format(FORMAT_DATE_ACTIVITI) + 'T00:00:00.000Z'; + private parseDate(input: string) { + const date = this.dateAdapter.parse(input, FORMAT_DATE_ACTIVITI); + return this.dateAdapter.format(date, FORMAT_DATE_ACTIVITI) + 'T00:00:00.000Z'; } - getTodayDate() { - return moment().format(FORMAT_DATE_ACTIVITI); - } - - convertNumber(value: string): number { + parseNumber(value: string): number { return value != null ? parseInt(value, 10) : 0; } - convertFormValuesToReportParamQuery(values: any): ReportQuery { - const reportParamQuery: ReportQuery = new ReportQuery(); + private convertFormValuesToReportParamQuery(values: ReportFormValues): ReportQuery { + const reportParamQuery = new ReportQuery(); if (values.dateRange) { - reportParamQuery.dateRange.startDate = this.convertMomentDate(values.dateRange.startDate); - reportParamQuery.dateRange.endDate = this.convertMomentDate(values.dateRange.endDate); + reportParamQuery.dateRange.startDate = this.parseDate(values.dateRange.startDate); + reportParamQuery.dateRange.endDate = this.parseDate(values.dateRange.endDate); } if (values.statusGroup) { reportParamQuery.status = values.statusGroup.status; @@ -220,7 +272,7 @@ export class AnalyticsReportParametersComponent implements OnInit, OnChanges, On reportParamQuery.dateRangeInterval = values.dateIntervalGroup.dateRangeInterval; } if (values.processInstanceGroup) { - reportParamQuery.slowProcessInstanceInteger = this.convertNumber(values.processInstanceGroup.slowProcessInstanceInteger); + reportParamQuery.slowProcessInstanceInteger = this.parseNumber(values.processInstanceGroup.slowProcessInstanceInteger); } if (values.typeFilteringGroup) { reportParamQuery.typeFiltering = values.typeFilteringGroup.typeFiltering; @@ -256,7 +308,9 @@ export class AnalyticsReportParametersComponent implements OnInit, OnChanges, On showDialog(event: string) { this.dialog.open(this.reportNameDialog, { width: '500px' }); this.action = event; - this.reportName = this.reportParameters.name + ' ( ' + this.getTodayDate() + ' )'; + + const date = this.dateAdapter.format(new Date(), FORMAT_DATE_ACTIVITI); + this.reportName = `${this.reportParameters.name} ( ${date} )`; } closeDialog() { @@ -274,23 +328,23 @@ export class AnalyticsReportParametersComponent implements OnInit, OnChanges, On this.resetActions(); } - resetActions() { + private resetActions() { this.action = ''; this.reportName = ''; } - isSaveAction() { + isSaveAction(): boolean { return this.action === 'Save'; } - doExport(paramQuery: ReportQuery) { + private doExport(paramQuery: ReportQuery) { this.analyticsService.exportReportToCsv(this.reportId, paramQuery).subscribe((data: any) => { const blob: Blob = new Blob([data], { type: 'text/csv' }); this.downloadService.downloadBlob(blob, paramQuery.reportName + '.csv'); }); } - doSave(paramQuery: ReportQuery) { + private doSave(paramQuery: ReportQuery) { this.analyticsService.saveReport(this.reportId, paramQuery).subscribe(() => { this.saveReportSuccess.emit(this.reportId); }); @@ -315,105 +369,106 @@ export class AnalyticsReportParametersComponent implements OnInit, OnChanges, On this.hideParameters = !this.hideParameters; } - isParametersHide() { + isParametersHide(): boolean { return this.hideParameters; } - isFormValid() { + isFormValid(): boolean { return this.reportForm?.dirty && this.reportForm.valid; } - get taskGroup(): UntypedFormGroup { - return this.reportForm.controls.taskGroup as UntypedFormGroup; + get taskGroup(): FormGroup { + return this.reportForm.controls.taskGroup; } - get processDefGroup(): UntypedFormGroup { - return this.reportForm.controls.processDefGroup as UntypedFormGroup; + get processDefGroup(): FormGroup { + return this.reportForm.controls.processDefGroup; } - get dateIntervalGroup(): UntypedFormGroup { - return this.reportForm.controls.dateIntervalGroup as UntypedFormGroup; + get dateIntervalGroup(): FormGroup { + return this.reportForm.controls.dateIntervalGroup; } - get dateRange(): UntypedFormGroup { - return this.reportForm.controls.dateRange as UntypedFormGroup; + get dateRange(): FormGroup { + return this.reportForm.controls.dateRange; } - get statusGroup(): UntypedFormGroup { - return this.reportForm.controls.statusGroup as UntypedFormGroup; + get statusGroup(): FormGroup { + return this.reportForm.controls.statusGroup; } - get typeFilteringGroup(): UntypedFormGroup { - return this.reportForm.controls.typeFilteringGroup as UntypedFormGroup; + get typeFilteringGroup(): FormGroup { + return this.reportForm.controls.typeFilteringGroup; } - get durationGroup(): UntypedFormGroup { - return this.reportForm.controls.durationGroup as UntypedFormGroup; + get durationGroup(): FormGroup { + return this.reportForm.controls.durationGroup; } - get processInstanceGroup(): UntypedFormGroup { - return this.reportForm.controls.processInstanceGroup as UntypedFormGroup; + get processInstanceGroup(): FormGroup { + return this.reportForm.controls.processInstanceGroup; } private generateFormGroupFromParameter(parameters: ReportParameterDetailsModel[]) { - const formBuilderGroup: any = {}; - parameters.forEach((param: ReportParameterDetailsModel) => { + const formBuilderGroup: ReportFormProps = {}; + + parameters.forEach((param) => { switch (param.type) { case 'dateRange': - formBuilderGroup.dateRange = new UntypedFormGroup({}, Validators.required); + formBuilderGroup.dateRange = new FormGroup({}, Validators.required); break; case 'processDefinition': - formBuilderGroup.processDefGroup = new UntypedFormGroup( + formBuilderGroup.processDefGroup = new FormGroup( { - processDefinitionId: new UntypedFormControl(null, Validators.required, null) + processDefinitionId: new FormControl(null, Validators.required, null) }, Validators.required ); break; case 'duration': - formBuilderGroup.durationGroup = new UntypedFormGroup( + formBuilderGroup.durationGroup = new FormGroup( { - duration: new UntypedFormControl(null, Validators.required, null) + duration: new FormControl(null, Validators.required, null) }, Validators.required ); break; case 'dateInterval': - formBuilderGroup.dateIntervalGroup = new UntypedFormGroup( + formBuilderGroup.dateIntervalGroup = new FormGroup( { - dateRangeInterval: new UntypedFormControl(null, Validators.required, null) + dateRangeInterval: new FormControl(null, Validators.required, null) }, Validators.required ); break; case 'boolean': - formBuilderGroup.typeFilteringGroup = new UntypedFormGroup( + formBuilderGroup.typeFilteringGroup = new FormGroup( { - typeFiltering: new UntypedFormControl(null, Validators.required, null) + typeFiltering: new FormControl(null, Validators.required, null) }, Validators.required ); break; case 'task': - formBuilderGroup.taskGroup = new UntypedFormGroup( + formBuilderGroup.taskGroup = new FormGroup( { - taskName: new UntypedFormControl(null, Validators.required, null) + taskName: new FormControl(null, Validators.required, null) }, Validators.required ); break; case 'integer': - formBuilderGroup.processInstanceGroup = new UntypedFormGroup( + formBuilderGroup.processInstanceGroup = new FormGroup( { - slowProcessInstanceInteger: new UntypedFormControl(null, Validators.required, null) + slowProcessInstanceInteger: new FormControl(null, Validators.required, null) }, Validators.required ); break; case 'status': - formBuilderGroup.statusGroup = new UntypedFormGroup( + formBuilderGroup.statusGroup = new FormGroup( { - status: new UntypedFormControl(null, Validators.required, null) + status: new FormControl(null, Validators.required, null) }, Validators.required ); @@ -422,7 +477,7 @@ export class AnalyticsReportParametersComponent implements OnInit, OnChanges, On return; } }); - this.reportForm = this.formBuilder.group(formBuilderGroup); + this.reportForm = this.formBuilder.group(formBuilderGroup); this.reportForm.valueChanges.subscribe((data) => this.onValueChanged(data)); this.reportForm.statusChanges.subscribe(() => this.onStatusChanged()); } @@ -430,7 +485,7 @@ export class AnalyticsReportParametersComponent implements OnInit, OnChanges, On private retrieveParameterOptions(parameters: ReportParameterDetailsModel[], appId: number, reportId?: string, processDefinitionId?: string) { parameters.forEach((param) => { this.analyticsService.getParamValuesByType(param.type, appId, reportId, processDefinitionId).subscribe( - (opts: ParameterValueModel[]) => { + (opts) => { param.options = opts; this.successParamOpt.emit(opts); }, diff --git a/lib/insights/src/lib/diagram/models/chart/bar-chart.model.ts b/lib/insights/src/lib/diagram/models/chart/bar-chart.model.ts index aa70cd3403f..7e357dfb690 100644 --- a/lib/insights/src/lib/diagram/models/chart/bar-chart.model.ts +++ b/lib/insights/src/lib/diagram/models/chart/bar-chart.model.ts @@ -15,8 +15,8 @@ * limitations under the License. */ -import moment from 'moment'; import { Chart } from './chart.model'; +import { format } from 'date-fns'; export class BarChart extends Chart { xAxisType: string; @@ -24,17 +24,20 @@ export class BarChart extends Chart { options: any = { responsive: true, scales: { - yAxes: [{ - ticks: { - beginAtZero: true, - stepSize: 1 + yAxes: [ + { + ticks: { + beginAtZero: true, + stepSize: 1 + } + } + ], + xAxes: [ + { + ticks: {}, + stacked: false } - }], - xAxes: [{ - ticks: { - }, - stacked: false - }] + ] } }; @@ -59,30 +62,30 @@ export class BarChart extends Chart { }); }); if (dataValue && dataValue.length > 0) { - this.datasets.push({data: dataValue, label: params.key}); + this.datasets.push({ data: dataValue, label: params.key }); } }); } } - xAxisTickFormatFunction(xAxisType) { - return (value) => { - if (xAxisType !== null && xAxisType !== undefined) { + xAxisTickFormatFunction(xAxisType: string) { + return (value: string) => { + if (xAxisType) { if ('date_day' === xAxisType) { - return moment(new Date(value)).format('DD'); + return format(new Date(value), 'dd'); } else if ('date_month' === xAxisType) { - return moment(new Date(value)).format('MMMM'); + return format(new Date(value), 'MMMM'); } else if ('date_year' === xAxisType) { - return moment(new Date(value)).format('YYYY'); + return format(new Date(value), 'yyyy'); } } return value; }; - }; + } - yAxisTickFormatFunction(yAxisType) { - return (value) => { - if (yAxisType !== null && yAxisType !== undefined) { + yAxisTickFormatFunction(yAxisType: string) { + return (value: string) => { + if (yAxisType) { if ('count' === yAxisType) { const label = '' + value; if (label.indexOf('.') !== -1) { @@ -92,5 +95,5 @@ export class BarChart extends Chart { } return value; }; - }; + } } diff --git a/lib/insights/src/lib/testing/insights.testing.module.ts b/lib/insights/src/lib/testing/insights.testing.module.ts index b149c8577ce..573e5d6ed29 100644 --- a/lib/insights/src/lib/testing/insights.testing.module.ts +++ b/lib/insights/src/lib/testing/insights.testing.module.ts @@ -33,7 +33,7 @@ import { imports: [ NoopAnimationsModule, TranslateModule, - CoreModule, + CoreModule.forRoot(), InsightsModule ], providers: [