diff --git a/demo-shell/src/app.config.json b/demo-shell/src/app.config.json index 95d7bac7bb..dfe236ac00 100644 --- a/demo-shell/src/app.config.json +++ b/demo-shell/src/app.config.json @@ -539,6 +539,16 @@ ] } }, + "edit-task-filter": { + "properties": [ + "state", "assignment", "sort", "order" + ] + }, + "edit-process-filter": { + "properties": [ + "state", "sort", "order", "processName" + ] + }, "content-metadata": { "presets": { "default": { diff --git a/demo-shell/src/app/components/app-layout/cloud/cloud-filters-demo.component.ts b/demo-shell/src/app/components/app-layout/cloud/cloud-filters-demo.component.ts index 6e90276b12..a6a193d7fe 100644 --- a/demo-shell/src/app/components/app-layout/cloud/cloud-filters-demo.component.ts +++ b/demo-shell/src/app/components/app-layout/cloud/cloud-filters-demo.component.ts @@ -49,7 +49,7 @@ export class CloudFiltersDemoComponent implements OnInit { this.currentTaskFilter$ = this.cloudLayoutService.getCurrentTaskFilterParam(); this.currentProcessFilter$ = this.cloudLayoutService.getCurrentProcessFilterParam(); let root = ''; - if ( this.route.snapshot && this.route.snapshot.firstChild) { + if (this.route.snapshot && this.route.snapshot.firstChild) { root = this.route.snapshot.firstChild.url[0].path; if (root === 'tasks') { this.expandTaskFilter = true; diff --git a/demo-shell/src/app/components/app-layout/cloud/cloud-layout.component.ts b/demo-shell/src/app/components/app-layout/cloud/cloud-layout.component.ts index 459f94d605..06d652bc74 100644 --- a/demo-shell/src/app/components/app-layout/cloud/cloud-layout.component.ts +++ b/demo-shell/src/app/components/app-layout/cloud/cloud-layout.component.ts @@ -35,14 +35,23 @@ export class CloudLayoutComponent implements OnInit { ) {} ngOnInit() { + let root: string = ''; this.route.params.subscribe((params) => { this.applicationName = params.applicationName; }); + if (this.route.snapshot && this.route.snapshot.firstChild) { + root = this.route.snapshot.firstChild.url[0].path; + } + this.route.queryParams.subscribe((params) => { - if (params.id) { + if (root === 'tasks' && params.id) { this.cloudLayoutService.setCurrentTaskFilterParam({ id: params.id }); } + + if (root === 'processes' && params.id) { + this.cloudLayoutService.setCurrentProcessFilterParam({ id: params.id }); + } }); } diff --git a/demo-shell/src/app/components/app-layout/cloud/processes-cloud-demo.component.html b/demo-shell/src/app/components/app-layout/cloud/processes-cloud-demo.component.html index 316c3aa6eb..daf84b66ac 100644 --- a/demo-shell/src/app/components/app-layout/cloud/processes-cloud-demo.component.html +++ b/demo-shell/src/app/components/app-layout/cloud/processes-cloud-demo.component.html @@ -2,6 +2,7 @@ @@ -9,6 +10,7 @@ diff --git a/demo-shell/src/app/components/app-layout/cloud/processes-cloud-demo.component.ts b/demo-shell/src/app/components/app-layout/cloud/processes-cloud-demo.component.ts index 38cf5c15f8..d4eb0de756 100644 --- a/demo-shell/src/app/components/app-layout/cloud/processes-cloud-demo.component.ts +++ b/demo-shell/src/app/components/app-layout/cloud/processes-cloud-demo.component.ts @@ -23,8 +23,8 @@ import { ProcessFiltersCloudComponent } from '@alfresco/adf-process-services-cloud'; -import { ActivatedRoute } from '@angular/router'; -import { UserPreferencesService } from '@alfresco/adf-core'; +import { ActivatedRoute, Router } from '@angular/router'; +import { UserPreferencesService, AppConfigService } from '@alfresco/adf-core'; import { CloudLayoutService } from './services/cloud-layout.service'; @Component({ @@ -33,6 +33,9 @@ import { CloudLayoutService } from './services/cloud-layout.service'; }) export class ProcessesCloudDemoComponent implements OnInit { + public static ACTION_SAVE_AS = 'SAVE_AS'; + static PROCESS_FILTER_PROPERTY_KEYS = 'edit-process-filter.properties'; + @ViewChild('processCloud') processCloud: ProcessListCloudComponent; @@ -45,13 +48,20 @@ export class ProcessesCloudDemoComponent implements OnInit { filterId: string = ''; sortArray: any = []; selectedRow: any; + processFilterProperties: any[] = []; editedFilter: ProcessFilterCloudModel; constructor( private route: ActivatedRoute, + private router: Router, private cloudLayoutService: CloudLayoutService, - private userPreference: UserPreferencesService) { + private userPreference: UserPreferencesService, + private appConfig: AppConfigService) { + const properties = this.appConfig.get>(ProcessesCloudDemoComponent.PROCESS_FILTER_PROPERTY_KEYS); + if (properties) { + this.processFilterProperties = properties; + } } ngOnInit() { @@ -80,7 +90,10 @@ export class ProcessesCloudDemoComponent implements OnInit { this.sortArray = [new ProcessListCloudSortingModel({ orderBy: this.editedFilter.sort, direction: this.editedFilter.order })]; } - onProcessFilterAction(filter: any) { - this.cloudLayoutService.setCurrentProcessFilterParam({id: filter.id}); + onProcessFilterAction(filterAction: any) { + this.cloudLayoutService.setCurrentProcessFilterParam({id: filterAction.filter.id}); + if (filterAction.actionType === ProcessesCloudDemoComponent.ACTION_SAVE_AS) { + this.router.navigate([`/cloud/${this.applicationName}/processes/`], { queryParams: filterAction.filter }); + } } } diff --git a/demo-shell/src/app/components/app-layout/cloud/tasks-cloud-demo.component.html b/demo-shell/src/app/components/app-layout/cloud/tasks-cloud-demo.component.html index 3cd478e279..4be5d6213b 100644 --- a/demo-shell/src/app/components/app-layout/cloud/tasks-cloud-demo.component.html +++ b/demo-shell/src/app/components/app-layout/cloud/tasks-cloud-demo.component.html @@ -2,6 +2,7 @@ diff --git a/demo-shell/src/app/components/app-layout/cloud/tasks-cloud-demo.component.ts b/demo-shell/src/app/components/app-layout/cloud/tasks-cloud-demo.component.ts index 92dc27c3a4..1835016027 100644 --- a/demo-shell/src/app/components/app-layout/cloud/tasks-cloud-demo.component.ts +++ b/demo-shell/src/app/components/app-layout/cloud/tasks-cloud-demo.component.ts @@ -17,7 +17,7 @@ import { Component, ViewChild, OnInit } from '@angular/core'; import { TaskListCloudComponent, TaskListCloudSortingModel, TaskFilterCloudModel } from '@alfresco/adf-process-services-cloud'; -import { UserPreferencesService } from '@alfresco/adf-core'; +import { UserPreferencesService, AppConfigService } from '@alfresco/adf-core'; import { ActivatedRoute, Router } from '@angular/router'; import { CloudLayoutService } from './services/cloud-layout.service'; @@ -28,6 +28,7 @@ import { CloudLayoutService } from './services/cloud-layout.service'; export class TasksCloudDemoComponent implements OnInit { public static ACTION_SAVE_AS = 'SAVE_AS'; + static TASK_FILTER_PROPERTY_KEYS = 'adf-edit-task-filter.properties'; @ViewChild('taskCloud') taskCloud: TaskListCloudComponent; @@ -40,6 +41,7 @@ export class TasksCloudDemoComponent implements OnInit { sortArray: TaskListCloudSortingModel[]; editedFilter: TaskFilterCloudModel; + taskFilterProperties: any[] = []; filterId; @@ -47,7 +49,13 @@ export class TasksCloudDemoComponent implements OnInit { private cloudLayoutService: CloudLayoutService, private route: ActivatedRoute, private router: Router, - private userPreference: UserPreferencesService) { + private userPreference: UserPreferencesService, + private appConfig: AppConfigService) { + + const properties = this.appConfig.get>(TasksCloudDemoComponent.TASK_FILTER_PROPERTY_KEYS); + if (properties) { + this.taskFilterProperties = properties; + } } ngOnInit() { diff --git a/demo-shell/src/app/components/config-editor/config-editor.component.html b/demo-shell/src/app/components/config-editor/config-editor.component.html index c6484883aa..1db402d80d 100644 --- a/demo-shell/src/app/components/config-editor/config-editor.component.html +++ b/demo-shell/src/app/components/config-editor/config-editor.component.html @@ -48,6 +48,20 @@ info + + + Edit process filter + + + + + Edit task filter + +
diff --git a/demo-shell/src/app/components/config-editor/config-editor.component.ts b/demo-shell/src/app/components/config-editor/config-editor.component.ts index 1ce6792b02..eea2ae8eaf 100644 --- a/demo-shell/src/app/components/config-editor/config-editor.component.ts +++ b/demo-shell/src/app/components/config-editor/config-editor.component.ts @@ -112,6 +112,18 @@ export class ConfigEditorComponent { this.indentCode(); } + editProcessFilterConfClick() { + this.code = JSON.stringify(this.appConfig.config['edit-process-filter']); + this.field = 'edit-process-filter'; + this.indentCode(); + } + + editTaskFilterConfClick() { + this.code = JSON.stringify(this.appConfig.config['edit-task-filter']); + this.field = 'edit-task-filter'; + this.indentCode(); + } + indentCode() { setTimeout(() => { this.editor.getAction('editor.action.formatDocument').run(); diff --git a/docs/docassets/images/edit-process-filter-cloud.component.png b/docs/docassets/images/edit-process-filter-cloud.component.png index 969570e8c6..14a08cc454 100644 Binary files a/docs/docassets/images/edit-process-filter-cloud.component.png and b/docs/docassets/images/edit-process-filter-cloud.component.png differ diff --git a/docs/docassets/images/edit-task-filter-cloud.component.png b/docs/docassets/images/edit-task-filter-cloud.component.png index 7752514f9f..727efad0b7 100644 Binary files a/docs/docassets/images/edit-task-filter-cloud.component.png and b/docs/docassets/images/edit-task-filter-cloud.component.png differ diff --git a/docs/process-services-cloud/edit-process-filter-cloud.component.md b/docs/process-services-cloud/edit-process-filter-cloud.component.md index 8baffbe0b6..ce4bdf4574 100644 --- a/docs/process-services-cloud/edit-process-filter-cloud.component.md +++ b/docs/process-services-cloud/edit-process-filter-cloud.component.md @@ -24,8 +24,11 @@ Shows Process Filter Details. | Name | Type | Default value | Description | | ---- | ---- | ------------- | ----------- | -| appName | `string` | | The name of the application. | -| id | `string` | | Id of the process instance filter. | +| appName | `string` | | (required) The name of the application. | +| id | `string` | | (required) Id of the process instance filter. | +| filterProperties | `string []` | `['state', 'sort', 'order']` | List of process filter properties to display. | +| showFilterActions | `boolean` | `true` | Toggles edit process filter actions. | +| showTitle | `boolean` | `true` | Toggles edit process filter title. | ### Events @@ -38,7 +41,7 @@ Shows Process Filter Details. ### Editing APS2 process filter -Use the process filter id property to edit process filter properties: +Use the application name and process filter id property to edit process filter properties: ```html ``` +By default these below properties are displayed: + +**_state_**, **_sort_**, **_order_**. + +However, you can also choose which properties to show using an input property +`filterProperties`: + +Populate the filterProperties in the component class: + +```ts +import { UserProcessModel } from '@alfresco/adf-core'; + +export class SomeComponent implements OnInit { + + filterProperties: string[] = [ + "appName", + "processInstanceId", + "startDate", + "startedAfter"]; + + onFilterChange(filter: ProcessFilterCloudModel) { + console.log('On filter change: ', filter); + } + + onAction($event: ProcessFilterActionType) { + console.log('Clicked action: ', $event); + } +``` + +With this configuration, only the four listed properties will be shown. + +```html + + +``` + + +All Available properties are: + +**_appName_**, **_initiator_**, **_state_**, **_sort_**, **_order_**, **_processDefinitionId_**, **_processDefinitionKey_**, **_processInstanceId_**, **_startDate_**, **_lastModified_**, **_lastModifiedFrom_**, **_lastModifiedTo_**. ![edit-process-filter-cloud](../docassets/images/edit-process-filter-cloud.component.png) diff --git a/docs/process-services-cloud/edit-task-filter-cloud.component.md b/docs/process-services-cloud/edit-task-filter-cloud.component.md index c325568f3e..d29cbbc5c3 100644 --- a/docs/process-services-cloud/edit-task-filter-cloud.component.md +++ b/docs/process-services-cloud/edit-task-filter-cloud.component.md @@ -25,10 +25,10 @@ Edits Task Filter Details. | Name | Type | Default value | Description | | ---- | ---- | ------------- | ----------- | | appName | `string` | | (required) Name of the app. | -| filterProperties | `string[]` | | List of task filter properties to display. | -| id | `string` | | (required) ID of the task filter. | -| showTitle | `boolean` | true | Toggles the title. | -| toggleFilterActions | `boolean` | true | Toggles the filter actions. | +| id | `string` | "" | (required) The id of the Task filter. | +| filterProperties | `string []` | `['state', 'assignment', 'sort', 'order']` | List of task filter properties to display. | +| showFilterActions | `boolean` | `true` | Toggles edit task filter actions. | +| showTitle | `boolean` | `true` | Toggles edit task filter title. | ### Events diff --git a/e2e/pages/adf/dataTablePage.ts b/e2e/pages/adf/dataTablePage.ts index dda2778120..ea702d3f1f 100644 --- a/e2e/pages/adf/dataTablePage.ts +++ b/e2e/pages/adf/dataTablePage.ts @@ -243,10 +243,12 @@ export class DataTablePage { checkSpinnerIsDisplayed() { Util.waitUntilElementIsPresent(this.spinner); + return this; } checkSpinnerIsNotDisplayed() { Util.waitUntilElementIsNotOnPage(this.spinner); + return this; } checkRowIsDisplayedByName(filename) { diff --git a/e2e/pages/adf/process-cloud/editProcessFilterCloudComponent.ts b/e2e/pages/adf/process-cloud/editProcessFilterCloudComponent.ts index 7a591a3b23..aae0cb198d 100644 --- a/e2e/pages/adf/process-cloud/editProcessFilterCloudComponent.ts +++ b/e2e/pages/adf/process-cloud/editProcessFilterCloudComponent.ts @@ -29,7 +29,7 @@ export class EditProcessFilterCloudComponent { } setStateFilterDropDown(option) { - this.clickOnDropDownArrow('status'); + this.clickOnDropDownArrow('state'); let stateElement = element.all(by.cssContainingText('mat-option span', option)).first(); Util.waitUntilElementIsClickable(stateElement); diff --git a/e2e/process-services-cloud/process-custom-filters.e2e.ts b/e2e/process-services-cloud/process-custom-filters.e2e.ts index 962dfb2b8c..bd42f16abb 100644 --- a/e2e/process-services-cloud/process-custom-filters.e2e.ts +++ b/e2e/process-services-cloud/process-custom-filters.e2e.ts @@ -98,6 +98,7 @@ describe('Process list cloud', () => { it('[C291783] Should display processes ordered by id when Id is selected from sort dropdown', async() => { processCloudDemoPage.editProcessFilterCloudComponent().clickCustomiseFilterHeader().setStateFilterDropDown('RUNNING') .setSortFilterDropDown('ID').setOrderFilterDropDown('ASC'); + processCloudDemoPage.processListCloudComponent().getDataTable().checkSpinnerIsDisplayed().checkSpinnerIsNotDisplayed(); processCloudDemoPage.getAllRowsByIdColumn().then(function (list) { let initialList = list.slice(0); list.sort(function (firstStr, secondStr) { @@ -107,6 +108,7 @@ describe('Process list cloud', () => { }); processCloudDemoPage.editProcessFilterCloudComponent().setOrderFilterDropDown('DESC'); + processCloudDemoPage.processListCloudComponent().getDataTable().checkSpinnerIsDisplayed().checkSpinnerIsNotDisplayed(); processCloudDemoPage.getAllRowsByIdColumn().then(function (list) { let initialList = list.slice(0); list.sort(function (firstStr, secondStr) { diff --git a/lib/process-services-cloud/src/lib/i18n/en.json b/lib/process-services-cloud/src/lib/i18n/en.json index d3829d0bf1..3463572c7c 100644 --- a/lib/process-services-cloud/src/lib/i18n/en.json +++ b/lib/process-services-cloud/src/lib/i18n/en.json @@ -126,21 +126,30 @@ }, "ADF_CLOUD_EDIT_PROCESS_FILTER": { "TITLE": "Customize your filter", - "STATUS": "Select a status", - "ASSIGNMENT": "ASSIGNMENT", - "COLUMN": "Select a column", - "DIRECTION": "Select a direction", + "LABEL": { + "APP_NAME": "ApplicationName", + "STATUS": "Status", + "INITIATOR": "Initiator", + "ASSIGNMENT": "Assignment", + "SORT": "Sort", + "DIRECTION": "Direction", + "PROCESS_DEF_ID": "ProcessDefinitionId", + "PROCESS_DEF_KEY": "ProcessDefinitionKey", + "PROCESS_INS_ID": "ProcessInstanceId", + "START_DATE": "StartDate", + "LAST_MODIFIED": "LastModified", + "LAST_MODIFIED_DATE_FORM": "LastModifiedFrom", + "LAST_MODIFIED_TO": "LastModifiedTo", + "PROCESS_NAME": "ProcessName" + }, + "ERROR": { + "DATE": "Date format DD/MM/YYYY" + }, "TOOL_TIP": { "SAVE": "Save filter", "SAVE_AS": "Save filter as", "DELETE": "Delete filter" }, - "LABEL": { - "STATUS": "Status", - "ASSIGNMENT": "Assignment", - "COLUMN": "Column", - "DIRECTION": "Direction" - }, "DIALOG": { "TITLE": "Save filter as", "SAVE": "SAVE", diff --git a/lib/process-services-cloud/src/lib/process-services-cloud.module.ts b/lib/process-services-cloud/src/lib/process-services-cloud.module.ts index 2b9eeaec79..169701b12d 100644 --- a/lib/process-services-cloud/src/lib/process-services-cloud.module.ts +++ b/lib/process-services-cloud/src/lib/process-services-cloud.module.ts @@ -20,12 +20,14 @@ import { TRANSLATION_PROVIDER } from '@alfresco/adf-core'; import { AppListCloudModule } from './app/app-list-cloud.module'; import { TaskCloudModule } from './task/task-cloud.module'; import { ProcessCloudModule } from './process/process-cloud.module'; +import { GroupCloudModule } from './group/group-cloud.module'; @NgModule({ imports: [ AppListCloudModule, ProcessCloudModule, - TaskCloudModule + TaskCloudModule, + GroupCloudModule ], providers: [ { @@ -40,7 +42,8 @@ import { ProcessCloudModule } from './process/process-cloud.module'; exports: [ AppListCloudModule, ProcessCloudModule, - TaskCloudModule + TaskCloudModule, + GroupCloudModule ] }) export class ProcessServicesCloudModule { } 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 c93ab1d40b..69787087f6 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 @@ -1,60 +1,65 @@ - + - {{processFilter.name | translate}} - - {{ 'ADF_CLOUD_EDIT_PROCESS_FILTER.TITLE' | translate}} + {{processFilter.name | translate}} + + {{ 'ADF_CLOUD_EDIT_PROCESS_FILTER.TITLE' | translate}} +
+ + + + + +
-
- - - - {{ state.label }} +
+ + + + + {{ propertyOption.label }} - + + [formControlName]="processFilterProperty.key" + type="text" + placeholder="{{processFilterProperty.label | translate}}" + [attr.data-automation-id]="'adf-cloud-edit-process-property-' + processFilterProperty.key"/> - - + + {{processFilterProperty.label | translate}} + + + +
+
+
{{'ADF_CLOUD_EDIT_PROCESS_FILTER.ERROR.DATE' | translate}}
+ warning +
+
- - - - {{ column.label }} - - - - - - - {{ direction }} - - - -
- - - -
-
+ +
diff --git a/lib/process-services-cloud/src/lib/process/process-filters/components/edit-process-filter-cloud.component.scss b/lib/process-services-cloud/src/lib/process/process-filters/components/edit-process-filter-cloud.component.scss index e69de29bb2..498ba1f835 100644 --- a/lib/process-services-cloud/src/lib/process/process-filters/components/edit-process-filter-cloud.component.scss +++ b/lib/process-services-cloud/src/lib/process/process-filters/components/edit-process-filter-cloud.component.scss @@ -0,0 +1,31 @@ +@mixin adf-cloud-edit-process-filter-theme($theme) { + + $warn: map-get($theme, warn); + + .adf-edit-process-filter-date-error-container { + position: absolute; + height: 20px; + margin-top: 12px; + width: 100%; + + & > div { + display: flex; + flex-flow: row; + justify-content: flex-start; + } + + .adf-error-text { + padding-right: 8px; + height: 16px; + font-size: 11px; + line-height: 1.33; + color: mat-color($warn); + width: auto; + } + + .adf-error-icon { + font-size: 16px; + color: mat-color($warn); + } + } +} 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 a1f6ab913f..5cfc342c3a 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 @@ -19,7 +19,7 @@ import { async, ComponentFixture, TestBed } from '@angular/core/testing'; import { SimpleChange } from '@angular/core'; import { By } from '@angular/platform-browser'; -import { setupTestBed, IdentityUserService } from '@alfresco/adf-core'; +import { setupTestBed } from '@alfresco/adf-core'; import { ProcessServiceCloudTestingModule } from '../../../testing/process-service-cloud.testing.module'; import { MatDialog } from '@angular/material'; import { of } from 'rxjs'; @@ -28,20 +28,24 @@ import { EditProcessFilterCloudComponent } from './edit-process-filter-cloud.com import { ProcessFiltersCloudModule } from '../process-filters-cloud.module'; import { ProcessFilterCloudModel } from '../models/process-filter-cloud.model'; import { ProcessFilterCloudService } from '../services/process-filter-cloud.service'; +import { AppsProcessCloudService } from '../../../app/services/apps-process-cloud.service'; +import { fakeApplicationInstance } from './../../../app/mock/app-model.mock'; describe('EditProcessFilterCloudComponent', () => { let component: EditProcessFilterCloudComponent; let service: ProcessFilterCloudService; - let identityService: IdentityUserService; let fixture: ComponentFixture; let dialog: MatDialog; + let appsService: AppsProcessCloudService; + let getRunningApplicationsSpy: jasmine.Spy; + let getProcessFilterByIdSpy: jasmine.Spy; let fakeFilter = new ProcessFilterCloudModel({ name: 'FakeRunningProcess', icon: 'adjust', - id: 10, + id: 'mock-process-filter-id', state: 'RUNNING', - appName: 'app-name', + appName: 'mock-app-name', processDefinitionId: 'process-def-id', assignment: 'fake-involved', order: 'ASC', @@ -57,14 +61,15 @@ describe('EditProcessFilterCloudComponent', () => { fixture = TestBed.createComponent(EditProcessFilterCloudComponent); component = fixture.componentInstance; service = TestBed.get(ProcessFilterCloudService); - identityService = TestBed.get(IdentityUserService); + appsService = TestBed.get(AppsProcessCloudService); dialog = TestBed.get(MatDialog); spyOn(dialog, 'open').and.returnValue({ afterClosed() { return of({ action: ProcessFilterDialogCloudComponent.ACTION_SAVE, icon: 'icon', name: 'fake-name' }); }}); - spyOn(service, 'getProcessFilterById').and.returnValue(fakeFilter); + getProcessFilterByIdSpy = spyOn(service, 'getProcessFilterById').and.returnValue(fakeFilter); + getRunningApplicationsSpy = spyOn(appsService, 'getDeployedApplicationsByStatus').and.returnValue(of(fakeApplicationInstance)); }); it('should create EditProcessFilterCloudComponent', () => { @@ -72,12 +77,12 @@ describe('EditProcessFilterCloudComponent', () => { }); it('should fetch process instance filter by id', async(() => { - let change = new SimpleChange(undefined, '10', true); - component.ngOnChanges({ 'id': change }); - fixture.detectChanges(); + let processFilterIDchange = new SimpleChange(undefined, 'mock-process-filter-id', true); + component.ngOnChanges({'id': processFilterIDchange}); fixture.detectChanges(); fixture.whenStable().then(() => { fixture.detectChanges(); + expect(getProcessFilterByIdSpy).toHaveBeenCalled(); expect(component.processFilter.name).toEqual('FakeRunningProcess'); expect(component.processFilter.icon).toEqual('adjust'); expect(component.processFilter.state).toEqual('RUNNING'); @@ -87,27 +92,26 @@ describe('EditProcessFilterCloudComponent', () => { })); it('should display filter name as title', () => { - let change = new SimpleChange(undefined, '10', true); - component.ngOnChanges({ 'id': change }); - fixture.detectChanges(); + let processFilterIDchange = new SimpleChange(undefined, 'mock-process-filter-id', true); + component.ngOnChanges({'id': processFilterIDchange}); fixture.detectChanges(); const title = fixture.debugElement.nativeElement.querySelector('#adf-edit-process-filter-title-id'); const subTitle = fixture.debugElement.nativeElement.querySelector('#adf-edit-process-filter-sub-title-id'); expect(title).toBeDefined(); expect(subTitle).toBeDefined(); expect(title.innerText).toEqual('FakeRunningProcess'); - expect(subTitle.innerText).toEqual('ADF_CLOUD_EDIT_PROCESS_FILTER.TITLE'); + expect(subTitle.innerText.trim()).toEqual('ADF_CLOUD_EDIT_PROCESS_FILTER.TITLE'); }); describe('EditProcessFilter form', () => { beforeEach(() => { - let change = new SimpleChange(undefined, '10', true); - component.ngOnChanges({ 'id': change }); + let processFilterIDchange = new SimpleChange(undefined, 'mock-process-filter-id', true); + component.ngOnChanges({'id': processFilterIDchange}); fixture.detectChanges(); }); - it('should define editProcessFilter form', () => { + it('should defined editProcessFilter form', () => { expect(component.editProcessFilterForm).toBeDefined(); }); @@ -129,6 +133,7 @@ describe('EditProcessFilterCloudComponent', () => { })); it('should disable save button if the process filter is not changed', async(() => { + component.toggleFilterActions = true; let expansionPanel = fixture.debugElement.nativeElement.querySelector('mat-expansion-panel-header'); expansionPanel.click(); fixture.detectChanges(); @@ -139,6 +144,7 @@ describe('EditProcessFilterCloudComponent', () => { })); it('should disable saveAs button if the process filter is not changed', async(() => { + component.toggleFilterActions = true; let expansionPanel = fixture.debugElement.nativeElement.querySelector('mat-expansion-panel-header'); expansionPanel.click(); fixture.detectChanges(); @@ -149,6 +155,7 @@ describe('EditProcessFilterCloudComponent', () => { })); it('should enable delete button by default', async(() => { + component.toggleFilterActions = true; let expansionPanel = fixture.debugElement.nativeElement.querySelector('mat-expansion-panel-header'); expansionPanel.click(); fixture.detectChanges(); @@ -159,33 +166,35 @@ describe('EditProcessFilterCloudComponent', () => { })); it('should display current process filter details', async(() => { - let expansionPanel = fixture.debugElement.nativeElement.querySelector('mat-expansion-panel-header'); - expansionPanel.click(); fixture.detectChanges(); fixture.whenStable().then(() => { - let stateElement = fixture.debugElement.nativeElement.querySelector('#adf-process-filter-state-id'); - let sortElement = fixture.debugElement.nativeElement.querySelector('#adf-process-filter-sort-id'); - let orderElement = fixture.debugElement.nativeElement.querySelector('#adf-process-filter-order-id'); + let expansionPanel = fixture.debugElement.nativeElement.querySelector('mat-expansion-panel-header'); + expansionPanel.click(); + fixture.detectChanges(); + let stateElement = fixture.debugElement.nativeElement.querySelector('[data-automation-id="adf-cloud-edit-process-property-state"]'); + let sortElement = fixture.debugElement.nativeElement.querySelector('[data-automation-id="adf-cloud-edit-process-property-sort"]'); + let orderElement = fixture.debugElement.nativeElement.querySelector('[data-automation-id="adf-cloud-edit-process-property-order"]'); expect(stateElement).toBeDefined(); expect(sortElement).toBeDefined(); expect(orderElement).toBeDefined(); - expect(stateElement.innerText.trim()).toBe('ADF_CLOUD_EDIT_PROCESS_FILTER.LABEL.STATUS'); - expect(sortElement.innerText.trim()).toBe('ADF_CLOUD_EDIT_PROCESS_FILTER.LABEL.COLUMN'); - expect(orderElement.innerText.trim()).toBe('ADF_CLOUD_EDIT_PROCESS_FILTER.LABEL.DIRECTION'); + expect(stateElement.innerText.trim()).toBe('RUNNING'); + expect(sortElement.innerText.trim()).toBe('ID'); + expect(orderElement.innerText.trim()).toBe('ASC'); }); })); it('should enable save button if the process filter is changed', async(() => { + fixture.detectChanges(); let expansionPanel = fixture.debugElement.nativeElement.querySelector('mat-expansion-panel-header'); expansionPanel.click(); - const stateElement = fixture.debugElement.query(By.css('#adf-process-filter-state-id .mat-select-trigger')).nativeElement; + let stateElement = fixture.debugElement.nativeElement.querySelector('[data-automation-id="adf-cloud-edit-process-property-state"] .mat-select-trigger'); stateElement.click(); fixture.detectChanges(); + const saveButton = fixture.debugElement.nativeElement.querySelector('#adf-save-id'); + const options = fixture.debugElement.queryAll(By.css('.mat-option-text')); + options[2].nativeElement.click(); + fixture.detectChanges(); fixture.whenStable().then(() => { - const saveButton = fixture.debugElement.nativeElement.querySelector('#adf-save-id'); - const options = fixture.debugElement.queryAll(By.css('.mat-option-text')); - options[2].nativeElement.click(); - fixture.detectChanges(); expect(saveButton.disabled).toBe(false); }); })); @@ -194,7 +203,7 @@ describe('EditProcessFilterCloudComponent', () => { fixture.detectChanges(); let expansionPanel = fixture.debugElement.nativeElement.querySelector('mat-expansion-panel-header'); expansionPanel.click(); - const stateElement = fixture.debugElement.query(By.css('#adf-process-filter-state-id .mat-select-trigger')).nativeElement; + const stateElement = fixture.debugElement.nativeElement.querySelector('[data-automation-id="adf-cloud-edit-process-property-state"] .mat-select-trigger'); stateElement.click(); fixture.detectChanges(); fixture.whenStable().then(() => { @@ -207,7 +216,7 @@ describe('EditProcessFilterCloudComponent', () => { fixture.detectChanges(); let expansionPanel = fixture.debugElement.nativeElement.querySelector('mat-expansion-panel-header'); expansionPanel.click(); - const sortElement = fixture.debugElement.query(By.css('#adf-process-filter-sort-id .mat-select-trigger')).nativeElement; + const sortElement = fixture.debugElement.nativeElement.querySelector('[data-automation-id="adf-cloud-edit-process-property-sort"] .mat-select-trigger'); sortElement.click(); fixture.detectChanges(); fixture.whenStable().then(() => { @@ -220,7 +229,7 @@ describe('EditProcessFilterCloudComponent', () => { fixture.detectChanges(); let expansionPanel = fixture.debugElement.nativeElement.querySelector('mat-expansion-panel-header'); expansionPanel.click(); - const orderElement = fixture.debugElement.query(By.css('#adf-process-filter-order-id .mat-select-trigger')).nativeElement; + const orderElement = fixture.debugElement.nativeElement.querySelector('[data-automation-id="adf-cloud-edit-process-property-order"] .mat-select-trigger'); orderElement.click(); fixture.detectChanges(); fixture.whenStable().then(() => { @@ -228,48 +237,117 @@ describe('EditProcessFilterCloudComponent', () => { expect(orderOptions.length).toEqual(2); }); })); + + it('should able to build a editProcessFilter form with default properties if input is empty', async(() => { + let processFilterIDchange = new SimpleChange(undefined, 'mock-process-filter-id', true); + component.ngOnChanges({'id': processFilterIDchange}); + component.filterProperties = []; + fixture.detectChanges(); + fixture.whenStable().then(() => { + const stateController = component.editProcessFilterForm.get('state'); + const sortController = component.editProcessFilterForm.get('sort'); + const orderController = component.editProcessFilterForm.get('order'); + fixture.detectChanges(); + expect(component.processFilterProperties).toBeDefined(); + expect(component.processFilterProperties.length).toBe(3); + expect(component.editProcessFilterForm).toBeDefined(); + expect(stateController).toBeDefined(); + expect(sortController).toBeDefined(); + expect(orderController).toBeDefined(); + expect(stateController.value).toBe('RUNNING'); + expect(sortController.value).toBe('id'); + expect(orderController.value).toBe('ASC'); + }); + })); + }); + + describe('Process filterProperties', () => { + + beforeEach(() => { + component.filterProperties = ['appName', 'processInstanceId', 'processName']; + }); + + it('should able to fetch running applications when appName property defined in the input', async(() => { + fixture.detectChanges(); + let processFilterIDchange = new SimpleChange(undefined, 'mock-process-filter-id', true); + component.ngOnChanges({'id': processFilterIDchange}); + const appController = component.editProcessFilterForm.get('appName'); + fixture.detectChanges(); + fixture.whenStable().then(() => { + expect(getRunningApplicationsSpy).toHaveBeenCalled(); + expect(appController).toBeDefined(); + expect(appController.value).toBe('mock-app-name'); + }); + })); + + it('should able to build a editProcessFilter form with given input properties', async(() => { + fixture.detectChanges(); + getProcessFilterByIdSpy.and.returnValue({ appName: 'mock-app-name', processInstanceId: 'process-instance-id', processName: 'mock-process-name' }); + let processFilterIDchange = new SimpleChange(undefined, 'mock-process-filter-id', true); + component.ngOnChanges({'id': processFilterIDchange}); + fixture.detectChanges(); + const appController = component.editProcessFilterForm.get('appName'); + const processNameController = component.editProcessFilterForm.get('processName'); + const processInsIdController = component.editProcessFilterForm.get('processInstanceId'); + fixture.detectChanges(); + fixture.whenStable().then(() => { + fixture.detectChanges(); + expect(getRunningApplicationsSpy).toHaveBeenCalled(); + expect(component.processFilterProperties).toBeDefined(); + expect(component.editProcessFilterForm).toBeDefined(); + expect(component.processFilterProperties.length).toBe(3); + expect(appController).toBeDefined(); + expect(processNameController).toBeDefined(); + expect(processInsIdController).toBeDefined(); + expect(appController.value).toBe('mock-app-name'); + }); + })); }); describe('edit filter actions', () => { beforeEach(() => { - let change = new SimpleChange(undefined, '10', true); - component.ngOnChanges({ 'id': change }); + let processFilterIDchange = new SimpleChange(undefined, 'mock-process-filter-id', true); + component.ngOnChanges({'id': processFilterIDchange}); + fixture.detectChanges(); }); it('should emit save event and save the filter on click save button', async(() => { - spyOn(identityService, 'getCurrentUserInfo').and.returnValue({username: 'currentUser'}); + component.toggleFilterActions = true; const saveFilterSpy = spyOn(service, 'updateFilter').and.returnValue(fakeFilter); let saveSpy: jasmine.Spy = spyOn(component.action, 'emit'); + fixture.detectChanges(); - let expansionPanel = fixture.debugElement.nativeElement.querySelector('mat-expansion-panel-header'); + const expansionPanel = fixture.debugElement.nativeElement.querySelector('mat-expansion-panel-header'); expansionPanel.click(); - const stateElement = fixture.debugElement.query(By.css('#adf-process-filter-state-id .mat-select-trigger')).nativeElement; + fixture.detectChanges(); + const stateElement = fixture.debugElement.nativeElement.querySelector('[data-automation-id="adf-cloud-edit-process-property-state"] .mat-select-trigger'); stateElement.click(); fixture.detectChanges(); + const saveButton = fixture.debugElement.nativeElement.querySelector('#adf-save-id'); + const stateOptions = fixture.debugElement.queryAll(By.css('.mat-option-text')); + stateOptions[2].nativeElement.click(); + saveButton.click(); + fixture.detectChanges(); fixture.whenStable().then(() => { - const saveButton = fixture.debugElement.nativeElement.querySelector('#adf-save-id'); - const stateOptions = fixture.debugElement.queryAll(By.css('.mat-option-text')); - stateOptions[2].nativeElement.click(); - fixture.detectChanges(); - saveButton.click(); - fixture.detectChanges(); expect(saveFilterSpy).toHaveBeenCalled(); expect(saveSpy).toHaveBeenCalled(); }); })); it('should emit delete event and delete the filter on click of delete button', async(() => { - spyOn(identityService, 'getCurrentUserInfo').and.returnValue({username: 'currentUser'}); + component.toggleFilterActions = true; const deleteFilterSpy = spyOn(service, 'deleteFilter').and.callThrough(); let deleteSpy: jasmine.Spy = spyOn(component.action, 'emit'); fixture.detectChanges(); - let expansionPanel = fixture.debugElement.nativeElement.querySelector('mat-expansion-panel-header'); + + const expansionPanel = fixture.debugElement.nativeElement.querySelector('mat-expansion-panel-header'); expansionPanel.click(); - const stateElement = fixture.debugElement.query(By.css('#adf-process-filter-state-id .mat-select-trigger')).nativeElement; + fixture.detectChanges(); + const stateElement = fixture.debugElement.nativeElement.querySelector('[data-automation-id="adf-cloud-edit-process-property-state"] .mat-select-trigger'); stateElement.click(); fixture.detectChanges(); - let deleteButton = fixture.debugElement.nativeElement.querySelector('#adf-delete-id'); + const deleteButton = fixture.debugElement.nativeElement.querySelector('#adf-delete-id'); deleteButton.click(); fixture.detectChanges(); fixture.whenStable().then(() => { @@ -279,13 +357,15 @@ describe('EditProcessFilterCloudComponent', () => { })); it('should emit saveAs event and add filter on click saveAs button', async(() => { - spyOn(identityService, 'getCurrentUserInfo').and.returnValue({username: 'currentUser'}); + component.toggleFilterActions = true; const saveAsFilterSpy = spyOn(service, 'addFilter').and.callThrough(); let saveAsSpy: jasmine.Spy = spyOn(component.action, 'emit'); fixture.detectChanges(); - let expansionPanel = fixture.debugElement.nativeElement.querySelector('mat-expansion-panel-header'); + + const expansionPanel = fixture.debugElement.nativeElement.querySelector('mat-expansion-panel-header'); expansionPanel.click(); - const stateElement = fixture.debugElement.query(By.css('#adf-process-filter-state-id .mat-select-trigger')).nativeElement; + fixture.detectChanges(); + const stateElement = fixture.debugElement.nativeElement.querySelector('[data-automation-id="adf-cloud-edit-process-property-state"] .mat-select-trigger'); stateElement.click(); fixture.detectChanges(); const saveButton = fixture.debugElement.nativeElement.querySelector('#adf-save-as-id'); 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 e5c1156d3b..307c26a717 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 @@ -16,25 +16,34 @@ */ import { Component, Input, Output, EventEmitter, OnChanges, SimpleChanges } from '@angular/core'; -import { FormGroup, FormBuilder } from '@angular/forms'; -import { ProcessFilterCloudModel, ProcessFilterActionType } from '../models/process-filter-cloud.model'; +import { FormGroup, FormBuilder, AbstractControl } from '@angular/forms'; +import { MatDialog } from '@angular/material'; +import { debounceTime, filter } from 'rxjs/operators'; +import moment from 'moment-es6'; + +import { ApplicationInstanceModel } from '../../../app/models/application-instance.model'; +import { AppsProcessCloudService } from '../../../app/services/apps-process-cloud.service'; +import { ProcessFilterCloudModel, ProcessFilterActionType, ProcessFilterProperties } from '../models/process-filter-cloud.model'; import { TranslationService } from '@alfresco/adf-core'; import { ProcessFilterCloudService } from '../services/process-filter-cloud.service'; import { ProcessFilterDialogCloudComponent } from './process-filter-dialog-cloud.component'; -import { MatDialog } from '@angular/material'; @Component({ - selector: 'adf-cloud-edit-process-filter', - templateUrl: './edit-process-filter-cloud.component.html', - styleUrls: ['./edit-process-filter-cloud.component.scss'] + selector: 'adf-cloud-edit-process-filter', + templateUrl: './edit-process-filter-cloud.component.html', + styleUrls: ['./edit-process-filter-cloud.component.scss'] }) export class EditProcessFilterCloudComponent implements OnChanges { public static ACTION_SAVE = 'SAVE'; public static ACTION_SAVE_AS = 'SAVE_AS'; public static ACTION_DELETE = 'DELETE'; + public static APPLICATION_NAME: string = 'appName'; + public static APP_RUNNING_STATUS: string = 'Running'; + public static DEFAULT_PROCESS_FILTER_PROPERTIES = ['state', 'sort', 'order']; + public FORMAT_DATE: string = 'DD/MM/YYYY'; - /** The name of the application. */ + /** The name of the application. */ @Input() appName: string; @@ -42,6 +51,16 @@ export class EditProcessFilterCloudComponent implements OnChanges { @Input() id: string; + /** List of process filter properties to display */ + @Input() + filterProperties: string[] = EditProcessFilterCloudComponent.DEFAULT_PROCESS_FILTER_PROPERTIES; // default ['state', 'sort', 'order'] + + @Input() + showFilterActions = true; + + @Input() + showTitle = true; + /** Emitted when an process instance filter property changes. */ @Output() filterChange: EventEmitter = new EventEmitter(); @@ -54,67 +73,129 @@ export class EditProcessFilterCloudComponent implements OnChanges { changedProcessFilter: ProcessFilterCloudModel; columns = [ - {key: 'id', label: 'ID'}, - {key: 'name', label: 'NAME'}, - {key: 'status', label: 'STATUS'}, - {key: 'startDate', label: 'START DATE'} - ]; - - status = [ - {label: 'ALL', value: ''}, - {label: 'RUNNING', value: 'RUNNING'}, - {label: 'COMPLETED', value: 'COMPLETED'} + { value: 'id', label: 'ID' }, + { value: 'name', label: 'NAME' }, + { value: 'status', label: 'STATUS' }, + { value: 'startDate', label: 'START DATE' } ]; - directions = ['ASC', 'DESC']; + status = [ + { label: 'ALL', value: '' }, + { label: 'RUNNING', value: 'RUNNING' }, + { label: 'COMPLETED', value: 'COMPLETED' } + ]; + + directions = [{ label: 'ASC', value: 'ASC' }, { label: 'DESC', value: 'DESC' }]; + applicationNames: any[] = []; formHasBeenChanged = false; editProcessFilterForm: FormGroup; + processFilterProperties: any[] = []; + toggleFilterActions: boolean = false; constructor( private formBuilder: FormBuilder, public dialog: MatDialog, private translateService: TranslationService, - private processFilterCloudService: ProcessFilterCloudService) {} + private processFilterCloudService: ProcessFilterCloudService, + private appsProcessCloudService: AppsProcessCloudService) { } ngOnChanges(changes: SimpleChanges) { const id = changes['id']; if (id && id.currentValue !== id.previousValue) { - this.retrieveProcessFilter(); - this.buildForm(); + this.processFilterProperties = this.createAndFilterProperties(); + this.buildForm(this.processFilterProperties); } } /** * Build process filter edit form */ - buildForm() { + buildForm(processFilterProperties: ProcessFilterProperties[]) { this.formHasBeenChanged = false; - this.editProcessFilterForm = this.formBuilder.group({ - state: this.processFilter.state ? this.processFilter.state : '', - sort: this.processFilter.sort, - order: this.processFilter.order, - processDefinitionId: this.processFilter.processDefinitionId, - appName: this.processFilter.appName - }); + this.editProcessFilterForm = this.formBuilder.group(this.getFormControlsConfig(processFilterProperties)); this.onFilterChange(); } + getFormControlsConfig(processFilterProperties: ProcessFilterProperties[]): any { + const properties = processFilterProperties.map((property: ProcessFilterProperties) => { + return { [property.key]: property.value }; + }); + return properties.reduce(((result, current) => Object.assign(result, current)), {}); + } + /** * Return process instance filter by application name and filter id */ - retrieveProcessFilter() { - this.processFilter = this.processFilterCloudService.getProcessFilterById(this.appName, this.id); + retrieveProcessFilter(): ProcessFilterCloudModel { + return new ProcessFilterCloudModel(this.processFilterCloudService.getProcessFilterById(this.appName, this.id)); } /** * Check process instance filter changes */ onFilterChange() { - this.editProcessFilterForm.valueChanges.subscribe((formValues: ProcessFilterCloudModel) => { - this.changedProcessFilter = new ProcessFilterCloudModel(Object.assign({}, this.processFilter, formValues)); - this.formHasBeenChanged = !this.compareFilters(this.changedProcessFilter, this.processFilter); - this.filterChange.emit(this.changedProcessFilter); - }); + this.editProcessFilterForm.valueChanges + .pipe(debounceTime(500), filter(() => this.isFormValid())) + .subscribe((formValues: ProcessFilterCloudModel) => { + this.changedProcessFilter = new ProcessFilterCloudModel(Object.assign({}, this.processFilter, formValues)); + this.formHasBeenChanged = !this.compareFilters(this.changedProcessFilter, this.processFilter); + this.filterChange.emit(this.changedProcessFilter); + }); + } + + createAndFilterProperties() { + this.checkMandatoryFilterProperties(); + if (this.checkForApplicationNameProperty()) { + this.getRunningApplications(); + } + this.processFilter = this.retrieveProcessFilter(); + const defaultProperties = this.createProcessFilterProperties(this.processFilter); + return defaultProperties.filter((filterProperty: ProcessFilterProperties) => this.isValidProperty(this.filterProperties, filterProperty)); + } + + checkMandatoryFilterProperties() { + if (this.filterProperties === undefined || this.filterProperties.length === 0) { + this.filterProperties = EditProcessFilterCloudComponent.DEFAULT_PROCESS_FILTER_PROPERTIES; + } + } + + checkForApplicationNameProperty(): boolean { + return this.filterProperties ? this.filterProperties.indexOf(EditProcessFilterCloudComponent.APPLICATION_NAME) >= 0 : false; + } + + private isValidProperty(filterProperties: string[], filterProperty: ProcessFilterProperties): boolean { + return filterProperties ? filterProperties.indexOf(filterProperty.key) >= 0 : true; + } + + isFormValid(): boolean { + return this.editProcessFilterForm.valid; + } + + getPropertyController(property: ProcessFilterProperties): AbstractControl { + return this.editProcessFilterForm.get(property.key); + } + + onDateChanged(newDateValue: any, dateProperty: ProcessFilterProperties) { + if (newDateValue) { + let momentDate; + + if (typeof newDateValue === 'string') { + momentDate = moment(newDateValue, this.FORMAT_DATE, true); + } else { + momentDate = newDateValue; + } + + if (momentDate.isValid()) { + this.getPropertyController(dateProperty).setValue(momentDate.toDate()); + this.getPropertyController(dateProperty).setErrors(null); + } else { + this.getPropertyController(dateProperty).setErrors({ invalid: true }); + } + } + } + + hasError(property: ProcessFilterProperties): boolean { + return this.getPropertyController(property).errors && this.getPropertyController(property).errors.invalid; } /** @@ -125,12 +206,24 @@ export class EditProcessFilterCloudComponent implements OnChanges { return JSON.stringify(editedQuery).toLowerCase() === JSON.stringify(currentQuery).toLowerCase(); } + getRunningApplications() { + this.appsProcessCloudService.getDeployedApplicationsByStatus(EditProcessFilterCloudComponent.APP_RUNNING_STATUS) + .subscribe((applications: ApplicationInstanceModel[]) => { + if (applications && applications.length > 0) { + applications.map((application) => { + this.applicationNames.push({ label: application.name, value: application.name }); + }); + } + }); + } + /** * Save a process instance filter */ onSave() { this.processFilterCloudService.updateFilter(this.changedProcessFilter); - this.action.emit({actionType: EditProcessFilterCloudComponent.ACTION_SAVE, id: this.changedProcessFilter.id}); + this.action.emit({ actionType: EditProcessFilterCloudComponent.ACTION_SAVE, filter: this.changedProcessFilter }); + this.formHasBeenChanged = this.compareFilters(this.changedProcessFilter, this.processFilter); } /** @@ -138,7 +231,7 @@ export class EditProcessFilterCloudComponent implements OnChanges { */ onDelete() { this.processFilterCloudService.deleteFilter(this.processFilter); - this.action.emit({actionType: EditProcessFilterCloudComponent.ACTION_DELETE, id: this.processFilter.id}); + this.action.emit({ actionType: EditProcessFilterCloudComponent.ACTION_DELETE, filter: this.processFilter }); } /** @@ -152,19 +245,19 @@ export class EditProcessFilterCloudComponent implements OnChanges { height: 'auto', minWidth: '30%' }); - dialogRef.afterClosed().subscribe( (result) => { + dialogRef.afterClosed().subscribe((result) => { if (result && result.action === ProcessFilterDialogCloudComponent.ACTION_SAVE) { const filterId = Math.random().toString(36).substr(2, 9); const filterKey = this.getSanitizeFilterName(result.name); const newFilter = { - name: result.name, - icon: result.icon, - id: filterId, - key: 'custom-' + filterKey - }; - const filter = Object.assign({}, this.changedProcessFilter, newFilter); - this.processFilterCloudService.addFilter(filter); - this.action.emit({actionType: EditProcessFilterCloudComponent.ACTION_SAVE_AS, id: filter.id}); + name: result.name, + icon: result.icon, + id: filterId, + key: 'custom-' + filterKey + }; + const resultFilter: ProcessFilterCloudModel = Object.assign({}, this.changedProcessFilter, newFilter); + this.processFilterCloudService.addFilter(resultFilter); + this.action.emit({ actionType: EditProcessFilterCloudComponent.ACTION_SAVE_AS, filter: resultFilter }); } }); } @@ -186,4 +279,115 @@ export class EditProcessFilterCloudComponent implements OnChanges { const regExt = new RegExp(' ', 'g'); return name.replace(regExt, '-'); } + + showActions(): boolean { + return this.showFilterActions; + } + + onExpand(event: any) { + this.toggleFilterActions = true; + } + + onClose(event: any) { + this.toggleFilterActions = false; + } + + isDateType(property: ProcessFilterProperties): boolean { + return property.type === 'date'; + } + + isSelectType(property: ProcessFilterProperties): boolean { + return property.type === 'select'; + } + + isTextType(property: ProcessFilterProperties): boolean { + return property.type === 'text'; + } + + createProcessFilterProperties(currentProcessFilter: ProcessFilterCloudModel): ProcessFilterProperties[] { + return [ + new ProcessFilterProperties({ + label: 'ADF_CLOUD_EDIT_PROCESS_FILTER.LABEL.APP_NAME', + type: 'select', + key: 'appName', + value: currentProcessFilter.appName || '', + options: this.applicationNames + }), + new ProcessFilterProperties({ + label: 'ADF_CLOUD_EDIT_PROCESS_FILTER.LABEL.INITIATOR', + type: 'text', + key: 'initiator', + value: currentProcessFilter.initiator || '' + }), + new ProcessFilterProperties({ + label: 'ADF_CLOUD_EDIT_PROCESS_FILTER.LABEL.STATUS', + type: 'select', + key: 'state', + value: currentProcessFilter.state || this.status[0].value, + options: this.status + }), + new ProcessFilterProperties({ + label: 'ADF_CLOUD_EDIT_PROCESS_FILTER.LABEL.SORT', + type: 'select', + key: 'sort', + value: currentProcessFilter.sort || this.columns[0].value, + options: this.columns + }), + new ProcessFilterProperties({ + label: 'ADF_CLOUD_EDIT_PROCESS_FILTER.LABEL.DIRECTION', + type: 'select', + key: 'order', + value: currentProcessFilter.order || this.directions[0].value, + options: this.directions + }), + new ProcessFilterProperties({ + label: 'ADF_CLOUD_EDIT_PROCESS_FILTER.LABEL.PROCESS_NAME', + type: 'text', + key: 'processName', + value: currentProcessFilter.processName || '' + }), + new ProcessFilterProperties({ + label: 'ADF_CLOUD_EDIT_PROCESS_FILTER.LABEL.PROCESS_DEF_ID', + type: 'text', + key: 'processDefinitionId', + value: currentProcessFilter.processDefinitionId || '' + }), + new ProcessFilterProperties({ + label: 'ADF_CLOUD_EDIT_PROCESS_FILTER.LABEL.PROCESS_DEF_KEY', + type: 'text', + key: 'processDefinitionKey', + value: currentProcessFilter.processDefinitionKey || '' + }), + new ProcessFilterProperties({ + label: 'ADF_CLOUD_EDIT_PROCESS_FILTER.LABEL.PROCESS_INS_ID', + type: 'text', + key: 'processInstanceId', + value: '' + }), + new ProcessFilterProperties({ + label: 'ADF_CLOUD_EDIT_PROCESS_FILTER.LABEL.START_DATE', + type: 'date', + key: 'startDate', + value: '' + }), + new ProcessFilterProperties({ + label: 'ADF_CLOUD_EDIT_PROCESS_FILTER.LABEL.LAST_MODIFIED', + type: 'date', + key: 'lastModified', + value: '' + }), + new ProcessFilterProperties({ + label: 'ADF_CLOUD_EDIT_PROCESS_FILTER.LABEL.LAST_MODIFIED_DATE_FORM', + type: 'date', + key: 'lastModifiedFrom', + value: '' + }), + new ProcessFilterProperties({ + label: 'ADF_CLOUD_EDIT_PROCESS_FILTER.LABEL.LAST_MODIFIED_TO', + type: 'date', + key: 'lastModifiedTo', + value: '' + }) + ]; + } } 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 2e77410b4e..86f1f0c0b2 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 @@ -21,11 +21,19 @@ export class ProcessFilterCloudModel { key: string; icon: string; index: number; - processDefinitionId: string; appName: string; + processName: string; + initiator: string; state: string; sort: string; order: string; + processDefinitionId: string; + processDefinitionKey: string; + processInstanceId: string; + startDate: Date; + lastModified: Date; + lastModifiedTo: Date; + lastModifiedFrom: Date; constructor(obj?: any) { if (obj) { @@ -35,15 +43,46 @@ export class ProcessFilterCloudModel { this.icon = obj.icon || null; this.index = obj.index || null; this.appName = obj.appName || null; - this.processDefinitionId = obj.processDefinitionId || null; + this.processName = obj.processName || null; + this.initiator = obj.initiator || null; this.state = obj.state || null; this.sort = obj.sort || null; this.order = obj.order || null; + this.processDefinitionId = obj.processDefinitionId || null; + this.processDefinitionKey = obj.processDefinitionKey || null; + this.processInstanceId = obj.processInstanceId || null; + this.startDate = obj.startDate || null; + this.lastModified = obj.lastModified || null; + this.lastModifiedTo = obj.lastModifiedTo || null; + this.lastModifiedFrom = obj.lastModifiedFrom || null; } } } export interface ProcessFilterActionType { actionType: string; - id: string; + filter: ProcessFilterCloudModel; +} + +export interface ProcessFilterOptions { + label?: string; + value?: string; +} + +export class ProcessFilterProperties { + label: string; + type: string; + value: string; + key: string; + options: ProcessFilterOptions[]; + + constructor(obj?: any) { + if (obj) { + this.label = obj.label || null; + this.type = obj.type || null; + this.value = obj.value || ''; + this.key = obj.key || null; + this.options = obj.options || null; + } + } } 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 0c0595b243..b7d8105547 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 { ProcessFilterCloudService } from './services/process-filter-cloud.servi import { HttpClientModule } from '@angular/common/http'; import { EditProcessFilterCloudComponent } from './components/edit-process-filter-cloud.component'; import { ProcessFilterDialogCloudComponent } from './components/process-filter-dialog-cloud.component'; +import { AppListCloudModule } from './../../app/app-list-cloud.module'; @NgModule({ imports: [ FormsModule, @@ -40,7 +41,8 @@ import { ProcessFilterDialogCloudComponent } from './components/process-filter-d } }), FlexLayoutModule, - MaterialModule + MaterialModule, + AppListCloudModule ], declarations: [ProcessFiltersCloudComponent, EditProcessFilterCloudComponent, ProcessFilterDialogCloudComponent], exports: [ProcessFiltersCloudComponent, EditProcessFilterCloudComponent, ProcessFilterDialogCloudComponent], diff --git a/lib/process-services-cloud/src/lib/styles/_index.scss b/lib/process-services-cloud/src/lib/styles/_index.scss index 96dbccb9bd..1558379abe 100644 --- a/lib/process-services-cloud/src/lib/styles/_index.scss +++ b/lib/process-services-cloud/src/lib/styles/_index.scss @@ -4,6 +4,7 @@ @import './../task/task-filters/components/edit-task-filter-cloud.component.scss'; @import './../process/process-list/components/process-list-cloud.component.scss'; @import './../task/start-task/components/start-task-cloud.component.scss'; +@import './../process/process-filters/components/edit-process-filter-cloud.component.scss'; @import './../task/start-task/components/people-cloud/people-cloud.component.scss'; @import './../group/components/group-cloud.component'; @@ -13,6 +14,7 @@ @include adf-cloud-app-details-theme($theme); @include adf-cloud-task-filters-theme($theme); @include adf-cloud-edit-task-filters-theme($theme); + @include adf-cloud-edit-process-filter-theme($theme); @include adf-process-filters-cloud-theme($theme); @include adf-start-task-cloud-theme($theme); @include adf-cloud-people-theme($theme); 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 2762237df8..de51e41fec 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 @@ -4,8 +4,8 @@ {{taskFilter.name | translate}} {{ 'ADF_CLOUD_EDIT_TASK_FILTER.TITLE' | translate}} -
- +
+ @@ -22,24 +22,24 @@
- + - + {{ propertyOption.label }} - + - + {{taskFilterProperty.label | translate}} { let fixture: ComponentFixture; let dialog: MatDialog; let getTaskFilterSpy: jasmine.Spy; - let getDeployedApplicationsByStatusSpy: jasmine.Spy; + let getRunningApplicationsSpy: jasmine.Spy; let fakeFilter = new TaskFilterCloudModel({ name: 'FakeInvolvedTasks', icon: 'adjust', - id: 10, + id: 'mock-task-filter-id', state: 'CREATED', - appName: 'app-name', + appName: 'mock-app-name', processDefinitionId: 'process-def-id', assignment: 'fake-involved', order: 'ASC', @@ -70,7 +70,8 @@ describe('EditTaskFilterCloudComponent', () => { name: 'fake-name' }); }}); getTaskFilterSpy = spyOn(service, 'getTaskFilterById').and.returnValue(fakeFilter); - getDeployedApplicationsByStatusSpy = spyOn(appsService, 'getDeployedApplicationsByStatus').and.returnValue(of(fakeApplicationInstance)); + getRunningApplicationsSpy = spyOn(appsService, 'getDeployedApplicationsByStatus').and.returnValue(of(fakeApplicationInstance)); + fixture.detectChanges(); }); it('should create EditTaskFilterCloudComponent', () => { @@ -78,10 +79,11 @@ describe('EditTaskFilterCloudComponent', () => { }); it('should fetch task filter by taskId', async(() => { - let change = new SimpleChange(undefined, '10', true); - component.ngOnChanges({ 'id': change }); + let taskFilterIDchange = new SimpleChange(undefined, 'mock-task-filter-id', true); + component.ngOnChanges({ 'id': taskFilterIDchange}); fixture.detectChanges(); fixture.whenStable().then(() => { + expect(getTaskFilterSpy).toHaveBeenCalled(); expect(component.taskFilter.name).toEqual('FakeInvolvedTasks'); expect(component.taskFilter.icon).toEqual('adjust'); expect(component.taskFilter.state).toEqual('CREATED'); @@ -91,8 +93,8 @@ describe('EditTaskFilterCloudComponent', () => { })); it('should display filter name as title', () => { - let change = new SimpleChange(undefined, '10', true); - component.ngOnChanges({ 'id': change }); + let taskFilterIDchange = new SimpleChange(undefined, 'mock-task-filter-id', true); + component.ngOnChanges({ 'id': taskFilterIDchange}); fixture.detectChanges(); const title = fixture.debugElement.nativeElement.querySelector('#adf-edit-task-filter-title-id'); const subTitle = fixture.debugElement.nativeElement.querySelector('#adf-edit-task-filter-sub-title-id'); @@ -105,8 +107,8 @@ describe('EditTaskFilterCloudComponent', () => { describe('EditTaskFilter form', () => { beforeEach(() => { - let change = new SimpleChange(undefined, '10', true); - component.ngOnChanges({ 'id': change }); + let taskFilterIDchange = new SimpleChange(undefined, 'mock-task-filter-id', true); + component.ngOnChanges({'id': taskFilterIDchange}); fixture.detectChanges(); }); @@ -135,7 +137,7 @@ describe('EditTaskFilterCloudComponent', () => { })); it('should disable save button if the task filter is not changed', async(() => { - component.showFilterActions = true; + component.toggleFilterActions = true; let expansionPanel = fixture.debugElement.nativeElement.querySelector('mat-expansion-panel-header'); expansionPanel.click(); fixture.detectChanges(); @@ -146,7 +148,7 @@ describe('EditTaskFilterCloudComponent', () => { })); it('should disable saveAs button if the task filter is not changed', async(() => { - component.showFilterActions = true; + component.toggleFilterActions = true; let expansionPanel = fixture.debugElement.nativeElement.querySelector('mat-expansion-panel-header'); expansionPanel.click(); fixture.detectChanges(); @@ -157,7 +159,7 @@ describe('EditTaskFilterCloudComponent', () => { })); it('should enable delete button by default', async(() => { - component.showFilterActions = true; + component.toggleFilterActions = true; fixture.detectChanges(); let expansionPanel = fixture.debugElement.nativeElement.querySelector('mat-expansion-panel-header'); expansionPanel.click(); @@ -230,27 +232,15 @@ describe('EditTaskFilterCloudComponent', () => { }); })); - it('should able to fetch running applications', async(() => { - component.appName = 'mock-app-name'; - component.filterProperties = ['appName', 'processInstanceId', 'dueBefore']; - let change = new SimpleChange(undefined, 'mock-task-id', true); - component.ngOnChanges({ 'id': change }); - const appController = component.editTaskFilterForm.get('appName'); - fixture.detectChanges(); - fixture.whenStable().then(() => { - expect(appController).toBeDefined(); - expect(appController.value).toBe('mock-app-name' ); - expect(getDeployedApplicationsByStatusSpy).toHaveBeenCalled(); - }); - })); - it('should able to build a editTaskFilter form with default properties if input is empty', async(() => { + let taskFilterIDchange = new SimpleChange(undefined, 'mock-task-filter-id', true); + component.ngOnChanges({ 'id': taskFilterIDchange}); component.filterProperties = []; fixture.detectChanges(); + const stateController = component.editTaskFilterForm.get('state'); + const sortController = component.editTaskFilterForm.get('sort'); + const orderController = component.editTaskFilterForm.get('order'); fixture.whenStable().then(() => { - const stateController = component.editTaskFilterForm.get('state'); - const sortController = component.editTaskFilterForm.get('sort'); - const orderController = component.editTaskFilterForm.get('order'); fixture.detectChanges(); expect(component.taskFilterProperties).toBeDefined(); expect(component.taskFilterProperties.length).toBe(4); @@ -263,28 +253,46 @@ describe('EditTaskFilterCloudComponent', () => { expect(orderController.value).toBe('ASC'); }); })); + }); + + describe('Task filterProperties', () => { + + beforeEach(() => { + component.filterProperties = ['appName', 'processInstanceId', 'priority']; + }); + + it('should able to fetch running applications when appName property defined in the input', async(() => { + fixture.detectChanges(); + let taskFilterIDchange = new SimpleChange(undefined, 'mock-task-filter-id', true); + component.ngOnChanges({ 'id': taskFilterIDchange}); + const appController = component.editTaskFilterForm.get('appName'); + fixture.detectChanges(); + fixture.whenStable().then(() => { + expect(getRunningApplicationsSpy).toHaveBeenCalled(); + expect(appController).toBeDefined(); + expect(appController.value).toBe('mock-app-name'); + }); + })); it('should able to build a editTaskFilter form with given input properties', async(() => { - getTaskFilterSpy.and.returnValue({ processInstanceId: 'process-instance-id', priority: '12' }); - component.appName = 'mock-app-name'; - component.filterProperties = ['appName', 'processInstanceId', 'priority']; - let change = new SimpleChange(undefined, 'mock-task-id', true); - component.ngOnChanges({ 'id': change }); + fixture.detectChanges(); + getTaskFilterSpy.and.returnValue({ appName: 'mock-app-name', processInstanceId: 'process-instance-id', priority: '12' }); + let taskFilterIDchange = new SimpleChange(undefined, 'mock-task-filter-id', true); + component.ngOnChanges({ 'id': taskFilterIDchange}); + fixture.detectChanges(); const appController = component.editTaskFilterForm.get('appName'); - const propertyController = component.editTaskFilterForm.get('priority'); + const priorityController = component.editTaskFilterForm.get('priority'); const processInsIdController = component.editTaskFilterForm.get('processInstanceId'); fixture.detectChanges(); fixture.whenStable().then(() => { fixture.detectChanges(); - expect(getDeployedApplicationsByStatusSpy).toHaveBeenCalled(); expect(component.taskFilterProperties).toBeDefined(); expect(component.editTaskFilterForm).toBeDefined(); expect(component.taskFilterProperties.length).toBe(3); expect(appController).toBeDefined(); - expect(propertyController.value).toBe('12'); + expect(priorityController.value).toBe('12'); expect(processInsIdController).toBeDefined(); expect(appController.value).toBe('mock-app-name'); - expect(processInsIdController.value).toBe('process-instance-id'); }); })); }); @@ -292,13 +300,14 @@ describe('EditTaskFilterCloudComponent', () => { describe('edit filter actions', () => { beforeEach(() => { - let change = new SimpleChange(undefined, '10', true); - component.ngOnChanges({ 'id': change }); - component.filterProperties = ['state']; + let taskFilterIDchange = new SimpleChange(undefined, 'mock-task-filter-id', true); + component.ngOnChanges({ 'id': taskFilterIDchange}); + fixture.detectChanges(); + }); it('should emit save event and save the filter on click save button', async(() => { - component.showFilterActions = true; + component.toggleFilterActions = true; const saveFilterSpy = spyOn(service, 'updateFilter').and.returnValue(fakeFilter); let saveSpy: jasmine.Spy = spyOn(component.action, 'emit'); fixture.detectChanges(); @@ -321,7 +330,7 @@ describe('EditTaskFilterCloudComponent', () => { })); it('should emit delete event and delete the filter on click of delete button', async(() => { - component.showFilterActions = true; + component.toggleFilterActions = true; const deleteFilterSpy = spyOn(service, 'deleteFilter').and.callThrough(); let deleteSpy: jasmine.Spy = spyOn(component.action, 'emit'); fixture.detectChanges(); @@ -341,7 +350,7 @@ describe('EditTaskFilterCloudComponent', () => { })); it('should emit saveAs event and add filter on click saveAs button', async(() => { - component.showFilterActions = true; + component.toggleFilterActions = true; const saveAsFilterSpy = spyOn(service, 'addFilter').and.callThrough(); let saveAsSpy: jasmine.Spy = spyOn(component.action, 'emit'); fixture.detectChanges(); 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 4870a1296b..c944f72e80 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 @@ -16,21 +16,20 @@ */ import { Component, OnChanges, Input, Output, EventEmitter, SimpleChanges } from '@angular/core'; -import { AbstractControl , FormGroup, FormBuilder } from '@angular/forms'; -import { TaskFilterCloudModel, FilterActionType, TaskFilterProperties, FilterOptions } from './../models/filter-cloud.model'; +import { AbstractControl, FormGroup, FormBuilder } from '@angular/forms'; +import { TaskFilterCloudModel, FilterActionType, TaskFilterProperties } from './../models/filter-cloud.model'; import { TaskFilterCloudService } from '../services/task-filter-cloud.service'; import { MatDialog } from '@angular/material'; import { TaskFilterDialogCloudComponent } from './task-filter-dialog-cloud.component'; import { TranslationService } from '@alfresco/adf-core'; -import { debounceTime, map, filter } from 'rxjs/operators'; -import { of, Observable } from 'rxjs'; +import { debounceTime, filter } from 'rxjs/operators'; import { AppsProcessCloudService } from '../../../app/services/apps-process-cloud.service'; import { ApplicationInstanceModel } from '../../../app/models/application-instance.model'; import moment from 'moment-es6'; @Component({ - selector: 'adf-cloud-edit-task-filter', - templateUrl: './edit-task-filter-cloud.component.html', + selector: 'adf-cloud-edit-task-filter', + templateUrl: './edit-task-filter-cloud.component.html', styleUrls: ['./edit-task-filter-cloud.component.scss'] }) export class EditTaskFilterCloudComponent implements OnChanges { @@ -40,6 +39,7 @@ export class EditTaskFilterCloudComponent implements OnChanges { public static ACTION_DELETE = 'DELETE'; public static APP_RUNNING_STATUS: string = 'RUNNING'; public static MIN_VALUE = 1; + public static APPLICATION_NAME: string = 'appName'; public static DEFAULT_TASK_FILTER_PROPERTIES = ['state', 'assignment', 'sort', 'order']; public FORMAT_DATE: string = 'DD/MM/YYYY'; @@ -57,7 +57,7 @@ export class EditTaskFilterCloudComponent implements OnChanges { /** Toggles the filter actions. */ @Input() - toggleFilterActions = true; + showFilterActions = true; /** Toggles the title. */ @Input() @@ -75,21 +75,21 @@ export class EditTaskFilterCloudComponent implements OnChanges { changedTaskFilter: TaskFilterCloudModel; columns = [ - {value: 'id', label: 'ID'}, - {value: 'name', label: 'NAME'}, - {value: 'createdDate', label: 'CREATED DATE'}, - {value: 'priority', label: 'PRIORITY'}, - {value: 'processDefinitionId', label: 'PROCESS DEFINITION ID'} - ]; + { value: 'id', label: 'ID' }, + { value: 'name', label: 'NAME' }, + { value: 'createdDate', label: 'Created Date' }, + { value: 'priority', label: 'PRIORITY' }, + { value: 'processDefinitionId', label: 'PROCESS DEFINITION ID' } + ]; status = [ - {label: 'ALL', value: ''}, - {label: 'CREATED', value: 'CREATED'}, - {label: 'CANCELLED', value: 'CANCELLED'}, - {label: 'ASSIGNED', value: 'ASSIGNED'}, - {label: 'SUSPENDED', value: 'SUSPENDED'}, - {label: 'COMPLETED', value: 'COMPLETED'}, - {label: 'DELETED', value: 'DELETED'} + { label: 'ALL', value: '' }, + { label: 'CREATED', value: 'CREATED' }, + { label: 'CANCELLED', value: 'CANCELLED' }, + { label: 'ASSIGNED', value: 'ASSIGNED' }, + { label: 'SUSPENDED', value: 'SUSPENDED' }, + { label: 'COMPLETED', value: 'COMPLETED' }, + { label: 'DELETED', value: 'DELETED' } ]; directions = [ @@ -97,10 +97,11 @@ export class EditTaskFilterCloudComponent implements OnChanges { { label: 'DESC', value: 'DESC' } ]; + applicationNames: any[] = []; formHasBeenChanged = false; editTaskFilterForm: FormGroup; taskFilterProperties: any[] = []; - showFilterActions: boolean = false; + toggleFilterActions: boolean = false; constructor( private formBuilder: FormBuilder, @@ -108,19 +109,18 @@ export class EditTaskFilterCloudComponent implements OnChanges { private translateService: TranslationService, private taskFilterCloudService: TaskFilterCloudService, private appsProcessCloudService: AppsProcessCloudService) { - } + } ngOnChanges(changes: SimpleChanges) { const id = changes['id']; if (id && id.currentValue !== id.previousValue) { - this.retrieveTaskFilter(); - this.initTaskFilterProperties(this.taskFilter); + this.taskFilterProperties = this.createAndFilterProperties(); this.buildForm(this.taskFilterProperties); } } - retrieveTaskFilter() { - this.taskFilter = new TaskFilterCloudModel(this.taskFilterCloudService.getTaskFilterById(this.appName, this.id)); + retrieveTaskFilter(): TaskFilterCloudModel { + return new TaskFilterCloudModel(this.taskFilterCloudService.getTaskFilterById(this.appName, this.id)); } buildForm(taskFilterProperties: TaskFilterProperties[]) { @@ -141,21 +141,28 @@ export class EditTaskFilterCloudComponent implements OnChanges { */ onFilterChange() { this.editTaskFilterForm.valueChanges - .pipe(debounceTime(500), - filter(() => this.isFormValid())) + .pipe(debounceTime(500), + filter(() => this.isFormValid())) .subscribe((formValues: TaskFilterCloudModel) => { this.changedTaskFilter = new TaskFilterCloudModel(Object.assign({}, this.taskFilter, formValues)); this.formHasBeenChanged = !this.compareFilters(this.changedTaskFilter, this.taskFilter); this.filterChange.emit(this.changedTaskFilter); - }); + }); } - initTaskFilterProperties(taskFilter: TaskFilterCloudModel) { - if (this.filterProperties && this.filterProperties.length > 0) { - const defaultProperties = this.defaultTaskFilterProperties(taskFilter); - this.taskFilterProperties = defaultProperties.filter((filterProperty) => this.isValidProperty(this.filterProperties, filterProperty)); - } else { - this.taskFilterProperties = EditTaskFilterCloudComponent.DEFAULT_TASK_FILTER_PROPERTIES; + createAndFilterProperties(): TaskFilterProperties[] { + this.checkMandatoryFilterProperties(); + if (this.checkForApplicationNameProperty()) { + this.getRunningApplications(); + } + this.taskFilter = this.retrieveTaskFilter(); + const defaultProperties = this.createTaskFilterProperties(this.taskFilter); + return defaultProperties.filter((filterProperty: TaskFilterProperties) => this.isValidProperty(this.filterProperties, filterProperty)); + } + + checkMandatoryFilterProperties() { + if (this.filterProperties === undefined || this.filterProperties.length === 0) { + this.filterProperties = EditTaskFilterCloudComponent.DEFAULT_TASK_FILTER_PROPERTIES; } } @@ -163,6 +170,10 @@ export class EditTaskFilterCloudComponent implements OnChanges { return filterProperties ? filterProperties.indexOf(filterProperty.key) >= 0 : true; } + checkForApplicationNameProperty(): boolean { + return this.filterProperties ? this.filterProperties.indexOf(EditTaskFilterCloudComponent.APPLICATION_NAME) >= 0 : false; + } + isFormValid(): boolean { return this.editTaskFilterForm.valid; } @@ -200,17 +211,15 @@ export class EditTaskFilterCloudComponent implements OnChanges { return JSON.stringify(editedQuery).toLowerCase() === JSON.stringify(currentQuery).toLowerCase(); } - getRunningApplications(): Observable { - return this.appsProcessCloudService.getDeployedApplicationsByStatus(EditTaskFilterCloudComponent.APP_RUNNING_STATUS).pipe( - map((applications: ApplicationInstanceModel[]) => { + getRunningApplications() { + this.appsProcessCloudService.getDeployedApplicationsByStatus(EditTaskFilterCloudComponent.APP_RUNNING_STATUS) + .subscribe((applications: ApplicationInstanceModel[]) => { if (applications && applications.length > 0) { - let options: FilterOptions[] = []; applications.map((application) => { - options.push({ label: application.name, value: application.name }); + this.applicationNames.push({ label: application.name, value: application.name }); }); - return options; } - })); + }); } onSave() { @@ -232,16 +241,16 @@ export class EditTaskFilterCloudComponent implements OnChanges { height: 'auto', minWidth: '30%' }); - dialogRef.afterClosed().subscribe( (result) => { + dialogRef.afterClosed().subscribe((result) => { if (result && result.action === TaskFilterDialogCloudComponent.ACTION_SAVE) { const filterId = Math.random().toString(36).substr(2, 9); const filterKey = this.getSanitizeFilterName(result.name); const newFilter = { - name: result.name, - icon: result.icon, - id: filterId, - key: 'custom-' + filterKey - }; + name: result.name, + icon: result.icon, + id: filterId, + key: 'custom-' + filterKey + }; const resultFilter = Object.assign({}, this.changedTaskFilter, newFilter); this.taskFilterCloudService.addFilter(resultFilter); this.action.emit({actionType: EditTaskFilterCloudComponent.ACTION_SAVE_AS, filter: resultFilter}); @@ -260,16 +269,16 @@ export class EditTaskFilterCloudComponent implements OnChanges { return name.replace(regExt, '-'); } - toggleActions(): boolean { - return this.toggleFilterActions; + showActions(): boolean { + return this.showFilterActions; } onExpand(event: any) { - this.showFilterActions = true; + this.toggleFilterActions = true; } onClose(event: any) { - this.showFilterActions = false; + this.toggleFilterActions = false; } isDateType(property: TaskFilterProperties): boolean { @@ -284,21 +293,21 @@ export class EditTaskFilterCloudComponent implements OnChanges { return property.type === 'text'; } - defaultTaskFilterProperties(currentTaskFilter: TaskFilterCloudModel): TaskFilterProperties[] { + createTaskFilterProperties(currentTaskFilter: TaskFilterCloudModel): TaskFilterProperties[] { return [ new TaskFilterProperties({ label: 'ADF_CLOUD_EDIT_TASK_FILTER.LABEL.APP_NAME', type: 'select', key: 'appName', - value: this.appName || '', - options: this.getRunningApplications() + value: currentTaskFilter.appName || '', + options: this.applicationNames }), new TaskFilterProperties({ label: 'ADF_CLOUD_EDIT_TASK_FILTER.LABEL.STATUS', type: 'select', key: 'state', value: currentTaskFilter.state || this.status[0].value, - options: of(this.status) + options: this.status }), new TaskFilterProperties({ label: 'ADF_CLOUD_EDIT_TASK_FILTER.LABEL.ASSIGNMENT', @@ -317,14 +326,14 @@ export class EditTaskFilterCloudComponent implements OnChanges { type: 'select', key: 'sort', value: currentTaskFilter.sort || this.columns[0].value, - options: of(this.columns) + options: this.columns }), new TaskFilterProperties({ label: 'ADF_CLOUD_EDIT_TASK_FILTER.LABEL.DIRECTION', type: 'select', key: 'order', value: currentTaskFilter.order || this.directions[0].value, - options: of(this.directions) + options: this.directions }), new TaskFilterProperties({ label: 'ADF_CLOUD_EDIT_TASK_FILTER.LABEL.PROCESS_INSTANCE_ID', 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 ed880ec310..5af3ee1899 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,8 +15,6 @@ * limitations under the License. */ -import { Observable } from 'rxjs'; - export class TaskFilterCloudModel { id: string; name: string; @@ -108,10 +106,10 @@ export interface FilterOptions { export class TaskFilterProperties { label: string; - type: string; // text|date|select + type: string; value: string; key: string; - options$: Observable; + options: FilterOptions[]; constructor(obj?: any) { if (obj) { @@ -119,7 +117,7 @@ export class TaskFilterProperties { this.type = obj.type || null; this.value = obj.value || null; this.key = obj.key || null; - this.options$ = obj.options || null; + this.options = obj.options || null; } } }