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 f0d8ca9059..63ea2f8616 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
@@ -5,7 +5,6 @@
(action)="onTaskFilterAction($event)"
(filterChange)="onFilterChange($event)">
-
```
+By default these below properties are displayed:
+
+**_state_**, **_assignment_**, **_sort_**, **_order_**.
+
+However, you can also choose which properties to show using a 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",
+ "createdDateTo",
+ "lastModifiedTo"];
+
+ onFilterChange(filter: TaskFilterCloudModel) {
+ console.log('On filter change: ', filter);
+ }
+
+ onAction($event: FilterActionType) {
+ console.log('Clicked action: ', $event);
+ }
+```
+
+With this configuration, only the four listed properties will be shown.
+
+```html
+
+
+```
+
+
+All Available properties are:
+
+**_appName_**, **_state_**, **_assignment_**, **_sort_**, **_order_**, **_processDefinitionId_**, **_processInstanceId_**, **_dueAfter_**, **_dueBefore_**, **_claimedDateFrom_**, **_claimedDateTo_**, **_createdDateFrom_**, **_createdDateTo_**, **_taskName_**, **_parentTaskId_**, **_priority_**, **_standAlone_**, **_lastModifiedFrom_**, **_lastModifiedTo_**, **_owner_**, **_dueDateFrom_**, **_dueDateTo_**.
+

diff --git a/lib/process-services-cloud/src/lib/app/components/app-list-cloud.component.ts b/lib/process-services-cloud/src/lib/app/components/app-list-cloud.component.ts
index 850dfcc21c..113d46b792 100644
--- a/lib/process-services-cloud/src/lib/app/components/app-list-cloud.component.ts
+++ b/lib/process-services-cloud/src/lib/app/components/app-list-cloud.component.ts
@@ -30,7 +30,7 @@
public static LAYOUT_LIST: string = 'LIST';
public static LAYOUT_GRID: string = 'GRID';
- public static RUNNING_STATUS: string = 'Running';
+ public static RUNNING_STATUS: string = 'RUNNING';
@ContentChild(EmptyCustomContentDirective)
emptyCustomContent: EmptyCustomContentDirective;
diff --git a/lib/process-services-cloud/src/lib/app/services/apps-process-cloud.service.ts b/lib/process-services-cloud/src/lib/app/services/apps-process-cloud.service.ts
index bc41d0e903..a819b0d8d3 100644
--- a/lib/process-services-cloud/src/lib/app/services/apps-process-cloud.service.ts
+++ b/lib/process-services-cloud/src/lib/app/services/apps-process-cloud.service.ts
@@ -16,7 +16,7 @@
*/
import { Injectable } from '@angular/core';
-import { Observable, from, throwError } from 'rxjs';
+import { Observable, from, throwError, of } from 'rxjs';
import { map, catchError } from 'rxjs/operators';
import { AlfrescoApiService } from '@alfresco/adf-core';
import { AppConfigService, LogService } from '@alfresco/adf-core';
@@ -26,22 +26,21 @@ import { ApplicationInstanceModel } from '../models/application-instance.model';
@Injectable()
export class AppsProcessCloudService {
- contextRoot = '';
-
constructor(
private apiService: AlfrescoApiService,
private logService: LogService,
- private appConfig: AppConfigService) {
- this.contextRoot = this.appConfig.get('bpmHost', '');
- }
+ private appConfigService: AppConfigService) {}
/**
* Gets a list of deployed apps for this user by status.
* @returns The list of deployed apps
*/
getDeployedApplicationsByStatus(status: string): Observable {
+ if (status === '') {
+ return of([]);
+ }
const api: Oauth2Auth = this.apiService.getInstance().oauth2Auth;
- const path = `${this.contextRoot}/alfresco-deployment-service/v1/applications`;
+ const path = this.getApplicationUrl();
const pathParams = {}, queryParams = {},
headerParams = {}, formParams = {}, bodyParam = {},
contentTypes = ['application/json'], accepts = ['application/json'];
@@ -49,17 +48,19 @@ export class AppsProcessCloudService {
return from(api.callCustomApi(path, 'GET', pathParams, queryParams, headerParams, formParams, bodyParam,
contentTypes, accepts))
.pipe(
- map((apps: Array<{}>) => {
- return apps.filter((app: ApplicationInstanceModel) => app.status === status)
- .map((app) => {
- return new ApplicationInstanceModel(app);
- });
- }
- ),
- catchError((err) => this.handleError(err))
+ map((applications: ApplicationInstanceModel[]) => {
+ return applications.map((application) => {
+ return new ApplicationInstanceModel(application);
+ });
+ }),
+ catchError((err) => this.handleError(err))
);
}
+ private getApplicationUrl() {
+ return `${this.appConfigService.get('bpmHost')}/alfresco-deployment-service/v1/applications`;
+ }
+
private handleError(error?: any) {
this.logService.error(error);
return throwError(error || 'Server error');
diff --git a/lib/process-services-cloud/src/lib/i18n/en.json b/lib/process-services-cloud/src/lib/i18n/en.json
index 910da9db0c..2986c5c904 100644
--- a/lib/process-services-cloud/src/lib/i18n/en.json
+++ b/lib/process-services-cloud/src/lib/i18n/en.json
@@ -92,10 +92,30 @@
"DELETE": "Delete filter"
},
"LABEL": {
+ "APP_NAME": "ApplicationName",
+ "PROCESS_DEF_ID": "ProcessDefinitionId",
"STATUS": "Status",
"ASSIGNMENT": "Assignment",
"COLUMN": "Column",
- "DIRECTION": "Direction"
+ "DIRECTION": "Direction",
+ "PROCESS_INSTANCE_ID": "ProcessInstanceId",
+ "DUE_BEFORE": "DueBefore",
+ "DUE_AFTER": "DueAfter",
+ "CLAIMED_DATE_FROM": "ClaimedDateFrom",
+ "CLAIMED_DATE_TO": "ClaimedDateTo",
+ "CREATED_DATE_FORM": "CreatedDateFrom",
+ "CREATED_DATE_TO": "CreatedDateTo",
+ "TASK_NAME": "TaskName",
+ "PARENT_TASK_ID": "ParentTaskId",
+ "PRIORITY": "Priority",
+ "STAND_ALONE": "StandAlone",
+ "LAST_MODIFIED_FROM": "LastModifiedFrom",
+ "LAST_MODIFIED_TO": "LastModifiedTo",
+ "OWNER": "Owner",
+ "DUE_DATE_TO": "DueDateTo",
+ "DUE_DATE_FROM": "DueDateFrom"
+
+
},
"DIALOG": {
"TITLE": "Save filter as",
diff --git a/lib/process-services-cloud/src/lib/styles/_index.scss b/lib/process-services-cloud/src/lib/styles/_index.scss
index d2beeb8557..6b5c25aa7a 100644
--- a/lib/process-services-cloud/src/lib/styles/_index.scss
+++ b/lib/process-services-cloud/src/lib/styles/_index.scss
@@ -1,6 +1,7 @@
@import './../app/components/app-details-cloud.component';
@import './../app/components/app-list-cloud.component';
@import './../task/task-filters/components/task-filters-cloud.component.scss';
+@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 './../task/start-task/components/people-cloud/people-cloud.component.scss';
@@ -10,6 +11,7 @@
@include adf-cloud-app-list-theme($theme);
@include adf-cloud-app-details-theme($theme);
@include adf-cloud-task-filters-theme($theme);
+ @include adf-cloud-edit-task-filters-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 9ef9afd3a1..2762237df8 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
@@ -1,67 +1,65 @@
-
+
diff --git a/lib/process-services-cloud/src/lib/task/task-filters/components/edit-task-filter-cloud.component.scss b/lib/process-services-cloud/src/lib/task/task-filters/components/edit-task-filter-cloud.component.scss
index e69de29bb2..6934382cf3 100644
--- a/lib/process-services-cloud/src/lib/task/task-filters/components/edit-task-filter-cloud.component.scss
+++ b/lib/process-services-cloud/src/lib/task/task-filters/components/edit-task-filter-cloud.component.scss
@@ -0,0 +1,31 @@
+@mixin adf-cloud-edit-task-filters-theme($theme) {
+
+ $warn: map-get($theme, warn);
+
+ .adf-edit-task-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: 10px;
+ 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/task/task-filters/components/edit-task-filter-cloud.component.spec.ts b/lib/process-services-cloud/src/lib/task/task-filters/components/edit-task-filter-cloud.component.spec.ts
index 9b84d4efff..00572c06cf 100644
--- a/lib/process-services-cloud/src/lib/task/task-filters/components/edit-task-filter-cloud.component.spec.ts
+++ b/lib/process-services-cloud/src/lib/task/task-filters/components/edit-task-filter-cloud.component.spec.ts
@@ -19,22 +19,27 @@ 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 { MatDialog } from '@angular/material';
+import { of } from 'rxjs';
+
import { ProcessServiceCloudTestingModule } from '../../../testing/process-service-cloud.testing.module';
+import { AppsProcessCloudService } from '../../../app/services/apps-process-cloud.service';
+import { fakeApplicationInstance } from '../../../app/mock/app-model.mock';
import { TaskFilterCloudModel } from '../models/filter-cloud.model';
import { TaskFiltersCloudModule } from '../task-filters-cloud.module';
import { EditTaskFilterCloudComponent } from './edit-task-filter-cloud.component';
import { TaskFilterCloudService } from '../services/task-filter-cloud.service';
-import { MatDialog } from '@angular/material';
-import { of } from 'rxjs';
import { TaskFilterDialogCloudComponent } from './task-filter-dialog-cloud.component';
describe('EditTaskFilterCloudComponent', () => {
let component: EditTaskFilterCloudComponent;
let service: TaskFilterCloudService;
- let identityService: IdentityUserService;
+ let appsService: AppsProcessCloudService;
let fixture: ComponentFixture;
let dialog: MatDialog;
+ let getTaskFilterSpy: jasmine.Spy;
+ let getDeployedApplicationsByStatusSpy: jasmine.Spy;
let fakeFilter = new TaskFilterCloudModel({
name: 'FakeInvolvedTasks',
@@ -57,14 +62,15 @@ describe('EditTaskFilterCloudComponent', () => {
fixture = TestBed.createComponent(EditTaskFilterCloudComponent);
component = fixture.componentInstance;
service = TestBed.get(TaskFilterCloudService);
- identityService = TestBed.get(IdentityUserService);
+ appsService = TestBed.get(AppsProcessCloudService);
dialog = TestBed.get(MatDialog);
spyOn(dialog, 'open').and.returnValue({ afterClosed() { return of({
action: TaskFilterDialogCloudComponent.ACTION_SAVE,
icon: 'icon',
name: 'fake-name'
}); }});
- spyOn(service, 'getTaskFilterById').and.returnValue(fakeFilter);
+ getTaskFilterSpy = spyOn(service, 'getTaskFilterById').and.returnValue(fakeFilter);
+ getDeployedApplicationsByStatusSpy = spyOn(appsService, 'getDeployedApplicationsByStatus').and.returnValue(of(fakeApplicationInstance));
});
it('should create EditTaskFilterCloudComponent', () => {
@@ -93,7 +99,7 @@ describe('EditTaskFilterCloudComponent', () => {
expect(title).toBeDefined();
expect(subTitle).toBeDefined();
expect(title.innerText).toEqual('FakeInvolvedTasks');
- expect(subTitle.innerText).toEqual('ADF_CLOUD_EDIT_TASK_FILTER.TITLE');
+ expect(subTitle.innerText.trim()).toEqual('ADF_CLOUD_EDIT_TASK_FILTER.TITLE');
});
describe('EditTaskFilter form', () => {
@@ -104,11 +110,11 @@ describe('EditTaskFilterCloudComponent', () => {
fixture.detectChanges();
});
- it('should define editTaskFilter form ', () => {
+ it('should defined editTaskFilter form ', () => {
expect(component.editTaskFilterForm).toBeDefined();
});
- it('should create editTaskFilter form with given input ', async(() => {
+ it('should create editTaskFilter form with default properties', async(() => {
fixture.detectChanges();
fixture.whenStable().then(() => {
const stateController = component.editTaskFilterForm.get('state');
@@ -129,6 +135,7 @@ describe('EditTaskFilterCloudComponent', () => {
}));
it('should disable save button if the task filter is not changed', async(() => {
+ component.showFilterActions = true;
let expansionPanel = fixture.debugElement.nativeElement.querySelector('mat-expansion-panel-header');
expansionPanel.click();
fixture.detectChanges();
@@ -139,6 +146,7 @@ describe('EditTaskFilterCloudComponent', () => {
}));
it('should disable saveAs button if the task filter is not changed', async(() => {
+ component.showFilterActions = true;
let expansionPanel = fixture.debugElement.nativeElement.querySelector('mat-expansion-panel-header');
expansionPanel.click();
fixture.detectChanges();
@@ -149,9 +157,11 @@ describe('EditTaskFilterCloudComponent', () => {
}));
it('should enable delete button by default', async(() => {
+ component.showFilterActions = true;
fixture.detectChanges();
let expansionPanel = fixture.debugElement.nativeElement.querySelector('mat-expansion-panel-header');
expansionPanel.click();
+ fixture.detectChanges();
fixture.whenStable().then(() => {
let deleteButton = fixture.debugElement.nativeElement.querySelector('#adf-delete-id');
expect(deleteButton.disabled).toBe(false);
@@ -159,21 +169,22 @@ describe('EditTaskFilterCloudComponent', () => {
}));
it('should display current task 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-task-filter-state-id');
- let assignmentElement = fixture.debugElement.nativeElement.querySelector('#adf-task-filter-assignment-id');
- let sortElement = fixture.debugElement.nativeElement.querySelector('#adf-task-filter-sort-id');
- let orderElement = fixture.debugElement.nativeElement.querySelector('#adf-task-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-task-property-state"]');
+ let assignmentElement = fixture.debugElement.nativeElement.querySelector('[data-automation-id="adf-cloud-edit-task-property-assignment"]');
+ let sortElement = fixture.debugElement.nativeElement.querySelector('[data-automation-id="adf-cloud-edit-task-property-sort"]');
+ let orderElement = fixture.debugElement.nativeElement.querySelector('[data-automation-id="adf-cloud-edit-task-property-order"]');
expect(stateElement).toBeDefined();
expect(assignmentElement).toBeDefined();
expect(sortElement).toBeDefined();
expect(orderElement).toBeDefined();
- expect(stateElement.innerText.trim()).toBe('ADF_CLOUD_EDIT_TASK_FILTER.LABEL.STATUS');
- expect(sortElement.innerText.trim()).toBe('ADF_CLOUD_EDIT_TASK_FILTER.LABEL.COLUMN');
- expect(orderElement.innerText.trim()).toBe('ADF_CLOUD_EDIT_TASK_FILTER.LABEL.DIRECTION');
+ expect(stateElement.textContent.trim()).toBe('CREATED');
+ expect(sortElement.textContent.trim()).toBe('ID');
+ expect(orderElement.textContent.trim()).toBe('ASC');
});
}));
@@ -181,7 +192,8 @@ describe('EditTaskFilterCloudComponent', () => {
fixture.detectChanges();
let expansionPanel = fixture.debugElement.nativeElement.querySelector('mat-expansion-panel-header');
expansionPanel.click();
- const stateElement = fixture.debugElement.query(By.css('#adf-task-filter-state-id .mat-select-trigger')).nativeElement;
+ fixture.detectChanges();
+ let stateElement = fixture.debugElement.nativeElement.querySelector('[data-automation-id="adf-cloud-edit-task-property-state"] .mat-select-trigger');
stateElement.click();
fixture.detectChanges();
fixture.whenStable().then(() => {
@@ -194,7 +206,8 @@ describe('EditTaskFilterCloudComponent', () => {
fixture.detectChanges();
let expansionPanel = fixture.debugElement.nativeElement.querySelector('mat-expansion-panel-header');
expansionPanel.click();
- const sortElement = fixture.debugElement.query(By.css('#adf-task-filter-sort-id .mat-select-trigger')).nativeElement;
+ fixture.detectChanges();
+ let sortElement = fixture.debugElement.nativeElement.querySelector('[data-automation-id="adf-cloud-edit-task-property-sort"]');
sortElement.click();
fixture.detectChanges();
fixture.whenStable().then(() => {
@@ -207,7 +220,8 @@ describe('EditTaskFilterCloudComponent', () => {
fixture.detectChanges();
let expansionPanel = fixture.debugElement.nativeElement.querySelector('mat-expansion-panel-header');
expansionPanel.click();
- const orderElement = fixture.debugElement.query(By.css('#adf-task-filter-order-id .mat-select-trigger')).nativeElement;
+ fixture.detectChanges();
+ let orderElement = fixture.debugElement.nativeElement.querySelector('[data-automation-id="adf-cloud-edit-task-property-order"]');
orderElement.click();
fixture.detectChanges();
fixture.whenStable().then(() => {
@@ -215,6 +229,64 @@ describe('EditTaskFilterCloudComponent', () => {
expect(orderOptions.length).toEqual(2);
});
}));
+
+ 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(() => {
+ component.filterProperties = [];
+ fixture.detectChanges();
+ 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);
+ expect(component.editTaskFilterForm).toBeDefined();
+ expect(stateController).toBeDefined();
+ expect(sortController).toBeDefined();
+ expect(orderController).toBeDefined();
+ expect(stateController.value).toBe('CREATED');
+ expect(sortController.value).toBe('id');
+ expect(orderController.value).toBe('ASC');
+ });
+ }));
+
+ it('should able to build a editTaskFilter form with given input properties', async(() => {
+ getTaskFilterSpy.and.returnValue({ processInstanceId: 'process-instance-id', dueBefore: 'Fri Jan 04 2019 19:16:32 GMT+0530 (IST)' });
+ 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');
+ const dueDateController = component.editTaskFilterForm.get('dueBefore');
+ 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(dueDateController).toBeDefined();
+ expect(processInsIdController).toBeDefined();
+ expect(appController.value).toBe('mock-app-name');
+ expect(processInsIdController.value).toBe('process-instance-id');
+ });
+ }));
});
describe('edit filter actions', () => {
@@ -222,16 +294,18 @@ describe('EditTaskFilterCloudComponent', () => {
beforeEach(() => {
let change = new SimpleChange(undefined, '10', true);
component.ngOnChanges({ 'id': change });
+ component.filterProperties = ['state'];
});
it('should emit save event and save the filter on click save button', async(() => {
- spyOn(identityService, 'getCurrentUserInfo').and.returnValue({username: 'currentUser'});
+ component.showFilterActions = 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');
expansionPanel.click();
- const stateElement = fixture.debugElement.query(By.css('#adf-task-filter-state-id .mat-select-trigger')).nativeElement;
+ fixture.detectChanges();
+ let stateElement = fixture.debugElement.nativeElement.querySelector('[data-automation-id="adf-cloud-edit-task-property-sort"] .mat-select-trigger');
stateElement.click();
fixture.detectChanges();
const stateOptions = fixture.debugElement.queryAll(By.css('.mat-option-text'));
@@ -247,13 +321,14 @@ describe('EditTaskFilterCloudComponent', () => {
}));
it('should emit delete event and delete the filter on click of delete button', async(() => {
- spyOn(identityService, 'getCurrentUserInfo').and.returnValue({username: 'currentUser'});
+ component.showFilterActions = 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');
expansionPanel.click();
- const stateElement = fixture.debugElement.query(By.css('#adf-task-filter-state-id .mat-select-trigger')).nativeElement;
+ fixture.detectChanges();
+ let stateElement = fixture.debugElement.nativeElement.querySelector('[data-automation-id="adf-cloud-edit-task-property-sort"] .mat-select-trigger');
stateElement.click();
fixture.detectChanges();
let deleteButton = fixture.debugElement.nativeElement.querySelector('#adf-delete-id');
@@ -266,13 +341,14 @@ describe('EditTaskFilterCloudComponent', () => {
}));
it('should emit saveAs event and add filter on click saveAs button', async(() => {
- spyOn(identityService, 'getCurrentUserInfo').and.returnValue({username: 'currentUser'});
+ component.showFilterActions = 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');
expansionPanel.click();
- const stateElement = fixture.debugElement.query(By.css('#adf-task-filter-state-id .mat-select-trigger')).nativeElement;
+ fixture.detectChanges();
+ let stateElement = fixture.debugElement.nativeElement.querySelector('[data-automation-id="adf-cloud-edit-task-property-sort"] .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/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 e584233fd7..0ff7399e0d 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,37 +16,53 @@
*/
import { Component, OnChanges, Input, Output, EventEmitter, SimpleChanges } from '@angular/core';
-import { FormGroup, FormBuilder } from '@angular/forms';
-import { TaskFilterCloudModel, FilterActionType } from './../models/filter-cloud.model';
+import { AbstractControl , FormGroup, FormBuilder } from '@angular/forms';
+import { TaskFilterCloudModel, FilterActionType, TaskFilterProperties, FilterOptions } 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 } from 'rxjs/operators';
+import { debounceTime, map, filter } from 'rxjs/operators';
+import { of, Observable } from 'rxjs';
+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',
- styleUrls: ['./edit-task-filter-cloud.component.scss']
+ styleUrls: ['./edit-task-filter-cloud.component.scss']
})
export class EditTaskFilterCloudComponent implements OnChanges {
public static ACTION_SAVE = 'SAVE';
public static ACTION_SAVE_AS = 'SAVE_AS';
public static ACTION_DELETE = 'DELETE';
+ public static APP_RUNNING_STATUS: string = 'RUNNING';
+ public static MIN_VALUE = 1;
+ public static DEFAULT_TASK_FILTER_PROPERTIES = ['state', 'assignment', 'sort', 'order'];
+ public FORMAT_DATE: string = 'DD/MM/YYYY';
- /** Name of the app. */
+ /** (required) Name of the app. */
@Input()
appName: string;
- /** ID of the task filter. */
+ /** (required) ID of the task filter. */
@Input()
id: string;
- taskFilter: TaskFilterCloudModel;
- changedTaskFilter: TaskFilterCloudModel;
+ @Input()
+ filterProperties: string[] = EditTaskFilterCloudComponent.DEFAULT_TASK_FILTER_PROPERTIES; // default ['state', 'assignment', 'sort', 'order']
- /** Emitted when a task filter property changes. */
+ /** Toggles the filter actions. */
+ @Input()
+ toggleFilterActions = true;
+
+ /** Toggles the title. */
+ @Input()
+ showTitle = true;
+
+ /** Emitted when an task filter property changes. */
@Output()
filterChange: EventEmitter = new EventEmitter();
@@ -54,12 +70,15 @@ export class EditTaskFilterCloudComponent implements OnChanges {
@Output()
action: EventEmitter = new EventEmitter();
+ taskFilter: TaskFilterCloudModel;
+ changedTaskFilter: TaskFilterCloudModel;
+
columns = [
- {key: 'id', label: 'ID'},
- {key: 'name', label: 'NAME'},
- {key: 'createdDate', label: 'Created Date'},
- {key: 'priority', label: 'PRIORITY'},
- {key: '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 = [
@@ -72,39 +91,48 @@ export class EditTaskFilterCloudComponent implements OnChanges {
{label: 'DELETED', value: 'DELETED'}
];
- directions = ['ASC', 'DESC'];
+ directions = [
+ { label: 'ASC', value: 'ASC' },
+ { label: 'DESC', value: 'DESC' }
+ ];
+
formHasBeenChanged = false;
editTaskFilterForm: FormGroup;
+ taskFilterProperties: any[] = [];
+ showFilterActions: boolean = false;
constructor(
private formBuilder: FormBuilder,
public dialog: MatDialog,
private translateService: TranslationService,
- private taskFilterCloudService: TaskFilterCloudService) {}
+ private taskFilterCloudService: TaskFilterCloudService,
+ private appsProcessCloudService: AppsProcessCloudService) {
+ }
ngOnChanges(changes: SimpleChanges) {
const id = changes['id'];
if (id && id.currentValue !== id.previousValue) {
this.retrieveTaskFilter();
- this.buildForm();
+ this.initTaskFilterProperties(this.taskFilter);
+ this.buildForm(this.taskFilterProperties);
}
}
- buildForm() {
+ retrieveTaskFilter() {
+ this.taskFilter = new TaskFilterCloudModel(this.taskFilterCloudService.getTaskFilterById(this.appName, this.id));
+ }
+
+ buildForm(taskFilterProperties: TaskFilterProperties[]) {
this.formHasBeenChanged = false;
- this.editTaskFilterForm = this.formBuilder.group({
- state: this.taskFilter.state,
- appName: this.taskFilter.appName,
- processDefinitionId: this.taskFilter.processDefinitionId,
- assignment: this.taskFilter.assignment,
- sort: this.taskFilter.sort,
- order: this.taskFilter.order
- });
+ this.editTaskFilterForm = this.formBuilder.group(this.getFormControlsConfig(taskFilterProperties));
this.onFilterChange();
}
- retrieveTaskFilter() {
- this.taskFilter = this.taskFilterCloudService.getTaskFilterById(this.appName, this.id);
+ getFormControlsConfig(taskFilterProperties: TaskFilterProperties[]): any {
+ const properties = taskFilterProperties.map((property: TaskFilterProperties) => {
+ return { [property.key]: property.value };
+ });
+ return properties.reduce(((result, current) => Object.assign(result, current)), {});
}
/**
@@ -112,14 +140,58 @@ export class EditTaskFilterCloudComponent implements OnChanges {
*/
onFilterChange() {
this.editTaskFilterForm.valueChanges
- .pipe(debounceTime(300))
+ .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);
+ 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;
+ }
+ }
+
+ private isValidProperty(filterProperties: string[], filterProperty: any): boolean {
+ return filterProperties ? filterProperties.indexOf(filterProperty.key) >= 0 : true;
+ }
+
+ isFormValid(): boolean {
+ return this.editTaskFilterForm.valid;
+ }
+
+ getPropertyController(property: TaskFilterProperties): AbstractControl {
+ return this.editTaskFilterForm.get(property.key);
+ }
+
+ onDateChanged(newDateValue: any, dateProperty: TaskFilterProperties) {
+ 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());
+ } else {
+ this.getPropertyController(dateProperty).setErrors({ invalid: true });
+ }
+ }
+ }
+
+ hasError(property: TaskFilterProperties): boolean {
+ return this.getPropertyController(property).errors && this.getPropertyController(property).errors.invalid;
+ }
+
/**
* Check if both filters are same
*/
@@ -127,6 +199,19 @@ 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[]) => {
+ if (applications && applications.length > 0) {
+ let options: FilterOptions[] = [];
+ applications.map((application) => {
+ options.push({ label: application.name, value: application.name });
+ });
+ return options;
+ }
+ }));
+ }
+
onSave() {
this.taskFilterCloudService.updateFilter(this.changedTaskFilter);
this.action.emit({actionType: EditTaskFilterCloudComponent.ACTION_SAVE, id: this.changedTaskFilter.id});
@@ -155,14 +240,14 @@ export class EditTaskFilterCloudComponent implements OnChanges {
id: filterId,
key: 'custom-' + filterKey
};
- const filter = Object.assign({}, this.changedTaskFilter, newFilter);
- this.taskFilterCloudService.addFilter(filter);
- this.action.emit({actionType: EditTaskFilterCloudComponent.ACTION_SAVE_AS, id: filter.id});
+ const resultFilter = Object.assign({}, this.changedTaskFilter, newFilter);
+ this.taskFilterCloudService.addFilter(resultFilter);
+ this.action.emit({actionType: EditTaskFilterCloudComponent.ACTION_SAVE_AS, id: resultFilter.id});
}
});
}
- getSanitizeFilterName(filterName) {
+ getSanitizeFilterName(filterName): string {
const nameWithHyphen = this.replaceSpaceWithHyphen(filterName.trim());
return nameWithHyphen.toLowerCase();
}
@@ -171,4 +256,171 @@ export class EditTaskFilterCloudComponent implements OnChanges {
const regExt = new RegExp(' ', 'g');
return name.replace(regExt, '-');
}
+
+ toggleActions(): boolean {
+ return this.toggleFilterActions;
+ }
+
+ onExpand(event: any) {
+ this.showFilterActions = true;
+ }
+
+ onClose(event: any) {
+ this.showFilterActions = false;
+ }
+
+ isDateType(property: TaskFilterProperties): boolean {
+ return property.type === 'date';
+ }
+
+ isSelectType(property: TaskFilterProperties): boolean {
+ return property.type === 'select';
+ }
+
+ isTextType(property: TaskFilterProperties): boolean {
+ return property.type === 'text';
+ }
+
+ defaultTaskFilterProperties(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()
+ }),
+ 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)
+ }),
+ new TaskFilterProperties({
+ label: 'ADF_CLOUD_EDIT_TASK_FILTER.LABEL.ASSIGNMENT',
+ type: 'text',
+ key: 'assignment',
+ value: currentTaskFilter.assignment || ''
+ }),
+ new TaskFilterProperties({
+ label: 'ADF_CLOUD_EDIT_TASK_FILTER.LABEL.PROCESS_DEF_ID',
+ type: 'text',
+ key: 'processDefinitionId',
+ value: currentTaskFilter.processDefinitionId || ''
+ }),
+ new TaskFilterProperties({
+ label: 'ADF_CLOUD_EDIT_TASK_FILTER.LABEL.COLUMN',
+ type: 'select',
+ key: 'sort',
+ value: currentTaskFilter.sort || this.columns[0].value,
+ options: of(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)
+ }),
+ new TaskFilterProperties({
+ label: 'ADF_CLOUD_EDIT_TASK_FILTER.LABEL.PROCESS_INSTANCE_ID',
+ type: 'text',
+ key: 'processInstanceId',
+ value: currentTaskFilter.processInstanceId || ''
+ }),
+ new TaskFilterProperties({
+ label: 'ADF_CLOUD_EDIT_TASK_FILTER.LABEL.DUE_AFTER',
+ type: 'date',
+ key: 'dueAfter',
+ value: ''
+ }),
+ new TaskFilterProperties({
+ label: 'ADF_CLOUD_EDIT_TASK_FILTER.LABEL.DUE_BEFORE',
+ type: 'date',
+ key: 'dueBefore',
+ value: ''
+ }),
+ new TaskFilterProperties({
+ label: 'ADF_CLOUD_EDIT_TASK_FILTER.LABEL.CLAIMED_DATE_FROM',
+ type: 'date',
+ key: 'claimedDateFrom',
+ value: ''
+ }),
+ new TaskFilterProperties({
+ label: 'ADF_CLOUD_EDIT_TASK_FILTER.LABEL.CLAIMED_DATE_TO',
+ type: 'date',
+ key: 'claimedDateTo',
+ value: ''
+ }),
+ new TaskFilterProperties({
+ label: 'ADF_CLOUD_EDIT_TASK_FILTER.LABEL.CREATED_DATE_FORM',
+ type: 'date',
+ key: 'createdDateFrom',
+ value: ''
+ }),
+ new TaskFilterProperties({
+ label: 'ADF_CLOUD_EDIT_TASK_FILTER.LABEL.CREATED_DATE_TO',
+ type: 'date',
+ key: 'createdDateTo',
+ value: ''
+ }),
+ new TaskFilterProperties({
+ label: 'ADF_CLOUD_EDIT_TASK_FILTER.LABEL.TASK_NAME',
+ type: 'text',
+ key: 'taskName',
+ value: currentTaskFilter.taskName || ''
+ }),
+ new TaskFilterProperties({
+ label: 'ADF_CLOUD_EDIT_TASK_FILTER.LABEL.PARENT_TASK_ID',
+ type: 'text',
+ key: 'parentTaskId',
+ value: currentTaskFilter.parentTaskId || ''
+ }),
+ new TaskFilterProperties({
+ label: 'ADF_CLOUD_EDIT_TASK_FILTER.LABEL.PRIORITY',
+ type: 'text',
+ key: 'priority',
+ value: currentTaskFilter.priority || ''
+ }),
+ new TaskFilterProperties({
+ label: 'ADF_CLOUD_EDIT_TASK_FILTER.LABEL.STAND_ALONE',
+ type: 'text',
+ key: 'standAlone',
+ value: currentTaskFilter.standAlone || ''
+ }),
+
+ new TaskFilterProperties({
+ label: 'ADF_CLOUD_EDIT_TASK_FILTER.LABEL.LAST_MODIFIED_FROM',
+ type: 'date',
+ key: 'lastModifiedFrom',
+ value: ''
+ }),
+
+ new TaskFilterProperties({
+ label: 'ADF_CLOUD_EDIT_TASK_FILTER.LABEL.LAST_MODIFIED_TO',
+ type: 'date',
+ key: 'lastModifiedTo',
+ value: ''
+ }),
+ new TaskFilterProperties({
+ label: 'ADF_CLOUD_EDIT_TASK_FILTER.LABEL.OWNER',
+ type: 'text',
+ key: 'owner',
+ value: currentTaskFilter.owner || ''
+ }),
+ new TaskFilterProperties({
+ label: 'ADF_CLOUD_EDIT_TASK_FILTER.LABEL.DUE_DATE_FROM',
+ type: 'date',
+ key: 'dueDateFrom',
+ value: ''
+ }),
+ new TaskFilterProperties({
+ label: 'ADF_CLOUD_EDIT_TASK_FILTER.LABEL.DUE_DATE_TO',
+ type: 'date',
+ key: 'dueDateTo',
+ value: ''
+ })
+ ];
+ }
}
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 0a1b89ea0e..a0bc0a3340 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,6 +15,8 @@
* limitations under the License.
*/
+import { Observable } from 'rxjs';
+
export class TaskFilterCloudModel {
id: string;
name: string;
@@ -27,6 +29,23 @@ export class TaskFilterCloudModel {
sort: string;
assignment: string;
order: string;
+ description: string;
+ dueAfter: Date;
+ dueBefore: Date;
+ owner: string;
+ processInstanceId: string;
+ claimedDateFrom: Date;
+ claimedDateTo: Date;
+ createdDateFrom: Date;
+ createdDateTo: Date;
+ dueDateFrom: Date;
+ dueDateTo: Date;
+ taskName: string;
+ parentTaskId: string;
+ priority: number;
+ standAlone: any;
+ lastModifiedFrom: Date;
+ lastModifiedTo: Date;
constructor(obj?: any) {
if (obj) {
@@ -41,14 +60,32 @@ export class TaskFilterCloudModel {
this.sort = obj.sort || null;
this.assignment = obj.assignment || null;
this.order = obj.order || null;
+ this.description = obj.description || null;
+ this.dueAfter = obj.dueAfter || null;
+ this.dueBefore = obj.dueBefore || null;
+ this.processInstanceId = obj.processInstanceId || null;
+ this.claimedDateFrom = obj.claimedDateFrom || null;
+ this.claimedDateTo = obj.claimedDateTo || null;
+ this.createdDateFrom = obj.createdDateFrom || null;
+ this.createdDateTo = obj.createdDateTo || null;
+ this.dueDateFrom = obj.dueDateFrom || null;
+ this.dueDateTo = obj.dueDateTo || null;
+ this.taskName = obj.taskName || null;
+ this.parentTaskId = obj.parentTaskId || null;
+ this.priority = obj.priority || null;
+ this.standAlone = obj.standAlone || null;
+ this.lastModifiedFrom = obj.lastModifiedFrom || null;
+ this.lastModifiedTo = obj.lastModifiedTo || null;
}
}
}
export class FilterParamsModel {
+
id?: string;
name?: string;
key?: string;
index?: number;
+
constructor(obj?: any) {
if (obj) {
this.id = obj.id || null;
@@ -58,7 +95,31 @@ export class FilterParamsModel {
}
}
}
+
export interface FilterActionType {
actionType: string;
id: string;
}
+
+export interface FilterOptions {
+ label?: string;
+ value?: string;
+}
+
+export class TaskFilterProperties {
+ label: string;
+ type: string; // text|date|select
+ value: string;
+ key: string;
+ options$: Observable;
+
+ constructor(obj?: any) {
+ if (obj) {
+ this.label = obj.label || null;
+ this.type = obj.type || null;
+ this.value = obj.value || null;
+ this.key = obj.key || null;
+ this.options$ = obj.options || null;
+ }
+ }
+}
diff --git a/lib/process-services-cloud/src/lib/task/task-filters/task-filters-cloud.module.ts b/lib/process-services-cloud/src/lib/task/task-filters/task-filters-cloud.module.ts
index 930b510afb..2e381c2b4f 100644
--- a/lib/process-services-cloud/src/lib/task/task-filters/task-filters-cloud.module.ts
+++ b/lib/process-services-cloud/src/lib/task/task-filters/task-filters-cloud.module.ts
@@ -27,6 +27,8 @@ import { TaskFilterCloudService } from './services/task-filter-cloud.service';
import { HttpClientModule } from '@angular/common/http';
import { EditTaskFilterCloudComponent } from './components/edit-task-filter-cloud.component';
import { TaskFilterDialogCloudComponent } from './components/task-filter-dialog-cloud.component';
+import { AppListCloudModule } from './../../app/app-list-cloud.module';
+
@NgModule({
imports: [
FormsModule,
@@ -40,7 +42,8 @@ import { TaskFilterDialogCloudComponent } from './components/task-filter-dialog-
useClass: TranslateLoaderService
}
}),
- MaterialModule
+ MaterialModule,
+ AppListCloudModule
],
declarations: [TaskFiltersCloudComponent, EditTaskFilterCloudComponent, TaskFilterDialogCloudComponent],
exports: [TaskFiltersCloudComponent, EditTaskFilterCloudComponent],