diff --git a/lib/process-services-cloud/src/lib/common/date-range-filter/date-range-filter.component.html b/lib/process-services-cloud/src/lib/common/date-range-filter/date-range-filter.component.html index b9c7da2e64..c669b8c801 100644 --- a/lib/process-services-cloud/src/lib/common/date-range-filter/date-range-filter.component.html +++ b/lib/process-services-cloud/src/lib/common/date-range-filter/date-range-filter.component.html @@ -2,9 +2,10 @@ - + {{ propertyOption.label | translate }} @@ -19,8 +20,5 @@ - - {{ 'ADF_CLOUD_EDIT_PROCESS_FILTER.ERROR.INDALID_START_DATE' | translate }} - {{ 'ADF_CLOUD_EDIT_PROCESS_FILTER.ERROR.INDALID_END_DATE' | translate }} diff --git a/lib/process-services-cloud/src/lib/common/date-range-filter/date-range-filter.component.spec.ts b/lib/process-services-cloud/src/lib/common/date-range-filter/date-range-filter.component.spec.ts index fb6eab65a5..3cdd24ddc2 100644 --- a/lib/process-services-cloud/src/lib/common/date-range-filter/date-range-filter.component.spec.ts +++ b/lib/process-services-cloud/src/lib/common/date-range-filter/date-range-filter.component.spec.ts @@ -59,6 +59,7 @@ describe('DateRangeFilterComponent', () => { it('should get on option change', async () => { spyOn(service, 'getDateRange'); + spyOn(component.dateTypeChange, 'emit'); const stateElement = fixture.debugElement.nativeElement.querySelector('[data-automation-id="adf-cloud-edit-process-property-createdDate"] .mat-select-trigger'); stateElement.click(); fixture.detectChanges(); @@ -67,32 +68,27 @@ describe('DateRangeFilterComponent', () => { options[2].nativeElement.click(); fixture.detectChanges(); await fixture.whenStable(); - expect(service.getDateRange).toHaveBeenCalled(); + expect(service.getDateRange).not.toHaveBeenCalled(); + expect(component.dateTypeChange.emit).toHaveBeenCalled(); }); it('should reset date range when no_date type is selected', () => { - spyOn(component.dateChanged, 'emit'); - const value = { value: DateCloudFilterType.NO_DATE }; - component.onSelectionChange(value); const expectedDate = { startDate: null, endDate: null }; - expect(component.dateChanged.emit).toHaveBeenCalledWith(expectedDate); + expect(service.getDateRange(DateCloudFilterType.NO_DATE)).toEqual(expectedDate); }); - it('should emit date range when any type is selected', () => { - spyOn(component.dateChanged, 'emit'); - const value = { value: DateCloudFilterType.TOMORROW }; - component.onSelectionChange(value); + it('should return correct date when any type is selected', () => { const expectedDate = { startDate: moment().endOf('day').toDate(), endDate: moment().add(1, 'days').startOf('day').toDate() }; - expect(component.dateChanged.emit).toHaveBeenCalledWith(expectedDate); + expect(service.getDateRange(DateCloudFilterType.TOMORROW)).toEqual(expectedDate); }); - it('should not emit any date change events when range type is selected', () => { + it('should not emit any date change events when any type is selected', () => { spyOn(component.dateChanged, 'emit'); const value = { value: DateCloudFilterType.RANGE }; component.onSelectionChange(value); @@ -105,10 +101,6 @@ describe('DateRangeFilterComponent', () => { expect(component.dateChanged.emit).toHaveBeenCalled(); }); - it('should throw error no supported type is selected', () => { - expect(function () { service.getDateRange(null); } ).toThrow(new Error('ADF_CLOUD_EDIT_PROCESS_FILTER.ERROR.INVALID_DATE_FILTER')); - }); - it('should show date-range picker when type is range', async () => { const value = { value: DateCloudFilterType.RANGE }; component.onSelectionChange(value); @@ -117,4 +109,29 @@ describe('DateRangeFilterComponent', () => { const rangePickerElement = fixture.debugElement.nativeElement.querySelector('.adf-cloud-date-range-picker'); expect(rangePickerElement).not.toBeNull(); }); + + it('should preselect values if filterProperty has attribute', () => { + const mockFilterProperty = { + key: 'createdDate', + label: 'mock-filter', + value: { + createdDateType: DateCloudFilterType.RANGE, + _startFrom: new Date().toISOString(), + _startTo: new Date().toISOString() + }, + type: 'dateRange', + options: null, + attributes: { + dateType: 'createdDateType', + from: '_startFrom', + to: '_startTo' + } + }; + component.processFilterProperty = mockFilterProperty; + component.ngOnInit(); + fixture.detectChanges(); + + expect(component.dateRangeForm.get('from').value).toEqual(moment(mockFilterProperty.value._startFrom)); + expect(component.dateRangeForm.get('to').value).toEqual(moment(mockFilterProperty.value._startTo)); + }); }); diff --git a/lib/process-services-cloud/src/lib/common/date-range-filter/date-range-filter.component.ts b/lib/process-services-cloud/src/lib/common/date-range-filter/date-range-filter.component.ts index 94a28b0a84..70ebe4700b 100644 --- a/lib/process-services-cloud/src/lib/common/date-range-filter/date-range-filter.component.ts +++ b/lib/process-services-cloud/src/lib/common/date-range-filter/date-range-filter.component.ts @@ -19,18 +19,8 @@ import { Component, Input, EventEmitter, Output } from '@angular/core'; import { MatSelectChange } from '@angular/material/select'; import { ProcessFilterProperties, ProcessFilterOptions } from '../../process/process-filters/models/process-filter-cloud.model'; import { FormGroup, FormControl } from '@angular/forms'; -import { DateRangeFilterService } from './date-range-filter.service'; import { DateRangeFilter, DateCloudFilterType } from '../../models/date-cloud-filter.model'; - -const DEFAULT_DATE_RANGE_OPTIONS = [ - DateCloudFilterType.NO_DATE, - DateCloudFilterType.TODAY, - DateCloudFilterType.WEEK, - DateCloudFilterType.MONTH, - DateCloudFilterType.QUARTER, - DateCloudFilterType.YEAR, - DateCloudFilterType.RANGE -]; +import moment from 'moment-es6'; @Component({ selector: 'adf-cloud-date-range-filter', @@ -43,11 +33,14 @@ const DEFAULT_DATE_RANGE_OPTIONS = [ processFilterProperty: ProcessFilterProperties; @Input() - options: DateCloudFilterType[] = DEFAULT_DATE_RANGE_OPTIONS; + options: DateCloudFilterType[]; @Output() dateChanged = new EventEmitter(); + @Output() + dateTypeChange = new EventEmitter(); + type: DateCloudFilterType; filteredProperties: ProcessFilterOptions[] = []; dateRangeForm = new FormGroup({ @@ -55,19 +48,18 @@ const DEFAULT_DATE_RANGE_OPTIONS = [ to: new FormControl() }); - constructor(private dateRangeFilterService: DateRangeFilterService) {} - ngOnInit() { + this.options = this.options ? this.options : this.createDefaultRangeOptions(); const defaultProperties = this.createDefaultDateOptions(); this.filteredProperties = defaultProperties.filter((filterProperty: ProcessFilterOptions) => this.isValidProperty(this.options, filterProperty)); + if (this.hasPreselectedValues()) { + this.setPreselectedValues(); + } } onSelectionChange(option: MatSelectChange) { this.type = option.value; - const dateRange = this.dateRangeFilterService.getDateRange(this.type); - if (!this.isDateRangeType()) { - this.dateChanged.emit(dateRange); - } + this.dateTypeChange.emit(this.type); } isDateRangeType(): boolean { @@ -82,10 +74,44 @@ const DEFAULT_DATE_RANGE_OPTIONS = [ this.dateChanged.emit(dateRange); } + private hasPreselectedValues() { + return !!this.processFilterProperty?.attributes && !!this.processFilterProperty?.value; + } + + private setPreselectedValues() { + const from = this.getFilterAttribute('from'); + const to = this.getFilterAttribute('to'); + const type = this.getFilterAttribute('dateType'); + + this.dateRangeForm.get('from').setValue(moment(this.getFilterValue(from))); + this.dateRangeForm.get('to').setValue(moment(this.getFilterValue(to))); + this.type = this.getFilterValue(type); + } + + private getFilterAttribute(key: string): string { + return this.processFilterProperty.attributes[key]; + } + + private getFilterValue(attribute: string) { + return this.processFilterProperty.value[attribute]; + } + private isValidProperty(filterProperties: string[], filterProperty: any): boolean { return filterProperties ? filterProperties.indexOf(filterProperty.value) >= 0 : true; } + private createDefaultRangeOptions(): DateCloudFilterType[] { + return [ + DateCloudFilterType.NO_DATE, + DateCloudFilterType.TODAY, + DateCloudFilterType.WEEK, + DateCloudFilterType.MONTH, + DateCloudFilterType.QUARTER, + DateCloudFilterType.YEAR, + DateCloudFilterType.RANGE + ]; + } + private createDefaultDateOptions(): ProcessFilterOptions[] { return [ { diff --git a/lib/process-services-cloud/src/lib/common/date-range-filter/date-range-filter.service.spec.ts b/lib/process-services-cloud/src/lib/common/date-range-filter/date-range-filter.service.spec.ts index a1ccaf391f..a925ad528a 100644 --- a/lib/process-services-cloud/src/lib/common/date-range-filter/date-range-filter.service.spec.ts +++ b/lib/process-services-cloud/src/lib/common/date-range-filter/date-range-filter.service.spec.ts @@ -86,8 +86,4 @@ describe('Date Range Filter service', () => { }; expect(service.getDateRange(DateCloudFilterType.NEXT_7_DAYS)).toEqual(expectedDate); }); - - it('should throw error no supported type is selected', () => { - expect(function () { service.getDateRange(null); } ).toThrow(new Error('ADF_CLOUD_EDIT_PROCESS_FILTER.ERROR.INVALID_DATE_FILTER')); - }); }); diff --git a/lib/process-services-cloud/src/lib/common/date-range-filter/date-range-filter.service.ts b/lib/process-services-cloud/src/lib/common/date-range-filter/date-range-filter.service.ts index d25feded19..e80abfa761 100644 --- a/lib/process-services-cloud/src/lib/common/date-range-filter/date-range-filter.service.ts +++ b/lib/process-services-cloud/src/lib/common/date-range-filter/date-range-filter.service.ts @@ -35,12 +35,14 @@ export class DateRangeFilterService { case DateCloudFilterType.MONTH: return this.getCurrentMonthDateRange(); case DateCloudFilterType.QUARTER: return this.getQuarterDateRange(); case DateCloudFilterType.YEAR: return this.getCurrentYearDateRange(); - case DateCloudFilterType.RANGE: return this.resetDateRange(); - case DateCloudFilterType.NO_DATE: return this.resetDateRange(); - default: throw new Error('ADF_CLOUD_EDIT_PROCESS_FILTER.ERROR.INVALID_DATE_FILTER'); + default: return this.resetDateRange(); } } + isDateRangeType(type: DateCloudFilterType) { + return type === DateCloudFilterType.RANGE; + } + private resetDateRange(): DateRangeFilter { return { startDate: null, diff --git a/lib/process-services-cloud/src/lib/i18n/en.json b/lib/process-services-cloud/src/lib/i18n/en.json index 2fa53f8f0d..551ce964be 100644 --- a/lib/process-services-cloud/src/lib/i18n/en.json +++ b/lib/process-services-cloud/src/lib/i18n/en.json @@ -10,6 +10,7 @@ "CREATED": "Created", "STATUS": "Status", "START_DATE": "Start Date", + "COMPLETED_DATE": "Completed Date", "ID": "Id", "INITIATOR": "Initiator", "APP_NAME": "Application Name", @@ -167,7 +168,8 @@ "LAST_MODIFIED_TO": "LastModifiedTo", "PROCESS_NAME": "Process Name", "APP_VERSION": "AppReleaseVersion", - "CREATED_DATE": "Created Date", + "STARTED_DATE": "Started Date", + "COMPLETED_DATE": "Completed Date", "DATE_RANGE": { "NO_DATE": "No Date", "TODAY": "Today", diff --git a/lib/process-services-cloud/src/lib/process/process-filters/components/edit-process-filter-cloud.component.html b/lib/process-services-cloud/src/lib/process/process-filters/components/edit-process-filter-cloud.component.html index 7c07181735..5625a9e62b 100644 --- a/lib/process-services-cloud/src/lib/process/process-filters/components/edit-process-filter-cloud.component.html +++ b/lib/process-services-cloud/src/lib/process/process-filters/components/edit-process-filter-cloud.component.html @@ -66,8 +66,11 @@ + diff --git a/lib/process-services-cloud/src/lib/process/process-filters/components/edit-process-filter-cloud.component.spec.ts b/lib/process-services-cloud/src/lib/process/process-filters/components/edit-process-filter-cloud.component.spec.ts index b1926625e2..8065aae60d 100644 --- a/lib/process-services-cloud/src/lib/process/process-filters/components/edit-process-filter-cloud.component.spec.ts +++ b/lib/process-services-cloud/src/lib/process/process-filters/components/edit-process-filter-cloud.component.spec.ts @@ -37,6 +37,7 @@ import { PROCESS_FILTERS_SERVICE_TOKEN } from '../../../services/cloud-token.ser import { LocalPreferenceCloudService } from '../../../services/local-preference-cloud.service'; import { TranslateModule } from '@ngx-translate/core'; import { ProcessCloudService } from '../../services/process-cloud.service'; +import { DateCloudFilterType } from '../../../models/date-cloud-filter.model'; describe('EditProcessFilterCloudComponent', () => { let component: EditProcessFilterCloudComponent; @@ -443,6 +444,21 @@ describe('EditProcessFilterCloudComponent', () => { }); })); + it('should get form attributes', async() => { + fixture.detectChanges(); + component.filterProperties = ['appName', 'completedDateRange']; + fixture.detectChanges(); + const processFilterIdChange = new SimpleChange(null, 'mock-process-filter-id', true); + component.ngOnChanges({ 'id': processFilterIdChange }); + fixture.detectChanges(); + fixture.whenStable().then(() => { + fixture.detectChanges(); + expect(component.editProcessFilterForm.get('_completedFrom')).toBeDefined(); + expect(component.editProcessFilterForm.get('_completedTo')).toBeDefined(); + expect(component.editProcessFilterForm.get('completedDateType')).toBeDefined(); + }); + }); + it('should able to build a editProcessFilter form with default properties if input is empty', async(() => { fixture.detectChanges(); component.filterProperties = []; @@ -767,6 +783,64 @@ describe('EditProcessFilterCloudComponent', () => { component.onFilterChange(); }); + it('should set the correct started date range when date range option is changed', (done) => { + component.appName = 'fake'; + component.filterProperties = ['appName', 'processInstanceId', 'priority', 'completedDateRange']; + const taskFilterIdChange = new SimpleChange(undefined, 'mock-task-filter-id', true); + component.ngOnChanges({ 'id': taskFilterIdChange }); + fixture.detectChanges(); + + const startedDateTypeControl: AbstractControl = component.editProcessFilterForm.get('completedDateType'); + startedDateTypeControl.setValue(DateCloudFilterType.TODAY); + const dateFilter = { + startFrom: moment().startOf('day').toDate(), + startTo: moment().endOf('day').toDate() + }; + + component.filterChange.subscribe(() => { + expect(component.changedProcessFilter.completedFrom).toEqual(dateFilter.startFrom.toISOString()); + expect(component.changedProcessFilter.completedTo).toEqual(dateFilter.startTo.toISOString()); + done(); + }); + component.onFilterChange(); + }); + + it('should update form on date range value is updated', (done) => { + component.appName = 'fake'; + component.filterProperties = ['appName', 'processInstanceId', 'priority', 'completedDateRange']; + const taskFilterIdChange = new SimpleChange(undefined, 'mock-task-filter-id', true); + component.ngOnChanges({ 'id': taskFilterIdChange }); + fixture.detectChanges(); + + const dateFilter = { + startDate: moment().startOf('day').toDate(), + endDate: moment().endOf('day').toDate() + }; + + const startedDateTypeControl: AbstractControl = component.editProcessFilterForm.get('completedDateType'); + startedDateTypeControl.setValue(DateCloudFilterType.RANGE); + + component.onDateRangeFilterChanged(dateFilter, { + key: 'completedDateRange', + label: '', + type: 'date-range', + value: '', + attributes: { + dateType: 'completedDateType', + from: '_completedFrom', + to: '_completedTo' + } + }); + + fixture.detectChanges(); + component.filterChange.subscribe(() => { + expect(component.changedProcessFilter.completedFrom).toEqual(dateFilter.startDate.toISOString()); + expect(component.changedProcessFilter.completedTo).toEqual(dateFilter.endDate.toISOString()); + done(); + }); + component.onFilterChange(); + }); + it('should call restore default filters service on deletion of last filter', (done) => { component.toggleFilterActions = true; const deleteFilterSpy = spyOn(service, 'deleteFilter').and.returnValue(of([])); diff --git a/lib/process-services-cloud/src/lib/process/process-filters/components/edit-process-filter-cloud.component.ts b/lib/process-services-cloud/src/lib/process/process-filters/components/edit-process-filter-cloud.component.ts index bb9d128ffa..2c05e5551a 100644 --- a/lib/process-services-cloud/src/lib/process/process-filters/components/edit-process-filter-cloud.component.ts +++ b/lib/process-services-cloud/src/lib/process/process-filters/components/edit-process-filter-cloud.component.ts @@ -32,7 +32,7 @@ import { ProcessFilterDialogCloudComponent } from './process-filter-dialog-cloud import { ApplicationInstanceModel } from '../../../app/models/application-instance.model'; import { ProcessCloudService } from '../../services/process-cloud.service'; import { ProcessDefinitionCloud } from '../../../models/process-definition-cloud.model'; -import { DateRangeFilter } from '../../../models/date-cloud-filter.model'; +import { DateCloudFilterType, DateRangeFilter } from '../../../models/date-cloud-filter.model'; @Component({ selector: 'adf-cloud-edit-process-filter', @@ -165,18 +165,22 @@ export class EditProcessFilterCloudComponent implements OnInit, OnChanges, OnDes getFormControlsConfig(processFilterProperties: ProcessFilterProperties[]): any { const properties = processFilterProperties.map((property: ProcessFilterProperties) => { - if (!property.rangeKeys) { - return { [property.key]: property.value }; + if (!!property.attributes) { + return this.getAttributesControlConfig(property); } else { - return { - [property.rangeKeys.from]: property.value[property.rangeKeys.from], - [property.rangeKeys.to]: property.value[property.rangeKeys.to] - }; + return { [property.key]: property.value }; } }); return properties.reduce(((result, current) => Object.assign(result, current)), {}); } + private getAttributesControlConfig(property: ProcessFilterProperties) { + return Object.values(property.attributes).reduce((result, key) => { + result[key] = property.value[key]; + return result; + }, {}); + } + /** * Fetches process instance filter by application name and filter id and creates filter properties, build form */ @@ -316,6 +320,19 @@ export class EditProcessFilterCloudComponent implements OnInit, OnChanges, OnDes } } + onDateTypeChange(dateType: DateCloudFilterType, property: ProcessFilterProperties) { + this.editProcessFilterForm.get(property.attributes.dateType).setValue(dateType); + } + + onDateRangeFilterChanged(dateRange: DateRangeFilter, property: ProcessFilterProperties) { + this.editProcessFilterForm.get(property.attributes?.from).setValue( + dateRange.startDate ? dateRange.startDate.toISOString() : null + ); + this.editProcessFilterForm.get(property.attributes?.to).setValue( + dateRange.endDate ? dateRange.endDate.toISOString() : null + ); + } + hasError(property: ProcessFilterProperties): boolean { return this.getPropertyController(property).errors && this.getPropertyController(property).errors.invalid; } @@ -455,15 +472,6 @@ export class EditProcessFilterCloudComponent implements OnInit, OnChanges, OnDes this.toggleFilterActions = false; } - onDateRangeFilterChanged(dateRange: DateRangeFilter, property: ProcessFilterProperties) { - this.editProcessFilterForm.get(property.rangeKeys.from).setValue( - dateRange.startDate ? dateRange.startDate.toISOString() : null - ); - this.editProcessFilterForm.get(property.rangeKeys.to).setValue( - dateRange.endDate ? dateRange.endDate.toISOString() : null - ); - } - isDateType(property: ProcessFilterProperties): boolean { return property.type === 'date'; } @@ -605,6 +613,11 @@ export class EditProcessFilterCloudComponent implements OnInit, OnChanges, OnDes key: 'processDefinitionId', value: 'processDefinitionId' }, + { + label: 'ADF_CLOUD_EDIT_PROCESS_FILTER.LABEL.PROCESS_DEF_NAME', + key: 'processDefinitionName', + value: 'processDefinitionName' + }, { label: 'ADF_CLOUD_EDIT_PROCESS_FILTER.LABEL.PROCESS_DEF_KEY', key: 'processDefinitionKey', @@ -697,13 +710,31 @@ export class EditProcessFilterCloudComponent implements OnInit, OnChanges, OnDes options: this.directions }), new ProcessFilterProperties({ - label: 'ADF_CLOUD_EDIT_TASK_FILTER.LABEL.START_DATE', + label: 'ADF_CLOUD_EDIT_PROCESS_FILTER.LABEL.COMPLETED_DATE', + type: 'date', + key: 'completedDate', + value: currentProcessFilter.completedDate || false + }), + new ProcessFilterProperties({ + label: 'ADF_CLOUD_EDIT_PROCESS_FILTER.LABEL.COMPLETED_DATE', type: 'date-range', - key: 'startDateRange', - rangeKeys: { from: 'startFrom', to: 'startTo'}, - values: { - from: currentProcessFilter.startFrom || null, - to: currentProcessFilter.startTo || null + key: 'completedDateRange', + attributes: { dateType: 'completedDateType', from: '_completedFrom', to: '_completedTo'}, + value: { + completedDateType: currentProcessFilter.completedDateType || null, + _completedFrom: currentProcessFilter.completedFrom || null, + _completedTo: currentProcessFilter.completedTo || null + } + }), + new ProcessFilterProperties({ + label: 'ADF_CLOUD_EDIT_PROCESS_FILTER.LABEL.STARTED_DATE', + type: 'date-range', + key: 'startedDateRange', + attributes: { dateType: 'startedDateType', from: '_startFrom', to: '_startTo'}, + value: { + startedDateType: currentProcessFilter.startedDateType || null, + _startFrom: currentProcessFilter.startFrom || null, + _startTo: currentProcessFilter.startTo || null } }) ]; diff --git a/lib/process-services-cloud/src/lib/process/process-filters/models/process-filter-cloud.model.ts b/lib/process-services-cloud/src/lib/process/process-filters/models/process-filter-cloud.model.ts index 94501af69a..641c6b7756 100644 --- a/lib/process-services-cloud/src/lib/process/process-filters/models/process-filter-cloud.model.ts +++ b/lib/process-services-cloud/src/lib/process/process-filters/models/process-filter-cloud.model.ts @@ -14,9 +14,13 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { DateCloudFilterType, RangeKeys } from '../../../models/date-cloud-filter.model'; +import { DateCloudFilterType } from '../../../models/date-cloud-filter.model'; +import { DateRangeFilterService } from '../../../common/date-range-filter/date-range-filter.service'; export class ProcessFilterCloudModel { + + private dateRangeFilterService = new DateRangeFilterService(); + id: string; name: string; key: string; @@ -37,8 +41,14 @@ export class ProcessFilterCloudModel { lastModifiedTo: Date; lastModifiedFrom: Date; startedDate: Date; - startFrom: Date; - startTo: Date; + completedDateType: DateCloudFilterType; + startedDateType: DateCloudFilterType; + completedDate: Date; + + private _completedFrom: string; + private _completedTo: string; + private _startFrom: string; + private _startTo: string; constructor(obj?: any) { if (obj) { @@ -62,10 +72,71 @@ export class ProcessFilterCloudModel { this.lastModifiedTo = obj.lastModifiedTo || null; this.lastModifiedFrom = obj.lastModifiedFrom || null; this.startedDate = obj.startedDate || null; - this.startFrom = obj.startFrom || null; - this.startTo = obj.startTo || null; + this.startFrom = obj._startFrom || null; + this.startTo = obj._startTo || null; + this.completedDateType = obj.completedDateType || null; + this.startedDateType = obj.startedDateType || null; + this.completedFrom = obj._completedFrom || null; + this.completedTo = obj._completedTo || null; + this.completedDate = obj.completedDate || null; } } + + set completedFrom(completedFrom: string) { + this._completedFrom = completedFrom; + } + + set completedTo(completedTo: string) { + this._completedTo = completedTo; + } + + get completedFrom() { + if (this.isDateRangeType(this.completedDateType)) { + return this._completedFrom; + } + return this.getStartDate(this.completedDateType); + } + + get completedTo() { + if (this.isDateRangeType(this.completedDateType)) { + return this._completedTo; + } + return this.getEndDate(this.completedDateType); + } + + set startFrom(startFrom: string) { + this._startFrom = startFrom; + } + + set startTo(startTo: string) { + this._startTo = startTo; + } + + get startFrom() { + if (this.isDateRangeType(this.startedDateType)) { + return this._startFrom; + } + return this.getStartDate(this.startedDateType); + } + + get startTo() { + if (this.isDateRangeType(this.startedDateType)) { + return this._startTo; + } + return this.getEndDate(this.startedDateType); + } + + private getStartDate(key: DateCloudFilterType) { + return this.dateRangeFilterService.getDateRange(key).startDate?.toISOString(); + } + + private getEndDate(key: DateCloudFilterType) { + return this.dateRangeFilterService.getDateRange(key).endDate?.toISOString(); + } + + private isDateRangeType(type: DateCloudFilterType) { + return !!this.dateRangeFilterService.isDateRangeType(type); + } } export class ProcessFilterAction { @@ -86,16 +157,16 @@ export class ProcessFilterAction { export interface ProcessFilterOptions { label?: string; - value?: string; + value?: string | object; } export class ProcessFilterProperties { label: string; type: string; - value: string; + value: string | object; key: string; - options: ProcessFilterOptions[]; - rangeKeys?: RangeKeys; + attributes?: { [key: string]: string; }; + options?: ProcessFilterOptions[]; dateFilterOptions?: DateCloudFilterType[]; constructor(obj?: any) { @@ -104,15 +175,15 @@ export class ProcessFilterProperties { this.type = obj.type || null; this.value = obj.value || ''; this.key = obj.key || null; + this.attributes = obj.attributes || null; this.options = obj.options || null; - this.rangeKeys = obj.rangeKeys || null; - this.dateFilterOptions = obj.dateFilterOptions || []; + this.dateFilterOptions = obj.dateFilterOptions || null; } } } export interface ProcessSortFilterProperties { label: string; - value: string; + value: string | object; key: string; } diff --git a/lib/process-services-cloud/src/lib/process/process-filters/services/process-filter-cloud.service.spec.ts b/lib/process-services-cloud/src/lib/process/process-filters/services/process-filter-cloud.service.spec.ts index 53882a1fd7..2992de3788 100644 --- a/lib/process-services-cloud/src/lib/process/process-filters/services/process-filter-cloud.service.spec.ts +++ b/lib/process-services-cloud/src/lib/process/process-filters/services/process-filter-cloud.service.spec.ts @@ -24,6 +24,7 @@ import { LocalPreferenceCloudService } from '../../../services/local-preference- import { ProcessServiceCloudTestingModule } from '../../../testing/process-service-cloud.testing.module'; import { TranslateModule } from '@ngx-translate/core'; import { ProcessFilterCloudModel } from '../models/process-filter-cloud.model'; +import { DateCloudFilterType } from 'process-services-cloud/src/lib/models/date-cloud-filter.model'; describe('ProcessFilterCloudService', () => { let service: ProcessFilterCloudService; @@ -40,7 +41,7 @@ describe('ProcessFilterCloudService', () => { email: 'fakeIdentity@email.com' }; - const fakeProcessFilter: ProcessFilterCloudModel = { + const fakeProcessFilter: ProcessFilterCloudModel = new ProcessFilterCloudModel({ name: 'MOCK_PROCESS_NAME_1', id: '1', key: 'all-mock-process', @@ -59,10 +60,14 @@ describe('ProcessFilterCloudService', () => { lastModified: null, lastModifiedTo: null, lastModifiedFrom: null, + completedDateType: DateCloudFilterType.NO_DATE, + startedDateType: DateCloudFilterType.NO_DATE, + _completedFrom: null, + _completedTo: null, startedDate: null, - startFrom: null, - startTo: null - }; + _startFrom: null, + _startTo: null + }); const fakeProcessCloudFilterEntries = { list: { diff --git a/lib/process-services-cloud/src/lib/process/process-list/components/process-list-cloud.component.ts b/lib/process-services-cloud/src/lib/process/process-list/components/process-list-cloud.component.ts index 8f48fa2180..f2dd082302 100644 --- a/lib/process-services-cloud/src/lib/process/process-list/components/process-list-cloud.component.ts +++ b/lib/process-services-cloud/src/lib/process/process-list/components/process-list-cloud.component.ts @@ -99,6 +99,18 @@ export class ProcessListCloudComponent extends DataTableSchema implements OnChan @Input() startTo: string = ''; + /** Filter the processes. Display only process with completedFrom equal to the supplied date. */ + @Input() + completedFrom: string = ''; + + /** Filter the processes. Display only process with completedTo equal to the supplied date. */ + @Input() + completedTo: string = ''; + + /** Filter the processes. Display only process with completedDate equal to the supplied date. */ + @Input() + completedDate: string = ''; + /** * Row selection mode. Can be "none", "single" or "multiple". * For multiple mode, you can use Cmd (macOS) or Ctrl (Win) modifier @@ -328,6 +340,9 @@ export class ProcessListCloudComponent extends DataTableSchema implements OnChan lastModifiedTo: this.lastModifiedTo, startFrom: this.startFrom, startTo: this.startTo, + completedFrom: this.completedFrom, + completedTo: this.completedTo, + completedDate: this.completedDate, sorting: this.sorting }; return new ProcessQueryCloudRequestModel(requestNode); diff --git a/lib/process-services-cloud/src/lib/process/process-list/models/process-cloud-query-request.model.ts b/lib/process-services-cloud/src/lib/process/process-list/models/process-cloud-query-request.model.ts index fbc6d983d0..68193c70e6 100644 --- a/lib/process-services-cloud/src/lib/process/process-list/models/process-cloud-query-request.model.ts +++ b/lib/process-services-cloud/src/lib/process/process-list/models/process-cloud-query-request.model.ts @@ -34,6 +34,9 @@ export class ProcessQueryCloudRequestModel { lastModifiedFrom?: string; startFrom?: string; startTo?: string; + completedFrom?: string; + completedTo?: string; + completedDate?: string; maxItems: number; skipCount: number; sorting?: ProcessListCloudSortingModel[]; @@ -55,6 +58,9 @@ export class ProcessQueryCloudRequestModel { this.lastModifiedFrom = obj.lastModifiedFrom; this.startFrom = obj.startFrom; this.startTo = obj.startTo; + this.completedFrom = obj.completedFrom; + this.completedTo = obj.completedTo; + this.completedDate = obj.completedDate; this.maxItems = obj.maxItems; this.skipCount = obj.skipCount; this.sorting = obj.sorting; diff --git a/lib/process-services-cloud/src/lib/task/task-filters/components/edit-task-filter-cloud.component.html b/lib/process-services-cloud/src/lib/task/task-filters/components/edit-task-filter-cloud.component.html index 050cff08f9..29f4c5da44 100644 --- a/lib/process-services-cloud/src/lib/task/task-filters/components/edit-task-filter-cloud.component.html +++ b/lib/process-services-cloud/src/lib/task/task-filters/components/edit-task-filter-cloud.component.html @@ -71,6 +71,7 @@ diff --git a/lib/process-services-cloud/src/lib/task/task-filters/components/edit-task-filter-cloud.component.spec.ts b/lib/process-services-cloud/src/lib/task/task-filters/components/edit-task-filter-cloud.component.spec.ts index 15f340cfb7..6a7db9bc3a 100644 --- a/lib/process-services-cloud/src/lib/task/task-filters/components/edit-task-filter-cloud.component.spec.ts +++ b/lib/process-services-cloud/src/lib/task/task-filters/components/edit-task-filter-cloud.component.spec.ts @@ -37,6 +37,7 @@ import { fakeFilter } from '../mock/task-filters-cloud.mock'; import { AbstractControl } from '@angular/forms'; import moment from 'moment-es6'; import { TranslateModule } from '@ngx-translate/core'; +import { DateCloudFilterType } from '../../../models/date-cloud-filter.model'; describe('EditTaskFilterCloudComponent', () => { let component: EditTaskFilterCloudComponent; @@ -467,6 +468,64 @@ describe('EditTaskFilterCloudComponent', () => { expect(appController.value).toBe('mock-app-name'); }); })); + + it('should set the correct started date range when date range option is changed', (done) => { + component.appName = 'fake'; + component.filterProperties = ['appName', 'processInstanceId', 'priority', 'dueDateRange']; + const taskFilterIdChange = new SimpleChange(undefined, 'mock-task-filter-id', true); + component.ngOnChanges({ 'id': taskFilterIdChange }); + fixture.detectChanges(); + + const startedDateTypeControl: AbstractControl = component.editTaskFilterForm.get('dueDateType'); + startedDateTypeControl.setValue(DateCloudFilterType.TODAY); + const dateFilter = { + startFrom: moment().startOf('day').toDate(), + startTo: moment().endOf('day').toDate() + }; + + component.filterChange.subscribe(() => { + expect(component.changedTaskFilter.dueDateFrom).toEqual(dateFilter.startFrom.toISOString()); + expect(component.changedTaskFilter.dueDateTo).toEqual(dateFilter.startTo.toISOString()); + done(); + }); + component.onFilterChange(); + }); + + it('should update form on date range value is updated', (done) => { + component.appName = 'fake'; + component.filterProperties = ['appName', 'processInstanceId', 'priority', 'dueDateRange']; + const taskFilterIdChange = new SimpleChange(undefined, 'mock-task-filter-id', true); + component.ngOnChanges({ 'id': taskFilterIdChange }); + fixture.detectChanges(); + + const dateFilter = { + startDate: moment().startOf('day').toDate(), + endDate: moment().endOf('day').toDate() + }; + + const startedDateTypeControl: AbstractControl = component.editTaskFilterForm.get('dueDateType'); + startedDateTypeControl.setValue(DateCloudFilterType.RANGE); + + component.onDateRangeFilterChanged(dateFilter, { + key: 'dueDateRange', + label: '', + type: 'date-range', + value: '', + attributes: { + dateType: 'dueDateType', + from: '_dueDateFrom', + to: '_dueDateTo' + } + }); + + fixture.detectChanges(); + component.filterChange.subscribe(() => { + expect(component.changedTaskFilter.dueDateFrom).toEqual(dateFilter.startDate.toISOString()); + expect(component.changedTaskFilter.dueDateTo).toEqual(dateFilter.endDate.toISOString()); + done(); + }); + component.onFilterChange(); + }); }); describe('sort properties', () => { diff --git a/lib/process-services-cloud/src/lib/task/task-filters/components/edit-task-filter-cloud.component.ts b/lib/process-services-cloud/src/lib/task/task-filters/components/edit-task-filter-cloud.component.ts index a95afb221a..803c0ec99f 100644 --- a/lib/process-services-cloud/src/lib/task/task-filters/components/edit-task-filter-cloud.component.ts +++ b/lib/process-services-cloud/src/lib/task/task-filters/components/edit-task-filter-cloud.component.ts @@ -170,18 +170,22 @@ export class EditTaskFilterCloudComponent implements OnInit, OnChanges, OnDestro getFormControlsConfig(taskFilterProperties: TaskFilterProperties[]): any { const properties = taskFilterProperties.map((property: TaskFilterProperties) => { - if (!property.rangeKeys) { - return { [property.key]: property.value }; + if (!!property.attributes) { + return this.getAttributesControlConfig(property); } else { - return { - [property.rangeKeys.from]: property.value[property.rangeKeys.from], - [property.rangeKeys.to]: property.value[property.rangeKeys.to] - }; + return { [property.key]: property.value }; } }); return properties.reduce(((result, current) => Object.assign(result, current)), {}); } + private getAttributesControlConfig(property: TaskFilterProperties) { + return Object.values(property.attributes).reduce((result, key) => { + result[key] = property.value[key]; + return result; + }, {}); + } + /** * Check for edit task filter form changes */ @@ -335,11 +339,15 @@ export class EditTaskFilterCloudComponent implements OnInit, OnChanges, OnDestro } } + onDateTypeChange(dateType: DateCloudFilterType, property: TaskFilterProperties) { + this.editTaskFilterForm.get(property.attributes.dateType).setValue(dateType); + } + onDateRangeFilterChanged(dateRange: DateRangeFilter, property: TaskFilterProperties) { - this.editTaskFilterForm.get(property.rangeKeys.from).setValue( + this.editTaskFilterForm.get(property.attributes?.from).setValue( dateRange.startDate ? dateRange.startDate.toISOString() : null ); - this.editTaskFilterForm.get(property.rangeKeys.to).setValue( + this.editTaskFilterForm.get(property.attributes?.to).setValue( dateRange.endDate ? dateRange.endDate.toISOString() : null ); } @@ -669,8 +677,12 @@ export class EditTaskFilterCloudComponent implements OnInit, OnChanges, OnDestro label: 'ADF_CLOUD_EDIT_TASK_FILTER.LABEL.DUE_DATE', type: 'date-range', key: 'dueDateRange', - rangeKeys: { from: 'dueDateFrom', to: 'dueDateTo'}, - value: currentTaskFilter.dueDate || false, + attributes: { dateType: 'dueDateType', from: '_dueDateFrom', to: '_dueDateTo'}, + value: { + dueDateType: currentTaskFilter.dueDateType || null, + _dueDateFrom: currentTaskFilter.dueDateFrom || null, + _dueDateTo: currentTaskFilter.dueDateTo || null + }, dateFilterOptions: [ DateCloudFilterType.NO_DATE, DateCloudFilterType.TODAY, diff --git a/lib/process-services-cloud/src/lib/task/task-filters/models/filter-cloud.model.ts b/lib/process-services-cloud/src/lib/task/task-filters/models/filter-cloud.model.ts index f42889f063..7911c1912c 100644 --- a/lib/process-services-cloud/src/lib/task/task-filters/models/filter-cloud.model.ts +++ b/lib/process-services-cloud/src/lib/task/task-filters/models/filter-cloud.model.ts @@ -15,7 +15,8 @@ * limitations under the License. */ -import { DateCloudFilterType, RangeKeys } from '../../../models/date-cloud-filter.model'; +import { DateCloudFilterType } from '../../../models/date-cloud-filter.model'; +import { DateRangeFilterService } from '../../../common/date-range-filter/date-range-filter.service'; export class TaskFilterCloudModel { id: string; @@ -33,9 +34,8 @@ export class TaskFilterCloudModel { processDefinitionId: string; processInstanceId: string; createdDate: Date; + dueDateType: DateCloudFilterType; dueDate: Date; - dueDateFrom: string; - dueDateTo: string; taskName: string; taskId: string; parentTaskId: string; @@ -44,6 +44,10 @@ export class TaskFilterCloudModel { lastModifiedFrom: Date; lastModifiedTo: Date; + private _dueDateFrom: string; + private _dueDateTo: string; + private dateRangeFilterService = new DateRangeFilterService(); + constructor(obj?: any) { if (obj) { this.id = obj.id || Math.random().toString(36).substr(2, 9); @@ -61,9 +65,10 @@ export class TaskFilterCloudModel { this.processDefinitionId = obj.processDefinitionId || null; this.processInstanceId = obj.processInstanceId || null; this.createdDate = obj.createdDate || null; + this.dueDateType = obj.dueDateType || null; this.dueDate = obj.dueDate || null; - this.dueDateFrom = obj.dueDateFrom || null; - this.dueDateTo = obj.dueDateTo || null; + this._dueDateFrom = obj._dueDateFrom || null; + this._dueDateTo = obj._dueDateTo || null; this.taskName = obj.taskName || null; this.taskId = obj.taskId || null; this.parentTaskId = obj.parentTaskId || null; @@ -73,6 +78,40 @@ export class TaskFilterCloudModel { this.lastModifiedTo = obj.lastModifiedTo || null; } } + + set dueDateFrom(dueDateFrom: string) { + this._dueDateFrom = dueDateFrom; + } + + set dueDateTo(dueDateTo: string) { + this._dueDateTo = dueDateTo; + } + + get dueDateFrom() { + if (this.isDateRangeType(this.dueDateType)) { + return this._dueDateFrom; + } + return this.getStartDate(this.dueDateType); + } + + get dueDateTo() { + if (this.isDateRangeType(this.dueDateType)) { + return this._dueDateTo; + } + return this.getEndDate(this.dueDateType); + } + + private getStartDate(key: DateCloudFilterType) { + return this.dateRangeFilterService.getDateRange(key).startDate?.toISOString(); + } + + private getEndDate(key: DateCloudFilterType) { + return this.dateRangeFilterService.getDateRange(key).endDate?.toISOString(); + } + + private isDateRangeType(type: DateCloudFilterType) { + return !!this.dateRangeFilterService.isDateRangeType(type); + } } export class FilterParamsModel { @@ -117,8 +156,8 @@ export class TaskFilterProperties { type: string; value: any; key: string; - rangeKeys?: RangeKeys; - options: FilterOptions[]; + attributes?: { [key: string]: string; }; + options?: FilterOptions[]; dateFilterOptions?: DateCloudFilterType[]; constructor(obj?: any) { @@ -127,7 +166,7 @@ export class TaskFilterProperties { this.type = obj.type || null; this.value = obj.value || ''; this.key = obj.key || null; - this.rangeKeys = obj.rangeKeys || null; + this.attributes = obj.attributes || null; this.options = obj.options || null; this.dateFilterOptions = obj.dateFilterOptions || null; } diff --git a/scripts/lint.sh b/scripts/lint.sh index 4ad7ba12c5..51eff7ea3f 100755 --- a/scripts/lint.sh +++ b/scripts/lint.sh @@ -3,7 +3,7 @@ DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" cd "$DIR/../" -if grep "envalfresco" . -R --exclude-dir={node_modules,.history,.idea,scripts,dist,e2e-output} --exclude={.env,.env.*}; then +if grep "envalfresco" . -R --exclude-dir={node_modules,.history,.idea,scripts,dist,e2e-output,.git} --exclude={.env,.env.*}; then echo not permitted word exit 1 fi