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 new file mode 100644 index 0000000000..9334d5561d --- /dev/null +++ b/lib/process-services-cloud/src/lib/common/date-range-filter/date-range-filter.component.html @@ -0,0 +1,26 @@ + + + + + {{ propertyOption.label | translate }} + + + + + + + {{ 'ADF_CLOUD_EDIT_PROCESS_FILTER.LABEL.DATE_RANGE_TITLE' | translate }} + + + + + + + + {{ '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.scss b/lib/process-services-cloud/src/lib/common/date-range-filter/date-range-filter.component.scss new file mode 100644 index 0000000000..213064fb20 --- /dev/null +++ b/lib/process-services-cloud/src/lib/common/date-range-filter/date-range-filter.component.scss @@ -0,0 +1,3 @@ +.adf-cloud-date-range-picker { + margin: 0 10px; +} 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 new file mode 100644 index 0000000000..239c834289 --- /dev/null +++ b/lib/process-services-cloud/src/lib/common/date-range-filter/date-range-filter.component.spec.ts @@ -0,0 +1,137 @@ +/*! + * @license + * Copyright 2019 Alfresco Software, Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { DateRangeFilterComponent } from './date-range-filter.component'; +import { ComponentFixture, TestBed, async } from '@angular/core/testing'; +import { setupTestBed } from 'core'; +import { TranslateModule } from '@ngx-translate/core'; +import { ProcessServiceCloudTestingModule } from '../../testing/process-service-cloud.testing.module'; +import { By } from '@angular/platform-browser'; +import { ProcessDateFilterType } from '../../process/process-filters/models/process-filter-cloud.model'; +import { MatSelectChange } from '@angular/material/select'; +import moment from 'moment-es6'; + +describe('DateRangeFilterComponent', () => { + let component: DateRangeFilterComponent; + let fixture: ComponentFixture; + + setupTestBed({ + imports: [ + TranslateModule.forRoot(), + ProcessServiceCloudTestingModule + ] + }); + + beforeEach(() => { + fixture = TestBed.createComponent(DateRangeFilterComponent); + component = fixture.componentInstance; + + component.processFilterProperty = { + key: 'createdDate', + label: 'mock-filter', + value: null, + type: 'dateRange', + options: null + }; + fixture.detectChanges(); + }); + + afterEach(() => { + fixture.destroy(); + }); + + it('should setDate on option change', async(() => { + spyOn(component, 'setDate'); + const stateElement = fixture.debugElement.nativeElement.querySelector('[data-automation-id="adf-cloud-edit-process-property-createdDate"] .mat-select-trigger'); + stateElement.click(); + fixture.detectChanges(); + + const options = fixture.debugElement.queryAll(By.css('.mat-option-text')); + options[2].nativeElement.click(); + fixture.detectChanges(); + fixture.whenStable().then(() => { + expect(component.setDate).toHaveBeenCalled(); + }); + })); + + it('should emit today range', () => { + spyOn(component.dateChanged, 'emit'); + const value = { value: ProcessDateFilterType.today }; + component.onSelectionChange(value); + const expectedDate = { + startDate: moment().startOf('day').toDate(), + endDate: moment().endOf('day').toDate() + }; + expect(component.dateChanged.emit).toHaveBeenCalledWith(expectedDate); + }); + + it('should emit month range', () => { + spyOn(component.dateChanged, 'emit'); + const value = { value: ProcessDateFilterType.month }; + component.onSelectionChange(value); + const expectedDate = { + startDate: moment().startOf('month').toDate(), + endDate: moment().endOf('month').toDate() + }; + expect(component.dateChanged.emit).toHaveBeenCalledWith(expectedDate); + }); + + it('should emit year range', () => { + spyOn(component.dateChanged, 'emit'); + const value = { value: ProcessDateFilterType.year }; + component.onSelectionChange(value); + const expectedDate = { + startDate: moment().startOf('year').toDate(), + endDate: moment().endOf('year').toDate() + }; + expect(component.dateChanged.emit).toHaveBeenCalledWith(expectedDate); + }); + + it('should emit quarter range', () => { + spyOn(component.dateChanged, 'emit'); + const value = { value: ProcessDateFilterType.quarter }; + component.onSelectionChange(value); + const currentDate = new Date(); + const quarter = Math.floor((currentDate.getMonth() / 3)); + const firstDate = new Date(currentDate.getFullYear(), quarter * 3, 1); + const expectedDate = { + startDate: firstDate, + endDate: new Date(firstDate.getFullYear(), firstDate.getMonth() + 3, 0) + }; + expect(component.dateChanged.emit).toHaveBeenCalledWith(expectedDate); + }); + + it('should reset date range when no type is selected', () => { + spyOn(component.dateChanged, 'emit'); + const value = { value: null }; + component.onSelectionChange(value); + const expectedDate = { + startDate: null, + endDate: null + }; + expect(component.dateChanged.emit).toHaveBeenCalledWith(expectedDate); + }); + + it('should show date-range picker when type is range', async () => { + const value = { value: ProcessDateFilterType.range }; + component.onSelectionChange(value); + fixture.detectChanges(); + await fixture.whenStable(); + const rangePickerElement = fixture.debugElement.nativeElement.querySelector('.adf-cloud-date-range-picker'); + expect(rangePickerElement).not.toBeNull(); + }); +}); 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 new file mode 100644 index 0000000000..7e8e8911b7 --- /dev/null +++ b/lib/process-services-cloud/src/lib/common/date-range-filter/date-range-filter.component.ts @@ -0,0 +1,158 @@ +/*! + * @license + * Copyright 2019 Alfresco Software, Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Component, Input, EventEmitter, Output } from '@angular/core'; +import { MatSelectChange } from '@angular/material/select'; +import moment from 'moment-es6'; +import { ProcessFilterProperties, DateRangeFilter, ProcessDateFilterType } from '../../process/process-filters/models/process-filter-cloud.model'; +import { FormGroup, FormControl } from '@angular/forms'; + +@Component({ + selector: 'adf-cloud-date-range-filter', + styleUrls: ['./date-range-filter.component.scss'], + templateUrl: './date-range-filter.component.html' + }) + export class DateRangeFilterComponent { + + @Input() + processFilterProperty: ProcessFilterProperties; + + @Output() + dateChanged = new EventEmitter(); + + type: ProcessDateFilterType; + currentDate = new Date(); + dateRange: DateRangeFilter = { + startDate: null, + endDate: null + }; + + dateRangeForm = new FormGroup({ + start: new FormControl(), + end: new FormControl() + }); + + options = [ + { + key: ProcessDateFilterType.today, + label: 'ADF_CLOUD_EDIT_PROCESS_FILTER.LABEL.DATE_RANGE.TODAY' + }, + { + key: ProcessDateFilterType.week, + label: 'ADF_CLOUD_EDIT_PROCESS_FILTER.LABEL.DATE_RANGE.WEEK' + }, + { + key: ProcessDateFilterType.month, + label: 'ADF_CLOUD_EDIT_PROCESS_FILTER.LABEL.DATE_RANGE.MONTH' + }, + { + key: ProcessDateFilterType.quarter, + label: 'ADF_CLOUD_EDIT_PROCESS_FILTER.LABEL.DATE_RANGE.QUARTER' + }, + { + key: ProcessDateFilterType.year, + label: 'ADF_CLOUD_EDIT_PROCESS_FILTER.LABEL.DATE_RANGE.YEAR' + }, + { + key: ProcessDateFilterType.range, + label: 'ADF_CLOUD_EDIT_PROCESS_FILTER.LABEL.DATE_RANGE.RANGE' + } + ]; + + onSelectionChange(option: MatSelectChange) { + this.type = option.value; + this.setDate(); + this.dateChanged.emit(this.dateRange); + } + + setDate() { + switch (this.type) { + case ProcessDateFilterType.today: + this.setTodayDateRange(); + break; + case ProcessDateFilterType.week: + this.setCurrentWeekRange(); + break; + case ProcessDateFilterType.month: + this.setCurrentMonthDateRange(); + break; + case ProcessDateFilterType.quarter: + this.setQuarterDateRange(); + break; + case ProcessDateFilterType.year: + this.setCurrentYearDateRange(); + break; + default: this.resetDateRange(); + } + } + + isDateRangeType(): boolean { + return this.type === ProcessDateFilterType.range; + } + + onDateRangeClosed() { + this.dateRange = { + startDate: this.dateRangeForm.controls.start.value, + endDate: this.dateRangeForm.controls.end.value + }; + this.dateChanged.emit(this.dateRange); + } + + private resetDateRange() { + this.dateRange = { + startDate: null, + endDate: null + }; + } + + private setCurrentYearDateRange() { + this.dateRange = { + startDate: moment().startOf('year').toDate(), + endDate: moment().endOf('year').toDate() + }; + } + + private setTodayDateRange() { + this.dateRange = { + startDate: moment().startOf('day').toDate(), + endDate: moment().endOf('day').toDate() + }; + } + + private setCurrentWeekRange() { + this.dateRange = { + startDate: moment().startOf('week').toDate(), + endDate: moment().endOf('week').toDate() + }; + } + + private setCurrentMonthDateRange() { + this.dateRange = { + startDate: moment().startOf('month').toDate(), + endDate: moment().endOf('month').toDate() + }; + } + + private setQuarterDateRange() { + const quarter = Math.floor((this.currentDate.getMonth() / 3)); + const firstDate = new Date(this.currentDate.getFullYear(), quarter * 3, 1); + this.dateRange = { + startDate: firstDate, + endDate: new Date(firstDate.getFullYear(), firstDate.getMonth() + 3, 0) + }; + } + } diff --git a/lib/process-services-cloud/src/lib/common/process-common.module.ts b/lib/process-services-cloud/src/lib/common/process-common.module.ts new file mode 100644 index 0000000000..c1d95ec3d1 --- /dev/null +++ b/lib/process-services-cloud/src/lib/common/process-common.module.ts @@ -0,0 +1,35 @@ +/*! + * @license + * Copyright 2019 Alfresco Software, Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { NgModule } from '@angular/core'; +import { CoreModule } from '@alfresco/adf-core'; +import { DateRangeFilterComponent } from './date-range-filter/date-range-filter.component'; +import { MaterialModule } from '../material.module'; +import { CommonModule } from '@angular/common'; + +@NgModule({ + declarations: [ DateRangeFilterComponent ], + imports: [ + CommonModule, + CoreModule, + MaterialModule + ], + exports: [ + DateRangeFilterComponent + ] +}) +export class ProcessCommonModule {} diff --git a/lib/process-services-cloud/src/lib/i18n/en.json b/lib/process-services-cloud/src/lib/i18n/en.json index 28ea02f603..30b2f2ebcb 100644 --- a/lib/process-services-cloud/src/lib/i18n/en.json +++ b/lib/process-services-cloud/src/lib/i18n/en.json @@ -165,10 +165,24 @@ "LAST_MODIFIED_DATE_FORM": "LastModifiedFrom", "LAST_MODIFIED_TO": "LastModifiedTo", "PROCESS_NAME": "ProcessName", - "APP_VERSION": "AppReleaseVersion" + "APP_VERSION": "AppReleaseVersion", + "CREATED_DATE": "Created Date", + "DATE_RANGE": { + "TODAY": "today", + "WEEK": "this week", + "MONTH": "this month", + "QUARTER": "this quarter", + "YEAR": "this year", + "RANGE": "Date within" + }, + "DATE_RANGE_TITLE": "Start date - End date", + "START_DATE": "Start date", + "END_DATE": "End date" }, "ERROR": { - "DATE": "Date format DD/MM/YYYY" + "DATE": "Date format DD/MM/YYYY", + "INDALID_START_DATE": "Invalid start date", + "INDALID_END_DATE": "Invalid end date" }, "TOOL_TIP": { "SAVE": "Save filter", 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 af7cfa20d9..d3bf7e2581 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 @@ -99,3 +99,17 @@ export class ProcessFilterProperties { } } } + +export enum ProcessDateFilterType { + today = 'today', + week = 'week', + month = 'month', + quarter = 'quarter', + year = 'year', + range = 'range' +} + +export interface DateRangeFilter { + startDate: Date; + endDate: Date; +} diff --git a/lib/process-services-cloud/src/lib/process/process-filters/process-filters-cloud.module.ts b/lib/process-services-cloud/src/lib/process/process-filters/process-filters-cloud.module.ts index 9f8d4a2496..b5a66b47a9 100644 --- a/lib/process-services-cloud/src/lib/process/process-filters/process-filters-cloud.module.ts +++ b/lib/process-services-cloud/src/lib/process/process-filters/process-filters-cloud.module.ts @@ -27,6 +27,7 @@ import { EditProcessFilterCloudComponent } from './components/edit-process-filte import { ProcessFilterDialogCloudComponent } from './components/process-filter-dialog-cloud.component'; import { AppListCloudModule } from './../../app/app-list-cloud.module'; import { DateAdapter, MAT_DATE_FORMATS } from '@angular/material/core'; +import { ProcessCommonModule } from '../../common/process-common.module'; @NgModule({ imports: [ @@ -37,8 +38,8 @@ import { DateAdapter, MAT_DATE_FORMATS } from '@angular/material/core'; FlexLayoutModule, MaterialModule, AppListCloudModule, - CoreModule - + CoreModule, + ProcessCommonModule ], declarations: [ProcessFiltersCloudComponent, EditProcessFilterCloudComponent, ProcessFilterDialogCloudComponent], exports: [ProcessFiltersCloudComponent, EditProcessFilterCloudComponent, ProcessFilterDialogCloudComponent],