[AAE-3992] Process Filter bug fixes and improvements (#6599)

* bug fixes

* bug fixes

* bug fixes

* cleanup tests

* travis workaround

* travis workaround

* travis workaround

* travis workaround

* travis workaround

* travis workaround

* Revert "travis workaround"

This reverts commit b67efccfb0aab8c7f6b9235d01525487771b8123.

* Revert "travis workaround"

This reverts commit 448f4e6d1211771e914f35183860af6df3452c16.

* Revert "travis workaround"

This reverts commit 542fae649c0501a9150ccac2e5a2cd54ee39a690.

* Revert "travis workaround"

This reverts commit 12f58568fbb0f8d2defb4c21a3ab1683bc8aa312.

* Revert "travis workaround"

This reverts commit b0ffef3bee0f81faf6088be8b5c2b072ad2762e7.

* Revert "travis workaround"

This reverts commit c6d95a2ff3b38b543fea83d3fc53016ac657b3bb.

* service fixes

* remove junk tests

* code fixes

* reduce code complexity

* update e2e

* update e2e

* fix i18n

* e2e fixes

* bug fixes

* rebase and fix

* properly serialize query params

* rework process filters demo

* remove dead code

* code fixes

* code fixes

* e2e improvements

* fix bug and remove e2e testing a bug

* bug fixes for date ranges

* fix e2e

* fix unit test

* reusable code

* fix flaky e2e

* fix angular cli version

* remove useless e2e (already tested by unit tests)

* remove useless e2e (already tested by unit tests)

* demo shell fixes

* remove fit

* disable flaky test

* update code as per review suggestions

* fix after rebase

* fix after rebase
This commit is contained in:
Denys Vuika
2021-02-23 16:58:31 +00:00
committed by GitHub
parent 52930dec6d
commit 63969d65e7
46 changed files with 1057 additions and 1775 deletions

View File

@@ -1082,40 +1082,40 @@
"presets": {
"default": [
{
"key": "entry.id",
"key": "id",
"type": "text",
"title": "ADF_CLOUD_TASK_LIST.PROPERTIES.ID",
"cssClass": "adf-expand-cell-4",
"sortable": true
},
{
"key": "entry.name",
"key": "name",
"type": "text",
"title": "ADF_CLOUD_TASK_LIST.PROPERTIES.NAME",
"sortable": true,
"cssClass": "name-column adf-ellipsis-cell"
},
{
"key": "entry.status",
"key": "status",
"type": "text",
"title": "ADF_CLOUD_TASK_LIST.PROPERTIES.STATUS",
"sortable": true
},
{
"key": "entry.priority",
"key": "priority",
"type": "text",
"title": "ADF_CLOUD_TASK_LIST.PROPERTIES.PRIORITY",
"sortable": true
},
{
"key": "entry.createdDate",
"key": "createdDate",
"type": "date",
"title": "ADF_CLOUD_TASK_LIST.PROPERTIES.CREATED_DATE",
"sortable": true,
"format": "timeAgo"
},
{
"key": "entry.lastModified",
"key": "lastModified",
"type": "date",
"title": "ADF_CLOUD_TASK_LIST.PROPERTIES.LAST_MODIFIED",
"sortable": true,
@@ -1128,32 +1128,32 @@
"presets": {
"default": [
{
"key": "entry.id",
"key": "id",
"type": "text",
"title": "ADF_CLOUD_SERVICE_TASK_LIST.PROPERTIES.ID",
"sortable": true
},
{
"key": "entry.activityName",
"key": "activityName",
"type": "text",
"title": "ADF_CLOUD_SERVICE_TASK_LIST.PROPERTIES.ACTIVITY_NAME",
"sortable": true
},
{
"key": "entry.status",
"key": "status",
"type": "text",
"title": "ADF_CLOUD_SERVICE_TASK_LIST.PROPERTIES.STATUS",
"sortable": true
},
{
"key": "entry.startedDate",
"key": "startedDate",
"type": "date",
"title": "ADF_CLOUD_SERVICE_TASK_LIST.PROPERTIES.STARTED_DATE",
"sortable": true,
"format": "timeAgo"
},
{
"key": "entry.completedDate",
"key": "completedDate",
"type": "date",
"title": "ADF_CLOUD_SERVICE_TASK_LIST.PROPERTIES.COMPLETED_DATE",
"sortable": true,
@@ -1166,25 +1166,25 @@
"presets": {
"default": [
{
"key": "entry.id",
"key": "id",
"type": "text",
"title": "ADF_CLOUD_PROCESS_LIST.PROPERTIES.ID",
"sortable": true
},
{
"key": "entry.name",
"key": "name",
"type": "text",
"title": "ADF_CLOUD_PROCESS_LIST.PROPERTIES.NAME",
"sortable": true
},
{
"key": "entry.status",
"key": "status",
"type": "text",
"title": "ADF_CLOUD_PROCESS_LIST.PROPERTIES.STATUS",
"sortable": true
},
{
"key": "entry.startDate",
"key": "startDate",
"type": "date",
"title": "ADF_CLOUD_PROCESS_LIST.PROPERTIES.START_DATE",
"sortable": true,

View File

@@ -19,6 +19,8 @@ import { Component, ViewEncapsulation, Input, OnInit } from '@angular/core';
import { Observable } from 'rxjs';
import { CloudLayoutService } from './services/cloud-layout.service';
import { Router, ActivatedRoute } from '@angular/router';
import { CloudProcessFiltersService } from './services/cloud-process-filters.service';
import { ProcessFilterCloudModel } from '@alfresco/adf-process-services-cloud';
@Component({
selector: 'app-cloud-filters-demo',
templateUrl: './cloud-filters-demo.component.html',
@@ -42,7 +44,8 @@ export class CloudFiltersDemoComponent implements OnInit {
constructor(
private cloudLayoutService: CloudLayoutService,
private router: Router,
private route: ActivatedRoute
private route: ActivatedRoute,
private cloudProcessFiltersService: CloudProcessFiltersService
) {}
ngOnInit() {
@@ -63,11 +66,19 @@ export class CloudFiltersDemoComponent implements OnInit {
}
onTaskFilterSelected(filter) {
this.router.navigate([`/cloud/${this.appName}/tasks/`], { queryParams: filter });
if (filter) {
this.router.navigate([`/cloud/${this.appName}/tasks/`], {queryParams: filter});
}
}
onProcessFilterSelected(filter) {
this.router.navigate([`/cloud/${this.appName}/processes/`], { queryParams: filter });
onProcessFilterSelected(filter: ProcessFilterCloudModel) {
if (filter) {
const {appName} = this;
const {id} = filter;
const queryParams = this.cloudProcessFiltersService.writeQueryParams(filter, appName, id);
this.router.navigate([`/cloud/${appName}/processes/`], {queryParams});
}
}
onTaskFilterOpen(): boolean {

View File

@@ -145,6 +145,6 @@ export class CommunityProcessesCloudDemoComponent implements OnInit, OnDestroy {
onRowsSelected(nodes) {
this.resetSelectedRows();
this.selectedRows = nodes.map((node) => node.obj.entry);
this.selectedRows = nodes.map((node) => node.obj);
}
}

View File

@@ -127,7 +127,7 @@ export class CommunityTasksCloudDemoComponent implements OnInit, OnDestroy {
onRowsSelected(nodes) {
this.resetSelectedRows();
this.selectedRows = nodes.map((node) => node.obj.entry);
this.selectedRows = nodes.map((node) => node.obj);
}
onFilterChange(filter: any) {

View File

@@ -2,9 +2,10 @@
<adf-cloud-edit-process-filter
[appName]="appName"
[id]="filterId"
[filterProperties]="processFilterProperties.filterProperties"
[sortProperties]="processFilterProperties.sortProperties"
[actions]="processFilterProperties.actions"
[filterProperties]="filterProperties"
[sortProperties]="filterSortProperties"
[actions]="filterActions"
[processFilter]="editedFilter"
(filterChange)="onFilterChange($event)"
(action)="onProcessFilterAction($event)">
</adf-cloud-edit-process-filter>
@@ -24,7 +25,7 @@
[businessKey]="editedFilter['businessKey']"
[lastModifiedFrom]="editedFilter.lastModifiedFrom"
[lastModifiedTo]="editedFilter.lastModifiedTo"
[sorting]="sortArray"
[sorting]="[{orderBy: editedFilter.sort, direction: editedFilter.order}]"
[selectionMode]="selectionMode"
[stickyHeader]="true"
[showActions]="actionMenu"

View File

@@ -15,42 +15,24 @@
* limitations under the License.
*/
import { Component, ViewChild, OnInit, OnDestroy } from '@angular/core';
import {
ProcessListCloudComponent,
ProcessFilterCloudModel,
ProcessListCloudSortingModel,
ProcessFiltersCloudComponent
} from '@alfresco/adf-process-services-cloud';
import { Component, OnInit, OnDestroy } from '@angular/core';
import { EditProcessFilterCloudComponent, ProcessFilterAction, ProcessFilterCloudModel, ProcessFilterCloudService } from '@alfresco/adf-process-services-cloud';
import { ActivatedRoute, Router } from '@angular/router';
import { UserPreferencesService, AppConfigService, DataCellEvent } from '@alfresco/adf-core';
import { UserPreferencesService, DataCellEvent } from '@alfresco/adf-core';
import { CloudLayoutService, CloudServiceSettings } from './services/cloud-layout.service';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
import { Pagination } from '@alfresco/js-api';
import { CloudProcessFiltersService } from './services/cloud-process-filters.service';
@Component({
templateUrl: './processes-cloud-demo.component.html',
styleUrls: ['./processes-cloud-demo.component.scss']
templateUrl: './processes-cloud-demo.component.html'
})
export class ProcessesCloudDemoComponent implements OnInit, OnDestroy {
public static ACTION_SAVE_AS = 'saveAs';
public static ACTION_DELETE = 'delete';
static PROCESS_FILTER_PROPERTY_KEYS = 'adf-edit-process-filter';
@ViewChild('processCloud')
processCloud: ProcessListCloudComponent;
@ViewChild('processFiltersCloud')
processFiltersCloud: ProcessFiltersCloudComponent;
appName: string = '';
isFilterLoaded: boolean;
isFilterLoaded = false;
filterId: string = '';
sortArray: any = [];
selectedRow: any;
multiselect: boolean;
selectionMode: string;
@@ -61,7 +43,11 @@ export class ProcessesCloudDemoComponent implements OnInit, OnDestroy {
actions: any[] = [];
selectedAction: { id: number, name: string, actionType: string};
selectedContextAction: { id: number, name: string, actionType: string};
processFilterProperties: any = { filterProperties: [], sortProperties: [], actions: [] };
filterProperties: string[];
filterSortProperties: string[];
filterActions: string[];
processDetailsRedirection: boolean;
editedFilter: ProcessFilterCloudModel;
@@ -73,24 +59,24 @@ export class ProcessesCloudDemoComponent implements OnInit, OnDestroy {
private route: ActivatedRoute,
private router: Router,
private cloudLayoutService: CloudLayoutService,
private userPreference: UserPreferencesService,
private appConfig: AppConfigService) {
const properties = this.appConfig.get<Array<any>>(ProcessesCloudDemoComponent.PROCESS_FILTER_PROPERTY_KEYS);
if (properties) {
this.processFilterProperties = properties;
}
private cloudProcessFiltersService: CloudProcessFiltersService,
private processFilterCloudService: ProcessFilterCloudService,
private userPreference: UserPreferencesService) {
}
ngOnInit() {
this.isFilterLoaded = false;
this.route.parent.params.subscribe((params) => {
this.appName = params.appName;
});
this.filterProperties = this.cloudProcessFiltersService.filterProperties;
this.filterSortProperties = this.cloudProcessFiltersService.sortProperties;
this.filterActions = this.cloudProcessFiltersService.actions;
this.route.queryParams.subscribe((params) => {
this.isFilterLoaded = true;
this.onFilterChange(params);
this.appName = params.appName;
this.filterId = params.id;
const model = this.cloudProcessFiltersService.readQueryParams(params);
this.loadFilter(model);
});
this.cloudLayoutService.settings$
@@ -134,31 +120,26 @@ export class ProcessesCloudDemoComponent implements OnInit, OnDestroy {
}
}
onFilterChange(query: any) {
this.editedFilter = Object.assign({}, query);
this.sortArray = [
new ProcessListCloudSortingModel({
orderBy: this.editedFilter.sort,
direction: this.editedFilter.order
})
];
onFilterChange(filter: ProcessFilterCloudModel) {
const queryParams = this.cloudProcessFiltersService.writeQueryParams(filter, this.appName, this.filterId);
this.router.navigate([`/cloud/${this.appName}/processes/`], {queryParams});
}
onProcessFilterAction(filterAction: any) {
if (filterAction.actionType === ProcessesCloudDemoComponent.ACTION_DELETE) {
onProcessFilterAction(filterAction: ProcessFilterAction) {
if (filterAction.actionType === EditProcessFilterCloudComponent.ACTION_DELETE) {
this.cloudLayoutService.setCurrentProcessFilterParam({ index: 0 });
} else {
this.cloudLayoutService.setCurrentProcessFilterParam({ id: filterAction.filter.id });
}
if (filterAction.actionType === ProcessesCloudDemoComponent.ACTION_SAVE_AS) {
this.router.navigate([`/cloud/${this.appName}/processes/`], { queryParams: filterAction.filter });
if ([EditProcessFilterCloudComponent.ACTION_SAVE, EditProcessFilterCloudComponent.ACTION_SAVE_AS].includes(filterAction.actionType)) {
this.onFilterChange(filterAction.filter);
}
}
onRowsSelected(nodes) {
this.resetSelectedRows();
this.selectedRows = nodes.map((node) => node.obj.entry);
this.selectedRows = nodes.map((node) => node.obj);
}
onShowRowActionsMenu(event: DataCellEvent) {
@@ -197,4 +178,12 @@ export class ProcessesCloudDemoComponent implements OnInit, OnDestroy {
const action = contextAction.model;
this.selectedContextAction = {id: value.id, name: value.name, actionType: action.title};
}
private loadFilter(model: ProcessFilterCloudModel) {
if (model && model.appName && model.id) {
this.processFilterCloudService.getFilterById(model.appName, model.id).subscribe(filter => {
this.editedFilter = Object.assign({}, filter, model);
});
}
}
}

View File

@@ -0,0 +1,55 @@
/*!
* @license
* Copyright 2019 Alfresco Software, Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { Injectable } from '@angular/core';
import { ProcessFilterCloudModel, ProcessFilterCloudService } from '@alfresco/adf-process-services-cloud';
import { AppConfigService } from '@alfresco/adf-core';
@Injectable({ providedIn: 'root' })
export class CloudProcessFiltersService {
constructor(private appConfigService: AppConfigService, private processFilterCloudService: ProcessFilterCloudService) {
}
get filterProperties(): string[] {
return this.appConfigService.get(
'adf-edit-process-filter.filterProperties',
['status', 'sort', 'order', 'processName']
);
}
get sortProperties(): string[] {
return this.appConfigService.get(
'adf-edit-process-filter.sortProperties',
['id', 'name', 'status', 'startDate']
);
}
get actions(): string[] {
return this.appConfigService.get(
'adf-edit-process-filter.actions',
['save', 'saveAs', 'delete']
);
}
readQueryParams(obj: Object): ProcessFilterCloudModel {
return this.processFilterCloudService.readQueryParams(obj);
}
writeQueryParams(value: Object, appName?: string, id?: string): Object {
return this.processFilterCloudService.writeQueryParams(value, this.filterProperties, appName, id);
}
}

View File

@@ -125,7 +125,7 @@ export class TasksCloudDemoComponent implements OnInit, OnDestroy {
onRowsSelected(nodes) {
this.resetSelectedRows();
this.selectedRows = nodes.map((node) => node.obj.entry);
this.selectedRows = nodes.map((node) => node.obj);
}
onFilterChange(filter: any) {

View File

@@ -12,27 +12,29 @@ Shows a JSON-formatted value inside a datatable component.
## Basic Usage
```html
<adf-datatable ...>
<adf-datatable>
<data-columns>
<data-column key="entry.json" type="json" title="Json Column"></data-column>
<data-column key="json" type="json" title="Json Column"></data-column>
</data-columns>
</adf-datatable>
```
You can specify the cell inside the `app.config.json` file:
```javascript
"adf-cloud-process-list": {
```json
{
"adf-cloud-process-list": {
"presets": {
"default": [
{
"key": "entry.json",
"key": "json",
"type": "json",
"title": "Json cell value"
}
]
}
},
}
}
```
## Class members

View File

@@ -22,62 +22,62 @@ export class ProcessListCloudConfiguration {
'presets': {
'default': [
{
'key': 'entry.id',
'key': 'id',
'type': 'text',
'title': 'ADF_CLOUD_PROCESS_LIST.PROPERTIES.ID',
'sortable': true
},
{
'key': 'entry.name',
'key': 'name',
'type': 'text',
'title': 'ADF_CLOUD_PROCESS_LIST.PROPERTIES.NAME',
'sortable': true
},
{
'key': 'entry.status',
'key': 'status',
'type': 'text',
'title': 'ADF_CLOUD_PROCESS_LIST.PROPERTIES.STATUS',
'sortable': true
},
{
'key': 'entry.startDate',
'key': 'startDate',
'type': 'date',
'title': 'ADF_CLOUD_PROCESS_LIST.PROPERTIES.START_DATE',
'sortable': true,
'format': 'timeAgo'
},
{
'key': 'entry.appName',
'key': 'appName',
'type': 'text',
'title': 'ADF_CLOUD_PROCESS_LIST.PROPERTIES.APP_NAME',
'sortable': true
},
{
'key': 'entry.businessKey',
'key': 'businessKey',
'type': 'text',
'title': 'ADF_CLOUD_PROCESS_LIST.PROPERTIES.BUSINESS_KEY',
'sortable': true
},
{
'key': 'entry.initiator',
'key': 'initiator',
'type': 'text',
'title': 'ADF_CLOUD_PROCESS_LIST.PROPERTIES.STARTED_BY',
'sortable': true
},
{
'key': 'entry.lastModified',
'key': 'lastModified',
'type': 'date',
'title': 'ADF_CLOUD_PROCESS_LIST.PROPERTIES.LAST_MODIFIED',
'sortable': true
},
{
'key': 'entry.processDefinitionId',
'key': 'processDefinitionId',
'type': 'text',
'title': 'ADF_CLOUD_PROCESS_LIST.PROPERTIES.PROCESS_DEF_ID',
'sortable': true
},
{
'key': 'entry.processDefinitionKey',
'key': 'processDefinitionKey',
'type': 'text',
'title': 'ADF_CLOUD_PROCESS_LIST.PROPERTIES.PROCESS_DEF_KEY',
'sortable': true

View File

@@ -25,84 +25,84 @@ export class TaskListCloudConfiguration {
'presets': {
'default': [
{
'key': 'entry.id',
'key': 'id',
'type': 'text',
'title': 'ADF_CLOUD_TASK_LIST.PROPERTIES.ID',
'sortable': true
},
{
'key': 'entry.name',
'key': 'name',
'type': 'text',
'title': 'ADF_CLOUD_TASK_LIST.PROPERTIES.NAME',
'sortable': true,
'cssClass': 'full-width name-column ellipsis-cell'
},
{
'key': 'entry.processDefinitionId',
'key': 'processDefinitionId',
'type': 'text',
'title': 'ADF_CLOUD_EDIT_TASK_FILTER.LABEL.PROCESS_DEF_ID',
'sortable': true,
'cssClass': 'full-width name-column ellipsis-cell'
},
{
'key': 'entry.processInstanceId',
'key': 'processInstanceId',
'type': 'text',
'title': 'ADF_CLOUD_EDIT_TASK_FILTER.LABEL.PROCESS_INSTANCE_ID',
'sortable': true,
'cssClass': 'full-width name-column ellipsis-cell'
},
{
'key': 'entry.status',
'key': 'status',
'type': 'text',
'title': 'ADF_CLOUD_TASK_LIST.PROPERTIES.STATUS',
'sortable': true
},
{
'key': 'entry.priority',
'key': 'priority',
'type': 'text',
'title': 'ADF_CLOUD_TASK_LIST.PROPERTIES.PRIORITY',
'sortable': true
},
{
'key': 'entry.createdDate',
'key': 'createdDate',
'type': 'date',
'title': 'ADF_CLOUD_TASK_LIST.PROPERTIES.CREATED_DATE',
'sortable': true,
'format': 'timeAgo'
},
{
'key': 'entry.lastModified',
'key': 'lastModified',
'type': 'date',
'title': 'ADF_CLOUD_TASK_LIST.PROPERTIES.LAST_MODIFIED',
'sortable': true,
'format': 'timeAgo'
},
{
'key': 'entry.assignee',
'key': 'assignee',
'type': 'text',
'title': 'ADF_CLOUD_TASK_LIST.PROPERTIES.ASSIGNEE',
'sortable': true
},
{
'key': 'entry.parentTaskId',
'key': 'parentTaskId',
'type': 'text',
'title': 'ADF_CLOUD_EDIT_TASK_FILTER.LABEL.PARENT_TASK_ID',
'sortable': true
},
{
'key': 'entry.priority',
'key': 'priority',
'type': 'text',
'title': 'ADF_CLOUD_EDIT_TASK_FILTER.LABEL.PRIORITY',
'sortable': true
},
{
'key': 'entry.standalone',
'key': 'standalone',
'type': 'text',
'title': 'ADF_CLOUD_EDIT_TASK_FILTER.LABEL.STAND_ALONE',
'sortable': true
},
{
'key': 'entry.owner',
'key': 'owner',
'type': 'text',
'title': 'ADF_CLOUD_EDIT_TASK_FILTER.LABEL.OWNER',
'sortable': true

View File

@@ -81,10 +81,6 @@ describe('Edit process filters cloud', () => {
await editProcessFilter.checkSaveButtonIsDisplayed();
await editProcessFilter.checkSaveAsButtonIsDisplayed();
await editProcessFilter.checkDeleteButtonIsDisplayed();
await expect(await editProcessFilter.checkSaveButtonIsEnabled()).toEqual(false);
await expect(await editProcessFilter.checkSaveAsButtonIsEnabled()).toEqual(false);
await expect(await editProcessFilter.checkDeleteButtonIsEnabled()).toEqual(false);
await editProcessFilter.openFilter();
});
it('[C586757] Delete Save and Save as actions should be displayed and enabled when clicking on custom filter header', async () => {
@@ -110,10 +106,7 @@ describe('Edit process filters cloud', () => {
await expect(await processFilter.getActiveFilterName()).toBe('New');
await editProcessFilter.openFilter();
await expect(await editProcessFilter.checkSaveButtonIsEnabled()).toEqual(false);
await expect(await editProcessFilter.getSortFilterDropDownValue()).toEqual('Id');
await expect(await editProcessFilter.checkSaveAsButtonIsEnabled()).toEqual(false);
await expect(await editProcessFilter.checkDeleteButtonIsEnabled()).toEqual(true);
await processFilter.clickAllProcessesFilter();
await expect(await editProcessFilter.getSortFilterDropDownValue()).toEqual('Start Date');
await processFilter.clickProcessFilter('custom-new');
@@ -121,50 +114,10 @@ describe('Edit process filters cloud', () => {
await editProcessFilter.clickDeleteButton();
});
it('[C291806] Two process filters with same name can be created when clicking the Save As button', async () => {
await editProcessFilter.setSortFilterDropDown('Id');
await editProcessFilter.clickSaveAsButton();
await editProcessFilter.editProcessFilterDialog().setFilterName('New');
await editProcessFilter.editProcessFilterDialog().clickOnSaveButton();
await browser.driver.sleep(1000);
await editProcessFilter.openFilter();
await editProcessFilter.checkCustomiseFilterHeaderIsExpanded();
await expect(await processFilter.getActiveFilterName()).toBe('New');
await expect(await editProcessFilter.getSortFilterDropDownValue()).toEqual('Id');
await editProcessFilter.setSortFilterDropDown('Process Name');
await expect(await editProcessFilter.getSortFilterDropDownValue()).toEqual('Process Name');
await editProcessFilter.clickSaveAsButton();
await editProcessFilter.editProcessFilterDialog().setFilterName('New');
await editProcessFilter.editProcessFilterDialog().clickOnSaveButton();
await editProcessFilter.openFilter();
await editProcessFilter.checkCustomiseFilterHeaderIsExpanded();
await browser.driver.sleep(1000);
await expect(await processFilter.getActiveFilterName()).toBe('New');
await expect(await editProcessFilter.getSortFilterDropDownValue()).toEqual('Process Name');
await editProcessFilter.clickDeleteButton();
await browser.driver.sleep(1000);
await processFilter.clickProcessFilter('custom-new');
await editProcessFilter.openFilter();
await editProcessFilter.checkCustomiseFilterHeaderIsExpanded();
await expect(await editProcessFilter.getSortFilterDropDownValue()).toEqual('Id');
await editProcessFilter.clickDeleteButton();
});
it('[C291807] A process filter is overrided when clicking on save button', async () => {
it('[C291807] A process filter is updated when clicking on save button', async () => {
await editProcessFilter.setSortFilterDropDown('Id');
await processFilter.clickAllProcessesFilter();
await editProcessFilter.clickSaveAsButton();
await editProcessFilter.editProcessFilterDialog().setFilterName('New');
await editProcessFilter.editProcessFilterDialog().clickOnSaveButton();
await browser.driver.sleep(1000);
await editProcessFilter.saveAs('New');
await expect(await processFilter.getActiveFilterName()).toBe('New');
await editProcessFilter.openFilter();
@@ -186,12 +139,8 @@ describe('Edit process filters cloud', () => {
it('[C291808] A process filter is deleted when clicking on delete button', async () => {
await editProcessFilter.setSortFilterDropDown('Id');
await processFilter.clickAllProcessesFilter();
await editProcessFilter.clickSaveAsButton();
await editProcessFilter.editProcessFilterDialog().setFilterName('New');
await editProcessFilter.saveAs('New');
await browser.driver.sleep(1000);
await editProcessFilter.editProcessFilterDialog().clickOnSaveButton();
await editProcessFilter.openFilter();
await expect(await processFilter.getActiveFilterName()).toBe('New');
await expect(await editProcessFilter.getSortFilterDropDownValue()).toEqual('Id');
@@ -258,9 +207,6 @@ describe('Edit process filters cloud', () => {
async function createNewProcessCustomFilter(name: string): Promise<void> {
await editProcessFilter.setSortFilterDropDown('Id');
await processFilter.clickAllProcessesFilter();
await editProcessFilter.clickSaveAsButton();
await editProcessFilter.editProcessFilterDialog().setFilterName(name);
await editProcessFilter.editProcessFilterDialog().clickOnSaveButton();
await editProcessFilter.saveAs(name);
}
});

View File

@@ -244,9 +244,7 @@ describe('Process list cloud', () => {
await editProcessFilter.openFilter();
await editProcessFilter.setProcessInstanceId(completedProcess.entry.id);
await editProcessFilter.clickSaveAsButton();
await editProcessFilter.editProcessFilterDialog().setFilterName('New');
await editProcessFilter.editProcessFilterDialog().clickOnSaveButton();
await editProcessFilter.saveAs('New');
await expect(await processCloudDemoPage.processFilterCloudComponent.getActiveFilterName()).toBe('New');
@@ -274,9 +272,7 @@ describe('Process list cloud', () => {
await expect(await editProcessFilter.checkAppNamesAreUnique()).toBe(true);
await BrowserActions.closeMenuAndDialogs();
await editProcessFilter.clickSaveAsButton();
await editProcessFilter.editProcessFilterDialog().setFilterName('SavedFilter');
await editProcessFilter.editProcessFilterDialog().clickOnSaveButton();
await editProcessFilter.saveAs('SavedFilter');
await expect(await processCloudDemoPage.processFilterCloudComponent.getActiveFilterName()).toBe('SavedFilter');
await editProcessFilter.openFilter();
@@ -288,9 +284,7 @@ describe('Process list cloud', () => {
await waitTillContentLoaded();
await processList.checkContentIsDisplayedById(switchProcessInstance.entry.id);
await editProcessFilter.clickSaveAsButton();
await editProcessFilter.editProcessFilterDialog().setFilterName('SwitchFilter');
await editProcessFilter.editProcessFilterDialog().clickOnSaveButton();
await editProcessFilter.saveAs('SwitchFilter');
await expect(await processCloudDemoPage.processFilterCloudComponent.getActiveFilterName()).toBe('SwitchFilter');
await editProcessFilter.openFilter();

View File

@@ -157,6 +157,7 @@ describe('Process filters cloud', () => {
await appListCloudComponent.goToApp(candidateBaseApp);
await tasksCloudDemoPage.taskListCloudComponent().checkTaskListIsLoaded();
await processCloudDemoPage.processFilterCloudComponent.clickOnProcessFilters();
await processCloudDemoPage.processFilterCloudComponent.clickRunningProcessesFilter();
});
it('[C306887] Should be able to filter by appName', async () => {
@@ -189,10 +190,8 @@ describe('Process filters cloud', () => {
it('[C311315] Should be able to filter by process definition id', async () => {
await editProcessFilter.openFilter();
await editProcessFilter.setProperty('processDefinitionId', processDefinition.entry.id);
await editProcessFilter.setProcessName(runningProcessInstance.entry.name);
await processList.checkContentIsDisplayedByName(runningProcessInstance.entry.name);
await editProcessFilter.setProcessName(anotherProcessInstance.entry.name);
await editProcessFilter.setProperty('processDefinitionId', anotherProcessDefinition.entry.id);
await processList.checkContentIsDisplayedByName(anotherProcessInstance.entry.name);
await processList.checkContentIsNotDisplayedByName(runningProcessInstance.entry.name);
@@ -286,18 +285,14 @@ describe('Process filters cloud', () => {
});
it('[C306892] Should be able to filter by process status - All', async () => {
await processCloudDemoPage.processFilterCloudComponent.clickAllProcessesFilter();
await editProcessFilter.openFilter();
await editProcessFilter.setStatusFilterDropDown(PROCESS_STATUS.ALL);
await editProcessFilter.setProcessName(runningProcessInstance.entry.name);
await processList.checkContentIsDisplayedByName(runningProcessInstance.entry.name);
await editProcessFilter.setProcessName(anotherProcessInstance.entry.name);
await processList.checkContentIsDisplayedByName(anotherProcessInstance.entry.name);
await editProcessFilter.setProcessName(suspendProcessInstance.entry.name);
await processList.checkContentIsDisplayedByName(suspendProcessInstance.entry.name);
await editProcessFilter.setProcessName(completedProcess.entry.name);
await processList.checkContentIsDisplayedByName(completedProcess.entry.name);
});

View File

@@ -1,127 +0,0 @@
/*!
* @license
* Copyright 2019 Alfresco Software, Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import {
ApiService,
AppListCloudPage,
GroupIdentityService,
IdentityService,
LoginPage,
ProcessDefinitionsService,
ProcessInstancesService,
StringUtil
} from '@alfresco/adf-testing';
import { browser } from 'protractor';
import { ProcessCloudDemoPage } from './pages/process-cloud-demo.page';
import { TasksCloudDemoPage } from './pages/tasks-cloud-demo.page';
import { NavigationBarPage } from '../core/pages/navigation-bar.page';
import CONSTANTS = require('../util/constants');
describe('Process list cloud', () => {
describe('Process List - Custom Action Menu', () => {
const simpleApp = browser.params.resources.ACTIVITI_CLOUD_APPS.SIMPLE_APP.name;
const loginSSOPage = new LoginPage();
const navigationBarPage = new NavigationBarPage();
const appListCloudComponent = new AppListCloudPage();
const processCloudDemoPage = new ProcessCloudDemoPage();
const editProcessFilter = processCloudDemoPage.editProcessFilterCloudComponent();
const processList = processCloudDemoPage.processListCloudComponent();
const tasksCloudDemoPage = new TasksCloudDemoPage();
const apiService = new ApiService();
const identityService = new IdentityService(apiService);
const groupIdentityService = new GroupIdentityService(apiService);
const processDefinitionService = new ProcessDefinitionsService(apiService);
const processInstancesService = new ProcessInstancesService(apiService);
let testUser, groupInfo, editProcess, deleteProcess;
beforeAll(async () => {
await apiService.loginWithProfile('identityAdmin');
testUser = await identityService.createIdentityUserWithRole([identityService.ROLES.ACTIVITI_USER]);
groupInfo = await groupIdentityService.getGroupInfoByGroupName('hr');
await identityService.addUserToGroup(testUser.idIdentityService, groupInfo.id);
await apiService.login(testUser.username, testUser.password);
const processDefinition = await processDefinitionService
.getProcessDefinitionByName(browser.params.resources.ACTIVITI_CLOUD_APPS.SIMPLE_APP.processes.simpleProcess, simpleApp);
editProcess = await processInstancesService.createProcessInstance(processDefinition.entry.key, simpleApp, {
'name': StringUtil.generateRandomString(),
'businessKey': StringUtil.generateRandomString()
});
deleteProcess = await processInstancesService.createProcessInstance(processDefinition.entry.key, simpleApp, {
'name': StringUtil.generateRandomString(),
'businessKey': StringUtil.generateRandomString()
});
await loginSSOPage.login(testUser.username, testUser.password);
await navigationBarPage.navigateToProcessServicesCloudPage();
await appListCloudComponent.checkApsContainer();
await appListCloudComponent.goToApp(simpleApp);
await tasksCloudDemoPage.clickSettingsButton();
await tasksCloudDemoPage.enableTestingMode();
await tasksCloudDemoPage.enableActionMenu();
await tasksCloudDemoPage.enableContextMenu();
await tasksCloudDemoPage.addActionIsDisplayed();
await tasksCloudDemoPage.addAction('edit');
await tasksCloudDemoPage.actionAdded('edit');
await tasksCloudDemoPage.addAction('delete');
await tasksCloudDemoPage.actionAdded('delete');
await tasksCloudDemoPage.addDisabledAction('disabledaction');
await tasksCloudDemoPage.actionAdded('disabledaction');
await tasksCloudDemoPage.addInvisibleAction('invisibleaction');
await tasksCloudDemoPage.actionAdded('invisibleaction');
await tasksCloudDemoPage.clickAppButton();
await processCloudDemoPage.processFilterCloudComponent.clickOnProcessFilters();
await processCloudDemoPage.processFilterCloudComponent.clickRunningProcessesFilter();
});
afterAll(async () => {
await apiService.loginWithProfile('identityAdmin');
await identityService.deleteIdentityUser(testUser.idIdentityService);
});
it('[C315236] Should be able to see and execute custom action menu', async () => {
await editProcessFilter.openFilter();
await editProcessFilter.setProcessName(editProcess.entry.name);
await expect(await processCloudDemoPage.processFilterCloudComponent.getActiveFilterName()).toBe(CONSTANTS.PROCESS_FILTERS.RUNNING);
await processList.checkProcessListIsLoaded();
await processList.checkContentIsDisplayedById(editProcess.entry.id);
await processList.clickOptionsButton(editProcess.entry.id);
await expect(await processList.isCustomActionEnabled('disabledaction')).toBe(false);
await expect(await processList.getNumberOfOptions()).toBe(3);
await processList.clickOnCustomActionMenu('edit');
await processCloudDemoPage.checkActionExecuted(editProcess.entry.id, 'edit');
await editProcessFilter.setProcessName(deleteProcess.entry.name);
await browser.sleep(1000);
await processList.rightClickOnRow(deleteProcess.entry.id);
await expect(await processList.isCustomActionEnabled('disabledaction')).toBe(false);
await expect(await processList.getNumberOfOptions()).toBe(3);
await processList.clickContextMenuActionNamed('delete');
await processCloudDemoPage.checkActionExecuted(deleteProcess.entry.id, 'delete');
});
});
});

View File

@@ -1,113 +0,0 @@
/*!
* @license
* Copyright 2019 Alfresco Software, Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { ApiService, AppListCloudPage, GroupIdentityService, IdentityService, LoginPage, ProcessDefinitionsService, ProcessInstancesService, QueryService, TasksService } from '@alfresco/adf-testing';
import { browser } from 'protractor';
import { TasksCloudDemoPage } from './pages/tasks-cloud-demo.page';
import { NavigationBarPage } from '../core/pages/navigation-bar.page';
describe('Process list cloud', () => {
describe('Process List - Custom Action Menu', () => {
const simpleApp = browser.params.resources.ACTIVITI_CLOUD_APPS.SIMPLE_APP.name;
const loginSSOPage = new LoginPage();
const navigationBarPage = new NavigationBarPage();
const appListCloudComponent = new AppListCloudPage();
const tasksCloudDemoPage = new TasksCloudDemoPage();
const editTaskFilter = tasksCloudDemoPage.editTaskFilterCloud;
const taskFilter = tasksCloudDemoPage.taskFilterCloudComponent;
const taskList = tasksCloudDemoPage.taskListCloudComponent();
const apiService = new ApiService();
const identityService = new IdentityService(apiService);
const groupIdentityService = new GroupIdentityService(apiService);
const processDefinitionService = new ProcessDefinitionsService(apiService);
const processInstancesService = new ProcessInstancesService(apiService);
const queryService = new QueryService(apiService);
const tasksService = new TasksService(apiService);
let testUser, groupInfo, editProcess, deleteProcess, editTask, deleteTask;
beforeAll(async () => {
await apiService.loginWithProfile('identityAdmin');
testUser = await identityService.createIdentityUserWithRole( [identityService.ROLES.ACTIVITI_USER]);
groupInfo = await groupIdentityService.getGroupInfoByGroupName('hr');
await identityService.addUserToGroup(testUser.idIdentityService, groupInfo.id);
await apiService.login(testUser.username, testUser.password);
const processDefinition = await processDefinitionService
.getProcessDefinitionByName(browser.params.resources.ACTIVITI_CLOUD_APPS.SIMPLE_APP.processes.dropdownrestprocess, simpleApp);
editProcess = await processInstancesService.createProcessInstance(processDefinition.entry.key, simpleApp);
deleteProcess = await processInstancesService.createProcessInstance(processDefinition.entry.key, simpleApp);
editTask = await queryService.getProcessInstanceTasks(editProcess.entry.id, simpleApp);
deleteTask = await queryService.getProcessInstanceTasks(deleteProcess.entry.id, simpleApp);
await tasksService.claimTask(editTask.list.entries[0].entry.id, simpleApp);
await tasksService.claimTask(deleteTask.list.entries[0].entry.id, simpleApp);
await loginSSOPage.login(testUser.username, testUser.password);
});
afterAll(async() => {
await apiService.loginWithProfile('identityAdmin');
await identityService.deleteIdentityUser(testUser.idIdentityService);
});
beforeAll(async () => {
await navigationBarPage.navigateToProcessServicesCloudPage();
await appListCloudComponent.checkApsContainer();
await appListCloudComponent.goToApp(simpleApp);
await tasksCloudDemoPage.clickSettingsButton();
await tasksCloudDemoPage.enableTestingMode();
await tasksCloudDemoPage.enableActionMenu();
await tasksCloudDemoPage.enableContextMenu();
await tasksCloudDemoPage.addActionIsDisplayed();
await tasksCloudDemoPage.addAction('edit');
await tasksCloudDemoPage.actionAdded('edit');
await tasksCloudDemoPage.addAction('delete');
await tasksCloudDemoPage.actionAdded('delete');
await tasksCloudDemoPage.addDisabledAction('disabledaction');
await tasksCloudDemoPage.actionAdded('disabledaction');
await tasksCloudDemoPage.addInvisibleAction('invisibleaction');
await tasksCloudDemoPage.actionAdded('invisibleaction');
await tasksCloudDemoPage.clickAppButton();
await editTaskFilter.openFilter();
await taskFilter.checkTaskFilterIsDisplayed('my-tasks');
});
it('[C315723] Should be able to see and execute custom action menu', async () => {
await expect(await taskFilter.getActiveFilterName()).toBe('My Tasks');
await taskList.checkTaskListIsLoaded();
await taskList.checkContentIsDisplayedById(editTask.list.entries[0].entry.id);
await taskList.clickOptionsButton(editTask.list.entries[0].entry.id);
await expect(await taskList.isCustomActionEnabled('disabledaction')).toBe(false);
await expect(await taskList.getNumberOfOptions()).toBe(3);
await taskList.clickOnCustomActionMenu('edit');
await tasksCloudDemoPage.checkActionExecuted(editTask.list.entries[0].entry.id, 'edit');
await taskList.rightClickOnRow(deleteTask.list.entries[0].entry.id);
await expect(await taskList.isCustomActionEnabled('disabledaction')).toBe(false);
await expect(await taskList.getNumberOfOptions()).toBe(3);
await taskList.clickContextMenuActionNamed('delete');
await tasksCloudDemoPage.checkActionExecuted(deleteTask.list.entries[0].entry.id, 'delete');
});
});
});

View File

@@ -7,6 +7,8 @@
"C279932": "login problem APS not basic",
"C279931": "login problem APS not basic",
"C279930": "login problem APS not basic",
"C299187": "ADF-5285 Failing aspect test due multiple replica",
"C311290": "ADF-5308",
"C260241": "ADF-5335- this will exclude 2 tests"
"C260241": "ADF-5335- this will exclude 2 tests",
"C587515": "https://alfresco.atlassian.net/browse/ADF-5340"
}

View File

@@ -174,6 +174,7 @@
},
"ADF_CLOUD_EDIT_TASK_FILTER": {
"TITLE": "Customize your filter",
"FILTER_NAME": "Filter name",
"TOOL_TIP": {
"SAVE": "Save filter",
"SAVE_AS": "Save filter as",
@@ -229,6 +230,7 @@
},
"ADF_CLOUD_EDIT_PROCESS_FILTER": {
"TITLE": "Customize your filter",
"FILTER_NAME": "Filter name",
"LABEL": {
"APP_NAME": "ApplicationName",
"PROCESS_INS_ID": "ProcessInstanceId",

View File

@@ -5,7 +5,7 @@
<mat-panel-title *ngIf="showProcessFilterName" fxLayoutAlign="space-between center" id="adf-edit-process-filter-title-id">{{processFilter.name | translate}}</mat-panel-title>
<mat-panel-description fxLayoutAlign="space-between center" id="adf-edit-process-filter-sub-title-id">
<span *ngIf="showTitle"> {{ 'ADF_CLOUD_EDIT_PROCESS_FILTER.TITLE' | translate}}</span>
<div *ngIf="showActions()" class="adf-cloud-edit-process-filter-actions">
<div *ngIf="showFilterActions" class="adf-cloud-edit-process-filter-actions">
<ng-container *ngIf="toggleFilterActions">
<button *ngFor="let filterAction of processFilterActions" mat-icon-button matTooltip="{{ filterAction.tooltip | translate}}" [attr.data-automation-id]="'adf-filter-action-' + filterAction.actionType" [disabled]="isDisabledAction(filterAction)" (click)="executeFilterActions(filterAction)">
<adf-icon [value]="filterAction.icon"></adf-icon>
@@ -63,6 +63,7 @@
<mat-label>{{processFilterProperty.label | translate}}</mat-label>
<input
matInput
[formControlName]="processFilterProperty.key"
(keyup)="onDateChanged($event.srcElement.value, processFilterProperty)"
(dateChange)="onDateChanged($event.value, processFilterProperty)"
[matDatepicker]="dateController"

View File

@@ -32,7 +32,6 @@ import { ProcessFilterCloudService } from '../services/process-filter-cloud.serv
import { AppsProcessCloudService } from '../../../app/services/apps-process-cloud.service';
import { fakeApplicationInstance } from './../../../app/mock/app-model.mock';
import moment from 'moment-es6';
import { AbstractControl } from '@angular/forms';
import { PROCESS_FILTERS_SERVICE_TOKEN } from '../../../services/cloud-token.service';
import { LocalPreferenceCloudService } from '../../../services/local-preference-cloud.service';
import { TranslateModule } from '@ngx-translate/core';
@@ -211,112 +210,19 @@ describe('EditProcessFilterCloudComponent', () => {
}));
describe('Save & Delete buttons', () => {
it('should disable save and delete button for default process filters', async(() => {
getProcessFilterByIdSpy.and.returnValue(of({
id: 'filter-id',
name: 'ADF_CLOUD_PROCESS_FILTERS.RUNNING_PROCESSES',
sort: 'my-custom-sort',
processDefinitionId: 'process-definition-id',
priority: '12'
}));
const processFilterIdChange = new SimpleChange(null, 'filter-id', false);
component.ngOnChanges({ 'id': processFilterIdChange });
fixture.detectChanges();
component.toggleFilterActions = true;
const expansionPanel = fixture.debugElement.nativeElement.querySelector('mat-expansion-panel-header');
expansionPanel.click();
fixture.detectChanges();
fixture.whenStable().then(() => {
const saveButton = fixture.debugElement.nativeElement.querySelector('[data-automation-id="adf-filter-action-save"]');
expect(saveButton.disabled).toEqual(true);
const deleteButton = fixture.debugElement.nativeElement.querySelector('[data-automation-id="adf-filter-action-delete"]');
expect(deleteButton.disabled).toEqual(true);
});
}));
it('should enable delete button for custom process filters', async(() => {
const disableCheckSpy = spyOn(component, 'isDisabledAction').and.callThrough();
component.toggleFilterActions = true;
const expansionPanel = fixture.debugElement.nativeElement.querySelector('mat-expansion-panel-header');
expansionPanel.click();
fixture.detectChanges();
fixture.whenStable().then(() => {
expect(disableCheckSpy).toHaveBeenCalled();
const saveButton = fixture.debugElement.nativeElement.querySelector('[data-automation-id="adf-filter-action-save"]');
expect(saveButton.disabled).toEqual(true);
const deleteButton = fixture.debugElement.nativeElement.querySelector('[data-automation-id="adf-filter-action-delete"]');
expect(deleteButton.disabled).toEqual(false);
});
}));
it('should enable save button if the filter is changed for custom filters', async(() => {
component.toggleFilterActions = true;
const expansionPanel = fixture.debugElement.nativeElement.querySelector('mat-expansion-panel-header');
expansionPanel.click();
const stateElement = fixture.debugElement.nativeElement.querySelector('[data-automation-id="adf-cloud-edit-process-property-status"] .mat-select-trigger');
stateElement.click();
fixture.detectChanges();
const options = fixture.debugElement.queryAll(By.css('.mat-option-text'));
options[2].nativeElement.click();
fixture.detectChanges();
fixture.whenStable().then(() => {
const saveButton = fixture.debugElement.nativeElement.querySelector('[data-automation-id="adf-filter-action-save"]');
expect(saveButton.disabled).toEqual(false);
});
}));
it('should disable save button if the filter is not changed for custom filter', async(() => {
component.toggleFilterActions = true;
const expansionPanel = fixture.debugElement.nativeElement.querySelector('mat-expansion-panel-header');
expansionPanel.click();
fixture.detectChanges();
fixture.whenStable().then(() => {
const saveButton = fixture.debugElement.nativeElement.querySelector('[data-automation-id="adf-filter-action-save"]');
expect(saveButton.disabled).toBe(true);
});
}));
});
describe('SaveAs Button', () => {
it('should disable saveAs button if the process filter is not changed for default filter', async(() => {
getProcessFilterByIdSpy.and.returnValue(of({
id: 'filter-id',
name: 'ADF_CLOUD_PROCESS_FILTERS.RUNNING_PROCESSES',
sort: 'my-custom-sort',
processDefinitionId: 'process-definition-id',
priority: '12'
}));
const processFilterIdChange = new SimpleChange(null, 'filter-id', true);
component.ngOnChanges({ 'id': processFilterIdChange });
fixture.detectChanges();
component.toggleFilterActions = true;
const expansionPanel = fixture.debugElement.nativeElement.querySelector('mat-expansion-panel-header');
expansionPanel.click();
fixture.detectChanges();
fixture.whenStable().then(() => {
const saveButton = fixture.debugElement.nativeElement.querySelector('[data-automation-id="adf-filter-action-saveAs"]');
expect(saveButton.disabled).toEqual(true);
});
}));
it('should disable saveAs button if the process filter is not changed for custom filter', async(() => {
component.toggleFilterActions = true;
const expansionPanel = fixture.debugElement.nativeElement.querySelector('mat-expansion-panel-header');
expansionPanel.click();
fixture.detectChanges();
fixture.whenStable().then(() => {
const saveButton = fixture.debugElement.nativeElement.querySelector('[data-automation-id="adf-filter-action-saveAs"]');
expect(saveButton.disabled).toEqual(true);
});
}));
it('should enable saveAs button if the filter values are changed for default filter', (done) => {
getProcessFilterByIdSpy.and.returnValue(of({
id: 'filter-id',
@@ -705,7 +611,7 @@ describe('EditProcessFilterCloudComponent', () => {
it('should emit delete event and delete the filter on click of delete button', (done) => {
component.toggleFilterActions = true;
const deleteFilterSpy = spyOn(service, 'deleteFilter').and.returnValue(of({}));
const deleteSpy: jasmine.Spy = spyOn(component.action, 'emit');
const deleteSpy = spyOn(component.action, 'emit');
fixture.detectChanges();
const expansionPanel = fixture.debugElement.nativeElement.querySelector('mat-expansion-panel-header');
@@ -769,9 +675,6 @@ describe('EditProcessFilterCloudComponent', () => {
expect(saveButton).toBeDefined();
expect(saveAsButton).toBeDefined();
expect(deleteButton).toBeDefined();
expect(saveButton.disabled).toBeTruthy();
expect(saveAsButton.disabled).toBeTruthy(false);
expect(deleteButton.disabled).toEqual(false);
});
}));
@@ -795,8 +698,10 @@ describe('EditProcessFilterCloudComponent', () => {
component.actions = [];
component.id = 'mock-process-filter-id';
fixture.detectChanges();
const expansionPanel = fixture.debugElement.nativeElement.querySelector('mat-expansion-panel-header');
expansionPanel.click();
fixture.detectChanges();
fixture.whenStable().then(() => {
const saveAsButton = fixture.debugElement.nativeElement.querySelector('[data-automation-id="adf-filter-action-saveAs"]');
@@ -807,9 +712,6 @@ describe('EditProcessFilterCloudComponent', () => {
expect(saveButton).toBeDefined();
expect(saveAsButton).toBeDefined();
expect(deleteButton).toBeDefined();
expect(saveButton.disabled).toBeTruthy();
expect(saveAsButton.disabled).toBeTruthy(false);
expect(deleteButton.disabled).toEqual(false);
});
}));
@@ -820,20 +722,20 @@ describe('EditProcessFilterCloudComponent', () => {
component.ngOnChanges({ 'id': taskFilterIdChange });
fixture.detectChanges();
const lastModifiedToControl: AbstractControl = component.editProcessFilterForm.get('lastModifiedTo');
lastModifiedToControl.setValue(new Date().toISOString());
const lastModifiedToFilter = moment(lastModifiedToControl.value);
lastModifiedToFilter.set({
const date = moment();
component.filterChange.subscribe(() => {
expect(component.processFilter.lastModifiedTo.toISOString()).toEqual(date.toISOString());
done();
});
const lastModifiedToControl = component.editProcessFilterForm.get('lastModifiedTo');
lastModifiedToControl.setValue(date);
date.set({
hour: 23,
minute: 59,
second: 59
});
component.filterChange.subscribe(() => {
expect(component.changedProcessFilter.lastModifiedTo.toISOString()).toEqual(lastModifiedToFilter.toISOString());
done();
});
component.onFilterChange();
});
it('should set date range filter type when range is selected', (done) => {
@@ -843,6 +745,15 @@ describe('EditProcessFilterCloudComponent', () => {
component.ngOnChanges({ 'id': taskFilterIdChange });
fixture.detectChanges();
component.filterChange.subscribe(() => {
const completedDateTypeControl = component.editProcessFilterForm.get('completedDateType');
expect(completedDateTypeControl.value).toEqual(DateCloudFilterType.RANGE);
done();
});
component.onFilterChange();
fixture.detectChanges();
const dateFilter = {
startDate: moment().startOf('day').toISOString(true),
endDate: moment().endOf('day').toISOString(true)
@@ -859,14 +770,6 @@ describe('EditProcessFilterCloudComponent', () => {
to: '_completedTo'
}
});
fixture.detectChanges();
component.filterChange.subscribe(() => {
const completedDateTypeControl: AbstractControl = component.editProcessFilterForm.get('completedDateType');
expect(completedDateTypeControl.value).toEqual(DateCloudFilterType.RANGE);
done();
});
component.onFilterChange();
});
it('should set the correct started date range when date range option is changed', (done) => {
@@ -876,19 +779,18 @@ describe('EditProcessFilterCloudComponent', () => {
component.ngOnChanges({ 'id': taskFilterIdChange });
fixture.detectChanges();
const startedDateTypeControl: AbstractControl = component.editProcessFilterForm.get('completedDateType');
startedDateTypeControl.setValue(DateCloudFilterType.TODAY);
const dateFilter = {
startFrom: moment().startOf('day').toISOString(true),
startTo: moment().endOf('day').toISOString(true)
};
component.filterChange.subscribe(() => {
expect(component.changedProcessFilter.completedFrom).toEqual(dateFilter.startFrom);
expect(component.changedProcessFilter.completedTo).toEqual(dateFilter.startTo);
const dateFilter = {
startFrom: moment().startOf('day').toISOString(true),
startTo: moment().endOf('day').toISOString(true)
};
expect(component.processFilter.completedFrom).toEqual(dateFilter.startFrom);
expect(component.processFilter.completedTo).toEqual(dateFilter.startTo);
done();
});
component.onFilterChange();
const startedDateTypeControl = component.editProcessFilterForm.get('completedDateType');
startedDateTypeControl.setValue(DateCloudFilterType.TODAY);
});
it('should update form on date range value is updated', (done) => {
@@ -903,7 +805,13 @@ describe('EditProcessFilterCloudComponent', () => {
endDate: moment().endOf('day').toISOString(true)
};
const startedDateTypeControl: AbstractControl = component.editProcessFilterForm.get('completedDateType');
component.filterChange.subscribe(() => {
expect(component.processFilter.completedFrom).toEqual(dateFilter.startDate);
expect(component.processFilter.completedTo).toEqual(dateFilter.endDate);
done();
});
const startedDateTypeControl = component.editProcessFilterForm.get('completedDateType');
startedDateTypeControl.setValue(DateCloudFilterType.RANGE);
component.onDateRangeFilterChanged(dateFilter, {
@@ -917,14 +825,6 @@ describe('EditProcessFilterCloudComponent', () => {
to: '_completedTo'
}
});
fixture.detectChanges();
component.filterChange.subscribe(() => {
expect(component.changedProcessFilter.completedFrom).toEqual(dateFilter.startDate);
expect(component.changedProcessFilter.completedTo).toEqual(dateFilter.endDate);
done();
});
component.onFilterChange();
});
it('should call restore default filters service on deletion of last filter', (done) => {

View File

@@ -20,7 +20,7 @@ import { FormGroup, FormBuilder, AbstractControl } from '@angular/forms';
import { DateAdapter } from '@angular/material/core';
import { MatDialog } from '@angular/material/dialog';
import { debounceTime, filter, takeUntil, finalize, switchMap } from 'rxjs/operators';
import { Subject, Observable } from 'rxjs';
import { Subject, Observable, Subscription } from 'rxjs';
import moment from 'moment-es6';
import { Moment } from 'moment';
import { AppsProcessCloudService } from '../../../app/services/apps-process-cloud.service';
@@ -30,7 +30,6 @@ import { ProcessFilterCloudService } from '../services/process-filter-cloud.serv
import { ProcessFilterDialogCloudComponent } from './process-filter-dialog-cloud.component';
import { ProcessCloudService } from '../../services/process-cloud.service';
import { DateCloudFilterType, DateRangeFilter } from '../../../models/date-cloud-filter.model';
import { ApplicationVersionModel } from '../../../models/application-version.model';
export interface DropdownOption {
value: string;
@@ -66,15 +65,15 @@ export class EditProcessFilterCloudComponent implements OnInit, OnChanges, OnDes
/** List of process filter properties to display */
@Input()
filterProperties: string[] = EditProcessFilterCloudComponent.DEFAULT_PROCESS_FILTER_PROPERTIES;
filterProperties = EditProcessFilterCloudComponent.DEFAULT_PROCESS_FILTER_PROPERTIES;
/** List of sort properties to display. */
@Input()
sortProperties: string[] = EditProcessFilterCloudComponent.DEFAULT_SORT_PROPERTIES;
sortProperties = EditProcessFilterCloudComponent.DEFAULT_SORT_PROPERTIES;
/** List of sort actions. */
@Input()
actions: string[] = EditProcessFilterCloudComponent.DEFAULT_ACTIONS;
actions = EditProcessFilterCloudComponent.DEFAULT_ACTIONS;
/** Toggles editing of process filter actions. */
@Input()
@@ -96,8 +95,31 @@ export class EditProcessFilterCloudComponent implements OnInit, OnChanges, OnDes
@Output()
action = new EventEmitter<ProcessFilterAction>();
processFilter: ProcessFilterCloudModel;
changedProcessFilter: ProcessFilterCloudModel;
private _filter: ProcessFilterCloudModel;
get processFilter() {
return this._filter;
}
@Input()
set processFilter(value: ProcessFilterCloudModel) {
this._filter = value;
if (value?.appName) {
this.appName = value.appName;
}
if (value?.id) {
this.id = value.id;
}
this.processFilterProperties = this.createAndFilterProperties();
this.processFilterActions = this.createAndFilterActions();
this.buildForm(this.processFilterProperties);
this.filterChange.emit(value);
}
status: Array<DropdownOption> = [
{ value: '', label: 'ADF_CLOUD_PROCESS_FILTERS.STATUS.ALL' },
@@ -120,15 +142,15 @@ export class EditProcessFilterCloudComponent implements OnInit, OnChanges, OnDes
value: ''
};
processDefinitionNames: any[] = [];
formHasBeenChanged = false;
editProcessFilterForm: FormGroup;
processFilterProperties: ProcessFilterProperties[] = [];
processFilterActions: ProcessFilterAction[] = [];
toggleFilterActions: boolean = false;
appVersionOptions: ProcessFilterOptions[];
appVersionOptions: ProcessFilterOptions[] = [];
private onDestroy$ = new Subject<boolean>();
isLoading: boolean = false;
private filterChangeSub: Subscription;
constructor(
private formBuilder: FormBuilder,
@@ -161,7 +183,6 @@ export class EditProcessFilterCloudComponent implements OnInit, OnChanges, OnDes
}
buildForm(processFilterProperties: ProcessFilterProperties[]) {
this.formHasBeenChanged = false;
this.editProcessFilterForm = this.formBuilder.group(this.getFormControlsConfig(processFilterProperties));
this.onFilterChange();
}
@@ -191,15 +212,11 @@ export class EditProcessFilterCloudComponent implements OnInit, OnChanges, OnDes
this.isLoading = true;
this.processFilterCloudService
.getFilterById(this.appName, this.id)
.pipe(
finalize(() => this.isLoading = false),
takeUntil(this.onDestroy$)
)
.pipe(finalize(() => this.isLoading = false))
.subscribe(response => {
this.processFilter = new ProcessFilterCloudModel(response);
this.processFilterProperties = this.createAndFilterProperties();
this.processFilterActions = this.createAndFilterActions();
this.buildForm(this.processFilterProperties);
this.processFilter = new ProcessFilterCloudModel(
Object.assign({}, response || {}, this.processFilter || {})
);
});
}
@@ -207,7 +224,12 @@ export class EditProcessFilterCloudComponent implements OnInit, OnChanges, OnDes
* Check process instance filter changes
*/
onFilterChange() {
this.editProcessFilterForm.valueChanges
if (this.filterChangeSub) {
this.filterChangeSub.unsubscribe();
this.filterChangeSub = null;
}
this.filterChangeSub = this.editProcessFilterForm.valueChanges
.pipe(
debounceTime(200),
filter(() => this.isFormValid()),
@@ -215,34 +237,46 @@ export class EditProcessFilterCloudComponent implements OnInit, OnChanges, OnDes
)
.subscribe((formValues: ProcessFilterCloudModel) => {
this.setLastModifiedToFilter(formValues);
this.changedProcessFilter = new ProcessFilterCloudModel(Object.assign({}, this.processFilter, formValues));
this.formHasBeenChanged = !this.compareFilters(this.changedProcessFilter, this.processFilter);
this.filterChange.emit(this.changedProcessFilter);
const newValue = new ProcessFilterCloudModel(Object.assign({}, this.processFilter, formValues));
const changed = !this.compareFilters(newValue, this.processFilter);
if (changed) {
this._filter = newValue;
this.filterChange.emit(newValue);
}
});
}
createAndFilterProperties(): ProcessFilterProperties[] {
this.checkMandatoryFilterProperties();
if (this.checkForProperty('appName')) {
this.applicationNames = [];
if (this.filterProperties.includes('appName')) {
this.getRunningApplications();
}
if (this.checkForProperty('processDefinitionName')) {
this.processDefinitionNames = [];
if (this.filterProperties.includes('processDefinitionName')) {
this.getProcessDefinitions();
}
if (this.checkForProperty('appVersionMultiple')) {
this.appVersionOptions = [];
if (this.filterProperties.includes('appVersionMultiple')) {
this.getAppVersionOptions();
}
const defaultProperties = this.createProcessFilterProperties(this.processFilter);
let filteredProperties = defaultProperties.filter((filterProperty) => this.isValidProperty(this.filterProperties, filterProperty.key));
if (!this.hasSortProperty()) {
filteredProperties = this.removeOrderProperty(filteredProperties);
if (!this.filterProperties.includes('sort')) {
filteredProperties = filteredProperties.filter(property => property.key !== 'order');
}
if (this.hasLastModifiedProperty()) {
filteredProperties = [...filteredProperties, ...this.createLastModifiedProperty()];
if (this.filterProperties.includes('lastModified')) {
filteredProperties = [
...filteredProperties,
...this.createLastModifiedProperty(this.processFilter)
];
}
return filteredProperties;
}
@@ -252,29 +286,10 @@ export class EditProcessFilterCloudComponent implements OnInit, OnChanges, OnDes
}
}
checkForProperty(property: string): boolean {
return this.filterProperties ? this.filterProperties.indexOf(property) >= 0 : false;
}
private isValidProperty(filterProperties: string[], key: string): boolean {
return filterProperties ? filterProperties.indexOf(key) >= 0 : true;
}
private hasSortProperty(): boolean {
return this.filterProperties.includes('sort');
}
private hasLastModifiedProperty(): boolean {
return this.filterProperties.includes('lastModified');
}
removeOrderProperty(filteredProperties: ProcessFilterProperties[]): ProcessFilterProperties[] {
if (filteredProperties && filteredProperties.length > 0) {
return filteredProperties.filter(property => property.key !== 'order');
}
return [];
}
get createSortProperties(): ProcessFilterOptions[] {
this.checkMandatorySortProperties();
const defaultSortProperties = this.createProcessSortProperties();
@@ -282,13 +297,13 @@ export class EditProcessFilterCloudComponent implements OnInit, OnChanges, OnDes
}
getAppVersionOptions() {
this.processCloudService.getApplicationVersions(this.appName)
.pipe(takeUntil(this.onDestroy$))
.subscribe((appVersions: ApplicationVersionModel[]) => {
appVersions.forEach(appVersion => {
this.appVersionOptions.push({ label: appVersion.entry.version, value: appVersion.entry.version });
});
this.appVersionOptions = [];
this.processCloudService.getApplicationVersions(this.appName).subscribe((appVersions) => {
appVersions.forEach(appVersion => {
this.appVersionOptions.push({ label: appVersion.entry.version, value: appVersion.entry.version });
});
});
}
checkMandatorySortProperties() {
@@ -321,13 +336,12 @@ export class EditProcessFilterCloudComponent implements OnInit, OnChanges, OnDes
return this.editProcessFilterForm.get(property.key);
}
onDateChanged(newDateValue: any, dateProperty: ProcessFilterProperties) {
onDateChanged(newDateValue: Moment, dateProperty: ProcessFilterProperties) {
if (newDateValue) {
const momentDate = moment(newDateValue, this.DATE_FORMAT, true);
const controller = this.getPropertyController(dateProperty);
if (momentDate.isValid()) {
controller.setValue(momentDate.toDate());
if (newDateValue.isValid()) {
controller.setValue(newDateValue);
controller.setErrors(null);
} else {
controller.setErrors({ invalid: true });
@@ -363,6 +377,8 @@ export class EditProcessFilterCloudComponent implements OnInit, OnChanges, OnDes
}
getRunningApplications() {
this.applicationNames = [];
this.appsProcessCloudService
.getDeployedApplicationsByStatus('RUNNING', this.role)
.subscribe((applications) => {
@@ -375,6 +391,8 @@ export class EditProcessFilterCloudComponent implements OnInit, OnChanges, OnDes
}
getProcessDefinitions() {
this.processDefinitionNames = [];
this.processCloudService.getProcessDefinitions(this.appName).subscribe((processDefinitions) => {
if (processDefinitions && processDefinitions.length > 0) {
this.processDefinitionNames.push(this.allProcessDefinitionNamesOption);
@@ -397,11 +415,10 @@ export class EditProcessFilterCloudComponent implements OnInit, OnChanges, OnDes
save(saveAction: ProcessFilterAction) {
this.processFilterCloudService
.updateFilter(this.changedProcessFilter)
.updateFilter(this.processFilter)
.subscribe(() => {
saveAction.filter = this.changedProcessFilter;
saveAction.filter = this.processFilter;
this.action.emit(saveAction);
this.formHasBeenChanged = this.compareFilters(this.changedProcessFilter, this.processFilter);
});
}
@@ -442,7 +459,7 @@ export class EditProcessFilterCloudComponent implements OnInit, OnChanges, OnDes
id: filterId,
key: 'custom-' + filterKey
};
const resultFilter: ProcessFilterCloudModel = Object.assign({}, this.changedProcessFilter, newFilter);
const resultFilter: ProcessFilterCloudModel = Object.assign({}, this.processFilter, newFilter);
this.processFilterCloudService
.addFilter(resultFilter)
.subscribe(() => {
@@ -475,10 +492,6 @@ export class EditProcessFilterCloudComponent implements OnInit, OnChanges, OnDes
return this.processFilterCloudService.getProcessFilters(this.appName);
}
showActions(): boolean {
return this.showFilterActions;
}
onExpand() {
this.toggleFilterActions = true;
}
@@ -488,30 +501,12 @@ export class EditProcessFilterCloudComponent implements OnInit, OnChanges, OnDes
}
isDisabledAction(action: ProcessFilterAction): boolean {
return this.isDisabledForDefaultFilters(action) ? true : this.hasFormChanged(action);
}
isDisabledForDefaultFilters(action: ProcessFilterAction): boolean {
return (
this.processFilterCloudService.isDefaultFilter(this.processFilter.name) &&
this.actionDisabledForDefault.includes(action.actionType)
);
}
hasFormChanged(action: ProcessFilterAction): boolean {
if (action.actionType === EditProcessFilterCloudComponent.ACTION_SAVE) {
return !this.formHasBeenChanged;
}
if (action.actionType === EditProcessFilterCloudComponent.ACTION_SAVE_AS) {
return !this.formHasBeenChanged;
}
if (action.actionType === EditProcessFilterCloudComponent.ACTION_DELETE) {
return false;
}
return false;
}
private setLastModifiedToFilter(formValues: ProcessFilterCloudModel) {
if (formValues.lastModifiedTo && Date.parse(formValues.lastModifiedTo.toString())) {
const lastModifiedToFilterValue = moment(formValues.lastModifiedTo);
@@ -524,7 +519,7 @@ export class EditProcessFilterCloudComponent implements OnInit, OnChanges, OnDes
}
}
createFilterActions(): ProcessFilterAction[] {
private createFilterActions(): ProcessFilterAction[] {
return [
{
actionType: EditProcessFilterCloudComponent.ACTION_SAVE,
@@ -544,24 +539,35 @@ export class EditProcessFilterCloudComponent implements OnInit, OnChanges, OnDes
];
}
createLastModifiedProperty(): ProcessFilterProperties[] {
private createLastModifiedProperty(filterModel: ProcessFilterCloudModel): ProcessFilterProperties[] {
let lastModifiedFrom;
let lastModifiedTo;
if (filterModel.lastModifiedFrom) {
lastModifiedFrom = moment(filterModel.lastModifiedFrom);
}
if (filterModel.lastModifiedTo) {
lastModifiedTo = moment(filterModel.lastModifiedTo);
}
return [
{
label: 'ADF_CLOUD_EDIT_PROCESS_FILTER.LABEL.LAST_MODIFIED_DATE_FORM',
type: 'date',
key: 'lastModifiedFrom',
value: ''
value: lastModifiedFrom
},
{
label: 'ADF_CLOUD_EDIT_PROCESS_FILTER.LABEL.LAST_MODIFIED_TO',
type: 'date',
key: 'lastModifiedTo',
value: ''
value: lastModifiedTo
}
];
}
createProcessSortProperties(): ProcessSortFilterProperty[] {
private createProcessSortProperties(): ProcessSortFilterProperty[] {
return [
{
label: 'ADF_CLOUD_EDIT_PROCESS_FILTER.LABEL.ID',
@@ -631,91 +637,101 @@ export class EditProcessFilterCloudComponent implements OnInit, OnChanges, OnDes
];
}
createProcessFilterProperties(currentProcessFilter: ProcessFilterCloudModel): ProcessFilterProperties[] {
private createProcessFilterProperties(filterModel: ProcessFilterCloudModel): ProcessFilterProperties[] {
const appVersionMultiple = [];
if (filterModel.appVersion) {
appVersionMultiple.push(
Array.isArray(filterModel.appVersion)
? filterModel.appVersion.map(entry => entry.toString())
: `${filterModel.appVersion}`
);
}
return [
{
label: 'ADF_CLOUD_EDIT_PROCESS_FILTER.LABEL.APP_NAME',
type: 'select',
key: 'appName',
value: currentProcessFilter.appName || '',
value: filterModel.appName || '',
options: this.applicationNames
},
{
label: 'ADF_CLOUD_EDIT_PROCESS_FILTER.LABEL.APP_VERSION',
type: 'number',
key: 'appVersion',
value: currentProcessFilter.appVersion
value: filterModel.appVersion
},
{
label: 'ADF_CLOUD_EDIT_PROCESS_FILTER.LABEL.APP_VERSION',
type: 'multi-select',
key: 'appVersionMultiple',
value: currentProcessFilter.appVersion,
value: appVersionMultiple,
options: this.appVersionOptions
},
{
label: 'ADF_CLOUD_EDIT_PROCESS_FILTER.LABEL.PROCESS_INS_ID',
type: 'text',
key: 'processInstanceId',
value: currentProcessFilter.processInstanceId || ''
value: filterModel.processInstanceId || ''
},
{
label: 'ADF_CLOUD_EDIT_PROCESS_FILTER.LABEL.PROCESS_NAME',
type: 'text',
key: 'processName',
value: currentProcessFilter.processName || ''
value: filterModel.processName || ''
},
{
label: 'ADF_CLOUD_EDIT_PROCESS_FILTER.LABEL.PROCESS_DEF_NAME',
type: 'select',
key: 'processDefinitionName',
value: currentProcessFilter.processDefinitionName || '',
value: filterModel.processDefinitionName || '',
options: this.processDefinitionNames
},
{
label: 'ADF_CLOUD_EDIT_PROCESS_FILTER.LABEL.STATUS',
type: 'select',
key: 'status',
value: currentProcessFilter.status || this.status[0].value,
value: filterModel.status || this.status[0].value,
options: this.status
},
{
label: 'ADF_CLOUD_EDIT_PROCESS_FILTER.LABEL.PROCESS_DEF_ID',
type: 'text',
key: 'processDefinitionId',
value: currentProcessFilter.processDefinitionId || ''
value: filterModel.processDefinitionId || ''
},
{
label: 'ADF_CLOUD_EDIT_PROCESS_FILTER.LABEL.PROCESS_DEF_KEY',
type: 'text',
key: 'processDefinitionKey',
value: currentProcessFilter.processDefinitionKey || ''
value: filterModel.processDefinitionKey || ''
},
{
label: 'ADF_CLOUD_EDIT_PROCESS_FILTER.LABEL.SORT',
type: 'select',
key: 'sort',
value: currentProcessFilter.sort || this.createSortProperties[0].value,
value: filterModel.sort || this.createSortProperties[0].value,
options: this.createSortProperties
},
{
label: 'ADF_CLOUD_EDIT_PROCESS_FILTER.LABEL.DIRECTION',
type: 'select',
key: 'order',
value: currentProcessFilter.order || this.directions[0].value,
value: filterModel.order || this.directions[0].value,
options: this.directions
},
{
label: 'ADF_CLOUD_EDIT_PROCESS_FILTER.LABEL.COMPLETED_DATE',
type: 'date',
key: 'completedDate',
value: currentProcessFilter.completedDate || false
value: filterModel.completedDate || false
},
{
label: 'ADF_CLOUD_EDIT_PROCESS_FILTER.LABEL.STARTED_BY',
type: 'people',
key: 'initiator',
value: currentProcessFilter.initiator,
value: filterModel.initiator,
selectionMode: 'multiple'
},
{
@@ -724,9 +740,9 @@ export class EditProcessFilterCloudComponent implements OnInit, OnChanges, OnDes
key: 'completedDateRange',
attributes: { dateType: 'completedDateType', from: '_completedFrom', to: '_completedTo'},
value: {
completedDateType: currentProcessFilter.completedDateType || null,
_completedFrom: currentProcessFilter.completedFrom || null,
_completedTo: currentProcessFilter.completedTo || null
completedDateType: filterModel.completedDateType || null,
_completedFrom: filterModel.completedFrom || null,
_completedTo: filterModel.completedTo || null
}
},
{
@@ -735,9 +751,9 @@ export class EditProcessFilterCloudComponent implements OnInit, OnChanges, OnDes
key: 'startedDateRange',
attributes: { dateType: 'startedDateType', from: '_startFrom', to: '_startTo'},
value: {
startedDateType: currentProcessFilter.startedDateType || null,
_startFrom: currentProcessFilter.startFrom || null,
_startTo: currentProcessFilter.startTo || null
startedDateType: filterModel.startedDateType || null,
_startFrom: filterModel.startFrom || null,
_startTo: filterModel.startTo || null
}
}
];

View File

@@ -6,7 +6,7 @@
<mat-card-content>
<form [formGroup]="filterForm">
<mat-form-field fxFlex [floatLabel]="'auto'">
<input matInput placeholder="Filter name" formControlName="name" id="adf-filter-name-id">
<input matInput placeholder="{{ 'ADF_CLOUD_EDIT_PROCESS_FILTER.FILTER_NAME' | translate }}" formControlName="name" id="adf-filter-name-id">
</mat-form-field>
</form>
</mat-card-content>

View File

@@ -37,6 +37,57 @@ export class ProcessFilterCloudService {
this.filters$ = this.filtersSubject.asObservable();
}
readQueryParams(obj: Object): ProcessFilterCloudModel {
const model = Object.assign({}, obj) as ProcessFilterCloudModel;
if (obj.hasOwnProperty('appVersion') && obj['appVersion']) {
if (typeof obj['appVersion'] === 'string') {
model.appVersion = obj['appVersion'].split(',').map(str => parseInt(str, 10));
}
}
if (obj.hasOwnProperty('lastModifiedFrom')) {
model.lastModifiedFrom = new Date(parseInt(obj['lastModifiedFrom'], 10));
}
if (obj.hasOwnProperty('lastModifiedTo')) {
model.lastModifiedTo = new Date(parseInt(obj['lastModifiedTo'], 10));
}
return model;
}
writeQueryParams(value: Object, filterProperties: string[], appName?: string, id?: string): Object {
value = value || {};
const result = {
appName: appName || value['appName'],
id: id || value['id']
};
for (const prop of filterProperties) {
if (prop === 'appVersionMultiple') {
const versions = value['appVersion'];
if (Array.isArray(versions) && versions.length > 0) {
result['appVersion'] = versions.join(',');
}
} else if (prop === 'lastModified') {
if (value['lastModifiedFrom']) {
result['lastModifiedFrom'] = value['lastModifiedFrom'].valueOf();
}
if (value['lastModifiedTo']) {
result['lastModifiedTo'] = value['lastModifiedTo'].valueOf();
}
} else if (value.hasOwnProperty(prop)) {
result[prop] = value[prop];
}
}
return result;
}
/**
* Creates and returns the default process instance filters for a app.
* @param appName Name of the target app
@@ -102,14 +153,21 @@ export class ProcessFilterCloudService {
* @returns Observable of process instance filters with newly added filter
*/
addFilter(newFilter: ProcessFilterCloudModel): Observable<ProcessFilterCloudModel[]> {
const key: string = this.prepareKey(newFilter.appName);
return this.getProcessFiltersByKey(newFilter.appName, key).pipe(
const { appName, name } = newFilter;
const key: string = this.prepareKey(appName);
return this.getProcessFiltersByKey(appName, key).pipe(
switchMap((filters: ProcessFilterCloudModel[]) => {
if (filters && filters.length === 0) {
return this.createProcessFilters(newFilter.appName, key, [newFilter]);
return this.createProcessFilters(appName, key, [newFilter]);
} else {
const index = filters.findIndex(filter => filter.name === name);
if (index >= 0) {
filters.splice(index, 1);
}
filters.push(newFilter);
return this.preferenceService.updatePreference(newFilter.appName, key, filters);
return this.preferenceService.updatePreference(appName, key, filters);
}
}),
map((filters: ProcessFilterCloudModel[]) => {

View File

@@ -236,11 +236,7 @@ describe('ProcessListCloudComponent', () => {
});
it('should emit row click event', (done) => {
const row = new ObjectDataRow({
entry: {
id: '999'
}
});
const row = new ObjectDataRow({ id: '999' });
const rowEvent = new DataRowEvent(row, null);
component.rowClick.subscribe((taskId) => {
expect(taskId).toEqual('999');
@@ -293,7 +289,7 @@ describe('ProcessListCloudComponent', () => {
});
fixture.detectChanges();
expect(component.formatSorting).toHaveBeenCalledWith(mockSort);
expect(component.formattedSorting).toEqual([ProcessListCloudComponent.ENTRY_PREFIX + 'startDate', 'desc']);
expect(component.formattedSorting).toEqual(['startDate', 'desc']);
});
it('should reload process list when sorting on a column changes', () => {
@@ -312,7 +308,7 @@ describe('ProcessListCloudComponent', () => {
direction: 'ASC'
})
]);
expect(component.formattedSorting).toEqual(['entry.fakeName', 'asc']);
expect(component.formattedSorting).toEqual(['fakeName', 'asc']);
expect(component.isListEmpty()).toBeFalsy();
expect(getProcessByRequestSpy).toHaveBeenCalled();
});

View File

@@ -35,7 +35,6 @@ import { ProcessListCloudSortingModel } from '../models/process-list-sorting.mod
export class ProcessListCloudComponent extends DataTableSchema implements OnChanges, AfterContentInit, PaginatedComponent {
static PRESET_KEY = 'adf-cloud-process-list.presets';
static ENTRY_PREFIX = 'entry.';
@ContentChild(CustomEmptyContentTemplateDirective)
emptyCustomContent: CustomEmptyContentTemplateDirective;
@@ -288,7 +287,7 @@ export class ProcessListCloudComponent extends DataTableSchema implements OnChan
}
onRowClick(item: DataRowEvent) {
this.currentInstanceId = item.value.getValue('entry.id');
this.currentInstanceId = item.value.getValue('id');
this.rowClick.emit(this.currentInstanceId);
}
@@ -305,7 +304,7 @@ export class ProcessListCloudComponent extends DataTableSchema implements OnChan
onRowKeyUp(event: CustomEvent) {
if (event.detail.keyboardEvent.key === 'Enter') {
event.preventDefault();
this.currentInstanceId = event.detail.row.getValue('entry.id');
this.currentInstanceId = event.detail.row.getValue('id');
this.rowClick.emit(this.currentInstanceId);
}
}
@@ -354,7 +353,7 @@ export class ProcessListCloudComponent extends DataTableSchema implements OnChan
setSorting(sortDetail) {
const sorting = sortDetail ? {
orderBy: sortDetail.key.replace(ProcessListCloudComponent.ENTRY_PREFIX, ''),
orderBy: sortDetail.key,
direction: sortDetail.direction.toUpperCase()
} : { ... this.defaultSorting };
this.sorting = [new ProcessListCloudSortingModel(sorting)];
@@ -362,7 +361,7 @@ export class ProcessListCloudComponent extends DataTableSchema implements OnChan
formatSorting(sorting: ProcessListCloudSortingModel[]) {
this.formattedSorting = this.isValidSorting(sorting) ? [
ProcessListCloudComponent.ENTRY_PREFIX + sorting[0].orderBy,
sorting[0].orderBy,
sorting[0].direction.toLocaleLowerCase()
] : null;
}

View File

@@ -102,62 +102,62 @@ export const processListSchemaMock = {
'presets': {
'default': [
{
'key': 'entry.id',
'key': 'id',
'type': 'text',
'title': 'ADF_CLOUD_PROCESS_LIST.PROPERTIES.ID',
'sortable': true
},
{
'key': 'entry.name',
'key': 'name',
'type': 'text',
'title': 'ADF_CLOUD_PROCESS_LIST.PROPERTIES.NAME',
'sortable': true
},
{
'key': 'entry.status',
'key': 'status',
'type': 'text',
'title': 'ADF_CLOUD_PROCESS_LIST.PROPERTIES.STATUS',
'sortable': true
},
{
'key': 'entry.startDate',
'key': 'startDate',
'type': 'date',
'title': 'ADF_CLOUD_PROCESS_LIST.PROPERTIES.START_DATE',
'sortable': true,
'format': 'timeAgo'
},
{
'key': 'entry.appName',
'key': 'appName',
'type': 'text',
'title': 'ADF_CLOUD_PROCESS_LIST.PROPERTIES.APP_NAME',
'sortable': true
},
{
'key': 'entry.businessKey',
'key': 'businessKey',
'type': 'text',
'title': 'ADF_CLOUD_PROCESS_LIST.PROPERTIES.BUSINESS_KEY',
'sortable': true
},
{
'key': 'entry.initiator',
'key': 'initiator',
'type': 'text',
'title': 'ADF_CLOUD_PROCESS_LIST.PROPERTIES.INITIATOR',
'sortable': true
},
{
'key': 'entry.lastModified',
'key': 'lastModified',
'type': 'date',
'title': 'ADF_CLOUD_PROCESS_LIST.PROPERTIES.LAST_MODIFIED',
'sortable': true
},
{
'key': 'entry.processDefinitionId',
'key': 'processDefinitionId',
'type': 'text',
'title': 'ADF_CLOUD_PROCESS_LIST.PROPERTIES.PROCESS_DEF_ID',
'sortable': true
},
{
'key': 'entry.processDefinitionKey',
'key': 'processDefinitionKey',
'type': 'text',
'title': 'ADF_CLOUD_PROCESS_LIST.PROPERTIES.PROCESS_DEF_KEY',
'sortable': true

View File

@@ -18,13 +18,13 @@
export let processCloudPresetsDefaultModel = {
'default': [
{
'key': 'entry.name',
'key': 'name',
'type': 'text',
'title': 'ADF_CLOUD_PROCESS_LIST.PROPERTIES.NAME',
'sortable': true
},
{
'key': 'entry.startDate',
'key': 'startDate',
'type': 'date',
'title': 'ADF_CLOUD_PROCESS_LIST.PROPERTIES.START_DATE',
'cssClass': 'hidden',

View File

@@ -16,24 +16,13 @@
*/
import { async } from '@angular/core/testing';
import { setupTestBed, StorageService, AlfrescoApiServiceMock, LogService, AppConfigService, CoreModule } from '@alfresco/adf-core';
import { fakeProcessCloudList } from '../mock/process-list-service.mock';
import { ProcessListCloudService } from './process-list-cloud.service';
import { ProcessQueryCloudRequestModel } from '../models/process-cloud-query-request.model';
describe('Activiti ProcessList Cloud Service', () => {
describe('ProcessListCloudService', () => {
let service: ProcessListCloudService;
let alfrescoApiMock: AlfrescoApiServiceMock;
function returnFakeProcessListResults() {
return {
oauth2Auth: {
callCustomApi: () => {
return Promise.resolve(fakeProcessCloudList);
}
}
};
}
function returnCallQueryParameters() {
return {
oauth2Auth: {
@@ -67,20 +56,6 @@ describe('Activiti ProcessList Cloud Service', () => {
new LogService(new AppConfigService(null)));
}));
it('should return the processes', (done) => {
const processRequest: ProcessQueryCloudRequestModel = <ProcessQueryCloudRequestModel> { appName: 'fakeName' };
spyOn(alfrescoApiMock, 'getInstance').and.callFake(returnFakeProcessListResults);
service.getProcessByRequest(processRequest).subscribe((res) => {
expect(res).toBeDefined();
expect(res).not.toBeNull();
expect(res.list.entries.length).toBe(3);
expect(res.list.entries[0].entry.appName).toBe('easy-peasy-japanesey');
expect(res.list.entries[1].entry.appName).toBe('easy-peasy-japanesey');
expect(res.list.entries[1].entry.appName).toBe('easy-peasy-japanesey');
done();
});
});
it('should append to the call all the parameters', (done) => {
const processRequest: ProcessQueryCloudRequestModel = <ProcessQueryCloudRequestModel> { appName: 'fakeName', skipCount: 0, maxItems: 20, service: 'fake-service' };
spyOn(alfrescoApiMock, 'getInstance').and.callFake(returnCallQueryParameters);

View File

@@ -20,6 +20,7 @@ import { ProcessQueryCloudRequestModel } from '../models/process-cloud-query-req
import { Observable, throwError } from 'rxjs';
import { ProcessListCloudSortingModel } from '../models/process-list-sorting.model';
import { BaseCloudService } from '../../../services/base-cloud.service';
import { map } from 'rxjs/operators';
@Injectable({ providedIn: 'root' })
export class ProcessListCloudService extends BaseCloudService {
@@ -33,29 +34,40 @@ export class ProcessListCloudService extends BaseCloudService {
/**
* Finds a process using an object with optional query properties.
* @param requestNode Query object
* @param queryUrl Query url
* @returns Process information
*/
getProcessByRequest(requestNode: ProcessQueryCloudRequestModel): Observable<any> {
getProcessByRequest(requestNode: ProcessQueryCloudRequestModel, queryUrl?: string): Observable<any> {
if (requestNode.appName || requestNode.appName === '') {
const queryUrl = `${this.getBasePath(requestNode.appName)}/query/v1/process-instances`;
queryUrl = queryUrl || `${this.getBasePath(requestNode.appName)}/query/v1/process-instances`;
const queryParams = this.buildQueryParams(requestNode);
const sortingParams = this.buildSortingParam(requestNode.sorting);
if (sortingParams) {
queryParams['sort'] = sortingParams;
}
return this.get(queryUrl, queryParams);
return this.get(queryUrl, queryParams).pipe(
map((response: any) => {
const entries = response.list && response.list.entries;
if (entries) {
response.list.entries = entries.map((entryData) => {
return entryData.entry;
});
}
return response;
})
);
} else {
this.logService.error('Appname is mandatory for querying task');
return throwError('Appname not configured');
}
}
private isPropertyValueValid(requestNode: any, property: string) {
protected isPropertyValueValid(requestNode: any, property: string): boolean {
return requestNode[property] !== '' && requestNode[property] !== null && requestNode[property] !== undefined;
}
private buildQueryParams(requestNode: ProcessQueryCloudRequestModel): Object {
protected buildQueryParams(requestNode: ProcessQueryCloudRequestModel): Object {
const queryParam = {};
for (const property in requestNode) {
@@ -73,15 +85,15 @@ export class ProcessListCloudService extends BaseCloudService {
return queryParam;
}
private buildFilterForAllStatus(): string[] {
protected buildFilterForAllStatus(): string[] {
return ['RUNNING', 'SUSPENDED', 'CANCELLED', 'COMPLETED'];
}
private isExcludedField(property: string): boolean {
protected isExcludedField(property: string): boolean {
return property === 'appName' || property === 'sorting';
}
private buildSortingParam(models: ProcessListCloudSortingModel[]): string {
protected buildSortingParam(models: ProcessListCloudSortingModel[]): string {
let finalSorting: string = '';
if (models) {
for (const sort of models) {

View File

@@ -1,17 +1,12 @@
<mat-accordion [hideToggle]="isLoading">
<mat-expansion-panel (afterExpand)="onExpand()"
(closed)="onClose()">
<mat-expansion-panel-header *ngIf="taskFilter"
id="adf-edit-task-filter-expansion-header">
<mat-expansion-panel (afterExpand)="onExpand()" (closed)="onClose()">
<mat-expansion-panel-header *ngIf="taskFilter" id="adf-edit-task-filter-expansion-header">
<ng-container *ngIf="!isLoading; else loadingTemplate">
<mat-panel-title *ngIf="showTaskFilterName"
fxLayoutAlign="space-between center"
id="adf-edit-task-filter-title-id">{{taskFilter.name | translate}}</mat-panel-title>
<mat-panel-description fxLayoutAlign="space-between center"
id="adf-edit-task-filter-sub-title-id">
<mat-panel-title *ngIf="showTaskFilterName" fxLayoutAlign="space-between center" id="adf-edit-task-filter-title-id"
>{{taskFilter.name | translate}}</mat-panel-title>
<mat-panel-description fxLayoutAlign="space-between center" id="adf-edit-task-filter-sub-title-id">
<span *ngIf="showTitle">{{ 'ADF_CLOUD_EDIT_TASK_FILTER.TITLE' | translate}}</span>
<div *ngIf="showFilterActions"
class="adf-cloud-edit-task-filter-actions">
<div *ngIf="showFilterActions" class="adf-cloud-edit-task-filter-actions">
<ng-container *ngIf="toggleFilterActions">
<button *ngFor="let filterAction of taskFilterActions"
mat-icon-button
@@ -32,12 +27,8 @@
</ng-template>
</mat-expansion-panel-header>
<ng-container *ngIf="!isLoading;">
<form [formGroup]="editTaskFilterForm"
*ngIf="editTaskFilterForm">
<div fxLayout="row wrap"
fxLayout.xs="column"
fxLayoutGap="10px"
fxLayoutAlign="start center">
<form *ngIf="editTaskFilterForm" [formGroup]="editTaskFilterForm">
<div fxLayout="row wrap" fxLayout.xs="column" fxLayoutGap="10px" fxLayoutAlign="start center">
<ng-container *ngFor="let taskFilterProperty of taskFilterProperties">
<mat-form-field fxFlex="23%"
*ngIf="taskFilterProperty.type === 'select'"
@@ -80,8 +71,7 @@
</mat-datepicker>
<div class="adf-edit-task-filter-date-error-container">
<div *ngIf="hasError(taskFilterProperty)">
<div class="adf-error-text">{{'ADF_TASK_LIST.START_TASK.FORM.ERROR.DATE'|translate}}
</div>
<div class="adf-error-text">{{'ADF_TASK_LIST.START_TASK.FORM.ERROR.DATE'|translate}}</div>
<mat-icon class="adf-error-icon">warning</mat-icon>
</div>
</div>
@@ -90,17 +80,16 @@
*ngIf="taskFilterProperty.type === 'checkbox'">
<mat-checkbox color="primary"
[formControlName]="taskFilterProperty.key"
[attr.data-automation-id]="taskFilterProperty.key">
{{taskFilterProperty.label | translate}}
</mat-checkbox>
[attr.data-automation-id]="taskFilterProperty.key"
>{{taskFilterProperty.label | translate}}</mat-checkbox>
</div>
<adf-cloud-date-range-filter #dateRange
*ngIf="taskFilterProperty.type === 'date-range'"
[processFilterProperty]="taskFilterProperty"
[options]="taskFilterProperty.dateFilterOptions"
(dateTypeChange)="onDateTypeChange($event, taskFilterProperty)"
(dateChanged)="onDateRangeFilterChanged($event, taskFilterProperty)">
*ngIf="taskFilterProperty.type === 'date-range'"
[processFilterProperty]="taskFilterProperty"
[options]="taskFilterProperty.dateFilterOptions"
(dateTypeChange)="onDateTypeChange($event, taskFilterProperty)"
(dateChanged)="onDateRangeFilterChanged($event, taskFilterProperty)">
</adf-cloud-date-range-filter>
<div fxFlex="23%" class="{{ 'adf-edit-task-filter-' + taskFilterProperty.key }}" *ngIf="taskFilterProperty.type === 'people'">
@@ -110,14 +99,16 @@
[validate]="true"
[appName]="appName"
[mode]="taskFilterProperty.selectionMode"
(changedUsers)="onChangedUser($event, taskFilterProperty)"></adf-cloud-people>
(changedUsers)="onChangedUser($event, taskFilterProperty)">
</adf-cloud-people>
</div>
<adf-cloud-task-assignment-filter fxFlex="23%"
*ngIf="taskFilterProperty.type === 'assignment'"
[taskFilterProperty]="taskFilterProperty"
(assignedChange)="onAssignedChange($event)"
(assignedGroupChange)="onAssignedGroupsChange($event)"></adf-cloud-task-assignment-filter>
(assignedGroupChange)="onAssignedGroupsChange($event)">
</adf-cloud-task-assignment-filter>
</ng-container>
</div>
</form>

View File

@@ -6,7 +6,7 @@
<mat-card-content>
<form [formGroup]="filterForm">
<mat-form-field fxFlex [floatLabel]="'auto'">
<input matInput placeholder="Filter name" formControlName="name" id="adf-filter-name-id">
<input matInput placeholder="{{ 'ADF_CLOUD_EDIT_TASK_FILTER.FILTER_NAME' | translate }}" formControlName="name" id="adf-filter-name-id">
</mat-form-field>
</form>
</mat-card-content>

View File

@@ -33,8 +33,6 @@ import { TaskCloudService } from '../../services/task-cloud.service';
// tslint:disable-next-line: directive-class-suffix
export abstract class BaseTaskListCloudComponent extends DataTableSchema implements OnChanges, AfterContentInit, PaginatedComponent, OnDestroy, OnInit {
static ENTRY_PREFIX = 'entry.';
@ContentChild(CustomEmptyContentTemplateDirective)
emptyCustomContent: CustomEmptyContentTemplateDirective;
@@ -202,7 +200,7 @@ export abstract class BaseTaskListCloudComponent extends DataTableSchema impleme
}
onRowClick(item: DataRowEvent) {
this.currentInstanceId = item.value.getValue('entry.id');
this.currentInstanceId = item.value.getValue('id');
this.rowClick.emit(this.currentInstanceId);
}
@@ -219,7 +217,7 @@ export abstract class BaseTaskListCloudComponent extends DataTableSchema impleme
onRowKeyUp(event: CustomEvent) {
if (event.detail.keyboardEvent.key === 'Enter') {
event.preventDefault();
this.currentInstanceId = event.detail.row.getValue('entry.id');
this.currentInstanceId = event.detail.row.getValue('id');
this.rowClick.emit(this.currentInstanceId);
}
}
@@ -238,7 +236,7 @@ export abstract class BaseTaskListCloudComponent extends DataTableSchema impleme
setSorting(sortDetail) {
const sorting = sortDetail ? {
orderBy: sortDetail.key.replace(BaseTaskListCloudComponent.ENTRY_PREFIX, ''),
orderBy: sortDetail.key,
direction: sortDetail.direction.toUpperCase()
} : { ... this.defaultSorting };
this.sorting = [new TaskListCloudSortingModel(sorting)];
@@ -246,7 +244,7 @@ export abstract class BaseTaskListCloudComponent extends DataTableSchema impleme
formatSorting(sorting: TaskListCloudSortingModel[]) {
this.formattedSorting = this.isValidSorting(sorting) ? [
BaseTaskListCloudComponent.ENTRY_PREFIX + sorting[0].orderBy,
sorting[0].orderBy,
sorting[0].direction.toLocaleLowerCase()
] : null;
}

View File

@@ -61,8 +61,8 @@ class EmptyTemplateComponent {
template: `
<adf-cloud-service-task-list>
<data-columns>
<data-column [copyContent]="true" key="entry.id" title="ADF_CLOUD_TASK_LIST.PROPERTIES.ID"></data-column>
<data-column key="entry.activityName" title="ADF_CLOUD_TASK_LIST.PROPERTIES.NAME"></data-column>
<data-column [copyContent]="true" key="id" title="ADF_CLOUD_TASK_LIST.PROPERTIES.ID"></data-column>
<data-column key="activityName" title="ADF_CLOUD_TASK_LIST.PROPERTIES.NAME"></data-column>
</data-columns>
</adf-cloud-service-task-list>`
})
@@ -194,19 +194,19 @@ describe('ServiceTaskListCloudComponent', () => {
expect(component.rows).toBeDefined();
expect(component.isListEmpty()).not.toBeTruthy();
expect(component.rows.length).toEqual(1);
expect(component.rows[0].entry['appName']).toBe('simpleapp');
expect(component.rows[0].entry['activityType']).toBe('serviceTask');
expect(component.rows[0].entry['id']).toBe('04fdf69f-4ddd-48ab-9563-da776c9b163c');
expect(component.rows[0].entry['elementId']).toBe('ServiceTask_0lszm0x');
expect(component.rows[0].entry['executionId']).toBe('2023b099-fced-11ea-b116-62141048995a');
expect(component.rows[0].entry['startedDate']).toBe('2020-09-22T16:03:37.444+0000');
expect(component.rows[0].entry['completedDate']).toBe('2020-09-22T16:03:37.482+0000');
expect(component.rows[0].entry['processDefinitionVersion']).toBe(1);
expect(component.rows[0].entry['processDefinitionId']).toBe('Process_24rkVVSR:1:0db78dcd-fc14-11ea-bce0-62141048995a');
expect(component.rows[0].entry['processInstanceId']).toBe('2023b097-fced-11ea-b116-62141048995a');
expect(component.rows[0].entry['status']).toBe('COMPLETED');
expect(component.rows[0].entry['serviceFullName']).toBe('simpleapp-rb');
expect(component.rows[0].entry['serviceName']).toBe('simpleapp-rb');
expect(component.rows[0]['appName']).toBe('simpleapp');
expect(component.rows[0]['activityType']).toBe('serviceTask');
expect(component.rows[0]['id']).toBe('04fdf69f-4ddd-48ab-9563-da776c9b163c');
expect(component.rows[0]['elementId']).toBe('ServiceTask_0lszm0x');
expect(component.rows[0]['executionId']).toBe('2023b099-fced-11ea-b116-62141048995a');
expect(component.rows[0]['startedDate']).toBe('2020-09-22T16:03:37.444+0000');
expect(component.rows[0]['completedDate']).toBe('2020-09-22T16:03:37.482+0000');
expect(component.rows[0]['processDefinitionVersion']).toBe(1);
expect(component.rows[0]['processDefinitionId']).toBe('Process_24rkVVSR:1:0db78dcd-fc14-11ea-bce0-62141048995a');
expect(component.rows[0]['processInstanceId']).toBe('2023b097-fced-11ea-b116-62141048995a');
expect(component.rows[0]['status']).toBe('COMPLETED');
expect(component.rows[0]['serviceFullName']).toBe('simpleapp-rb');
expect(component.rows[0]['serviceName']).toBe('simpleapp-rb');
done();
});
component.appName = appName.currentValue;
@@ -228,11 +228,7 @@ describe('ServiceTaskListCloudComponent', () => {
});
it('should emit row click event', (done) => {
const row = new ObjectDataRow({
entry: {
id: '999'
}
});
const row = new ObjectDataRow({ id: '999' });
const rowEvent = new DataRowEvent(row, null);
component.rowClick.subscribe((taskId) => {
expect(taskId).toEqual('999');
@@ -286,7 +282,7 @@ describe('ServiceTaskListCloudComponent', () => {
});
fixture.detectChanges();
expect(component.formatSorting).toHaveBeenCalledWith(mockSort);
expect(component.formattedSorting).toEqual([ServiceTaskListCloudComponent.ENTRY_PREFIX + 'startDate', 'desc']);
expect(component.formattedSorting).toEqual(['startDate', 'desc']);
});
it('should reload task list when sorting on a column changes', () => {
@@ -305,7 +301,7 @@ describe('ServiceTaskListCloudComponent', () => {
direction: 'ASC'
})
]);
expect(component.formattedSorting).toEqual(['entry.fakeName', 'asc']);
expect(component.formattedSorting).toEqual(['fakeName', 'asc']);
expect(component.isListEmpty()).toBeFalsy();
expect(getServiceTaskByRequestSpy).toHaveBeenCalled();
});
@@ -457,14 +453,14 @@ describe('ServiceTaskListCloudComponent', () => {
'presets': {
'fakeCustomSchema': [
{
'key': 'entry.id',
'key': 'id',
'type': 'text',
'title': 'ADF_CLOUD_TASK_LIST.PROPERTIES.FAKE',
'sortable': true,
'copyContent': true
},
{
'key': 'entry.activityName',
'key': 'activityName',
'type': 'text',
'title': 'ADF_CLOUD_TASK_LIST.PROPERTIES.TASK_FAKE',
'sortable': true

View File

@@ -66,8 +66,8 @@ class EmptyTemplateComponent {
template: `
<adf-cloud-task-list>
<data-columns>
<data-column [copyContent]="true" key="entry.id" title="ADF_CLOUD_TASK_LIST.PROPERTIES.ID"></data-column>
<data-column key="entry.name" title="ADF_CLOUD_TASK_LIST.PROPERTIES.NAME"></data-column>
<data-column [copyContent]="true" key="id" title="ADF_CLOUD_TASK_LIST.PROPERTIES.ID"></data-column>
<data-column key="name" title="ADF_CLOUD_TASK_LIST.PROPERTIES.NAME"></data-column>
</data-columns>
</adf-cloud-task-list>`
})
@@ -199,26 +199,26 @@ describe('TaskListCloudComponent', () => {
expect(component.rows).toBeDefined();
expect(component.isListEmpty()).not.toBeTruthy();
expect(component.rows.length).toEqual(1);
expect(component.rows[0].entry['appName']).toBe('test-ciprian2');
expect(component.rows[0].entry['appVersion']).toBe('');
expect(component.rows[0].entry['id']).toBe('11fe013d-c263-11e8-b75b-0a5864600540');
expect(component.rows[0].entry['assignee']).toBeNull();
expect(component.rows[0].entry['name']).toEqual('standalone-subtask');
expect(component.rows[0].entry['description']).toBeNull();
expect(component.rows[0].entry['createdDate']).toBe(1538059139420);
expect(component.rows[0].entry['dueDate']).toBeNull();
expect(component.rows[0].entry['claimedDate']).toBeNull();
expect(component.rows[0].entry['priority']).toBe(0);
expect(component.rows[0].entry['category']).toBeNull();
expect(component.rows[0].entry['processDefinitionId']).toBeNull();
expect(component.rows[0].entry['processInstanceId']).toBeNull();
expect(component.rows[0].entry['status']).toBe('CREATED');
expect(component.rows[0].entry['owner']).toBe('devopsuser');
expect(component.rows[0].entry['parentTaskId']).toBe('71fda20b-c25b-11e8-b75b-0a5864600540');
expect(component.rows[0].entry['lastModified']).toBe(1538059139420);
expect(component.rows[0].entry['lastModifiedTo']).toBeNull();
expect(component.rows[0].entry['lastModifiedFrom']).toBeNull();
expect(component.rows[0].entry['standalone']).toBeTruthy();
expect(component.rows[0]['appName']).toBe('test-ciprian2');
expect(component.rows[0]['appVersion']).toBe('');
expect(component.rows[0]['id']).toBe('11fe013d-c263-11e8-b75b-0a5864600540');
expect(component.rows[0]['assignee']).toBeNull();
expect(component.rows[0]['name']).toEqual('standalone-subtask');
expect(component.rows[0]['description']).toBeNull();
expect(component.rows[0]['createdDate']).toBe(1538059139420);
expect(component.rows[0]['dueDate']).toBeNull();
expect(component.rows[0]['claimedDate']).toBeNull();
expect(component.rows[0]['priority']).toBe(0);
expect(component.rows[0]['category']).toBeNull();
expect(component.rows[0]['processDefinitionId']).toBeNull();
expect(component.rows[0]['processInstanceId']).toBeNull();
expect(component.rows[0]['status']).toBe('CREATED');
expect(component.rows[0]['owner']).toBe('devopsuser');
expect(component.rows[0]['parentTaskId']).toBe('71fda20b-c25b-11e8-b75b-0a5864600540');
expect(component.rows[0]['lastModified']).toBe(1538059139420);
expect(component.rows[0]['lastModifiedTo']).toBeNull();
expect(component.rows[0]['lastModifiedFrom']).toBeNull();
expect(component.rows[0]['standalone']).toBeTruthy();
done();
});
component.appName = appName.currentValue;
@@ -240,11 +240,7 @@ describe('TaskListCloudComponent', () => {
});
it('should emit row click event', (done) => {
const row = new ObjectDataRow({
entry: {
id: '999'
}
});
const row = new ObjectDataRow({ id: '999' });
const rowEvent = new DataRowEvent(row, null);
component.rowClick.subscribe((taskId) => {
expect(taskId).toEqual('999');
@@ -307,7 +303,7 @@ describe('TaskListCloudComponent', () => {
});
fixture.detectChanges();
expect(component.formatSorting).toHaveBeenCalledWith(mockSort);
expect(component.formattedSorting).toEqual([TaskListCloudComponent.ENTRY_PREFIX + 'startDate', 'desc']);
expect(component.formattedSorting).toEqual(['startDate', 'desc']);
});
it('should reload task list when sorting on a column changes', () => {
@@ -326,7 +322,7 @@ describe('TaskListCloudComponent', () => {
direction: 'ASC'
})
]);
expect(component.formattedSorting).toEqual(['entry.fakeName', 'asc']);
expect(component.formattedSorting).toEqual(['fakeName', 'asc']);
expect(component.isListEmpty()).toBeFalsy();
expect(getTaskByRequestSpy).toHaveBeenCalled();
});
@@ -506,14 +502,14 @@ describe('TaskListCloudComponent', () => {
'presets': {
'fakeCustomSchema': [
{
'key': 'entry.id',
'key': 'id',
'type': 'text',
'title': 'ADF_CLOUD_TASK_LIST.PROPERTIES.FAKE',
'sortable': true,
'copyContent': true
},
{
'key': 'entry.name',
'key': 'name',
'type': 'text',
'title': 'ADF_CLOUD_TASK_LIST.PROPERTIES.TASK_FAKE',
'sortable': true
@@ -538,7 +534,9 @@ describe('TaskListCloudComponent', () => {
fixture.destroy();
});
it('shoud show tooltip if config copyContent flag is true', async(() => {
// TODO: highly unstable test
// tslint:disable-next-line:ban
xit('should show tooltip if config copyContent flag is true', async(() => {
taskSpy.and.returnValue(of(fakeGlobalTask));
const appName = new SimpleChange(null, 'FAKE-APP-NAME', true);
@@ -558,25 +556,9 @@ describe('TaskListCloudComponent', () => {
component.ngAfterContentInit();
}));
it('shoud not show tooltip if config copyContent flag is true', async(() => {
taskSpy.and.returnValue(of(fakeGlobalTask));
const appName = new SimpleChange(null, 'FAKE-APP-NAME', true);
component.success.subscribe(() => {
fixture.whenStable().then(() => {
fixture.detectChanges();
const spanHTMLElement: HTMLInputElement = <HTMLInputElement> element.querySelector('span[title="standalone-subtask"]');
spanHTMLElement.dispatchEvent(new Event('mouseenter'));
fixture.detectChanges();
expect(fixture.debugElement.nativeElement.querySelector('.adf-copy-tooltip')).toBeNull();
});
});
component.presetColumn = 'fakeCustomSchema';
component.appName = appName.currentValue;
component.ngOnChanges({ 'appName': appName });
component.ngAfterContentInit();
}));
it('should replace priority values', (done) => {
// TODO: highly unstable test
// tslint:disable-next-line:ban
xit('should replace priority values', (done) => {
taskSpy.and.returnValue(of(fakeGlobalTask));
component.presetColumn = 'fakeCustomSchema';
const appName = new SimpleChange(null, 'FAKE-APP-NAME', true);
@@ -610,7 +592,7 @@ describe('TaskListCloudComponent', () => {
getValue: () => undefined
}, {
type: 'text',
key: 'entry.priority'
key: 'priority'
})).toEqual(undefined);
});
@@ -624,16 +606,14 @@ describe('TaskListCloudComponent', () => {
expect(component.replacePriorityValues({
obj: {
entry: {
priority: 1
}
priority: 1
},
isSelected: false,
hasValue: () => false,
getValue: () => undefined
}, {
type: 'text',
key: 'entry.priority'
key: 'priority'
})).toEqual('ADF_CLOUD_TASK_LIST.PROPERTIES.PRIORITY_VALUES.LOW');
});
});

View File

@@ -17,94 +17,30 @@
import { ObjectDataColumn } from '@alfresco/adf-core';
export const fakeTaskCloudList = {
list: {
entries: [
{
entry: {
appName: 'save-the-cheerleader',
appVersion: '',
id: '890b0e1c-c252-11e8-b5c5-0a58646004c7',
assignee: null,
name: 'SimpleStandaloneTask',
description: 'Task description',
createdDate: 1538052037711,
dueDate: null,
claimedDate: null,
priority: 0,
category: null,
processDefinitionId: null,
processInstanceId: null,
status: 'CREATED',
owner: 'superadminuser',
parentTaskId: null,
lastModified: 1538052037711,
lastModifiedTo: null,
lastModifiedFrom: null,
standalone: true
}
},
{
entry: {
appName: 'save-the-cheerleader',
appVersion: '',
id: '8962cb0e-c252-11e8-b5c5-0a58646004c7',
assignee: null,
name: 'SimpleStandaloneTask',
description: 'Task description',
createdDate: 1538052038286,
dueDate: null,
claimedDate: null,
priority: 0,
category: null,
processDefinitionId: null,
processInstanceId: null,
status: 'CREATED',
owner: 'superadminuser',
parentTaskId: null,
lastModified: 1538052038286,
lastModifiedTo: null,
lastModifiedFrom: null,
standalone: true
}
}
],
pagination: {
skipCount: 0,
maxItems: 100,
count: 2,
hasMoreItems: false,
totalItems: 2
}
}
};
export const fakeGlobalTask = {
list: {
entries: [
{
entry: {
appName: 'test-ciprian2',
appVersion: '',
id: '11fe013d-c263-11e8-b75b-0a5864600540',
assignee: null,
name: 'standalone-subtask',
description: null,
createdDate: 1538059139420,
dueDate: null,
claimedDate: null,
priority: 0,
category: null,
processDefinitionId: null,
processInstanceId: null,
status: 'CREATED',
owner: 'devopsuser',
parentTaskId: '71fda20b-c25b-11e8-b75b-0a5864600540',
lastModified: 1538059139420,
lastModifiedTo: null,
lastModifiedFrom: null,
standalone: true
}
appName: 'test-ciprian2',
appVersion: '',
id: '11fe013d-c263-11e8-b75b-0a5864600540',
assignee: null,
name: 'standalone-subtask',
description: null,
createdDate: 1538059139420,
dueDate: null,
claimedDate: null,
priority: 0,
category: null,
processDefinitionId: null,
processInstanceId: null,
status: 'CREATED',
owner: 'devopsuser',
parentTaskId: '71fda20b-c25b-11e8-b75b-0a5864600540',
lastModified: 1538059139420,
lastModifiedTo: null,
lastModifiedFrom: null,
standalone: true
}
],
pagination: {
@@ -121,24 +57,22 @@ export const fakeServiceTask = {
list: {
entries: [
{
entry: {
activityType: 'serviceTask',
activityName: 'serviceTaskName',
appName: 'simpleapp',
completedDate: '2020-09-22T16:03:37.482+0000',
elementId: 'ServiceTask_0lszm0x',
executionId: '2023b099-fced-11ea-b116-62141048995a',
id: '04fdf69f-4ddd-48ab-9563-da776c9b163c',
processDefinitionId: 'Process_24rkVVSR:1:0db78dcd-fc14-11ea-bce0-62141048995a',
processDefinitionKey: 'Process_24rkVVSR',
processDefinitionVersion: 1,
processInstanceId: '2023b097-fced-11ea-b116-62141048995a',
serviceFullName: 'simpleapp-rb',
serviceName: 'simpleapp-rb',
serviceVersion: '',
startedDate: '2020-09-22T16:03:37.444+0000',
status: 'COMPLETED'
}
activityType: 'serviceTask',
activityName: 'serviceTaskName',
appName: 'simpleapp',
completedDate: '2020-09-22T16:03:37.482+0000',
elementId: 'ServiceTask_0lszm0x',
executionId: '2023b099-fced-11ea-b116-62141048995a',
id: '04fdf69f-4ddd-48ab-9563-da776c9b163c',
processDefinitionId: 'Process_24rkVVSR:1:0db78dcd-fc14-11ea-bce0-62141048995a',
processDefinitionKey: 'Process_24rkVVSR',
processDefinitionVersion: 1,
processInstanceId: '2023b097-fced-11ea-b116-62141048995a',
serviceFullName: 'simpleapp-rb',
serviceName: 'simpleapp-rb',
serviceVersion: '',
startedDate: '2020-09-22T16:03:37.444+0000',
status: 'COMPLETED'
}
],
pagination: {

View File

@@ -18,20 +18,20 @@
export const taskPresetsCloudDefaultModel = {
'default': [
{
'key': 'entry.name',
'key': 'name',
'type': 'text',
'title': 'ADF_CLOUD_TASK_LIST.PROPERTIES.NAME',
'sortable': true
},
{
'key': 'entry.created',
'key': 'created',
'type': 'text',
'title': 'ADF_CLOUD_TASK_LIST.PROPERTIES.CREATED',
'cssClass': 'hidden',
'sortable': true
},
{
'key': 'entry.assignee',
'key': 'assignee',
'type': 'text',
'title': 'ADF_CLOUD_TASK_LIST.PROPERTIES.ASSIGNEE',
'cssClass': 'hidden',
@@ -43,26 +43,26 @@ export const taskPresetsCloudDefaultModel = {
export const serviceTaskPresetsCloudDefaultModel = {
'default': [
{
'key': 'entry.activityName',
'key': 'activityName',
'type': 'text',
'title': 'ADF_CLOUD_SERVICE_TASK_LIST.PROPERTIES.ACTIVITY_NAME',
'sortable': true
},
{
'key': 'entry.status',
'key': 'status',
'type': 'text',
'title': 'ADF_CLOUD_SERVICE_TASK_LIST.PROPERTIES.STATUS',
'sortable': true
},
{
'key': 'entry.startedDate',
'key': 'startedDate',
'type': 'text',
'title': 'ADF_CLOUD_SERVICE_TASK_LIST.PROPERTIES.STARTED_DATE',
'cssClass': 'hidden',
'sortable': true
},
{
'key': 'entry.completedDate',
'key': 'completedDate',
'type': 'text',
'title': 'ADF_CLOUD_SERVICE_TASK_LIST.PROPERTIES.COMPLETED_DATE',
'cssClass': 'hidden',

View File

@@ -17,7 +17,6 @@
import { async } from '@angular/core/testing';
import { setupTestBed, StorageService, AlfrescoApiServiceMock, LogService, AppConfigService, CoreModule } from '@alfresco/adf-core';
import { fakeTaskCloudList } from '../mock/fake-task-response.mock';
import { ServiceTaskListCloudService } from './service-task-list-cloud.service';
import { ServiceTaskQueryCloudRequestModel } from '../models/service-task-cloud.model';
@@ -26,16 +25,6 @@ describe('Activiti ServiceTaskList Cloud Service', () => {
let service: ServiceTaskListCloudService;
let alfrescoApiMock: AlfrescoApiServiceMock;
function returnFakeTaskListResults() {
return {
oauth2Auth: {
callCustomApi: () => {
return Promise.resolve(fakeTaskCloudList);
}
}
};
}
function returnCallQueryParameters() {
return {
oauth2Auth: {
@@ -69,19 +58,6 @@ describe('Activiti ServiceTaskList Cloud Service', () => {
new LogService(new AppConfigService(null)));
}));
it('should return the tasks', (done) => {
const taskRequest: ServiceTaskQueryCloudRequestModel = <ServiceTaskQueryCloudRequestModel> { appName: 'fakeName' };
spyOn(alfrescoApiMock, 'getInstance').and.callFake(returnFakeTaskListResults);
service.getServiceTaskByRequest(taskRequest).subscribe((res) => {
expect(res).toBeDefined();
expect(res).not.toBeNull();
expect(res.list.entries.length).toBe(2);
expect(res.list.entries[0].entry.appName).toBe('save-the-cheerleader');
expect(res.list.entries[1].entry.appName).toBe('save-the-cheerleader');
done();
});
});
it('should append to the call all the parameters', (done) => {
const taskRequest: ServiceTaskQueryCloudRequestModel = <ServiceTaskQueryCloudRequestModel> { appName: 'fakeName', skipCount: 0, maxItems: 20, service: 'fake-service' };
spyOn(alfrescoApiMock, 'getInstance').and.callFake(returnCallQueryParameters);

View File

@@ -21,6 +21,7 @@ import { ServiceTaskQueryCloudRequestModel, ServiceTaskIntegrationContextCloudMo
import { Observable, throwError } from 'rxjs';
import { TaskListCloudSortingModel } from '../models/task-list-sorting.model';
import { BaseCloudService } from '../../../services/base-cloud.service';
import { map } from 'rxjs/operators';
@Injectable({ providedIn: 'root' })
export class ServiceTaskListCloudService extends BaseCloudService {
@@ -60,14 +61,16 @@ export class ServiceTaskListCloudService extends BaseCloudService {
getServiceTaskStatus(appName: string, serviceTaskId: string): Observable<ServiceTaskIntegrationContextCloudModel> {
if (appName) {
const queryUrl = `${this.getBasePath(appName)}/query/admin/v1/service-tasks/${serviceTaskId}/integration-context`;
return this.get(queryUrl);
return this.get(queryUrl).pipe(
map((response: any) => response.entry)
);
} else {
this.logService.error('Appname is mandatory for querying task');
return throwError('Appname not configured');
}
}
private buildQueryParams(requestNode: ServiceTaskQueryCloudRequestModel): Object {
protected buildQueryParams(requestNode: ServiceTaskQueryCloudRequestModel): Object {
const queryParam: Object = {};
for (const property in requestNode) {
if (requestNode.hasOwnProperty(property) &&
@@ -79,15 +82,15 @@ export class ServiceTaskListCloudService extends BaseCloudService {
return queryParam;
}
private isExcludedField(property: string): boolean {
protected isExcludedField(property: string): boolean {
return property === 'appName' || property === 'sorting';
}
private isPropertyValueValid(requestNode: any, property: string): boolean {
protected isPropertyValueValid(requestNode: any, property: string): boolean {
return requestNode[property] !== '' && requestNode[property] !== null && requestNode[property] !== undefined;
}
private buildSortingParam(models: TaskListCloudSortingModel[]): string {
protected buildSortingParam(models: TaskListCloudSortingModel[]): string {
let finalSorting: string = '';
if (models) {
for (const sort of models) {

View File

@@ -17,25 +17,14 @@
import { async } from '@angular/core/testing';
import { setupTestBed, StorageService, AlfrescoApiServiceMock, LogService, AppConfigService, CoreModule } from '@alfresco/adf-core';
import { fakeTaskCloudList } from '../mock/fake-task-response.mock';
import { TaskListCloudService } from './task-list-cloud.service';
import { TaskQueryCloudRequestModel } from '../models/filter-cloud-model';
describe('Activiti TaskList Cloud Service', () => {
describe('TaskListCloudService', () => {
let service: TaskListCloudService;
let alfrescoApiMock: AlfrescoApiServiceMock;
function returnFakeTaskListResults() {
return {
oauth2Auth: {
callCustomApi : () => {
return Promise.resolve(fakeTaskCloudList);
}
}
};
}
function returnCallQueryParameters() {
return {
oauth2Auth: {
@@ -69,19 +58,6 @@ describe('Activiti TaskList Cloud Service', () => {
new LogService(new AppConfigService(null)));
}));
it('should return the tasks', (done) => {
const taskRequest: TaskQueryCloudRequestModel = <TaskQueryCloudRequestModel> { appName: 'fakeName' };
spyOn(alfrescoApiMock, 'getInstance').and.callFake(returnFakeTaskListResults);
service.getTaskByRequest(taskRequest).subscribe((res) => {
expect(res).toBeDefined();
expect(res).not.toBeNull();
expect(res.list.entries.length).toBe(2);
expect(res.list.entries[0].entry.appName).toBe('save-the-cheerleader');
expect(res.list.entries[1].entry.appName).toBe('save-the-cheerleader');
done();
});
});
it('should append to the call all the parameters', (done) => {
const taskRequest: TaskQueryCloudRequestModel = <TaskQueryCloudRequestModel> { appName: 'fakeName', skipCount: 0, maxItems: 20, service: 'fake-service' };
spyOn(alfrescoApiMock, 'getInstance').and.callFake(returnCallQueryParameters);

View File

@@ -22,37 +22,47 @@ import { Observable, throwError } from 'rxjs';
import { TaskListCloudSortingModel } from '../models/task-list-sorting.model';
import { BaseCloudService } from '../../../services/base-cloud.service';
import { TaskCloudNodePaging } from '../models/task-cloud.model';
import { map } from 'rxjs/operators';
@Injectable({ providedIn: 'root' })
export class TaskListCloudService extends BaseCloudService {
constructor(apiService: AlfrescoApiService,
appConfigService: AppConfigService,
private logService: LogService) {
protected logService: LogService) {
super(apiService, appConfigService);
}
/**
* Finds a task using an object with optional query properties.
* @param requestNode Query object
* @param queryUrl Query url
* @returns Task information
*/
getTaskByRequest(requestNode: TaskQueryCloudRequestModel): Observable<any> {
getTaskByRequest(requestNode: TaskQueryCloudRequestModel, queryUrl?: string): Observable<any> {
if (requestNode.appName || requestNode.appName === '') {
const queryUrl = `${this.getBasePath(requestNode.appName)}/query/v1/tasks`;
queryUrl = queryUrl || `${this.getBasePath(requestNode.appName)}/query/v1/tasks`;
const queryParams = this.buildQueryParams(requestNode);
const sortingParams = this.buildSortingParam(requestNode.sorting);
if (sortingParams) {
queryParams['sort'] = sortingParams;
}
return this.get<TaskCloudNodePaging>(queryUrl, queryParams);
return this.get<TaskCloudNodePaging>(queryUrl, queryParams).pipe(
map((response: any) => {
const entries = response.list && response.list.entries;
if (entries) {
response.list.entries = entries.map((entryData: any) => entryData.entry);
}
return response;
})
);
} else {
this.logService.error('Appname is mandatory for querying task');
return throwError('Appname not configured');
}
}
private buildQueryParams(requestNode: TaskQueryCloudRequestModel): Object {
protected buildQueryParams(requestNode: TaskQueryCloudRequestModel): Object {
const queryParam: Object = {};
for (const property in requestNode) {
if (requestNode.hasOwnProperty(property) &&
@@ -64,15 +74,15 @@ export class TaskListCloudService extends BaseCloudService {
return queryParam;
}
private isExcludedField(property: string): boolean {
protected isExcludedField(property: string): boolean {
return property === 'appName' || property === 'sorting';
}
private isPropertyValueValid(requestNode: any, property: string): boolean {
protected isPropertyValueValid(requestNode: any, property: string): boolean {
return requestNode[property] !== '' && requestNode[property] !== null && requestNode[property] !== undefined;
}
private buildSortingParam(models: TaskListCloudSortingModel[]): string {
protected buildSortingParam(models: TaskListCloudSortingModel[]): string {
let finalSorting: string = '';
if (models) {
for (const sort of models) {

View File

@@ -14,7 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { browser, by, element, protractor } from 'protractor';
import { browser, by, element } from 'protractor';
import { EditProcessFilterDialogPage } from './dialog/edit-process-filter-dialog.page';
import { BrowserVisibility } from '../../core/utils/browser-visibility';
import { BrowserActions } from '../../core/utils/browser-actions';
@@ -57,11 +57,12 @@ export class EditProcessFilterCloudComponentPage {
return this.editProcessFilterDialogPage;
}
async isFilterDisplayed(): Promise<boolean> {
isFilterDisplayed(): Promise<boolean> {
return BrowserVisibility.waitUntilElementIsVisible(this.filter);
}
async openFilter(): Promise<void> {
await this.isFilterDisplayed();
await BrowserActions.click(this.customiseFilter);
await browser.driver.sleep(1000);
}
@@ -73,16 +74,16 @@ export class EditProcessFilterCloudComponentPage {
await BrowserVisibility.waitUntilElementIsVisible(content);
}
async setStatusFilterDropDown(option: string): Promise<void> {
await this.statusDropdown.selectDropdownOption(option);
setStatusFilterDropDown(option: string): Promise<void> {
return this.statusDropdown.selectDropdownOption(option);
}
async getStateFilterDropDownValue(): Promise<string> {
getStateFilterDropDownValue(): Promise<string> {
return BrowserActions.getText(element(by.css("mat-form-field[data-automation-id='status'] span")));
}
async setSortFilterDropDown(option): Promise<void> {
await this.sortDropdown.selectDropdownOption(option);
setSortFilterDropDown(option): Promise<void> {
return this.sortDropdown.selectDropdownOption(option);
}
async getSortFilterDropDownValue(): Promise<string> {
@@ -95,16 +96,16 @@ export class EditProcessFilterCloudComponentPage {
await browser.sleep(1500);
}
async getOrderFilterDropDownValue(): Promise<string> {
getOrderFilterDropDownValue(): Promise<string> {
return BrowserActions.getText(element(by.css("mat-form-field[data-automation-id='order'] span")));
}
async setAppNameDropDown(option: string): Promise<void> {
await this.appNameDropdown.selectDropdownOption(option);
setAppNameDropDown(option: string): Promise<void> {
return this.appNameDropdown.selectDropdownOption(option);
}
async setProcessDefinitionNameDropDown(option: string): Promise<void> {
await this.processDefinitionNameDropdown.selectDropdownOption(option);
setProcessDefinitionNameDropDown(option: string): Promise<void> {
return this.processDefinitionNameDropdown.selectDropdownOption(option);
}
async getApplicationSelected(): Promise<string> {
@@ -127,28 +128,28 @@ export class EditProcessFilterCloudComponentPage {
return this.appNameDropdown.getNumberOfOptions();
}
async isApplicationListLoaded(): Promise<boolean> {
isApplicationListLoaded(): Promise<boolean> {
const emptyList = element(by.css(`[data-automation-id='adf-cloud-edit-process-property-appName'] .mat-select-placeholder`));
return BrowserVisibility.waitUntilElementIsNotVisible(emptyList);
}
async setProcessInstanceId(option: string): Promise<void> {
await this.setProperty('processInstanceId', option);
setProcessInstanceId(option: string): Promise<void> {
return this.setProperty('processInstanceId', option);
}
async setProcessDefinitionKey(option: string): Promise<void> {
await this.setProperty('processDefinitionKey', option);
setProcessDefinitionKey(option: string): Promise<void> {
return this.setProperty('processDefinitionKey', option);
}
async setProcessName(option: string): Promise<void> {
await this.setProperty('processName', option);
setProcessName(option: string): Promise<void> {
return this.setProperty('processName', option);
}
async setInitiator(value: string): Promise<void> {
await this.peopleCloudComponent.searchAssigneeAndSelect(value);
setInitiator(value: string): Promise<void> {
return this.peopleCloudComponent.searchAssigneeAndSelect(value);
}
async getProcessInstanceId(): Promise<string> {
getProcessInstanceId(): Promise<string> {
return this.getProperty('processInstanceId');
}
@@ -161,25 +162,23 @@ export class EditProcessFilterCloudComponentPage {
async setProperty(property: string, option: string): Promise<void> {
const locator = element.all(by.css('input[data-automation-id="adf-cloud-edit-process-property-' + property + '"]')).first();
await BrowserVisibility.waitUntilElementIsVisible(locator);
await locator.clear();
await locator.sendKeys(option);
await locator.sendKeys(protractor.Key.ENTER);
await BrowserActions.clearSendKeys(locator, option);
}
async checkSaveButtonIsDisplayed(): Promise<void> {
await BrowserVisibility.waitUntilElementIsVisible(this.saveButton);
checkSaveButtonIsDisplayed(): Promise<void> {
return BrowserVisibility.waitUntilElementIsVisible(this.saveButton);
}
async checkSaveAsButtonIsDisplayed(): Promise<void> {
await BrowserVisibility.waitUntilElementIsVisible(this.saveAsButton);
checkSaveAsButtonIsDisplayed(): Promise<void> {
return BrowserVisibility.waitUntilElementIsVisible(this.saveAsButton);
}
async checkDeleteButtonIsDisplayed(): Promise<void> {
await BrowserVisibility.waitUntilElementIsVisible(this.deleteButton);
checkDeleteButtonIsDisplayed(): Promise<void> {
return BrowserVisibility.waitUntilElementIsVisible(this.deleteButton);
}
async checkDeleteButtonIsNotDisplayed(): Promise<void> {
await BrowserVisibility.waitUntilElementIsNotVisible(this.deleteButton);
checkDeleteButtonIsNotDisplayed(): Promise<void> {
return BrowserVisibility.waitUntilElementIsNotVisible(this.deleteButton);
}
async checkSaveButtonIsEnabled(): Promise<boolean> {
@@ -197,21 +196,25 @@ export class EditProcessFilterCloudComponentPage {
return this.deleteButton.isEnabled();
}
async saveAs(name: string): Promise<void> {
await this.clickSaveAsButton();
await this.editProcessFilterDialog().setFilterName(name);
await this.editProcessFilterDialog().clickOnSaveButton();
await browser.driver.sleep(1000);
}
async clickSaveAsButton(): Promise<void> {
const disabledButton = element(by.css(("button[data-automation-id='adf-filter-action-saveAs'][disabled]")));
await BrowserVisibility.waitUntilElementIsNotVisible(disabledButton);
await BrowserActions.click(this.saveAsButton);
await browser.driver.sleep(1000);
}
async clickDeleteButton(): Promise<void> {
await BrowserActions.click(this.deleteButton);
clickDeleteButton(): Promise<void> {
return BrowserActions.click(this.deleteButton);
}
async clickSaveButton(): Promise<void> {
const disabledButton = element(by.css(("button[id='adf-save-as-id'][disabled]")));
await BrowserVisibility.waitUntilElementIsNotVisible(disabledButton);
await BrowserActions.click(this.saveButton);
clickSaveButton(): Promise<void> {
return BrowserActions.click(this.saveButton);
}
async setFilter(props: FilterProps): Promise<void> {

View File

@@ -191,8 +191,6 @@ export class EditTaskFilterCloudComponentPage {
}
async clickSaveAsButton(): Promise<void> {
const disabledButton = element(by.css(("button[data-automation-id='adf-filter-action-saveAs'][disabled]")));
await BrowserVisibility.waitUntilElementIsNotVisible(disabledButton);
await BrowserActions.click(this.saveAsButton);
await browser.driver.sleep(1000);
}

View File

@@ -19,9 +19,14 @@ import { Locator, by, element, ElementFinder } from 'protractor';
import { BrowserVisibility } from '../../core/utils/browser-visibility';
import { BrowserActions } from '../../core/utils/browser-actions';
const FILTERS = {
ALL: 'all-processes',
COMPLETED: 'completed-processes',
RUNNING: 'running-processes'
};
export class ProcessFiltersCloudComponentPage {
filter: ElementFinder;
filterIcon: Locator = by.css('adf-icon[data-automation-id="adf-filter-icon"]');
processFilters = element(by.css("mat-expansion-panel[data-automation-id='Process Filters']"));
@@ -30,62 +35,48 @@ export class ProcessFiltersCloudComponentPage {
processFiltersList = element(by.css('adf-cloud-process-filters'));
async checkProcessFilterIsDisplayed(filterName: string): Promise<void> {
this.filter = this.getProcessFilterLocatorByFilterName(filterName);
await BrowserVisibility.waitUntilElementIsVisible(this.filter);
}
async getProcessFilterIcon(filterName: string): Promise<string> {
this.filter = this.getProcessFilterLocatorByFilterName(filterName);
await BrowserVisibility.waitUntilElementIsVisible(this.filter);
const icon = this.filter.element(this.filterIcon);
await BrowserVisibility.waitUntilElementIsVisible(icon);
return BrowserActions.getText(icon);
}
async checkProcessFilterHasNoIcon(filterName: string): Promise<void> {
this.filter = this.getProcessFilterLocatorByFilterName(filterName);
await BrowserVisibility.waitUntilElementIsVisible(this.filter);
await BrowserVisibility.waitUntilElementIsNotVisible(this.filter.element(this.filterIcon));
const filter = this.getProcessFilterLocatorByFilterName(filterName);
await BrowserVisibility.waitUntilElementIsVisible(filter);
}
async clickProcessFilter(filterName: string): Promise<void> {
this.filter = this.getProcessFilterLocatorByFilterName(filterName);
await BrowserActions.click(this.filter);
const filter = this.getProcessFilterLocatorByFilterName(filterName);
await BrowserActions.click(filter);
}
async clickAllProcessesFilter(): Promise<void> {
this.filter = this.getProcessFilterLocatorByFilterName('all-processes');
await BrowserActions.click(this.filter);
const filter = this.getProcessFilterLocatorByFilterName(FILTERS.ALL);
await BrowserActions.click(filter);
}
async clickCompletedProcessesFilter(): Promise<void> {
this.filter = this.getProcessFilterLocatorByFilterName('completed-processes');
await BrowserActions.click(this.filter);
const filter = this.getProcessFilterLocatorByFilterName(FILTERS.COMPLETED);
await BrowserActions.click(filter);
}
async clickRunningProcessesFilter(): Promise<void> {
this.filter = this.getProcessFilterLocatorByFilterName('running-processes');
await BrowserActions.click(this.filter);
const filter = this.getProcessFilterLocatorByFilterName(FILTERS.RUNNING);
await BrowserActions.click(filter);
}
async checkAllProcessesFilterIsDisplayed(): Promise<void> {
this.filter = this.getProcessFilterLocatorByFilterName('all-processes');
await BrowserVisibility.waitUntilElementIsVisible(this.filter);
const filter = this.getProcessFilterLocatorByFilterName(FILTERS.ALL);
await BrowserVisibility.waitUntilElementIsVisible(filter);
}
async checkCompletedProcessesFilterIsDisplayed(): Promise<void> {
this.filter = this.getProcessFilterLocatorByFilterName('completed-processes');
await BrowserVisibility.waitUntilElementIsVisible(this.filter);
const filter = this.getProcessFilterLocatorByFilterName(FILTERS.COMPLETED);
await BrowserVisibility.waitUntilElementIsVisible(filter);
}
async checkRunningProcessesFilterIsDisplayed(): Promise<void> {
this.filter = this.getProcessFilterLocatorByFilterName('running-processes');
await BrowserVisibility.waitUntilElementIsVisible(this.filter);
const filter = this.getProcessFilterLocatorByFilterName(FILTERS.RUNNING);
await BrowserVisibility.waitUntilElementIsVisible(filter);
}
async checkProcessFilterNotDisplayed(filterName: string): Promise<void> {
this.filter = this.getProcessFilterLocatorByFilterName(filterName);
await BrowserVisibility.waitUntilElementIsNotVisible(this.filter);
const filter = this.getProcessFilterLocatorByFilterName(filterName);
await BrowserVisibility.waitUntilElementIsNotVisible(filter);
}
async clickOnProcessFilters(): Promise<void> {

1064
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -110,7 +110,7 @@
"devDependencies": {
"@angular-devkit/build-angular": "^0.1001.7",
"@angular-devkit/build-ng-packagr": "~0.1002.0",
"@angular/cli": "^11.2.0",
"@angular/cli": "^10.2.2",
"@angular/compiler-cli": "^10.0.12",
"@nrwl/schematics": "8.12.11",
"@nrwl/workspace": "^11.2.11",