diff --git a/demo-shell/resources/i18n/en.json b/demo-shell/resources/i18n/en.json index ae460cccb4..647904c1b0 100644 --- a/demo-shell/resources/i18n/en.json +++ b/demo-shell/resources/i18n/en.json @@ -105,7 +105,8 @@ "PEOPLE_CLOUD": "People Cloud Component", "GROUPS_CLOUD": "Groups Cloud Component", "CONFIRM-DIALOG": "Confirmation Dialog", - "COMMUNITY": "Community" + "COMMUNITY": "Community", + "SERVICE_TASK_LIST": "Service Task List" }, "TRASHCAN": { "ACTIONS": { diff --git a/demo-shell/src/app.config.json b/demo-shell/src/app.config.json index 0f3ecbdc8f..cf55983c35 100644 --- a/demo-shell/src/app.config.json +++ b/demo-shell/src/app.config.json @@ -969,6 +969,35 @@ "delete" ] }, + "adf-edit-service-task-filter": { + "filterProperties": [ + "appName", + "serviceTaskId", + "activityName", + "activityType", + "completedDate", + "startedDate", + "sort", + "order", + "status", + "elementId", + "serviceName", + "processInstanceId", + "processDefinitionId", + "serviceName" + ], + "sortProperties": [ + "id", + "activityName", + "completedDate", + "startedDate" + ], + "actions": [ + "save", + "saveAs", + "delete" + ] + }, "adf-edit-process-filter": { "filterProperties": [ "status", @@ -1066,6 +1095,44 @@ ] } }, + "adf-cloud-service-task-list": { + "presets": { + "default": [ + { + "key": "entry.id", + "type": "text", + "title": "ADF_CLOUD_SERVICE_TASK_LIST.PROPERTIES.ID", + "sortable": true + }, + { + "key": "entry.activityName", + "type": "text", + "title": "ADF_CLOUD_SERVICE_TASK_LIST.PROPERTIES.ACTIVITY_NAME", + "sortable": true + }, + { + "key": "entry.status", + "type": "text", + "title": "ADF_CLOUD_SERVICE_TASK_LIST.PROPERTIES.STATUS", + "sortable": true + }, + { + "key": "entry.startedDate", + "type": "date", + "title": "ADF_CLOUD_SERVICE_TASK_LIST.PROPERTIES.STARTED_DATE", + "sortable": true, + "format": "timeAgo" + }, + { + "key": "entry.completedDate", + "type": "date", + "title": "ADF_CLOUD_SERVICE_TASK_LIST.PROPERTIES.COMPLETED_DATE", + "sortable": true, + "format": "timeAgo" + } + ] + } + }, "adf-cloud-process-list": { "presets": { "default": [ diff --git a/demo-shell/src/app/app.module.ts b/demo-shell/src/app/app.module.ts index a881122c5e..af28ee60db 100644 --- a/demo-shell/src/app/app.module.ts +++ b/demo-shell/src/app/app.module.ts @@ -65,6 +65,7 @@ import { TasksCloudDemoComponent } from './components/cloud/tasks-cloud-demo.com import { ProcessesCloudDemoComponent } from './components/cloud/processes-cloud-demo.component'; import { TaskDetailsCloudDemoComponent } from './components/cloud/task-details-cloud-demo.component'; import { TaskHeaderCloudDemoComponent } from './components/cloud/task-header-cloud-demo.component'; +import { ServiceTaskListCloudDemoComponent } from './components/cloud/service-task-list-cloud-demo.component'; import { CloudViewerComponent } from './components/cloud/cloud-viewer.component'; import { ProcessDetailsCloudDemoComponent } from './components/cloud/process-details-cloud-demo.component'; import { StartTaskCloudDemoComponent } from './components/cloud/start-task-cloud-demo.component'; @@ -189,7 +190,8 @@ registerLocaleData(localeSv); FormCloudDemoComponent, ConfirmDialogExampleComponent, SampleWidgetComponent, - ProcessCloudLayoutComponent + ProcessCloudLayoutComponent, + ServiceTaskListCloudDemoComponent ], providers: [ { diff --git a/demo-shell/src/app/app.routes.ts b/demo-shell/src/app/app.routes.ts index c98c513e92..6bd5e74a23 100644 --- a/demo-shell/src/app/app.routes.ts +++ b/demo-shell/src/app/app.routes.ts @@ -54,6 +54,7 @@ import { DemoErrorComponent } from './components/error/demo-error.component'; import { TaskHeaderCloudDemoComponent } from './components/cloud/task-header-cloud-demo.component'; import { FilteredSearchComponent } from './components/files/filtered-search.component'; import { ProcessCloudLayoutComponent } from './components/cloud/process-cloud-layout.component'; +import { ServiceTaskListCloudDemoComponent } from './components/cloud/service-task-list-cloud-demo.component'; export const appRoutes: Routes = [ { path: 'login', loadChildren: () => import('./components/login/login.module').then(m => m.AppLoginModule) }, @@ -176,22 +177,31 @@ export const appRoutes: Routes = [ { path: 'cloud', canActivate: [AuthGuardSsoRoleService], - data: { roles: ['ACTIVITI_USER'], redirectUrl: '/error/403' }, + data: { roles: ['ACTIVITI_ADMIN', 'ACTIVITI_USER'], redirectUrl: '/error/403' }, children: [ { path: '', + data: { roles: ['ACTIVITI_USER'], redirectUrl: '/error/403' }, component: AppsCloudDemoComponent }, { path: 'people-group-cloud', + data: { roles: ['ACTIVITI_USER'], redirectUrl: '/error/403' }, component: PeopleGroupCloudDemoComponent }, { path: 'task-header-cloud', + data: { roles: ['ACTIVITI_USER'], redirectUrl: '/error/403' }, component: TaskHeaderCloudDemoComponent }, + { + path: 'service-task-list', + data: { roles: ['ACTIVITI_ADMIN'], redirectUrl: '/error/403' }, + component: ServiceTaskListCloudDemoComponent + }, { path: 'community', + data: { roles: ['ACTIVITI_USER'], redirectUrl: '/error/403' }, loadChildren: () => import('./components/cloud/community/community.module').then(m => m.AppCommunityModule) }, { diff --git a/demo-shell/src/app/components/app-layout/app-layout.component.ts b/demo-shell/src/app/components/app-layout/app-layout.component.ts index 334c159f47..76faedde67 100644 --- a/demo-shell/src/app/components/app-layout/app-layout.component.ts +++ b/demo-shell/src/app/components/app-layout/app-layout.component.ts @@ -55,7 +55,8 @@ export class AppLayoutComponent implements OnInit, OnDestroy { { href: '/cloud/community', icon: 'cloud', title: 'APP_LAYOUT.COMMUNITY' }, { href: '/form-cloud', icon: 'poll', title: 'APP_LAYOUT.FORM' }, { href: '/cloud/people-group-cloud', icon: 'group', title: 'APP_LAYOUT.PEOPLE_GROUPS_CLOUD' }, - { href: '/cloud/task-header-cloud', icon: 'cloud', title: 'APP_LAYOUT.TASK_HEADER_CLOUD.COMPONENT_NAME' } + { href: '/cloud/task-header-cloud', icon: 'cloud', title: 'APP_LAYOUT.TASK_HEADER_CLOUD.COMPONENT_NAME' }, + { href: '/cloud/service-task-list', icon: 'cloud', title: 'APP_LAYOUT.SERVICE_TASK_LIST' } ] }, { href: '/activiti', icon: 'device_hub', title: 'APP_LAYOUT.PROCESS_SERVICES', children: [ diff --git a/demo-shell/src/app/components/cloud/service-task-list-cloud-demo.component.html b/demo-shell/src/app/components/cloud/service-task-list-cloud-demo.component.html new file mode 100644 index 0000000000..908f74a916 --- /dev/null +++ b/demo-shell/src/app/components/cloud/service-task-list-cloud-demo.component.html @@ -0,0 +1,32 @@ +
+ + +
+ + + + +
+
diff --git a/demo-shell/src/app/components/cloud/service-task-list-cloud-demo.component.ts b/demo-shell/src/app/components/cloud/service-task-list-cloud-demo.component.ts new file mode 100644 index 0000000000..fe337d977e --- /dev/null +++ b/demo-shell/src/app/components/cloud/service-task-list-cloud-demo.component.ts @@ -0,0 +1,98 @@ +/*! + * @license + * Copyright 2019 Alfresco Software, Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Component, OnInit, OnDestroy } from '@angular/core'; +import { TaskListCloudSortingModel, TaskFilterCloudModel } from '@alfresco/adf-process-services-cloud'; +import { UserPreferencesService, AppConfigService } from '@alfresco/adf-core'; +import { CloudLayoutService } from './services/cloud-layout.service'; +import { Subject } from 'rxjs'; +import { takeUntil } from 'rxjs/operators'; + +@Component({ + templateUrl: 'service-task-list-cloud-demo.component.html' +}) +export class ServiceTaskListCloudDemoComponent implements OnInit, OnDestroy { + + public static ACTION_SAVE_AS = 'saveAs'; + public static ACTION_DELETE = 'delete'; + static TASK_FILTER_PROPERTY_KEYS = 'adf-edit-service-task-filter'; + + isFilterLoaded = false; + + selectedRow: any; + + sortArray: TaskListCloudSortingModel[]; + editedFilter: TaskFilterCloudModel; + taskFilterProperties: any = { filterProperties: [], sortProperties: [], actions: [] }; + + multiselect: boolean; + selectedRows: string[] = []; + actionMenu: boolean; + contextMenu: boolean; + actions: any[] = []; + selectedAction: { id: number, name: string, actionType: string}; + selectedContextAction: { id: number, name: string, actionType: string}; + selectionMode: string; + + private onDestroy$ = new Subject(); + + constructor( + private cloudLayoutService: CloudLayoutService, + private userPreference: UserPreferencesService, + private appConfig: AppConfigService) { + + const properties = this.appConfig.get>(ServiceTaskListCloudDemoComponent.TASK_FILTER_PROPERTY_KEYS); + if (properties) { + this.taskFilterProperties = properties; + } + } + + ngOnInit() { + this.isFilterLoaded = false; + this.cloudLayoutService.settings$ + .pipe(takeUntil(this.onDestroy$)) + .subscribe(settings => this.setCurrentSettings(settings)); + } + + ngOnDestroy() { + this.onDestroy$.next(true); + this.onDestroy$.complete(); + } + + setCurrentSettings(settings) { + if (settings) { + this.multiselect = settings.multiselect; + this.selectionMode = settings.selectionMode; + this.actionMenu = settings.actionMenu; + this.contextMenu = settings.contextMenu; + this.actions = settings.actions; + } + } + + onChangePageSize(event) { + this.userPreference.paginationSize = event.maxItems; + } + + resetSelectedRows() { + this.selectedRows = []; + } + + onFilterChange(filter: any) { + this.editedFilter = Object.assign({}, filter); + this.sortArray = [new TaskListCloudSortingModel({ orderBy: this.editedFilter.sort, direction: this.editedFilter.order })]; + } +} diff --git a/docs/process-services-cloud/components/edit-task-filter-cloud.component.md b/docs/process-services-cloud/components/edit-task-filter-cloud.component.md index 9397688b9b..5d8097b5d2 100644 --- a/docs/process-services-cloud/components/edit-task-filter-cloud.component.md +++ b/docs/process-services-cloud/components/edit-task-filter-cloud.component.md @@ -52,13 +52,14 @@ Edits task filter details. | showTaskFilterName | `boolean` | true | Toggles display of task filter name | | showTitle | `boolean` | true | Toggles the title. | | sortProperties | `string[]` | | List of sort properties to display. | +| TaskType | `string` | userTask | The type of tasks to be listed. `userTask | serviceTask` | ### Events | Name | Type | Description | | ---- | ---- | ----------- | | action | [`EventEmitter`](https://angular.io/api/core/EventEmitter)`<`[`TaskFilterAction`](../../../lib/process-services-cloud/src/lib/task/task-filters/models/filter-cloud.model.ts)`>` | Emitted when a filter action occurs (i.e Save, Save As, Delete). | -| filterChange | [`EventEmitter`](https://angular.io/api/core/EventEmitter)`<`[`TaskFilterCloudModel`](../../../lib/process-services-cloud/src/lib/task/task-filters/models/filter-cloud.model.ts)`>` | Emitted when a task filter property changes. | +| filterChange | [`EventEmitter`](https://angular.io/api/core/EventEmitter)`<`[`TaskFilterCloudModel`](../../../lib/process-services-cloud/src/lib/task/task-filters/models/filter-cloud.model.ts)` | `[`ServiceTaskFilterCloudModel`](../../../lib/process-services-cloud/src/lib/task/task-filters/models/filter-cloud.model.ts)`>` | Emitted when a task filter property changes. | ## Details @@ -211,6 +212,18 @@ Users can save a filter if they make any changes to it in an application using t - An Activiti Enterprise version uses the preference service to store saved filters. This allows for user's custom filters to be available between sessions and between devices. +### Filtering Service Tasks + +Use the `taskType` to choose which task type to edit: + +```html + + +``` + ## See also - [Edit process filter cloud component](edit-process-filter-cloud.component.md) diff --git a/docs/process-services-cloud/components/task-list-cloud.component.md b/docs/process-services-cloud/components/task-list-cloud.component.md index c591ff2c01..7e7f956f5c 100644 --- a/docs/process-services-cloud/components/task-list-cloud.component.md +++ b/docs/process-services-cloud/components/task-list-cloud.component.md @@ -76,6 +76,8 @@ when the task list is empty: | standalone | `boolean` | false | Filter the tasks. Display only the tasks that belong to a process in case is false or tasks that doesn't belong to a process in case of true. | | status | `string` | "" | Filter the tasks. Display only tasks with status equal to the supplied value. | | stickyHeader | `boolean` | false | Toggles the sticky header mode. | +| TaskType | `string` | userTask | The type of tasks to be listed. `userTask | serviceTask` | +| queryFilter | `Object` | {} | An object containing a key/value for each of the properties that a service task will be filtered by. | ### Events @@ -334,6 +336,31 @@ When an action is selected in the dropdown menu, the [`TaskListCloudComponent`]( Use this to handle the response, inspect the action payload (and all custom properties defined earlier), and perform the corresponding actions. +#### Listing service tasks + +Emitted when the user executes a row action. + +This usually accompanies a `showRowActionsMenu` event. +The [`TaskListCloudComponent`](../../process-services-cloud/components/task-list-cloud.component.md) itself does not execute actions but provides support for external +integration. If actions are provided using the `showRowActionsMenu` event +then `executeRowAction` will be automatically executed when the user clicks a +corresponding menu item. + +```ts +const queryParams = { + activityName: "serviceTask1", + maxItems: 10, + skipCount: 0 +} +``` + +```html + + +``` + ## See also - [Data column component](../../core/components/data-column.component.md) diff --git a/lib/core/datatable/data/data-table.schema.ts b/lib/core/datatable/data/data-table.schema.ts index ad0198286d..219bb2bc4e 100644 --- a/lib/core/datatable/data/data-table.schema.ts +++ b/lib/core/datatable/data/data-table.schema.ts @@ -79,4 +79,12 @@ export abstract class DataTableSchema { private getDefaultLayoutPreset(): DataColumn[] { return (this.layoutPresets['default']).map((col) => new ObjectDataColumn(col)); } + + public setPresetKey(presetKey: string) { + this.presetKey = presetKey; + } + + public setPresetsModel(presetsModel: any) { + this.presetsModel = presetsModel; + } } diff --git a/lib/process-services-cloud/src/lib/i18n/en.json b/lib/process-services-cloud/src/lib/i18n/en.json index 2fa53f8f0d..e86d7884ac 100644 --- a/lib/process-services-cloud/src/lib/i18n/en.json +++ b/lib/process-services-cloud/src/lib/i18n/en.json @@ -98,6 +98,16 @@ } } }, + "ADF_CLOUD_SERVICE_TASK_LIST": { + "PROPERTIES": { + "ACTIVITY_NAME": "Activity name", + "ACTIVITY_TYPE": "Status", + "ID": "Id", + "COMPLETED_DATE": "Completed date", + "STARTED_DATE": "Started date", + "STATUS": "Status" + } + }, "ADF_CLOUD_TASK_FILTERS": { "MY_TASKS": "My Tasks", "QUEUED_TASKS": "Queued Tasks", @@ -149,6 +159,24 @@ "CANCEL": "CANCEL" } }, + "ADF_CLOUD_EDIT_SERVICE_TASK_FILTER": { + "LABEL": { + "APP_NAME": "ApplicationName", + "SERVICE_TASK_ID": "ServiceTaskId", + "SERVICE_NAME": "ServiceName", + "ELEMENT_ID": "ElementId", + "PROCESS_DEF_NAME": "ProcessDefinitionName", + "PROCESS_DEF_ID": "ProcessDefinitionId", + "PROCESS_INSTANCE_ID": "ProcessInstanceId", + "STATUS": "Status", + "DIRECTION": "Direction", + "ACTIVITY_NAME": "ActivityName", + "ACTIVITY_TYPE": "ActivityType", + "SORT": "Sort", + "STARTED_DATE": "StartedDate", + "COMPLETED_DATE": "CompletedDate" + } + }, "ADF_CLOUD_EDIT_PROCESS_FILTER": { "TITLE": "Customize your filter", "LABEL": { diff --git a/lib/process-services-cloud/src/lib/task/task-filters/components/edit-task-filter-cloud.component.spec.ts b/lib/process-services-cloud/src/lib/task/task-filters/components/edit-task-filter-cloud.component.spec.ts index 15f340cfb7..00d32f0517 100644 --- a/lib/process-services-cloud/src/lib/task/task-filters/components/edit-task-filter-cloud.component.spec.ts +++ b/lib/process-services-cloud/src/lib/task/task-filters/components/edit-task-filter-cloud.component.spec.ts @@ -37,6 +37,7 @@ import { fakeFilter } from '../mock/task-filters-cloud.mock'; import { AbstractControl } from '@angular/forms'; import moment from 'moment-es6'; import { TranslateModule } from '@ngx-translate/core'; +import { TaskFilterCloudModel, ServiceTaskFilterCloudModel } from '../models/filter-cloud.model'; describe('EditTaskFilterCloudComponent', () => { let component: EditTaskFilterCloudComponent; @@ -67,11 +68,13 @@ describe('EditTaskFilterCloudComponent', () => { appsService = TestBed.inject(AppsProcessCloudService); taskService = TestBed.inject(TaskCloudService); dialog = TestBed.inject(MatDialog); - spyOn(dialog, 'open').and.returnValue({ afterClosed: of({ - action: TaskFilterDialogCloudComponent.ACTION_SAVE, - icon: 'icon', - name: 'fake-name' - }) }); + spyOn(dialog, 'open').and.returnValue({ + afterClosed: of({ + action: TaskFilterDialogCloudComponent.ACTION_SAVE, + icon: 'icon', + name: 'fake-name' + }) + }); getTaskFilterSpy = spyOn(service, 'getTaskFilterById').and.returnValue(of(fakeFilter)); getRunningApplicationsSpy = spyOn(appsService, 'getDeployedApplicationsByStatus').and.returnValue(of(fakeApplicationInstance)); fixture.detectChanges(); @@ -171,7 +174,7 @@ describe('EditTaskFilterCloudComponent', () => { expect(component.editTaskFilterForm).toBeDefined(); }); - it('should create editTaskFilter form with default properties', async(() => { + it('should create editTaskFilter form with default user task properties', async(() => { fixture.detectChanges(); fixture.whenStable().then(() => { const stateController = component.editTaskFilterForm.get('status'); @@ -187,6 +190,24 @@ describe('EditTaskFilterCloudComponent', () => { }); })); + it('should emit ServiceTaskFilterCloudModel when the taskType is set to serviceTask', (done) => { + component.appName = 'fake'; + component.taskType = 'serviceTask'; + component.filterProperties = ['appName', 'status']; + const taskFilterIdChange = new SimpleChange(undefined, 'mock-task-filter-id', true); + component.ngOnChanges({ 'id': taskFilterIdChange }); + fixture.detectChanges(); + + const statusControl: AbstractControl = component.editTaskFilterForm.get('status'); + statusControl.setValue('COMPLETED'); + + component.filterChange.subscribe(() => { + expect(component.changedTaskFilter instanceof ServiceTaskFilterCloudModel).toBeTruthy(); + done(); + }); + component.onFilterChange(); + }); + describe('Save & Delete buttons', () => { it('should disable save and delete button for default task filters', async(() => { getTaskFilterSpy.and.returnValue(of({ @@ -243,13 +264,13 @@ describe('EditTaskFilterCloudComponent', () => { fixture.detectChanges(); component.editTaskFilterForm.valueChanges - .pipe(debounceTime(300)) - .subscribe(() => { - const saveButton = fixture.debugElement.nativeElement.querySelector('[data-automation-id="adf-filter-action-save"]'); - fixture.detectChanges(); - expect(saveButton.disabled).toBe(false); - done(); - }); + .pipe(debounceTime(300)) + .subscribe(() => { + const saveButton = fixture.debugElement.nativeElement.querySelector('[data-automation-id="adf-filter-action-save"]'); + fixture.detectChanges(); + expect(saveButton.disabled).toBe(false); + done(); + }); const stateElement = fixture.debugElement.nativeElement.querySelector('[data-automation-id="adf-cloud-edit-task-property-sort"] .mat-select-trigger'); stateElement.click(); @@ -329,13 +350,13 @@ describe('EditTaskFilterCloudComponent', () => { fixture.detectChanges(); component.editTaskFilterForm.valueChanges - .pipe(debounceTime(300)) - .subscribe(() => { - const saveButton = fixture.debugElement.nativeElement.querySelector('[data-automation-id="adf-filter-action-saveAs"]'); - fixture.detectChanges(); - expect(saveButton.disabled).toEqual(false); - done(); - }); + .pipe(debounceTime(300)) + .subscribe(() => { + const saveButton = fixture.debugElement.nativeElement.querySelector('[data-automation-id="adf-filter-action-saveAs"]'); + fixture.detectChanges(); + expect(saveButton.disabled).toEqual(false); + done(); + }); const stateElement = fixture.debugElement.nativeElement.querySelector('[data-automation-id="adf-cloud-edit-task-property-sort"] .mat-select-trigger'); stateElement.click(); @@ -353,13 +374,13 @@ describe('EditTaskFilterCloudComponent', () => { fixture.detectChanges(); component.editTaskFilterForm.valueChanges - .pipe(debounceTime(300)) - .subscribe(() => { - const saveButton = fixture.debugElement.nativeElement.querySelector('[data-automation-id="adf-filter-action-saveAs"]'); - fixture.detectChanges(); - expect(saveButton.disabled).toEqual(false); - done(); - }); + .pipe(debounceTime(300)) + .subscribe(() => { + const saveButton = fixture.debugElement.nativeElement.querySelector('[data-automation-id="adf-filter-action-saveAs"]'); + fixture.detectChanges(); + expect(saveButton.disabled).toEqual(false); + done(); + }); const stateElement = fixture.debugElement.nativeElement.querySelector('[data-automation-id="adf-cloud-edit-task-property-sort"] .mat-select-trigger'); stateElement.click(); @@ -598,7 +619,9 @@ describe('EditTaskFilterCloudComponent', () => { }); component.filterChange.subscribe(() => { - expect(component.changedTaskFilter.lastModifiedTo.toISOString()).toEqual(lastModifiedToFilter.toISOString()); + if (component.changedTaskFilter instanceof TaskFilterCloudModel) { + expect(component.changedTaskFilter.lastModifiedTo.toISOString()).toEqual(lastModifiedToFilter.toISOString()); + } done(); }); component.onFilterChange(); @@ -705,7 +728,7 @@ describe('EditTaskFilterCloudComponent', () => { it('should not call restore default filters service on deletion of first filter', async(() => { component.toggleFilterActions = true; - spyOn(service, 'deleteFilter').and.returnValue(of([{ name: 'mock-filter-name'}])); + spyOn(service, 'deleteFilter').and.returnValue(of([{ name: 'mock-filter-name' }])); const restoreDefaultFiltersSpy = spyOn(component, 'restoreDefaultTaskFilters').and.returnValue(of([])); fixture.detectChanges(); const expansionPanel = fixture.debugElement.nativeElement.querySelector('mat-expansion-panel-header'); diff --git a/lib/process-services-cloud/src/lib/task/task-filters/components/edit-task-filter-cloud.component.ts b/lib/process-services-cloud/src/lib/task/task-filters/components/edit-task-filter-cloud.component.ts index 05775d99de..e3bfceb883 100644 --- a/lib/process-services-cloud/src/lib/task/task-filters/components/edit-task-filter-cloud.component.ts +++ b/lib/process-services-cloud/src/lib/task/task-filters/components/edit-task-filter-cloud.component.ts @@ -24,7 +24,7 @@ import { Subject, Observable } from 'rxjs'; import moment from 'moment-es6'; import { Moment } from 'moment'; -import { TaskFilterCloudModel, TaskFilterProperties, FilterOptions, TaskFilterAction } from './../models/filter-cloud.model'; +import { TaskFilterCloudModel, TaskFilterProperties, FilterOptions, TaskFilterAction, ServiceTaskFilterCloudModel, TaskType } from './../models/filter-cloud.model'; import { TaskFilterCloudService } from '../services/task-filter-cloud.service'; import { TaskFilterDialogCloudComponent } from './task-filter-dialog-cloud.component'; import { TranslationService, UserPreferencesService, UserPreferenceValues } from '@alfresco/adf-core'; @@ -51,7 +51,9 @@ export class EditTaskFilterCloudComponent implements OnInit, OnChanges, OnDestro public static SORT: string = 'sort'; public static ORDER: string = 'order'; public static DEFAULT_TASK_FILTER_PROPERTIES = ['status', 'assignee', 'sort', 'order']; - public static DEFAULT_SORT_PROPERTIES = ['id', 'name', 'createdDate', 'priority']; + public static DEFAULT_SERVICE_TASK_FILTER_PROPERTIES = ['appName', 'activityName', 'status', 'sort', 'order']; + public static DEFAULT_USER_TASK_SORT_PROPERTIES = ['id', 'name', 'createdDate', 'priority']; + public static DEFAULT_SERVICE_TASK_SORT_PROPERTIES = ['id', 'name', 'startedDate', 'completedDate']; public static DEFAULT_ACTIONS = ['save', 'saveAs', 'delete']; public FORMAT_DATE: string = 'DD/MM/YYYY'; @@ -69,11 +71,11 @@ export class EditTaskFilterCloudComponent implements OnInit, OnChanges, OnDestro /** List of task filter properties to display. */ @Input() - filterProperties: string[] = EditTaskFilterCloudComponent.DEFAULT_TASK_FILTER_PROPERTIES; + filterProperties: string[] = []; /** List of sort properties to display. */ @Input() - sortProperties: string[] = EditTaskFilterCloudComponent.DEFAULT_SORT_PROPERTIES; + sortProperties: string[] = []; /** List of task filter actions. */ @Input() @@ -91,18 +93,22 @@ export class EditTaskFilterCloudComponent implements OnInit, OnChanges, OnDestro @Input() showTaskFilterName = true; + /** Task type: userTask | serviceTask */ + @Input() + taskType = 'userTask'; + /** Emitted when a task filter property changes. */ @Output() - filterChange: EventEmitter = new EventEmitter(); + filterChange: EventEmitter = new EventEmitter(); /** Emitted when a filter action occurs (i.e Save, Save As, Delete). */ @Output() action: EventEmitter = new EventEmitter(); - taskFilter: TaskFilterCloudModel; - changedTaskFilter: TaskFilterCloudModel; + taskFilter: TaskFilterCloudModel | ServiceTaskFilterCloudModel; + changedTaskFilter: TaskFilterCloudModel | ServiceTaskFilterCloudModel; - status = [ + userTaskStatus = [ { label: 'ALL', value: '' }, { label: 'CREATED', value: 'CREATED' }, { label: 'ASSIGNED', value: 'ASSIGNED' }, @@ -111,6 +117,14 @@ export class EditTaskFilterCloudComponent implements OnInit, OnChanges, OnDestro { label: 'COMPLETED', value: 'COMPLETED' } ]; + serviceTaskStatus = [ + { label: 'ALL', value: '' }, + { label: 'STARTED', value: 'STARTED' }, + { label: 'COMPLETED', value: 'COMPLETED' }, + { label: 'CANCELLED', value: 'CANCELLED' }, + { label: 'ERROR', value: 'ERROR' } + ]; + directions = [ { label: 'ASC', value: 'ASC' }, { label: 'DESC', value: 'DESC' } @@ -192,9 +206,14 @@ export class EditTaskFilterCloudComponent implements OnInit, OnChanges, OnDestro filter(() => this.isFormValid()), takeUntil(this.onDestroy$) ) - .subscribe((formValues: TaskFilterCloudModel) => { - this.setLastModifiedToFilter(formValues); - this.changedTaskFilter = new TaskFilterCloudModel(Object.assign({}, this.taskFilter, formValues)); + .subscribe((formValues: TaskFilterCloudModel | ServiceTaskFilterCloudModel) => { + if (this.taskType === TaskType.UserTask) { + this.setLastModifiedToFilter( formValues); + this.changedTaskFilter = new TaskFilterCloudModel(Object.assign({}, this.taskFilter, formValues)); + } else { + this.changedTaskFilter = new ServiceTaskFilterCloudModel(Object.assign({}, this.taskFilter, formValues)); + } + this.formHasBeenChanged = !this.compareFilters(this.changedTaskFilter, this.taskFilter); this.filterChange.emit(this.changedTaskFilter); }); @@ -218,16 +237,20 @@ export class EditTaskFilterCloudComponent implements OnInit, OnChanges, OnDestro retrieveTaskFilterAndBuildForm() { this.isLoading = true; this.taskFilterCloudService.getTaskFilterById(this.appName, this.id) - .pipe( - finalize(() => this.isLoading = false), - takeUntil(this.onDestroy$) - ) - .subscribe(response => { - this.taskFilter = new TaskFilterCloudModel(response); - this.taskFilterProperties = this.createAndFilterProperties(); - this.taskFilterActions = this.createAndFilterActions(); - this.buildForm(this.taskFilterProperties); - }); + .pipe( + finalize(() => this.isLoading = false), + takeUntil(this.onDestroy$) + ) + .subscribe(response => { + if (this.taskType === TaskType.ServiceTask) { + this.taskFilter = new ServiceTaskFilterCloudModel(response); + } else { + this.taskFilter = new TaskFilterCloudModel(response); + } + this.taskFilterProperties = this.createAndFilterProperties(); + this.taskFilterActions = this.createAndFilterActions(); + this.buildForm(this.taskFilterProperties); + }); } createAndFilterProperties() { @@ -257,7 +280,11 @@ export class EditTaskFilterCloudComponent implements OnInit, OnChanges, OnDestro checkMandatoryFilterProperties() { if (this.filterProperties === undefined || this.filterProperties.length === 0) { - this.filterProperties = EditTaskFilterCloudComponent.DEFAULT_TASK_FILTER_PROPERTIES; + if (this.taskType === TaskType.ServiceTask) { + this.filterProperties = EditTaskFilterCloudComponent.DEFAULT_SERVICE_TASK_FILTER_PROPERTIES; + } else { + this.filterProperties = EditTaskFilterCloudComponent.DEFAULT_TASK_FILTER_PROPERTIES; + } } } @@ -294,7 +321,11 @@ export class EditTaskFilterCloudComponent implements OnInit, OnChanges, OnDestro checkMandatorySortProperties(): void { if (this.sortProperties === undefined || this.sortProperties.length === 0) { - this.sortProperties = EditTaskFilterCloudComponent.DEFAULT_SORT_PROPERTIES; + if (this.taskType === TaskType.ServiceTask) { + this.sortProperties = EditTaskFilterCloudComponent.DEFAULT_SERVICE_TASK_SORT_PROPERTIES; + } else { + this.sortProperties = EditTaskFilterCloudComponent.DEFAULT_USER_TASK_SORT_PROPERTIES; + } } } @@ -330,7 +361,7 @@ export class EditTaskFilterCloudComponent implements OnInit, OnChanges, OnDestro this.getPropertyController(dateProperty).setValue(momentDate.toDate()); this.getPropertyController(dateProperty).setErrors(null); } else { - this.getPropertyController(dateProperty).setErrors({invalid: true}); + this.getPropertyController(dateProperty).setErrors({ invalid: true }); } } } @@ -352,7 +383,10 @@ export class EditTaskFilterCloudComponent implements OnInit, OnChanges, OnDestro * Return true if both filters are same * @param editedQuery, @param currentQuery */ - compareFilters(editedQuery: TaskFilterCloudModel, currentQuery: TaskFilterCloudModel): boolean { + compareFilters( + editedQuery: TaskFilterCloudModel | ServiceTaskFilterCloudModel, + currentQuery: TaskFilterCloudModel | ServiceTaskFilterCloudModel + ): boolean { return JSON.stringify(editedQuery).toLowerCase() === JSON.stringify(currentQuery).toLowerCase(); } @@ -414,7 +448,7 @@ export class EditTaskFilterCloudComponent implements OnInit, OnChanges, OnDestro }), switchMap(() => this.restoreDefaultTaskFilters()), takeUntil(this.onDestroy$)) - .subscribe(() => {}); + .subscribe(() => { }); } saveAs(saveAsAction: TaskFilterAction): void { @@ -435,12 +469,12 @@ export class EditTaskFilterCloudComponent implements OnInit, OnChanges, OnDestro id: filterId, key: 'custom-' + filterKey }; - const resultFilter: TaskFilterCloudModel = Object.assign({}, this.changedTaskFilter, newFilter); + const resultFilter: TaskFilterCloudModel | ServiceTaskFilterCloudModel = Object.assign({}, this.changedTaskFilter, newFilter); this.taskFilterCloudService.addFilter(resultFilter) - .pipe(takeUntil(this.onDestroy$)).subscribe(() => { - saveAsAction.filter = resultFilter; - this.action.emit(saveAsAction); - }); + .pipe(takeUntil(this.onDestroy$)).subscribe(() => { + saveAsAction.filter = resultFilter; + this.action.emit(saveAsAction); + }); } }); } @@ -463,7 +497,7 @@ export class EditTaskFilterCloudComponent implements OnInit, OnChanges, OnDestro return name.replace(regExt, '-'); } - restoreDefaultTaskFilters(): Observable { + restoreDefaultTaskFilters(): Observable { return this.taskFilterCloudService.getTaskListFilters(this.appName); } @@ -562,7 +596,94 @@ export class EditTaskFilterCloudComponent implements OnInit, OnChanges, OnDestro ]; } - createTaskFilterProperties(currentTaskFilter: TaskFilterCloudModel): TaskFilterProperties[] { + createServiceTaskFilterProperties(currentTaskFilter: ServiceTaskFilterCloudModel): TaskFilterProperties[] { + return [ + new TaskFilterProperties({ + label: 'ADF_CLOUD_EDIT_SERVICE_TASK_FILTER.LABEL.APP_NAME', + type: 'select', + key: 'appName', + value: currentTaskFilter.appName || '', + options: this.applicationNames + }), + new TaskFilterProperties({ + label: 'ADF_CLOUD_EDIT_SERVICE_TASK_FILTER.LABEL.SERVICE_TASK_ID', + type: 'text', + key: 'serviceTaskId', + value: currentTaskFilter.serviceTaskId || '' + }), + new TaskFilterProperties({ + label: 'ADF_CLOUD_EDIT_SERVICE_TASK_FILTER.LABEL.ELEMENT_ID', + type: 'text', + key: 'elementId', + value: currentTaskFilter.elementId || '' + }), + new TaskFilterProperties({ + label: 'ADF_CLOUD_EDIT_SERVICE_TASK_FILTER.LABEL.ACTIVITY_NAME', + type: 'text', + key: 'activityName', + value: currentTaskFilter.activityName || '' + }), + new TaskFilterProperties({ + label: 'ADF_CLOUD_EDIT_SERVICE_TASK_FILTER.LABEL.ACTIVITY_TYPE', + type: 'text', + key: 'activityType', + value: currentTaskFilter.activityType || '' + }), + new TaskFilterProperties({ + label: 'ADF_CLOUD_EDIT_SERVICE_TASK_FILTER.LABEL.SORT', + type: 'select', + key: 'sort', + value: currentTaskFilter.sort || this.createSortProperties[0].value, + options: this.createSortProperties + }), + new TaskFilterProperties({ + label: 'ADF_CLOUD_EDIT_SERVICE_TASK_FILTER.LABEL.DIRECTION', + type: 'select', + key: 'order', + value: currentTaskFilter.order || this.directions[0].value, + options: this.directions + }), + new TaskFilterProperties({ + label: 'ADF_CLOUD_EDIT_SERVICE_TASK_FILTER.LABEL.STATUS', + type: 'select', + key: 'status', + value: currentTaskFilter.status || this.serviceTaskStatus[0].value, + options: this.serviceTaskStatus + }), + new TaskFilterProperties({ + label: 'ADF_CLOUD_EDIT_SERVICE_TASK_FILTER.LABEL.STARTED_DATE', + type: 'date', + key: 'startedDate', + value: currentTaskFilter.completedDate || false + }), + new TaskFilterProperties({ + label: 'ADF_CLOUD_EDIT_SERVICE_TASK_FILTER.LABEL.COMPLETED_DATE', + type: 'date', + key: 'completedDate', + value: currentTaskFilter.completedDate || false + }), + new TaskFilterProperties({ + label: 'ADF_CLOUD_EDIT_SERVICE_TASK_FILTER.LABEL.PROCESS_INSTANCE_ID', + type: 'text', + key: 'processInstanceId', + value: currentTaskFilter.processInstanceId || '' + }), + new TaskFilterProperties({ + label: 'ADF_CLOUD_EDIT_SERVICE_TASK_FILTER.LABEL.PROCESS_DEF_ID', + type: 'text', + key: 'processDefinitionId', + value: currentTaskFilter.processDefinitionId || '' + }), + new TaskFilterProperties({ + label: 'ADF_CLOUD_EDIT_SERVICE_TASK_FILTER.LABEL.SERVICE_NAME', + type: 'text', + key: 'serviceName', + value: currentTaskFilter.serviceName || '' + }) + ]; + } + + createUserTaskFilterProperties(currentTaskFilter: TaskFilterCloudModel): TaskFilterProperties[] { return [ new TaskFilterProperties({ label: 'ADF_CLOUD_EDIT_TASK_FILTER.LABEL.APP_NAME', @@ -581,8 +702,8 @@ export class EditTaskFilterCloudComponent implements OnInit, OnChanges, OnDestro label: 'ADF_CLOUD_EDIT_TASK_FILTER.LABEL.STATUS', type: 'select', key: 'status', - value: currentTaskFilter.status || this.status[0].value, - options: this.status + value: currentTaskFilter.status || this.userTaskStatus[0].value, + options: this.userTaskStatus }), new TaskFilterProperties({ label: 'ADF_CLOUD_EDIT_TASK_FILTER.LABEL.ASSIGNMENT', @@ -675,4 +796,12 @@ export class EditTaskFilterCloudComponent implements OnInit, OnChanges, OnDestro }) ]; } + + createTaskFilterProperties(currentTaskFilter: TaskFilterCloudModel | ServiceTaskFilterCloudModel): TaskFilterProperties[] { + if (this.taskType === TaskType.ServiceTask) { + return this.createServiceTaskFilterProperties( currentTaskFilter); + } else { + return this.createUserTaskFilterProperties( currentTaskFilter); + } + } } diff --git a/lib/process-services-cloud/src/lib/task/task-filters/components/task-filters-cloud.component.ts b/lib/process-services-cloud/src/lib/task/task-filters/components/task-filters-cloud.component.ts index 97970c0a6c..cf5f56d066 100644 --- a/lib/process-services-cloud/src/lib/task/task-filters/components/task-filters-cloud.component.ts +++ b/lib/process-services-cloud/src/lib/task/task-filters/components/task-filters-cloud.component.ts @@ -18,7 +18,7 @@ import { Component, EventEmitter, Input, OnChanges, Output, SimpleChanges, OnDestroy, OnInit } from '@angular/core'; import { Observable, Subject } from 'rxjs'; import { TaskFilterCloudService } from '../services/task-filter-cloud.service'; -import { TaskFilterCloudModel, FilterParamsModel } from '../models/filter-cloud.model'; +import { TaskFilterCloudModel, FilterParamsModel, ServiceTaskFilterCloudModel } from '../models/filter-cloud.model'; import { TranslationService } from '@alfresco/adf-core'; import { takeUntil } from 'rxjs/operators'; @@ -45,7 +45,7 @@ export class TaskFiltersCloudComponent implements OnInit, OnChanges, OnDestroy { /** Emitted when a filter in the list is clicked. */ @Output() - filterClick: EventEmitter = new EventEmitter(); + filterClick: EventEmitter = new EventEmitter(); /** Emitted when the list is loaded. */ @Output() @@ -55,11 +55,11 @@ export class TaskFiltersCloudComponent implements OnInit, OnChanges, OnDestroy { @Output() error: EventEmitter = new EventEmitter(); - filters$: Observable; + filters$: Observable; - currentFilter: TaskFilterCloudModel; + filters: TaskFilterCloudModel[] | ServiceTaskFilterCloudModel[] = []; - filters: TaskFilterCloudModel [] = []; + currentFilter: TaskFilterCloudModel | ServiceTaskFilterCloudModel; private onDestroy$ = new Subject(); @@ -92,7 +92,7 @@ export class TaskFiltersCloudComponent implements OnInit, OnChanges, OnDestroy { this.filters$ = this.taskFilterCloudService.getTaskListFilters(appName); this.filters$.pipe(takeUntil(this.onDestroy$)).subscribe( - (res: TaskFilterCloudModel[]) => { + (res: TaskFilterCloudModel[] | ServiceTaskFilterCloudModel[]) => { this.resetFilter(); this.filters = Object.assign([], res); this.selectFilterAndEmit(this.filterParam); @@ -106,7 +106,7 @@ export class TaskFiltersCloudComponent implements OnInit, OnChanges, OnDestroy { public selectFilter(paramFilter: FilterParamsModel) { if (paramFilter) { - this.currentFilter = this.filters.find( (filter: TaskFilterCloudModel, index) => + this.currentFilter = (this.filters as Array).find((filter: any, index) => paramFilter.index === index || paramFilter.key === filter.key || paramFilter.id === filter.id || @@ -137,7 +137,7 @@ export class TaskFiltersCloudComponent implements OnInit, OnChanges, OnDestroy { /** * Return the current task */ - getCurrentFilter(): TaskFilterCloudModel { + getCurrentFilter(): TaskFilterCloudModel | ServiceTaskFilterCloudModel { return this.currentFilter; } diff --git a/lib/process-services-cloud/src/lib/task/task-filters/mock/task-filters-cloud.mock.ts b/lib/process-services-cloud/src/lib/task/task-filters/mock/task-filters-cloud.mock.ts index b8a70bd993..30c80dc421 100644 --- a/lib/process-services-cloud/src/lib/task/task-filters/mock/task-filters-cloud.mock.ts +++ b/lib/process-services-cloud/src/lib/task/task-filters/mock/task-filters-cloud.mock.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -import { TaskFilterCloudModel } from '../models/filter-cloud.model'; +import { TaskFilterCloudModel, ServiceTaskFilterCloudModel } from '../models/filter-cloud.model'; export let fakeGlobalFilter = [ new TaskFilterCloudModel({ @@ -56,6 +56,18 @@ export let fakeFilter = new TaskFilterCloudModel({ sort: 'id' }); +export let fakeServiceFilter = new ServiceTaskFilterCloudModel({ + name: 'FakeInvolvedTasks', + icon: 'adjust', + id: 'mock-task-filter-id', + status: 'CREATED', + appName: 'mock-app-name', + processDefinitionId: 'process-def-id', + activityName: 'fake-activity', + order: 'ASC', + sort: 'id' +}); + export let fakeAllTaskFilter = new TaskFilterCloudModel({ name: 'AllTasks', icon: 'adjust', diff --git a/lib/process-services-cloud/src/lib/task/task-filters/models/filter-cloud.model.ts b/lib/process-services-cloud/src/lib/task/task-filters/models/filter-cloud.model.ts index e41d4ccbb0..81b85ee466 100644 --- a/lib/process-services-cloud/src/lib/task/task-filters/models/filter-cloud.model.ts +++ b/lib/process-services-cloud/src/lib/task/task-filters/models/filter-cloud.model.ts @@ -17,7 +17,7 @@ import { DateCloudFilterType } from '../../../models/date-cloud-filter.model'; -export class TaskFilterCloudModel { +export class TaskFilterCloudModel { id: string; name: string; key: string; @@ -74,6 +74,66 @@ export class TaskFilterCloudModel { } } } + +export class ServiceTaskFilterCloudModel { + id: string; + name: string; + key: string; + icon: string; + index: number; + appName: string; + status: string; + sort: string; + order: string; + activityName: string; + activityType: string; + completedDate: Date; + elementId: string; + executionId: string; + processDefinitionId: string; + processDefinitionKey: string; + processDefinitionVersion: number; + processInstanceId: string; + serviceTaskId: string; + serviceFullName: string; + serviceName: string; + serviceVersion: string; + startedDate: Date; + + constructor(obj?: any) { + if (obj) { + this.id = obj.id || Math.random().toString(36).substr(2, 9); + this.name = obj.name || null; + this.key = obj.key || null; + this.icon = obj.icon || null; + this.index = obj.index || null; + this.appName = obj.appName || obj.appName === '' ? obj.appName : null; + this.status = obj.status || null; + this.sort = obj.sort || null; + this.order = obj.order || null; + this.activityName = obj.activityName || null; + this.activityType = obj.activityType || null; + this.elementId = obj.elementId || null; + this.executionId = obj.executionId || null; + this.processDefinitionId = obj.processDefinitionId || null; + this.processDefinitionKey = obj.processDefinitionKey || null; + this.processDefinitionVersion = obj.processDefinitionVersion || null; + this.processInstanceId = obj.processInstanceId || null; + this.completedDate = obj.completedDate || null; + this.startedDate = obj.startedDate || null; + this.serviceVersion = obj.serviceVersion || null; + this.serviceTaskId = obj.serviceTaskId || null; + this.serviceName = obj.serviceName || null; + this.serviceFullName = obj.serviceFullName || null; + } + } +} + +export enum TaskType { + UserTask = 'userTask', + ServiceTask = 'serviceTask' +} + export class FilterParamsModel { id?: string; @@ -95,7 +155,7 @@ export class TaskFilterAction { actionType: string; icon: string; tooltip: string; - filter: TaskFilterCloudModel; + filter: TaskFilterCloudModel | ServiceTaskFilterCloudModel; constructor(obj?: any) { if (obj) { diff --git a/lib/process-services-cloud/src/lib/task/task-filters/services/task-filter-cloud.service.spec.ts b/lib/process-services-cloud/src/lib/task/task-filters/services/task-filter-cloud.service.spec.ts index c4bf692ab0..72d5a9fcd2 100644 --- a/lib/process-services-cloud/src/lib/task/task-filters/services/task-filter-cloud.service.spec.ts +++ b/lib/process-services-cloud/src/lib/task/task-filters/services/task-filter-cloud.service.spec.ts @@ -38,6 +38,7 @@ import { import { UserPreferenceCloudService } from '../../../services/user-preference-cloud.service'; import { PreferenceCloudServiceInterface } from '../../../services/preference-cloud.interface'; import { HttpClientTestingModule } from '@angular/common/http/testing'; +import { TaskFilterCloudModel } from '../models/filter-cloud.model'; describe('TaskFilterCloudService', () => { let service: TaskFilterCloudService; @@ -257,7 +258,7 @@ describe('Inject [LocalPreferenceCloudService] into the TaskFilterCloudService', it('should create default task filters if there are no task filter preferences', (done) => { const appName = 'fakeAppName'; - service.getTaskListFilters(appName).subscribe((res) => { + service.getTaskListFilters(appName).subscribe((res: TaskFilterCloudModel[]) => { expect(res.length).toEqual(3); expect(res[0].name).toEqual('ADF_CLOUD_TASK_FILTERS.MY_TASKS'); diff --git a/lib/process-services-cloud/src/lib/task/task-filters/services/task-filter-cloud.service.ts b/lib/process-services-cloud/src/lib/task/task-filters/services/task-filter-cloud.service.ts index e680365539..389c3d7bda 100644 --- a/lib/process-services-cloud/src/lib/task/task-filters/services/task-filter-cloud.service.ts +++ b/lib/process-services-cloud/src/lib/task/task-filters/services/task-filter-cloud.service.ts @@ -18,7 +18,7 @@ import { IdentityUserService } from '@alfresco/adf-core'; import { Injectable, Inject } from '@angular/core'; import { Observable, of, BehaviorSubject, throwError } from 'rxjs'; -import { TaskFilterCloudModel } from '../models/filter-cloud.model'; +import { TaskFilterCloudModel, ServiceTaskFilterCloudModel } from '../models/filter-cloud.model'; import { switchMap, map, catchError } from 'rxjs/operators'; import { PreferenceCloudServiceInterface } from '../../../services/preference-cloud.interface'; import { TASK_FILTERS_SERVICE_TOKEN } from '../../../services/cloud-token.service'; @@ -27,8 +27,8 @@ import { TASK_FILTERS_SERVICE_TOKEN } from '../../../services/cloud-token.servic providedIn: 'root' }) export class TaskFilterCloudService { - private filtersSubject: BehaviorSubject; - filters$: Observable; + private filtersSubject: BehaviorSubject; + filters$: Observable; constructor( private identityUserService: IdentityUserService, @@ -49,9 +49,7 @@ export class TaskFilterCloudService { this.preferenceService.getPreferences(appName, key).pipe( switchMap((response: any) => { const preferences = (response && response.list && response.list.entries) ? response.list.entries : []; - if (!this.hasPreferences(preferences)) { - return this.createTaskFilters(appName, key, this.defaultTaskFilters(appName)); - } else if (!this.hasTaskFilters(preferences, key)) { + if (!this.hasPreferences(preferences) || !this.hasTaskFilters(preferences, key)) { return this.createTaskFilters(appName, key, this.defaultTaskFilters(appName)); } else { return of(this.findFiltersByKeyInPreferences(preferences, key)); @@ -91,7 +89,7 @@ export class TaskFilterCloudService { * @param filters Details of new task filter * @returns Observable of created task filters */ - private createTaskFilters(appName: string, key: string, filters: TaskFilterCloudModel[]): Observable { + private createTaskFilters(appName: string, key: string, filters: TaskFilterCloudModel[] | ServiceTaskFilterCloudModel[]): Observable { return this.preferenceService.createPreference(appName, key, filters); } @@ -101,7 +99,7 @@ export class TaskFilterCloudService { * @param key Key of the task filters * @returns Observable of task filters */ - private getTaskFiltersByKey(appName: string, key: string): Observable { + private getTaskFiltersByKey(appName: string, key: string): Observable { return this.preferenceService.getPreferenceByKey(appName, key); } @@ -110,7 +108,7 @@ export class TaskFilterCloudService { * @param appName Name of the target app * @returns Observable of task filter details */ - getTaskListFilters(appName?: string): Observable { + getTaskListFilters(appName?: string): Observable { this.createDefaultFilters(appName); return this.filters$; } @@ -121,23 +119,23 @@ export class TaskFilterCloudService { * @param id ID of the task * @returns Details of the task filter */ - getTaskFilterById(appName: string, id: string): Observable { + getTaskFilterById(appName: string, id: string): Observable { const key: string = this.prepareKey(appName); return this.getTaskFiltersByKey(appName, key).pipe( - switchMap((filters: TaskFilterCloudModel[]) => { + switchMap((filters: TaskFilterCloudModel[] | ServiceTaskFilterCloudModel[]) => { if (filters && filters.length === 0) { return this.createTaskFilters(appName, key, this.defaultTaskFilters(appName)); } else { return of(filters); } }), - map((filters: TaskFilterCloudModel[]) => { - return filters.filter((filter: TaskFilterCloudModel) => { + map((filters: any) => { + return filters.filter((filter: TaskFilterCloudModel | ServiceTaskFilterCloudModel) => { return filter.id === id; })[0]; }), catchError((err) => this.handleTaskError(err)) - ); + ); } /** @@ -145,18 +143,18 @@ export class TaskFilterCloudService { * @param filter The new filter to add * @returns Observable of task instance filters with newly added filter */ - addFilter(newFilter: TaskFilterCloudModel): Observable { + addFilter(newFilter: TaskFilterCloudModel | ServiceTaskFilterCloudModel): Observable { const key: string = this.prepareKey(newFilter.appName); return this.getTaskFiltersByKey(newFilter.appName, key).pipe( - switchMap((filters: TaskFilterCloudModel[]) => { + switchMap((filters: any) => { if (filters && filters.length === 0) { - return this.createTaskFilters(newFilter.appName, key, [newFilter]); + return this.createTaskFilters(newFilter.appName, key, [newFilter]); } else { filters.push(newFilter); return this.preferenceService.updatePreference(newFilter.appName, key, filters); } }), - map((filters: TaskFilterCloudModel[]) => { + map((filters: TaskFilterCloudModel[] | ServiceTaskFilterCloudModel[]) => { this.addFiltersToStream(filters); return filters; }), @@ -164,7 +162,7 @@ export class TaskFilterCloudService { ); } - private addFiltersToStream(filters: TaskFilterCloudModel[]) { + private addFiltersToStream(filters: TaskFilterCloudModel[] | ServiceTaskFilterCloudModel[]) { this.filtersSubject.next(filters); } @@ -173,19 +171,19 @@ export class TaskFilterCloudService { * @param filter The filter to update * @returns Observable of task instance filters with updated filter */ - updateFilter(updatedFilter: TaskFilterCloudModel): Observable { + updateFilter(updatedFilter: TaskFilterCloudModel | ServiceTaskFilterCloudModel): Observable { const key: string = this.prepareKey(updatedFilter.appName); return this.getTaskFiltersByKey(updatedFilter.appName, key).pipe( switchMap((filters: any) => { if (filters && filters.length === 0) { - return this.createTaskFilters(updatedFilter.appName, key, [updatedFilter]); + return this.createTaskFilters(updatedFilter.appName, key, [updatedFilter]); } else { - const itemIndex = filters.findIndex((filter: TaskFilterCloudModel) => filter.id === updatedFilter.id); + const itemIndex = filters.findIndex((filter: TaskFilterCloudModel | ServiceTaskFilterCloudModel) => filter.id === updatedFilter.id); filters[itemIndex] = updatedFilter; return this.updateTaskFilters(updatedFilter.appName, key, filters); } }), - map((updatedFilters: TaskFilterCloudModel[]) => { + map((updatedFilters: TaskFilterCloudModel[] | ServiceTaskFilterCloudModel[]) => { this.addFiltersToStream(updatedFilters); return updatedFilters; }), @@ -198,10 +196,10 @@ export class TaskFilterCloudService { * @param filter The filter to delete * @returns Observable of task instance filters without deleted filter */ - deleteFilter(deletedFilter: TaskFilterCloudModel): Observable { + deleteFilter(deletedFilter: TaskFilterCloudModel | ServiceTaskFilterCloudModel): Observable { const key = this.prepareKey(deletedFilter.appName); return this.getTaskFiltersByKey(deletedFilter.appName, key).pipe( - switchMap(filters => { + switchMap((filters: any) => { if (filters && filters.length > 0) { filters = filters.filter(filter => filter.id !== deletedFilter.id); return this.updateTaskFilters(deletedFilter.appName, key, filters); @@ -233,7 +231,7 @@ export class TaskFilterCloudService { * @param filters Details of update filter * @returns Observable of updated task filters */ - private updateTaskFilters(appName: string, key: string, filters: TaskFilterCloudModel[]): Observable { + private updateTaskFilters(appName: string, key: string, filters: TaskFilterCloudModel[] | ServiceTaskFilterCloudModel[]): Observable { return this.preferenceService.updatePreference(appName, key, filters); } @@ -260,7 +258,7 @@ export class TaskFilterCloudService { * @param appName Name of the target app * @returns Array of TaskFilterCloudModel */ - private findFiltersByKeyInPreferences(preferences: any, key: string): TaskFilterCloudModel[] { + private findFiltersByKeyInPreferences(preferences: any, key: string): TaskFilterCloudModel[] | ServiceTaskFilterCloudModel[] { const result = preferences.find((filter: any) => { return filter.entry.key === key; }); return result && result.entry ? JSON.parse(result.entry.value) : []; } diff --git a/lib/process-services-cloud/src/lib/task/task-list/components/task-list-cloud.component.spec.ts b/lib/process-services-cloud/src/lib/task/task-list/components/task-list-cloud.component.spec.ts index 655f0a261f..294109161e 100644 --- a/lib/process-services-cloud/src/lib/task/task-list/components/task-list-cloud.component.spec.ts +++ b/lib/process-services-cloud/src/lib/task/task-list/components/task-list-cloud.component.spec.ts @@ -21,7 +21,7 @@ import { By } from '@angular/platform-browser'; import { AppConfigService, setupTestBed, DataRowEvent, ObjectDataRow } from '@alfresco/adf-core'; import { TaskListCloudService } from '../services/task-list-cloud.service'; import { TaskListCloudComponent } from './task-list-cloud.component'; -import { fakeGlobalTask, fakeCustomSchema } from '../mock/fake-task-response.mock'; +import { fakeGlobalTask, fakeCustomSchema, fakeServiceTask } from '../mock/fake-task-response.mock'; import { of } from 'rxjs'; import { ProcessServiceCloudTestingModule } from '../../../testing/process-service-cloud.testing.module'; import { Person } from '@alfresco/js-api'; @@ -50,7 +50,7 @@ class CustomTaskListComponent { getFullName(person: Person): string { return `${person.firstName} ${person.lastName}`; } - } +} @Component({ template: ` @@ -130,7 +130,7 @@ describe('TaskListCloudComponent', () => { }); it('should display empty content when process list is empty', () => { - const emptyList = {list: {entries: []}}; + const emptyList = { list: { entries: [] } }; spyOn(taskListCloudService, 'getTaskByRequest').and.returnValue(of(emptyList)); fixture.detectChanges(); @@ -254,6 +254,34 @@ describe('TaskListCloudComponent', () => { component.onRowClick(rowEvent); }); + it('should display service task list when typeTask is set to serviceTask', () => { + component.taskType = 'serviceTask'; + component.ngOnInit(); + fixture.detectChanges(); + expect(component.columns).toBeDefined(); + expect(component.columns.length).toEqual(4); + }); + + it('should load the service task list when input parameters changed', () => { + const getServiceTaskByRequestSpy = spyOn(taskListCloudService, 'getServiceTaskByRequest').and.returnValue(of(fakeServiceTask)); + component.appName = 'mock-app-name'; + component.priority = 1; + component.status = 'mock-status'; + component.lastModifiedFrom = 'mock-lastmodified-date'; + component.owner = 'mock-owner-name'; + + component.taskType = 'serviceTask'; + component.ngOnInit(); + + const queryParams = new SimpleChange(undefined, { + activityName: 'service1' + }, true); + component.ngOnChanges({ queryParams }); + fixture.detectChanges(); + expect(component.isListEmpty()).toBeFalsy(); + expect(getServiceTaskByRequestSpy).toHaveBeenCalled(); + }); + describe('component changes', () => { beforeEach(() => { @@ -341,14 +369,14 @@ describe('TaskListCloudComponent', () => { const size = component.size; const skipCount = component.skipCount; component.pagination.pipe(skip(3)) - .subscribe((updatedPagination) => { + .subscribe((updatedPagination) => { fixture.detectChanges(); expect(component.size).toBe(size); expect(component.skipCount).toBe(skipCount); expect(updatedPagination.maxItems).toEqual(size); expect(updatedPagination.skipCount).toEqual(skipCount); done(); - }); + }); const pagination = { maxItems: 250, @@ -371,14 +399,14 @@ describe('TaskListCloudComponent', () => { skipCount: 200 }; component.pagination.pipe(skip(1)) - .subscribe((updatedPagination) => { + .subscribe((updatedPagination) => { fixture.detectChanges(); expect(component.size).toBe(pagination.maxItems); expect(component.skipCount).toBe(pagination.skipCount); expect(updatedPagination.maxItems).toEqual(pagination.maxItems); expect(updatedPagination.skipCount).toEqual(pagination.skipCount); done(); - }); + }); component.updatePagination(pagination); }); @@ -442,7 +470,7 @@ describe('TaskListCloudComponent', () => { it('it should not show copy tooltip when key is not present in data-column', (done) => { const appName = new SimpleChange(null, 'FAKE-APP-NAME', true); - customCopyComponent.taskList.success.subscribe( () => { + customCopyComponent.taskList.success.subscribe(() => { copyFixture.whenStable().then(() => { copyFixture.detectChanges(); const spanHTMLElement: HTMLInputElement = element.querySelector('span[title="standalone-subtask"]'); @@ -456,13 +484,13 @@ describe('TaskListCloudComponent', () => { customCopyComponent.taskList.ngOnChanges({ 'appName': appName }); copyFixture.detectChanges(); }); - }); + }); describe('Creating an empty custom template - EmptyTemplateComponent', () => { let fixtureEmpty: ComponentFixture; beforeEach(() => { - const emptyList = {list: {entries: []}}; + const emptyList = { list: { entries: [] } }; spyOn(taskListCloudService, 'getTaskByRequest').and.returnValue(of(emptyList)); fixtureEmpty = TestBed.createComponent(EmptyTemplateComponent); @@ -498,7 +526,7 @@ describe('TaskListCloudComponent', () => { ] }); - beforeEach( () => { + beforeEach(() => { appConfig = TestBed.inject(AppConfigService); taskListCloudService = TestBed.inject(TaskListCloudService); appConfig.config = Object.assign(appConfig.config, { @@ -536,7 +564,7 @@ describe('TaskListCloudComponent', () => { taskSpy.and.returnValue(of(fakeGlobalTask)); const appName = new SimpleChange(null, 'FAKE-APP-NAME', true); - component.success.subscribe( () => { + component.success.subscribe(() => { fixture.whenStable().then(() => { fixture.detectChanges(); const spanHTMLElement: HTMLInputElement = element.querySelector('span[title="11fe013d-c263-11e8-b75b-0a5864600540"]'); @@ -555,7 +583,7 @@ describe('TaskListCloudComponent', () => { 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( () => { + component.success.subscribe(() => { fixture.whenStable().then(() => { fixture.detectChanges(); const spanHTMLElement: HTMLInputElement = element.querySelector('span[title="standalone-subtask"]'); diff --git a/lib/process-services-cloud/src/lib/task/task-list/components/task-list-cloud.component.ts b/lib/process-services-cloud/src/lib/task/task-list/components/task-list-cloud.component.ts index 6f32144ce0..2fc03852f5 100644 --- a/lib/process-services-cloud/src/lib/task/task-list/components/task-list-cloud.component.ts +++ b/lib/process-services-cloud/src/lib/task/task-list/components/task-list-cloud.component.ts @@ -16,27 +16,31 @@ */ import { Component, ViewEncapsulation, OnChanges, Input, SimpleChanges, Output, EventEmitter, ContentChild, AfterContentInit, OnDestroy, OnInit } from '@angular/core'; -import { AppConfigService, UserPreferencesService, - DataTableSchema, UserPreferenceValues, - PaginatedComponent, PaginationModel, - DataRowEvent, CustomEmptyContentTemplateDirective, DataCellEvent, DataRowActionEvent } from '@alfresco/adf-core'; -import { taskPresetsCloudDefaultModel } from '../models/task-preset-cloud.model'; -import { TaskQueryCloudRequestModel } from '../models/filter-cloud-model'; -import { BehaviorSubject, Subject } from 'rxjs'; +import { + AppConfigService, UserPreferencesService, + DataTableSchema, UserPreferenceValues, + PaginatedComponent, PaginationModel, + DataRowEvent, CustomEmptyContentTemplateDirective, DataCellEvent, DataRowActionEvent +} from '@alfresco/adf-core'; +import { taskPresetsCloudDefaultModel, serviceTaskPresetsCloudDefaultModel } from '../models/task-preset-cloud.model'; +import { BehaviorSubject, Subject, Observable } from 'rxjs'; +import { TaskQueryCloudRequestModel, ServiceTaskQueryCloudRequestModel } from '../models/filter-cloud-model'; import { TaskListCloudService } from '../services/task-list-cloud.service'; import { TaskListCloudSortingModel } from '../models/task-list-sorting.model'; import { takeUntil } from 'rxjs/operators'; +import { TaskType } from '../../task-filters/models/filter-cloud.model'; @Component({ - selector: 'adf-cloud-task-list', - templateUrl: './task-list-cloud.component.html', - styleUrls: ['./task-list-cloud.component.scss'], - encapsulation: ViewEncapsulation.None + selector: 'adf-cloud-task-list', + templateUrl: './task-list-cloud.component.html', + styleUrls: ['./task-list-cloud.component.scss'], + encapsulation: ViewEncapsulation.None }) export class TaskListCloudComponent extends DataTableSchema implements OnChanges, AfterContentInit, PaginatedComponent, OnDestroy, OnInit { - static PRESET_KEY = 'adf-cloud-task-list.presets'; + static USER_TASKS_PRESET_KEY = 'adf-cloud-task-list.presets'; + static SERVICE_TASKS_PRESET_KEY = 'adf-cloud-service-task-list.presets'; static ENTRY_PREFIX = 'entry.'; @ContentChild(CustomEmptyContentTemplateDirective) @@ -70,7 +74,7 @@ export class TaskListCloudComponent extends DataTableSchema implements OnChanges @Input() lastModifiedTo: string = ''; - /** Filter the tasks. Display only tasks with dueDate greater or equal than the supplied date. */ + /** Filter the tasks. Display only tasks with dueDate greater or equal than the supplied date. */ @Input() dueDateFrom: string = ''; @@ -152,6 +156,14 @@ export class TaskListCloudComponent extends DataTableSchema implements OnChanges @Input() showContextMenu: boolean = false; + /** Task type: userTask | serviceTask */ + @Input() + taskType: string = TaskType.UserTask; + + /** An object that contains properties used to query the service task list */ + @Input() + queryParams: any = {}; + /** Emitted before the context menu is displayed for a row. */ @Output() showRowContextMenu = new EventEmitter(); @@ -197,7 +209,7 @@ export class TaskListCloudComponent extends DataTableSchema implements OnChanges constructor(private taskListCloudService: TaskListCloudService, appConfigService: AppConfigService, private userPreferences: UserPreferencesService) { - super(appConfigService, TaskListCloudComponent.PRESET_KEY, taskPresetsCloudDefaultModel); + super(appConfigService, TaskListCloudComponent.USER_TASKS_PRESET_KEY, taskPresetsCloudDefaultModel); this.size = userPreferences.paginationSize; this.pagination = new BehaviorSubject( { @@ -213,6 +225,12 @@ export class TaskListCloudComponent extends DataTableSchema implements OnChanges .select(UserPreferenceValues.PaginationSize) .pipe(takeUntil(this.onDestroy$)) .subscribe(pageSize => this.size = pageSize); + + if (this.taskType === TaskType.ServiceTask) { + super.setPresetKey(TaskListCloudComponent.SERVICE_TASKS_PRESET_KEY); + super.setPresetsModel(serviceTaskPresetsCloudDefaultModel); + super.loadLayoutPresets(); + } } ngOnChanges(changes: SimpleChanges) { @@ -261,7 +279,14 @@ export class TaskListCloudComponent extends DataTableSchema implements OnChanges private load(requestNode: TaskQueryCloudRequestModel) { this.isLoading = true; - this.taskListCloudService.getTaskByRequest(requestNode).subscribe( + let taskRequest: Observable; + if (this.taskType === TaskType.UserTask) { + taskRequest = this.taskListCloudService.getTaskByRequest( requestNode); + } else { + taskRequest = this.taskListCloudService.getServiceTaskByRequest( requestNode); + } + + taskRequest.subscribe( (tasks) => { this.rows = tasks.list.entries; this.success.emit(tasks); @@ -343,7 +368,14 @@ export class TaskListCloudComponent extends DataTableSchema implements OnChanges } private createRequestNode() { + if (this.taskType === TaskType.UserTask) { + return this.createUserTaskRequest(); + } else { + return this.createServiceTaskRequest(); + } + } + createUserTaskRequest() { const requestNode = { appName: this.appName, assignee: this.assignee, @@ -370,6 +402,31 @@ export class TaskListCloudComponent extends DataTableSchema implements OnChanges return new TaskQueryCloudRequestModel(requestNode); } + createServiceTaskRequest() { + const requestNode = { + appName: this.appName, + id: this.queryParams.serviceTaskId, + activityName: this.queryParams.activityName, + activityType: this.queryParams.activityType, + completedDate: this.queryParams.completedDate, + elementId: this.queryParams.elementId, + executionId: this.queryParams.executionId, + processDefinitionId: this.queryParams.processDefinitionId, + processDefinitionKey: this.queryParams.processDefinitionKey, + processDefinitionVersion: this.queryParams.processDefinitionVersion, + processInstanceId: this.queryParams.processInstanceId, + serviceFullName: this.queryParams.serviceFullName, + serviceName: this.queryParams.serviceName, + serviceVersion: this.queryParams.serviceVersion, + startedDate: this.queryParams.startedDate, + status: this.queryParams.status, + maxItems: this.size, + skipCount: this.skipCount, + sorting: this.sorting + }; + return new ServiceTaskQueryCloudRequestModel(requestNode); + } + setSorting(sortDetail) { const sorting = sortDetail ? { orderBy: sortDetail.key.replace(TaskListCloudComponent.ENTRY_PREFIX, ''), diff --git a/lib/process-services-cloud/src/lib/task/task-list/mock/fake-task-response.mock.ts b/lib/process-services-cloud/src/lib/task/task-list/mock/fake-task-response.mock.ts index 217591cecb..0937b05714 100644 --- a/lib/process-services-cloud/src/lib/task/task-list/mock/fake-task-response.mock.ts +++ b/lib/process-services-cloud/src/lib/task/task-list/mock/fake-task-response.mock.ts @@ -117,6 +117,44 @@ export let fakeGlobalTask = { } }; +export let fakeServiceTask = { + 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 + } + } + ], + pagination: { + skipCount: 0, + maxItems: 100, + count: 1, + hasMoreItems: false, + totalItems: 1 + } + } +}; + export let fakeCustomSchema = [ new ObjectDataColumn({ diff --git a/lib/process-services-cloud/src/lib/task/task-list/models/filter-cloud-model.ts b/lib/process-services-cloud/src/lib/task/task-list/models/filter-cloud-model.ts index fb6fcf1252..e9e39ace77 100644 --- a/lib/process-services-cloud/src/lib/task/task-list/models/filter-cloud-model.ts +++ b/lib/process-services-cloud/src/lib/task/task-list/models/filter-cloud-model.ts @@ -72,3 +72,51 @@ export class TaskQueryCloudRequestModel { } } } + +export class ServiceTaskQueryCloudRequestModel { + appName: string; + appVersion?: string; + id?: string; + status?: string; + maxItems: number; + skipCount: number; + sorting?: TaskListCloudSortingModel[]; + activityName?: string; + activityType?: string; + completedDate?: Date; + elementId?: string; + executionId?: string; + processDefinitionId?: string; + processDefinitionKey?: string; + processDefinitionVersion?: number; + processInstanceId?: string; + serviceFullName?: string; + serviceName?: string; + serviceVersion?: string; + startedDate?: Date; + + constructor(obj?: any) { + + if (obj) { + this.appName = obj.appName; + this.appVersion = obj.appVersion; + this.id = obj.id; + this.status = obj.status; + this.maxItems = obj.maxItems; + this.skipCount = obj.skipCount; + this.sorting = obj.sorting; + this.activityName = obj.activityName; + this.activityType = obj.activityType; + this.elementId = obj.elementId; + this.executionId = obj.executionId; + this.processDefinitionKey = obj.processDefinitionKey; + this.processDefinitionVersion = obj.processDefinitionVersion; + this.processInstanceId = obj.processInstanceId; + this.completedDate = obj.completedDate; + this.startedDate = obj.startedDate; + this.serviceVersion = obj.serviceVersion; + this.serviceName = obj.serviceName; + this.serviceFullName = obj.serviceFullName; + } + } +} diff --git a/lib/process-services-cloud/src/lib/task/task-list/models/task-preset-cloud.model.ts b/lib/process-services-cloud/src/lib/task/task-list/models/task-preset-cloud.model.ts index 48f0f7babd..9145ac51a8 100644 --- a/lib/process-services-cloud/src/lib/task/task-list/models/task-preset-cloud.model.ts +++ b/lib/process-services-cloud/src/lib/task/task-list/models/task-preset-cloud.model.ts @@ -39,3 +39,34 @@ export let taskPresetsCloudDefaultModel = { } ] }; + +export let serviceTaskPresetsCloudDefaultModel = { + 'default': [ + { + 'key': 'entry.activityName', + 'type': 'text', + 'title': 'ADF_CLOUD_SERVICE_TASK_LIST.PROPERTIES.ACTIVITY_NAME', + 'sortable': true + }, + { + 'key': 'entry.status', + 'type': 'text', + 'title': 'ADF_CLOUD_SERVICE_TASK_LIST.PROPERTIES.STATUS', + 'sortable': true + }, + { + 'key': 'entry.startedDate', + 'type': 'text', + 'title': 'ADF_CLOUD_SERVICE_TASK_LIST.PROPERTIES.STARTED_DATE', + 'cssClass': 'hidden', + 'sortable': true + }, + { + 'key': 'entry.completedDate', + 'type': 'text', + 'title': 'ADF_CLOUD_SERVICE_TASK_LIST.PROPERTIES.COMPLETED_DATE', + 'cssClass': 'hidden', + 'sortable': true + } + ] +}; diff --git a/lib/process-services-cloud/src/lib/task/task-list/services/task-list-cloud.service.ts b/lib/process-services-cloud/src/lib/task/task-list/services/task-list-cloud.service.ts index 809431fc56..a64351ab0b 100644 --- a/lib/process-services-cloud/src/lib/task/task-list/services/task-list-cloud.service.ts +++ b/lib/process-services-cloud/src/lib/task/task-list/services/task-list-cloud.service.ts @@ -17,7 +17,7 @@ import { Injectable } from '@angular/core'; import { AlfrescoApiService, AppConfigService, LogService } from '@alfresco/adf-core'; -import { TaskQueryCloudRequestModel } from '../models/filter-cloud-model'; +import { TaskQueryCloudRequestModel, ServiceTaskQueryCloudRequestModel } from '../models/filter-cloud-model'; import { Observable, throwError } from 'rxjs'; import { TaskListCloudSortingModel } from '../models/task-list-sorting.model'; import { BaseCloudService } from '../../../services/base-cloud.service'; @@ -51,6 +51,26 @@ export class TaskListCloudService extends BaseCloudService { } } + /** + * Finds a task using an object with optional query properties. + * @param requestNode Query object + * @returns Task information + */ + getServiceTaskByRequest(requestNode: ServiceTaskQueryCloudRequestModel): Observable { + if (requestNode.appName || requestNode.appName === '') { + const queryUrl = `${this.getBasePath(requestNode.appName)}/query/admin/v1/service-tasks`; + const queryParams = this.buildQueryParams(requestNode); + const sortingParams = this.buildSortingParam(requestNode.sorting); + if (sortingParams) { + queryParams['sort'] = sortingParams; + } + return this.get(queryUrl, queryParams); + } else { + this.logService.error('Appname is mandatory for querying task'); + return throwError('Appname not configured'); + } + } + private buildQueryParams(requestNode: TaskQueryCloudRequestModel): Object { const queryParam: Object = {}; for (const property in requestNode) {