mirror of
https://github.com/Alfresco/alfresco-ng2-components.git
synced 2025-05-12 17:04:57 +00:00
AAE-26192 New task search API (#10319)
* AAE-26192 New task search API * small changes * use DI instead of inputs * cr * fix units
This commit is contained in:
parent
2303cb2d59
commit
0a89d9be97
@ -34,7 +34,8 @@ Allows one or more users to be selected (with auto-suggestion) based on the inpu
|
|||||||
| required | `boolean` | false | Mark this field as required |
|
| required | `boolean` | false | Mark this field as required |
|
||||||
| roles | `string[]` | | Role names of the users to be listed. |
|
| roles | `string[]` | | Role names of the users to be listed. |
|
||||||
| searchUserCtrl | `FormControl<any>` | | FormControl to search the user |
|
| searchUserCtrl | `FormControl<any>` | | FormControl to search the user |
|
||||||
| title | `string` | | Placeholder translation key |
|
| title | `string` | | Label translation key |
|
||||||
|
| placeholder | `string` | | Placeholder for the input field |
|
||||||
| hideInputOnSingleSelection | `boolean` | false | Hide the input field when a user is selected in single selection mode. The input will be shown again when the user is removed using the icon on the chip. |
|
| hideInputOnSingleSelection | `boolean` | false | Hide the input field when a user is selected in single selection mode. The input will be shown again when the user is removed using the icon on the chip. |
|
||||||
| formFieldAppearance | [`MatFormFieldAppearance`](https://material.angular.io/components/form-field/api#MatFormFieldAppearance) | "fill" | Material form field appearance (fill / outline). |
|
| formFieldAppearance | [`MatFormFieldAppearance`](https://material.angular.io/components/form-field/api#MatFormFieldAppearance) | "fill" | Material form field appearance (fill / outline). |
|
||||||
| formFieldSubscriptSizing | [`SubscriptSizing`](https://material.angular.io/components/form-field/api#SubscriptSizing) | "fixed" | Material form field subscript sizing (fixed / dynamic). |
|
| formFieldSubscriptSizing | [`SubscriptSizing`](https://material.angular.io/components/form-field/api#SubscriptSizing) | "fixed" | Material form field subscript sizing (fixed / dynamic). |
|
||||||
|
@ -87,6 +87,12 @@ 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. |
|
| 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. |
|
| status | `string` | "" | Filter the tasks. Display only tasks with status equal to the supplied value. |
|
||||||
| stickyHeader | `boolean` | false | Toggles the sticky header mode. |
|
| stickyHeader | `boolean` | false | Toggles the sticky header mode. |
|
||||||
|
| names | `string[]` | [] | Filter the tasks. Display only tasks with names matching any of the supplied strings. This input will be used only if `TASK_SEARCH_API_METHOD_TOKEN` is provided with `POST` value. |
|
||||||
|
| processDefinitionNames | `string[]` | [] | Filter the tasks. Display only tasks under provided processes. This input will be used only if `TASK_SEARCH_API_METHOD_TOKEN` is provided with `POST` value. |
|
||||||
|
| statuses | `string[]` | [] | Filter the tasks. Display only tasks with provided statuses. This input will be used only if `TASK_SEARCH_API_METHOD_TOKEN` is provided with `POST` value. |
|
||||||
|
| assignees | `string[]` | [] | Filter the tasks. Display only tasks with assignees whose usernames are present in the array. This input will be used only if `TASK_SEARCH_API_METHOD_TOKEN` is provided with `POST` value. |
|
||||||
|
| priorities | `string[]` | [] | Filter the tasks. Display only tasks with provided priorities. This input will be used only if `TASK_SEARCH_API_METHOD_TOKEN` is provided with `POST` value. |
|
||||||
|
| completedByUsers | `string[]` | [] | Filter the tasks. Display only tasks completed by users whose usernames are present in the array. This input will be used only if `TASK_SEARCH_API_METHOD_TOKEN` is provided with `POST` value. |
|
||||||
|
|
||||||
### Events
|
### Events
|
||||||
|
|
||||||
|
@ -15,7 +15,9 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import { Pagination } from '@alfresco/js-api';
|
||||||
import { TaskListCloudSortingModel } from './task-list-sorting.model';
|
import { TaskListCloudSortingModel } from './task-list-sorting.model';
|
||||||
|
import { TaskFilterCloudModel } from '../task/task-filters/models/filter-cloud.model';
|
||||||
|
|
||||||
export class TaskQueryCloudRequestModel {
|
export class TaskQueryCloudRequestModel {
|
||||||
appName: string;
|
appName: string;
|
||||||
@ -90,3 +92,102 @@ export class TaskQueryCloudRequestModel {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface TaskListRequestTaskVariableFilter {
|
||||||
|
name?: string;
|
||||||
|
type?: string;
|
||||||
|
value?: string;
|
||||||
|
operator?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class TaskListRequestModel {
|
||||||
|
appName: string;
|
||||||
|
pagination?: Pagination;
|
||||||
|
sorting?: TaskListCloudSortingModel[];
|
||||||
|
|
||||||
|
onlyStandalone?: boolean;
|
||||||
|
onlyRoot?: boolean;
|
||||||
|
name?: string[];
|
||||||
|
description?: string[];
|
||||||
|
processDefinitionName?: string[];
|
||||||
|
priority?: string[];
|
||||||
|
status?: string[];
|
||||||
|
completedBy?: string[];
|
||||||
|
assignee?: string[];
|
||||||
|
createdFrom?: string;
|
||||||
|
createdTo?: string;
|
||||||
|
lastModifiedFrom?: string;
|
||||||
|
lastModifiedTo?: string;
|
||||||
|
lastClaimedFrom?: string;
|
||||||
|
lastClaimedTo?: string;
|
||||||
|
dueDateFrom?: string;
|
||||||
|
dueDateTo?: string;
|
||||||
|
completedFrom?: string;
|
||||||
|
completedTo?: string;
|
||||||
|
candidateUserId?: string[];
|
||||||
|
candidateGroupId?: string[];
|
||||||
|
|
||||||
|
taskVariableFilters?: TaskListRequestTaskVariableFilter[];
|
||||||
|
variableKeys?: string[];
|
||||||
|
|
||||||
|
constructor(obj: Partial<TaskListRequestModel>) {
|
||||||
|
if (!obj.appName) {
|
||||||
|
throw new Error('appName not configured');
|
||||||
|
}
|
||||||
|
|
||||||
|
this.appName = obj.appName;
|
||||||
|
this.pagination = obj.pagination;
|
||||||
|
this.sorting = obj.sorting;
|
||||||
|
|
||||||
|
this.onlyStandalone = obj.onlyStandalone;
|
||||||
|
this.onlyRoot = obj.onlyRoot;
|
||||||
|
this.name = obj.name;
|
||||||
|
this.description = obj.description;
|
||||||
|
this.processDefinitionName = obj.processDefinitionName;
|
||||||
|
this.priority = obj.priority;
|
||||||
|
this.status = obj.status;
|
||||||
|
this.completedBy = obj.completedBy;
|
||||||
|
this.assignee = obj.assignee;
|
||||||
|
this.createdFrom = obj.createdFrom;
|
||||||
|
this.createdTo = obj.createdTo;
|
||||||
|
this.lastModifiedFrom = obj.lastModifiedFrom;
|
||||||
|
this.lastModifiedTo = obj.lastModifiedTo;
|
||||||
|
this.lastClaimedFrom = obj.lastClaimedFrom;
|
||||||
|
this.lastClaimedTo = obj.lastClaimedTo;
|
||||||
|
this.dueDateFrom = obj.dueDateFrom;
|
||||||
|
this.dueDateTo = obj.dueDateTo;
|
||||||
|
this.completedFrom = obj.completedFrom;
|
||||||
|
this.completedTo = obj.completedTo;
|
||||||
|
this.candidateUserId = obj.candidateUserId;
|
||||||
|
this.candidateGroupId = obj.candidateGroupId;
|
||||||
|
this.taskVariableFilters = obj.taskVariableFilters;
|
||||||
|
this.variableKeys = obj.variableKeys;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class TaskFilterCloudAdapter extends TaskListRequestModel {
|
||||||
|
constructor(filter: TaskFilterCloudModel) {
|
||||||
|
super({
|
||||||
|
appName: filter.appName,
|
||||||
|
pagination: { maxItems: 25, skipCount: 0 },
|
||||||
|
sorting: [{ orderBy: filter.sort, direction: filter.order }],
|
||||||
|
|
||||||
|
onlyStandalone: filter.standalone,
|
||||||
|
name: filter.taskNames,
|
||||||
|
processDefinitionName: filter.processDefinitionNames,
|
||||||
|
priority: filter.priorities?.map((priority) => priority.toString()),
|
||||||
|
status: filter.statuses,
|
||||||
|
completedBy: filter.completedByUsers,
|
||||||
|
assignee: filter.assignees,
|
||||||
|
createdFrom: filter.createdFrom,
|
||||||
|
createdTo: filter.createdTo,
|
||||||
|
lastModifiedFrom: filter.lastModifiedFrom,
|
||||||
|
lastModifiedTo: filter.lastModifiedTo,
|
||||||
|
dueDateFrom: filter.dueDateFrom,
|
||||||
|
dueDateTo: filter.dueDateTo,
|
||||||
|
completedFrom: filter.completedFrom,
|
||||||
|
completedTo: filter.completedTo,
|
||||||
|
candidateGroupId: filter.candidateGroups?.map((group) => group.id)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -29,10 +29,13 @@
|
|||||||
[matAutocomplete]="auto"
|
[matAutocomplete]="auto"
|
||||||
[matChipInputFor]="userMultipleChipList"
|
[matChipInputFor]="userMultipleChipList"
|
||||||
[required]="required"
|
[required]="required"
|
||||||
|
[placeholder]="placeholder"
|
||||||
(focus)="setFocus(true)"
|
(focus)="setFocus(true)"
|
||||||
(blur)="setFocus(false); markAsTouched()"
|
(blur)="setFocus(false); markAsTouched()"
|
||||||
class="adf-cloud-input"
|
class="adf-cloud-input"
|
||||||
data-automation-id="adf-people-cloud-search-input" #userInput>
|
data-automation-id="adf-people-cloud-search-input"
|
||||||
|
#userInput
|
||||||
|
>
|
||||||
</mat-chip-grid>
|
</mat-chip-grid>
|
||||||
|
|
||||||
|
|
||||||
|
@ -119,11 +119,17 @@ export class PeopleCloudComponent implements OnInit, OnChanges, OnDestroy, After
|
|||||||
searchUserCtrl = new UntypedFormControl({ value: '', disabled: false });
|
searchUserCtrl = new UntypedFormControl({ value: '', disabled: false });
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Placeholder translation key
|
* Label translation key
|
||||||
*/
|
*/
|
||||||
@Input()
|
@Input()
|
||||||
title: string;
|
title: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Placeholder for the input field
|
||||||
|
*/
|
||||||
|
@Input()
|
||||||
|
placeholder: string;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Hide the matInput associated with the chip grid when a single user is selected in single selection mode.
|
* Hide the matInput associated with the chip grid when a single user is selected in single selection mode.
|
||||||
* The input will be shown again when the user is removed using the icon on the chip.
|
* The input will be shown again when the user is removed using the icon on the chip.
|
||||||
|
@ -19,13 +19,12 @@ import { Injectable } from '@angular/core';
|
|||||||
import { Observable, throwError } from 'rxjs';
|
import { Observable, throwError } from 'rxjs';
|
||||||
import { BaseCloudService } from '../../../services/base-cloud.service';
|
import { BaseCloudService } from '../../../services/base-cloud.service';
|
||||||
import { map } from 'rxjs/operators';
|
import { map } from 'rxjs/operators';
|
||||||
import { TaskListCloudServiceInterface } from '../../../services/task-list-cloud.service.interface';
|
|
||||||
import { TaskQueryCloudRequestModel } from '../../../models/filter-cloud-model';
|
import { TaskQueryCloudRequestModel } from '../../../models/filter-cloud-model';
|
||||||
import { TaskCloudNodePaging } from '../../../models/task-cloud.model';
|
import { TaskCloudNodePaging } from '../../../models/task-cloud.model';
|
||||||
import { TaskListCloudSortingModel } from '../../../models/task-list-sorting.model';
|
import { TaskListCloudSortingModel } from '../../../models/task-list-sorting.model';
|
||||||
|
|
||||||
@Injectable({ providedIn: 'root' })
|
@Injectable({ providedIn: 'root' })
|
||||||
export class ProcessTaskListCloudService extends BaseCloudService implements TaskListCloudServiceInterface {
|
export class ProcessTaskListCloudService extends BaseCloudService {
|
||||||
/**
|
/**
|
||||||
* Finds a task using an object with optional query properties.
|
* Finds a task using an object with optional query properties.
|
||||||
*
|
*
|
||||||
|
@ -28,3 +28,9 @@ export const PROCESS_FILTERS_SERVICE_TOKEN = new InjectionToken<PreferenceCloudS
|
|||||||
export const TASK_FILTERS_SERVICE_TOKEN = new InjectionToken<PreferenceCloudServiceInterface>('task-filters-cloud');
|
export const TASK_FILTERS_SERVICE_TOKEN = new InjectionToken<PreferenceCloudServiceInterface>('task-filters-cloud');
|
||||||
|
|
||||||
export const TASK_LIST_CLOUD_TOKEN = new InjectionToken<TaskListCloudServiceInterface>('task-list-cloud');
|
export const TASK_LIST_CLOUD_TOKEN = new InjectionToken<TaskListCloudServiceInterface>('task-list-cloud');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Token used to indicate the API used to search for tasks.
|
||||||
|
* 'POST' value should be provided only if the used Activiti version is 8.7.0 or higher.
|
||||||
|
*/
|
||||||
|
export const TASK_SEARCH_API_METHOD_TOKEN = new InjectionToken<'GET' | 'POST'>('task-search-method');
|
||||||
|
@ -16,8 +16,26 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { Observable } from 'rxjs';
|
import { Observable } from 'rxjs';
|
||||||
import { TaskQueryCloudRequestModel } from '../models/filter-cloud-model';
|
import { TaskListRequestModel, TaskQueryCloudRequestModel } from '../models/filter-cloud-model';
|
||||||
|
|
||||||
export interface TaskListCloudServiceInterface {
|
export interface TaskListCloudServiceInterface {
|
||||||
|
/**
|
||||||
|
* Finds a task using an object with optional query properties.
|
||||||
|
*
|
||||||
|
* @deprecated From Activiti 8.7.0 forward, use TaskListCloudService.fetchTaskList instead.
|
||||||
|
* @param requestNode Query object
|
||||||
|
* @param queryUrl Query url
|
||||||
|
* @returns Task information
|
||||||
|
*/
|
||||||
getTaskByRequest(requestNode: TaskQueryCloudRequestModel, queryUrl?: string): Observable<any>;
|
getTaskByRequest(requestNode: TaskQueryCloudRequestModel, queryUrl?: string): Observable<any>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Available from Activiti version 8.7.0 onwards.
|
||||||
|
* Retrieves a list of tasks using an object with optional query properties.
|
||||||
|
*
|
||||||
|
* @param requestNode Query object
|
||||||
|
* @param queryUrl Query url
|
||||||
|
* @returns List of tasks
|
||||||
|
*/
|
||||||
|
fetchTaskList(requestNode: TaskListRequestModel, queryUrl?: string): Observable<any>;
|
||||||
}
|
}
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -24,6 +24,9 @@ import { debounceTime, takeUntil, tap } from 'rxjs/operators';
|
|||||||
import { BaseTaskFiltersCloudComponent } from './base-task-filters-cloud.component';
|
import { BaseTaskFiltersCloudComponent } from './base-task-filters-cloud.component';
|
||||||
import { TaskDetailsCloudModel } from '../../start-task/models/task-details-cloud.model';
|
import { TaskDetailsCloudModel } from '../../start-task/models/task-details-cloud.model';
|
||||||
import { TaskCloudEngineEvent } from '../../../models/engine-event-cloud.model';
|
import { TaskCloudEngineEvent } from '../../../models/engine-event-cloud.model';
|
||||||
|
import { TaskListCloudService } from '../../task-list/services/task-list-cloud.service';
|
||||||
|
import { TaskFilterCloudAdapter } from '../../../models/filter-cloud-model';
|
||||||
|
import { TASK_SEARCH_API_METHOD_TOKEN } from '../../../services/cloud-token.service';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'adf-cloud-task-filters',
|
selector: 'adf-cloud-task-filters',
|
||||||
@ -55,8 +58,10 @@ export class TaskFiltersCloudComponent extends BaseTaskFiltersCloudComponent imp
|
|||||||
currentFiltersValues: { [key: string]: number } = {};
|
currentFiltersValues: { [key: string]: number } = {};
|
||||||
|
|
||||||
private readonly taskFilterCloudService = inject(TaskFilterCloudService);
|
private readonly taskFilterCloudService = inject(TaskFilterCloudService);
|
||||||
|
private readonly taskListCloudService = inject(TaskListCloudService);
|
||||||
private readonly translationService = inject(TranslationService);
|
private readonly translationService = inject(TranslationService);
|
||||||
private readonly appConfigService = inject(AppConfigService);
|
private readonly appConfigService = inject(AppConfigService);
|
||||||
|
private readonly searchMethod = inject<'GET' | 'POST'>(TASK_SEARCH_API_METHOD_TOKEN, { optional: true });
|
||||||
|
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
this.enableNotifications = this.appConfigService.get('notifications', true);
|
this.enableNotifications = this.appConfigService.get('notifications', true);
|
||||||
@ -114,24 +119,31 @@ export class TaskFiltersCloudComponent extends BaseTaskFiltersCloudComponent imp
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Get current value for filter and check if value has changed
|
* Get current value for filter and check if value has changed
|
||||||
|
*
|
||||||
* @param filter filter
|
* @param filter filter
|
||||||
*/
|
*/
|
||||||
updateFilterCounter(filter: TaskFilterCloudModel): void {
|
updateFilterCounter(filter: TaskFilterCloudModel): void {
|
||||||
if (filter?.showCounter) {
|
if (!filter?.showCounter) {
|
||||||
this.taskFilterCloudService
|
return;
|
||||||
.getTaskFilterCounter(filter)
|
|
||||||
.pipe(
|
|
||||||
tap((filterCounter) => {
|
|
||||||
this.checkIfFilterValuesHasBeenUpdated(filter.key, filterCounter);
|
|
||||||
})
|
|
||||||
)
|
|
||||||
.subscribe((data) => {
|
|
||||||
this.counters = {
|
|
||||||
...this.counters,
|
|
||||||
[filter.key]: data
|
|
||||||
};
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
this.fetchTaskFilterCounter(filter)
|
||||||
|
.pipe(
|
||||||
|
tap((filterCounter) => {
|
||||||
|
this.checkIfFilterValuesHasBeenUpdated(filter.key, filterCounter);
|
||||||
|
})
|
||||||
|
)
|
||||||
|
.subscribe((data) => {
|
||||||
|
this.counters = {
|
||||||
|
...this.counters,
|
||||||
|
[filter.key]: data
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private fetchTaskFilterCounter(filter: TaskFilterCloudModel): Observable<number> {
|
||||||
|
return this.searchMethod === 'POST'
|
||||||
|
? this.taskListCloudService.getTaskListCounter(new TaskFilterCloudAdapter(filter))
|
||||||
|
: this.taskFilterCloudService.getTaskFilterCounter(filter);
|
||||||
}
|
}
|
||||||
|
|
||||||
initFilterCounterNotifications() {
|
initFilterCounterNotifications() {
|
||||||
|
@ -21,6 +21,7 @@ import { TaskFilterCloudModel, ServiceTaskFilterCloudModel, AssignmentType, Task
|
|||||||
|
|
||||||
export const fakeGlobalFilter: any[] = [
|
export const fakeGlobalFilter: any[] = [
|
||||||
{
|
{
|
||||||
|
appName: 'fake-app-name',
|
||||||
name: 'FakeInvolvedTasks',
|
name: 'FakeInvolvedTasks',
|
||||||
key: 'fake-involved-tasks',
|
key: 'fake-involved-tasks',
|
||||||
icon: 'adjust',
|
icon: 'adjust',
|
||||||
@ -244,37 +245,37 @@ export const fakeTaskFilter = new TaskFilterCloudModel({
|
|||||||
status: 'ALL'
|
status: 'ALL'
|
||||||
});
|
});
|
||||||
|
|
||||||
export const fakeTaskCloudFilters = [
|
export const fakeTaskCloudFilters: TaskFilterCloudModel[] = [
|
||||||
{
|
new TaskFilterCloudModel({
|
||||||
name: 'FAKE_TASK_1',
|
name: 'FAKE_TASK_1',
|
||||||
id: '1',
|
id: '1',
|
||||||
key: 'all-fake-task',
|
key: 'completed-fake-task',
|
||||||
icon: 'adjust',
|
icon: 'adjust',
|
||||||
appName: 'fakeAppName',
|
appName: 'fakeAppName',
|
||||||
sort: 'startDate',
|
sort: 'startDate',
|
||||||
status: 'ALL',
|
status: TaskStatusFilter.COMPLETED,
|
||||||
order: 'DESC'
|
order: 'DESC'
|
||||||
},
|
}),
|
||||||
{
|
new TaskFilterCloudModel({
|
||||||
name: 'FAKE_TASK_2',
|
name: 'FAKE_TASK_2',
|
||||||
id: '2',
|
id: '2',
|
||||||
key: 'run-fake-task',
|
key: 'run-fake-task',
|
||||||
icon: 'adjust',
|
icon: 'adjust',
|
||||||
appName: 'fakeAppName',
|
appName: 'fakeAppName',
|
||||||
sort: 'startDate',
|
sort: 'startDate',
|
||||||
status: 'RUNNING',
|
status: TaskStatusFilter.ASSIGNED,
|
||||||
order: 'DESC'
|
order: 'DESC'
|
||||||
},
|
}),
|
||||||
{
|
new TaskFilterCloudModel({
|
||||||
name: 'FAKE_TASK_3',
|
name: 'FAKE_TASK_3',
|
||||||
id: '3',
|
id: '3',
|
||||||
key: 'complete-fake-task',
|
key: 'complete-fake-task',
|
||||||
icon: 'adjust',
|
icon: 'adjust',
|
||||||
appName: 'fakeAppName',
|
appName: 'fakeAppName',
|
||||||
sort: 'startDate',
|
sort: 'startDate',
|
||||||
status: 'COMPLETED',
|
status: TaskStatusFilter.COMPLETED,
|
||||||
order: 'DESC'
|
order: 'DESC'
|
||||||
}
|
})
|
||||||
];
|
];
|
||||||
|
|
||||||
export const taskNotifications = [
|
export const taskNotifications = [
|
||||||
@ -290,8 +291,8 @@ export const taskCloudEngineEventsMock = {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export const defaultTaskFiltersMock = [
|
export const defaultTaskFiltersMock: TaskFilterCloudModel[] = [
|
||||||
{
|
new TaskFilterCloudModel({
|
||||||
name: 'CREATED_TASK_FILTER',
|
name: 'CREATED_TASK_FILTER',
|
||||||
id: '1',
|
id: '1',
|
||||||
key: 'created',
|
key: 'created',
|
||||||
@ -300,8 +301,8 @@ export const defaultTaskFiltersMock = [
|
|||||||
sort: 'startDate',
|
sort: 'startDate',
|
||||||
status: TaskStatusFilter.CREATED,
|
status: TaskStatusFilter.CREATED,
|
||||||
order: 'DESC'
|
order: 'DESC'
|
||||||
},
|
}),
|
||||||
{
|
new TaskFilterCloudModel({
|
||||||
name: 'ASSIGNED_TASK_FILTER',
|
name: 'ASSIGNED_TASK_FILTER',
|
||||||
id: '2',
|
id: '2',
|
||||||
key: 'assigned',
|
key: 'assigned',
|
||||||
@ -310,8 +311,8 @@ export const defaultTaskFiltersMock = [
|
|||||||
sort: 'startDate',
|
sort: 'startDate',
|
||||||
status: TaskStatusFilter.ASSIGNED,
|
status: TaskStatusFilter.ASSIGNED,
|
||||||
order: 'DESC'
|
order: 'DESC'
|
||||||
},
|
}),
|
||||||
{
|
new TaskFilterCloudModel({
|
||||||
name: 'COMPLETED_TASK_FILTER',
|
name: 'COMPLETED_TASK_FILTER',
|
||||||
id: '3',
|
id: '3',
|
||||||
key: 'complete-fake-task',
|
key: 'complete-fake-task',
|
||||||
@ -320,7 +321,7 @@ export const defaultTaskFiltersMock = [
|
|||||||
sort: 'startDate',
|
sort: 'startDate',
|
||||||
status: TaskStatusFilter.COMPLETED,
|
status: TaskStatusFilter.COMPLETED,
|
||||||
order: 'DESC'
|
order: 'DESC'
|
||||||
}
|
})
|
||||||
];
|
];
|
||||||
|
|
||||||
export const fakeFilterNotification: TaskDetailsCloudModel = {
|
export const fakeFilterNotification: TaskDetailsCloudModel = {
|
||||||
|
@ -25,7 +25,7 @@ import { ComponentSelectionMode } from '../../../types';
|
|||||||
import { IdentityGroupModel } from '../../../group/models/identity-group.model';
|
import { IdentityGroupModel } from '../../../group/models/identity-group.model';
|
||||||
import { IdentityUserModel } from '../../../people/models/identity-user.model';
|
import { IdentityUserModel } from '../../../people/models/identity-user.model';
|
||||||
|
|
||||||
export class TaskFilterCloudModel {
|
export class TaskFilterCloudModel {
|
||||||
id: string;
|
id: string;
|
||||||
name: string;
|
name: string;
|
||||||
key: string;
|
key: string;
|
||||||
@ -60,6 +60,13 @@ export class TaskFilterCloudModel {
|
|||||||
completedBy: IdentityUserModel;
|
completedBy: IdentityUserModel;
|
||||||
showCounter: boolean;
|
showCounter: boolean;
|
||||||
|
|
||||||
|
taskNames: string[] | null;
|
||||||
|
statuses: TaskStatusFilter[] | null;
|
||||||
|
assignees: string[] | null;
|
||||||
|
processDefinitionNames: string[] | null;
|
||||||
|
priorities: string[] | null;
|
||||||
|
completedByUsers: string[] | null;
|
||||||
|
|
||||||
private _completedFrom: string;
|
private _completedFrom: string;
|
||||||
private _completedTo: string;
|
private _completedTo: string;
|
||||||
private _dueDateFrom: string;
|
private _dueDateFrom: string;
|
||||||
@ -108,6 +115,13 @@ export class TaskFilterCloudModel {
|
|||||||
this.createdTo = obj._createdTo || null;
|
this.createdTo = obj._createdTo || null;
|
||||||
this.candidateGroups = obj.candidateGroups || null;
|
this.candidateGroups = obj.candidateGroups || null;
|
||||||
this.showCounter = obj.showCounter || false;
|
this.showCounter = obj.showCounter || false;
|
||||||
|
|
||||||
|
this.taskNames = obj.taskNames || null;
|
||||||
|
this.statuses = obj.statuses || null;
|
||||||
|
this.assignees = obj.assignees || null;
|
||||||
|
this.processDefinitionNames = obj.processDefinitionNames || null;
|
||||||
|
this.priorities = obj.priorities || null;
|
||||||
|
this.completedByUsers = obj.completedByUsers || null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -36,6 +36,7 @@ import { ProcessServiceCloudTestingModule } from '../../../testing/process-servi
|
|||||||
import { IdentityUserService } from '../../../people/services/identity-user.service';
|
import { IdentityUserService } from '../../../people/services/identity-user.service';
|
||||||
import { ApolloModule } from 'apollo-angular';
|
import { ApolloModule } from 'apollo-angular';
|
||||||
import { StorageService } from '@alfresco/adf-core';
|
import { StorageService } from '@alfresco/adf-core';
|
||||||
|
import { TaskStatusFilter } from '../public-api';
|
||||||
|
|
||||||
describe('TaskFilterCloudService', () => {
|
describe('TaskFilterCloudService', () => {
|
||||||
let service: TaskFilterCloudService;
|
let service: TaskFilterCloudService;
|
||||||
@ -46,18 +47,17 @@ describe('TaskFilterCloudService', () => {
|
|||||||
let createPreferenceSpy: jasmine.Spy;
|
let createPreferenceSpy: jasmine.Spy;
|
||||||
let getCurrentUserInfoSpy: jasmine.Spy;
|
let getCurrentUserInfoSpy: jasmine.Spy;
|
||||||
|
|
||||||
const identityUserMock = { username: 'fakeusername', firstName: 'fake-identity-first-name', lastName: 'fake-identity-last-name', email: 'fakeIdentity@email.com' };
|
const identityUserMock = {
|
||||||
|
username: 'fakeusername',
|
||||||
|
firstName: 'fake-identity-first-name',
|
||||||
|
lastName: 'fake-identity-last-name',
|
||||||
|
email: 'fakeIdentity@email.com'
|
||||||
|
};
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
TestBed.configureTestingModule({
|
TestBed.configureTestingModule({
|
||||||
imports: [
|
imports: [HttpClientTestingModule, ProcessServiceCloudTestingModule, ApolloModule],
|
||||||
HttpClientTestingModule,
|
providers: [{ provide: TASK_FILTERS_SERVICE_TOKEN, useClass: UserPreferenceCloudService }]
|
||||||
ProcessServiceCloudTestingModule,
|
|
||||||
ApolloModule
|
|
||||||
],
|
|
||||||
providers: [
|
|
||||||
{ provide: TASK_FILTERS_SERVICE_TOKEN, useClass: UserPreferenceCloudService }
|
|
||||||
]
|
|
||||||
});
|
});
|
||||||
service = TestBed.inject(TaskFilterCloudService);
|
service = TestBed.inject(TaskFilterCloudService);
|
||||||
notificationCloudService = TestBed.inject(NotificationCloudService);
|
notificationCloudService = TestBed.inject(NotificationCloudService);
|
||||||
@ -90,17 +90,20 @@ describe('TaskFilterCloudService', () => {
|
|||||||
expect(res[0].appName).toBe('fakeAppName');
|
expect(res[0].appName).toBe('fakeAppName');
|
||||||
expect(res[0].id).toBe('1');
|
expect(res[0].id).toBe('1');
|
||||||
expect(res[0].name).toBe('FAKE_TASK_1');
|
expect(res[0].name).toBe('FAKE_TASK_1');
|
||||||
expect(res[0].status).toBe('ALL');
|
expect(res[0].status).toBe(TaskStatusFilter.COMPLETED);
|
||||||
|
expect(res[0].statuses).toContain(TaskStatusFilter.COMPLETED);
|
||||||
|
|
||||||
expect(res[1].appName).toBe('fakeAppName');
|
expect(res[1].appName).toBe('fakeAppName');
|
||||||
expect(res[1].id).toBe('2');
|
expect(res[1].id).toBe('2');
|
||||||
expect(res[1].name).toBe('FAKE_TASK_2');
|
expect(res[1].name).toBe('FAKE_TASK_2');
|
||||||
expect(res[1].status).toBe('RUNNING');
|
expect(res[1].status).toBe(TaskStatusFilter.ASSIGNED);
|
||||||
|
expect(res[1].statuses).toContain(TaskStatusFilter.ASSIGNED);
|
||||||
|
|
||||||
expect(res[2].appName).toBe('fakeAppName');
|
expect(res[2].appName).toBe('fakeAppName');
|
||||||
expect(res[2].id).toBe('3');
|
expect(res[2].id).toBe('3');
|
||||||
expect(res[2].name).toBe('FAKE_TASK_3');
|
expect(res[2].name).toBe('FAKE_TASK_3');
|
||||||
expect(res[2].status).toBe('COMPLETED');
|
expect(res[2].status).toBe(TaskStatusFilter.COMPLETED);
|
||||||
|
expect(res[2].statuses).toContain(TaskStatusFilter.COMPLETED);
|
||||||
|
|
||||||
expect(createPreferenceSpy).toHaveBeenCalled();
|
expect(createPreferenceSpy).toHaveBeenCalled();
|
||||||
done();
|
done();
|
||||||
@ -116,17 +119,20 @@ describe('TaskFilterCloudService', () => {
|
|||||||
expect(res[0].appName).toBe('fakeAppName');
|
expect(res[0].appName).toBe('fakeAppName');
|
||||||
expect(res[0].id).toBe('1');
|
expect(res[0].id).toBe('1');
|
||||||
expect(res[0].name).toBe('FAKE_TASK_1');
|
expect(res[0].name).toBe('FAKE_TASK_1');
|
||||||
expect(res[0].status).toBe('ALL');
|
expect(res[0].status).toBe(TaskStatusFilter.COMPLETED);
|
||||||
|
expect(res[0].statuses).toContain(TaskStatusFilter.COMPLETED);
|
||||||
|
|
||||||
expect(res[1].appName).toBe('fakeAppName');
|
expect(res[1].appName).toBe('fakeAppName');
|
||||||
expect(res[1].id).toBe('2');
|
expect(res[1].id).toBe('2');
|
||||||
expect(res[1].name).toBe('FAKE_TASK_2');
|
expect(res[1].name).toBe('FAKE_TASK_2');
|
||||||
expect(res[1].status).toBe('RUNNING');
|
expect(res[1].status).toBe(TaskStatusFilter.ASSIGNED);
|
||||||
|
expect(res[1].statuses).toContain(TaskStatusFilter.ASSIGNED);
|
||||||
|
|
||||||
expect(res[2].appName).toBe('fakeAppName');
|
expect(res[2].appName).toBe('fakeAppName');
|
||||||
expect(res[2].id).toBe('3');
|
expect(res[2].id).toBe('3');
|
||||||
expect(res[2].name).toBe('FAKE_TASK_3');
|
expect(res[2].name).toBe('FAKE_TASK_3');
|
||||||
expect(res[2].status).toBe('COMPLETED');
|
expect(res[2].status).toBe(TaskStatusFilter.COMPLETED);
|
||||||
|
expect(res[2].statuses).toContain(TaskStatusFilter.COMPLETED);
|
||||||
|
|
||||||
expect(getPreferencesSpy).toHaveBeenCalled();
|
expect(getPreferencesSpy).toHaveBeenCalled();
|
||||||
done();
|
done();
|
||||||
@ -144,17 +150,20 @@ describe('TaskFilterCloudService', () => {
|
|||||||
expect(res[0].appName).toBe('fakeAppName');
|
expect(res[0].appName).toBe('fakeAppName');
|
||||||
expect(res[0].id).toBe('1');
|
expect(res[0].id).toBe('1');
|
||||||
expect(res[0].name).toBe('FAKE_TASK_1');
|
expect(res[0].name).toBe('FAKE_TASK_1');
|
||||||
expect(res[0].status).toBe('ALL');
|
expect(res[0].status).toBe(TaskStatusFilter.COMPLETED);
|
||||||
|
expect(res[0].statuses).toContain(TaskStatusFilter.COMPLETED);
|
||||||
|
|
||||||
expect(res[1].appName).toBe('fakeAppName');
|
expect(res[1].appName).toBe('fakeAppName');
|
||||||
expect(res[1].id).toBe('2');
|
expect(res[1].id).toBe('2');
|
||||||
expect(res[1].name).toBe('FAKE_TASK_2');
|
expect(res[1].name).toBe('FAKE_TASK_2');
|
||||||
expect(res[1].status).toBe('RUNNING');
|
expect(res[1].status).toBe(TaskStatusFilter.ASSIGNED);
|
||||||
|
expect(res[1].statuses).toContain(TaskStatusFilter.ASSIGNED);
|
||||||
|
|
||||||
expect(res[2].appName).toBe('fakeAppName');
|
expect(res[2].appName).toBe('fakeAppName');
|
||||||
expect(res[2].id).toBe('3');
|
expect(res[2].id).toBe('3');
|
||||||
expect(res[2].name).toBe('FAKE_TASK_3');
|
expect(res[2].name).toBe('FAKE_TASK_3');
|
||||||
expect(res[2].status).toBe('COMPLETED');
|
expect(res[2].status).toBe(TaskStatusFilter.COMPLETED);
|
||||||
|
expect(res[2].statuses).toContain(TaskStatusFilter.COMPLETED);
|
||||||
|
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
@ -167,7 +176,8 @@ describe('TaskFilterCloudService', () => {
|
|||||||
expect(res.appName).toBe('fakeAppName');
|
expect(res.appName).toBe('fakeAppName');
|
||||||
expect(res.id).toBe('2');
|
expect(res.id).toBe('2');
|
||||||
expect(res.name).toBe('FAKE_TASK_2');
|
expect(res.name).toBe('FAKE_TASK_2');
|
||||||
expect(res.status).toBe('RUNNING');
|
expect(res.status).toBe(TaskStatusFilter.ASSIGNED);
|
||||||
|
expect(res.statuses).toContain(TaskStatusFilter.ASSIGNED);
|
||||||
|
|
||||||
expect(getPreferenceByKeySpy).toHaveBeenCalled();
|
expect(getPreferenceByKeySpy).toHaveBeenCalled();
|
||||||
done();
|
done();
|
||||||
@ -183,7 +193,8 @@ describe('TaskFilterCloudService', () => {
|
|||||||
expect(res.appName).toBe('fakeAppName');
|
expect(res.appName).toBe('fakeAppName');
|
||||||
expect(res.id).toBe('2');
|
expect(res.id).toBe('2');
|
||||||
expect(res.name).toBe('FAKE_TASK_2');
|
expect(res.name).toBe('FAKE_TASK_2');
|
||||||
expect(res.status).toBe('RUNNING');
|
expect(res.status).toBe(TaskStatusFilter.ASSIGNED);
|
||||||
|
expect(res.statuses).toContain(TaskStatusFilter.ASSIGNED);
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -245,14 +256,17 @@ describe('Inject [LocalPreferenceCloudService] into the TaskFilterCloudService',
|
|||||||
let getPreferencesSpy: jasmine.Spy;
|
let getPreferencesSpy: jasmine.Spy;
|
||||||
let storageService: StorageService;
|
let storageService: StorageService;
|
||||||
|
|
||||||
const identityUserMock = { username: 'fakeusername', firstName: 'fake-identity-first-name', lastName: 'fake-identity-last-name', email: 'fakeIdentity@email.com' };
|
const identityUserMock = {
|
||||||
|
username: 'fakeusername',
|
||||||
|
firstName: 'fake-identity-first-name',
|
||||||
|
lastName: 'fake-identity-last-name',
|
||||||
|
email: 'fakeIdentity@email.com'
|
||||||
|
};
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
TestBed.configureTestingModule({
|
TestBed.configureTestingModule({
|
||||||
imports: [HttpClientTestingModule, ProcessServiceCloudTestingModule, ApolloModule],
|
imports: [HttpClientTestingModule, ProcessServiceCloudTestingModule, ApolloModule],
|
||||||
providers: [
|
providers: [{ provide: TASK_FILTERS_SERVICE_TOKEN, useClass: LocalPreferenceCloudService }]
|
||||||
{ provide: TASK_FILTERS_SERVICE_TOKEN, useClass: LocalPreferenceCloudService }
|
|
||||||
]
|
|
||||||
});
|
});
|
||||||
service = TestBed.inject(TaskFilterCloudService);
|
service = TestBed.inject(TaskFilterCloudService);
|
||||||
preferenceCloudService = service.preferenceService;
|
preferenceCloudService = service.preferenceService;
|
||||||
@ -272,20 +286,24 @@ describe('Inject [LocalPreferenceCloudService] into the TaskFilterCloudService',
|
|||||||
expect(res[0].key).toEqual('my-tasks');
|
expect(res[0].key).toEqual('my-tasks');
|
||||||
expect(res[0].appName).toEqual(appName);
|
expect(res[0].appName).toEqual(appName);
|
||||||
expect(res[0].icon).toEqual('inbox');
|
expect(res[0].icon).toEqual('inbox');
|
||||||
expect(res[0].status).toEqual('ASSIGNED');
|
expect(res[0].status).toEqual(TaskStatusFilter.ASSIGNED);
|
||||||
|
expect(res[0].statuses).toContain(TaskStatusFilter.ASSIGNED);
|
||||||
expect(res[0].assignee).toEqual(identityUserMock.username);
|
expect(res[0].assignee).toEqual(identityUserMock.username);
|
||||||
|
expect(res[0].assignees).toContain(identityUserMock.username);
|
||||||
|
|
||||||
expect(res[1].name).toEqual('ADF_CLOUD_TASK_FILTERS.QUEUED_TASKS');
|
expect(res[1].name).toEqual('ADF_CLOUD_TASK_FILTERS.QUEUED_TASKS');
|
||||||
expect(res[1].key).toEqual('queued-tasks');
|
expect(res[1].key).toEqual('queued-tasks');
|
||||||
expect(res[1].appName).toEqual(appName);
|
expect(res[1].appName).toEqual(appName);
|
||||||
expect(res[1].icon).toEqual('queue');
|
expect(res[1].icon).toEqual('queue');
|
||||||
expect(res[1].status).toEqual('CREATED');
|
expect(res[1].status).toEqual(TaskStatusFilter.CREATED);
|
||||||
|
expect(res[1].statuses).toContain(TaskStatusFilter.CREATED);
|
||||||
|
|
||||||
expect(res[2].name).toEqual('ADF_CLOUD_TASK_FILTERS.COMPLETED_TASKS');
|
expect(res[2].name).toEqual('ADF_CLOUD_TASK_FILTERS.COMPLETED_TASKS');
|
||||||
expect(res[2].key).toEqual('completed-tasks');
|
expect(res[2].key).toEqual('completed-tasks');
|
||||||
expect(res[2].appName).toEqual(appName);
|
expect(res[2].appName).toEqual(appName);
|
||||||
expect(res[2].icon).toEqual('done');
|
expect(res[2].icon).toEqual('done');
|
||||||
expect(res[2].status).toEqual('COMPLETED');
|
expect(res[2].status).toEqual(TaskStatusFilter.COMPLETED);
|
||||||
|
expect(res[2].statuses).toContain(TaskStatusFilter.COMPLETED);
|
||||||
expect(getPreferencesSpy).toHaveBeenCalled();
|
expect(getPreferencesSpy).toHaveBeenCalled();
|
||||||
|
|
||||||
const localData = JSON.parse(storageService.getItem(`task-filters-${appName}-${identityUserMock.username}`));
|
const localData = JSON.parse(storageService.getItem(`task-filters-${appName}-${identityUserMock.username}`));
|
||||||
@ -295,20 +313,24 @@ describe('Inject [LocalPreferenceCloudService] into the TaskFilterCloudService',
|
|||||||
expect(localData[0].key).toEqual('my-tasks');
|
expect(localData[0].key).toEqual('my-tasks');
|
||||||
expect(localData[0].appName).toEqual(appName);
|
expect(localData[0].appName).toEqual(appName);
|
||||||
expect(localData[0].icon).toEqual('inbox');
|
expect(localData[0].icon).toEqual('inbox');
|
||||||
expect(localData[0].status).toEqual('ASSIGNED');
|
expect(localData[0].status).toEqual(TaskStatusFilter.ASSIGNED);
|
||||||
|
expect(localData[0].statuses).toContain(TaskStatusFilter.ASSIGNED);
|
||||||
expect(localData[0].assignee).toEqual(identityUserMock.username);
|
expect(localData[0].assignee).toEqual(identityUserMock.username);
|
||||||
|
expect(localData[0].assignees).toContain(identityUserMock.username);
|
||||||
|
|
||||||
expect(localData[1].name).toEqual('ADF_CLOUD_TASK_FILTERS.QUEUED_TASKS');
|
expect(localData[1].name).toEqual('ADF_CLOUD_TASK_FILTERS.QUEUED_TASKS');
|
||||||
expect(localData[1].key).toEqual('queued-tasks');
|
expect(localData[1].key).toEqual('queued-tasks');
|
||||||
expect(localData[1].appName).toEqual(appName);
|
expect(localData[1].appName).toEqual(appName);
|
||||||
expect(localData[1].icon).toEqual('queue');
|
expect(localData[1].icon).toEqual('queue');
|
||||||
expect(localData[1].status).toEqual('CREATED');
|
expect(localData[1].status).toEqual(TaskStatusFilter.CREATED);
|
||||||
|
expect(localData[1].statuses).toContain(TaskStatusFilter.CREATED);
|
||||||
|
|
||||||
expect(localData[2].name).toEqual('ADF_CLOUD_TASK_FILTERS.COMPLETED_TASKS');
|
expect(localData[2].name).toEqual('ADF_CLOUD_TASK_FILTERS.COMPLETED_TASKS');
|
||||||
expect(localData[2].key).toEqual('completed-tasks');
|
expect(localData[2].key).toEqual('completed-tasks');
|
||||||
expect(localData[2].appName).toEqual(appName);
|
expect(localData[2].appName).toEqual(appName);
|
||||||
expect(localData[2].icon).toEqual('done');
|
expect(localData[2].icon).toEqual('done');
|
||||||
expect(localData[2].status).toEqual('COMPLETED');
|
expect(localData[2].status).toEqual(TaskStatusFilter.COMPLETED);
|
||||||
|
expect(localData[2].statuses).toContain(TaskStatusFilter.COMPLETED);
|
||||||
|
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
|
@ -80,7 +80,8 @@ export class TaskFilterCloudService extends BaseCloudService {
|
|||||||
} else {
|
} else {
|
||||||
return of(this.findFiltersByKeyInPreferences(preferences, key));
|
return of(this.findFiltersByKeyInPreferences(preferences, key));
|
||||||
}
|
}
|
||||||
})
|
}),
|
||||||
|
switchMap((filters) => this.handleCreateFilterBackwardsCompatibility(appName, key, filters))
|
||||||
)
|
)
|
||||||
.subscribe((filters) => {
|
.subscribe((filters) => {
|
||||||
this.addFiltersToStream(filters);
|
this.addFiltersToStream(filters);
|
||||||
@ -379,4 +380,45 @@ export class TaskFilterCloudService extends BaseCloudService {
|
|||||||
refreshFilter(filterKey: string): void {
|
refreshFilter(filterKey: string): void {
|
||||||
this.filterKeyToBeRefreshedSource.next(filterKey);
|
this.filterKeyToBeRefreshedSource.next(filterKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method is run after retrieving the filter array from preferences.
|
||||||
|
* It handles the backwards compatibility with the new API by looking for the new properties and their counterparts in each passed filter.
|
||||||
|
* If the new property is not found, it is created and assigned the value constructed from the old property.
|
||||||
|
* The filters are then updated in the preferences and returned.
|
||||||
|
* Old properties are left untouched for purposes like feature toggling.
|
||||||
|
*
|
||||||
|
* @param appName Name of the target app.
|
||||||
|
* @param key Key of the task filters.
|
||||||
|
* @param filters Array of task filters to be checked for backward compatibility.
|
||||||
|
* @returns Observable of task filters with updated properties.
|
||||||
|
*/
|
||||||
|
private handleCreateFilterBackwardsCompatibility(
|
||||||
|
appName: string,
|
||||||
|
key: string,
|
||||||
|
filters: TaskFilterCloudModel[]
|
||||||
|
): Observable<TaskFilterCloudModel[]> {
|
||||||
|
filters.forEach((filter) => {
|
||||||
|
if (filter.taskName && !filter.taskNames) {
|
||||||
|
filter.taskNames = [filter.taskName];
|
||||||
|
}
|
||||||
|
if (filter.status && !filter.statuses) {
|
||||||
|
filter.statuses = [filter.status];
|
||||||
|
}
|
||||||
|
if (filter.assignee && !filter.assignees) {
|
||||||
|
filter.assignees = [filter.assignee];
|
||||||
|
}
|
||||||
|
if (filter.processDefinitionName && !filter.processDefinitionNames) {
|
||||||
|
filter.processDefinitionNames = [filter.processDefinitionName];
|
||||||
|
}
|
||||||
|
if (filter.completedBy?.username && !filter.completedByUsers) {
|
||||||
|
filter.completedByUsers = [filter.completedBy.username];
|
||||||
|
}
|
||||||
|
if (filter.priority && !filter.priorities) {
|
||||||
|
filter.priorities = [`${filter.priority}`];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return this.updateTaskFilters(appName, key, filters);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -27,7 +27,7 @@ import { ProcessServiceCloudTestingModule } from '../../../testing/process-servi
|
|||||||
import { TaskListCloudSortingModel } from '../../../models/task-list-sorting.model';
|
import { TaskListCloudSortingModel } from '../../../models/task-list-sorting.model';
|
||||||
import { shareReplay, skip } from 'rxjs/operators';
|
import { shareReplay, skip } from 'rxjs/operators';
|
||||||
import { TaskListCloudServiceInterface } from '../../../services/task-list-cloud.service.interface';
|
import { TaskListCloudServiceInterface } from '../../../services/task-list-cloud.service.interface';
|
||||||
import { TASK_LIST_CLOUD_TOKEN, TASK_LIST_PREFERENCES_SERVICE_TOKEN } from '../../../services/cloud-token.service';
|
import { TASK_LIST_CLOUD_TOKEN, TASK_LIST_PREFERENCES_SERVICE_TOKEN, TASK_SEARCH_API_METHOD_TOKEN } from '../../../services/cloud-token.service';
|
||||||
import { TaskListCloudModule } from '../task-list-cloud.module';
|
import { TaskListCloudModule } from '../task-list-cloud.module';
|
||||||
import { PreferenceCloudServiceInterface } from '../../../services/preference-cloud.interface';
|
import { PreferenceCloudServiceInterface } from '../../../services/preference-cloud.interface';
|
||||||
import { HarnessLoader } from '@angular/cdk/testing';
|
import { HarnessLoader } from '@angular/cdk/testing';
|
||||||
@ -100,7 +100,7 @@ describe('TaskListCloudComponent', () => {
|
|||||||
updatePreference: of({})
|
updatePreference: of({})
|
||||||
});
|
});
|
||||||
|
|
||||||
beforeEach(() => {
|
const configureTestingModule = (providers: any[]) => {
|
||||||
TestBed.configureTestingModule({
|
TestBed.configureTestingModule({
|
||||||
imports: [ProcessServiceCloudTestingModule],
|
imports: [ProcessServiceCloudTestingModule],
|
||||||
providers: [
|
providers: [
|
||||||
@ -111,7 +111,8 @@ describe('TaskListCloudComponent', () => {
|
|||||||
{
|
{
|
||||||
provide: TASK_LIST_PREFERENCES_SERVICE_TOKEN,
|
provide: TASK_LIST_PREFERENCES_SERVICE_TOKEN,
|
||||||
useValue: preferencesService
|
useValue: preferencesService
|
||||||
}
|
},
|
||||||
|
...providers
|
||||||
]
|
]
|
||||||
});
|
});
|
||||||
appConfig = TestBed.inject(AppConfigService);
|
appConfig = TestBed.inject(AppConfigService);
|
||||||
@ -141,352 +142,512 @@ describe('TaskListCloudComponent', () => {
|
|||||||
|
|
||||||
component.isColumnSchemaCreated$ = of(true).pipe(shareReplay(1));
|
component.isColumnSchemaCreated$ = of(true).pipe(shareReplay(1));
|
||||||
loader = TestbedHarnessEnvironment.loader(fixture);
|
loader = TestbedHarnessEnvironment.loader(fixture);
|
||||||
});
|
};
|
||||||
|
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
fixture.destroy();
|
fixture.destroy();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should be able to inject TaskListCloudService instance', () => {
|
describe('TASK_SEARCH_API_METHOD_TOKEN injected with GET value', () => {
|
||||||
fixture.detectChanges();
|
|
||||||
|
|
||||||
expect(component.taskListCloudService instanceof TaskListCloudService).toBeTruthy();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should use the default schemaColumn as default', () => {
|
|
||||||
component.ngAfterContentInit();
|
|
||||||
expect(component.columns).toBeDefined();
|
|
||||||
expect(component.columns.length).toEqual(3);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should display empty content when process list is empty', async () => {
|
|
||||||
const emptyList = { list: { entries: [] } };
|
|
||||||
spyOn(taskListCloudService, 'getTaskByRequest').and.returnValue(of(emptyList));
|
|
||||||
fixture.detectChanges();
|
|
||||||
|
|
||||||
const appName = new SimpleChange(null, 'FAKE-APP-NAME', true);
|
|
||||||
component.ngOnChanges({ appName });
|
|
||||||
fixture.detectChanges();
|
|
||||||
|
|
||||||
expect(await loader.hasHarness(MatProgressSpinnerHarness)).toBe(false);
|
|
||||||
|
|
||||||
const emptyContent = fixture.debugElement.query(By.css('.adf-empty-content'));
|
|
||||||
expect(emptyContent.nativeElement).toBeDefined();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should load spinner and show the content', async () => {
|
|
||||||
spyOn(taskListCloudService, 'getTaskByRequest').and.returnValue(of(fakeGlobalTasks));
|
|
||||||
const appName = new SimpleChange(null, 'FAKE-APP-NAME', true);
|
|
||||||
|
|
||||||
fixture.detectChanges();
|
|
||||||
component.ngOnChanges({ appName });
|
|
||||||
fixture.detectChanges();
|
|
||||||
|
|
||||||
expect(await loader.hasHarness(MatProgressSpinnerHarness)).toBe(false);
|
|
||||||
|
|
||||||
const emptyContent = fixture.debugElement.query(By.css('.adf-empty-content'));
|
|
||||||
expect(emptyContent).toBeFalsy();
|
|
||||||
|
|
||||||
expect(component.rows.length).toEqual(1);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should use the custom schemaColumn from app.config.json', () => {
|
|
||||||
component.presetColumn = 'fakeCustomSchema';
|
|
||||||
component.ngAfterContentInit();
|
|
||||||
fixture.detectChanges();
|
|
||||||
expect(component.columns).toEqual(fakeCustomSchema);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should hide columns on applying new columns visibility through columns selector', () => {
|
|
||||||
component.showMainDatatableActions = true;
|
|
||||||
spyOn(taskListCloudService, 'getTaskByRequest').and.returnValue(of(fakeGlobalTasks));
|
|
||||||
component.ngAfterContentInit();
|
|
||||||
|
|
||||||
const appName = new SimpleChange(null, 'FAKE-APP-NAME', true);
|
|
||||||
component.ngOnChanges({ appName });
|
|
||||||
|
|
||||||
fixture.detectChanges();
|
|
||||||
|
|
||||||
const mainMenuButton = fixture.debugElement.query(By.css('[data-automation-id="adf-datatable-main-menu-button"]'));
|
|
||||||
mainMenuButton.triggerEventHandler('click', {});
|
|
||||||
fixture.detectChanges();
|
|
||||||
|
|
||||||
const columnSelectorMenu = fixture.debugElement.query(By.css('adf-datatable-column-selector'));
|
|
||||||
expect(columnSelectorMenu).toBeTruthy();
|
|
||||||
|
|
||||||
const columnsSelectorInstance = columnSelectorMenu.componentInstance as ColumnsSelectorComponent;
|
|
||||||
expect(columnsSelectorInstance.columns).toBe(component.columns, 'should pass columns as input');
|
|
||||||
|
|
||||||
const newColumns = (component.columns as DataColumn[]).map((column, index) => ({
|
|
||||||
...column,
|
|
||||||
isHidden: index !== 0 // only first one is shown
|
|
||||||
}));
|
|
||||||
|
|
||||||
columnSelectorMenu.triggerEventHandler('submitColumnsVisibility', newColumns);
|
|
||||||
fixture.detectChanges();
|
|
||||||
|
|
||||||
const displayedColumns = fixture.debugElement.queryAll(By.css('.adf-datatable-cell-header'));
|
|
||||||
expect(displayedColumns.length).toBe(2, 'only column with isHidden set to false and action column should be shown');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should fetch custom schemaColumn when the input presetColumn is defined', () => {
|
|
||||||
component.presetColumn = 'fakeCustomSchema';
|
|
||||||
fixture.detectChanges();
|
|
||||||
expect(component.columns).toBeDefined();
|
|
||||||
expect(component.columns.length).toEqual(2);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should return an empty task list when no input parameters are passed', () => {
|
|
||||||
component.ngAfterContentInit();
|
|
||||||
expect(component.rows).toBeDefined();
|
|
||||||
expect(component.isListEmpty()).toBeTruthy();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should return the results if an application name is given', (done) => {
|
|
||||||
spyOn(taskListCloudService, 'getTaskByRequest').and.returnValue(of(fakeGlobalTasks));
|
|
||||||
|
|
||||||
component.success.subscribe((res) => {
|
|
||||||
expect(res).toBeDefined();
|
|
||||||
expect(component.rows).toBeDefined();
|
|
||||||
expect(component.isListEmpty()).not.toBeTruthy();
|
|
||||||
expect(component.rows.length).toEqual(1);
|
|
||||||
|
|
||||||
const expectedTask = {
|
|
||||||
...fakeGlobalTask,
|
|
||||||
variables: fakeGlobalTask.processVariables
|
|
||||||
};
|
|
||||||
|
|
||||||
expect(component.rows[0]).toEqual(expectedTask);
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
|
|
||||||
component.reload();
|
|
||||||
fixture.detectChanges();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should emit row click event', (done) => {
|
|
||||||
const row = new ObjectDataRow({ id: '999' });
|
|
||||||
const rowEvent = new DataRowEvent(row, null);
|
|
||||||
component.rowClick.subscribe((taskId) => {
|
|
||||||
expect(taskId).toEqual('999');
|
|
||||||
expect(component.currentInstanceId).toEqual('999');
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
component.onRowClick(rowEvent);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should re-create columns when a column width gets changed', () => {
|
|
||||||
component.reload();
|
|
||||||
fixture.detectChanges();
|
|
||||||
|
|
||||||
const newColumns = [...component.columns];
|
|
||||||
newColumns[0].width = 120;
|
|
||||||
component.onColumnsWidthChanged(newColumns);
|
|
||||||
|
|
||||||
expect(component.columns[0].width).toBe(120);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should update columns widths when a column width gets changed', () => {
|
|
||||||
component.appName = 'fake-app-name';
|
|
||||||
component.reload();
|
|
||||||
fixture.detectChanges();
|
|
||||||
|
|
||||||
const newColumns = [...component.columns];
|
|
||||||
newColumns[0].width = 120;
|
|
||||||
component.onColumnsWidthChanged(newColumns);
|
|
||||||
|
|
||||||
expect(component.columns[0].width).toBe(120);
|
|
||||||
expect(preferencesService.updatePreference).toHaveBeenCalledWith('fake-app-name', 'tasks-list-cloud-columns-widths', {
|
|
||||||
name: 120
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should update columns widths while preserving previously saved widths when a column width gets changed', () => {
|
|
||||||
component.appName = 'fake-app-name';
|
|
||||||
component.reload();
|
|
||||||
fixture.detectChanges();
|
|
||||||
|
|
||||||
const newColumns = [...component.columns];
|
|
||||||
newColumns[0].width = 120;
|
|
||||||
component.onColumnsWidthChanged(newColumns);
|
|
||||||
|
|
||||||
expect(component.columns[0].width).toBe(120);
|
|
||||||
expect(preferencesService.updatePreference).toHaveBeenCalledWith('fake-app-name', 'tasks-list-cloud-columns-widths', {
|
|
||||||
name: 120
|
|
||||||
});
|
|
||||||
|
|
||||||
newColumns[1].width = 150;
|
|
||||||
component.onColumnsWidthChanged(newColumns);
|
|
||||||
|
|
||||||
expect(component.columns[0].width).toBe(120);
|
|
||||||
expect(component.columns[1].width).toBe(150);
|
|
||||||
expect(preferencesService.updatePreference).toHaveBeenCalledWith('fake-app-name', 'tasks-list-cloud-columns-widths', {
|
|
||||||
name: 120,
|
|
||||||
created: 150
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should re-create columns when a column order gets changed', () => {
|
|
||||||
component.reload();
|
|
||||||
fixture.detectChanges();
|
|
||||||
|
|
||||||
expect(component.columns[0].title).toBe('ADF_CLOUD_TASK_LIST.PROPERTIES.NAME');
|
|
||||||
expect(component.columns[1].title).toBe('ADF_CLOUD_TASK_LIST.PROPERTIES.CREATED');
|
|
||||||
expect(component.columns[2].title).toBe('ADF_CLOUD_TASK_LIST.PROPERTIES.ASSIGNEE');
|
|
||||||
|
|
||||||
component.onColumnOrderChanged([component.columns[1], ...component.columns]);
|
|
||||||
fixture.detectChanges();
|
|
||||||
|
|
||||||
expect(component.columns[0].title).toBe('ADF_CLOUD_TASK_LIST.PROPERTIES.CREATED');
|
|
||||||
expect(component.columns[1].title).toBe('ADF_CLOUD_TASK_LIST.PROPERTIES.NAME');
|
|
||||||
expect(component.columns[2].title).toBe('ADF_CLOUD_TASK_LIST.PROPERTIES.ASSIGNEE');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should create datatable schema when a column visibility gets changed', () => {
|
|
||||||
component.ngAfterContentInit();
|
|
||||||
spyOn(component, 'createDatatableSchema');
|
|
||||||
|
|
||||||
component.onColumnsVisibilityChange(component.columns);
|
|
||||||
|
|
||||||
fixture.detectChanges();
|
|
||||||
|
|
||||||
expect(component.createDatatableSchema).toHaveBeenCalled();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should call endpoint when a column visibility gets changed', () => {
|
|
||||||
spyOn(taskListCloudService, 'getTaskByRequest');
|
|
||||||
component.ngAfterContentInit();
|
|
||||||
spyOn(component, 'createDatatableSchema');
|
|
||||||
component.appName = 'fake-app-name';
|
|
||||||
component.reload();
|
|
||||||
fixture.detectChanges();
|
|
||||||
|
|
||||||
component.onColumnsVisibilityChange(component.columns);
|
|
||||||
|
|
||||||
fixture.detectChanges();
|
|
||||||
|
|
||||||
expect(taskListCloudService.getTaskByRequest).toHaveBeenCalledTimes(1);
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('component changes', () => {
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
component.rows = fakeGlobalTasks.list.entries;
|
configureTestingModule([{ provide: TASK_SEARCH_API_METHOD_TOKEN, useValue: 'GET' }]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should load spinner and show the content', async () => {
|
||||||
|
spyOn(taskListCloudService, 'getTaskByRequest').and.returnValue(of(fakeGlobalTasks));
|
||||||
|
const appName = new SimpleChange(null, 'FAKE-APP-NAME', true);
|
||||||
|
|
||||||
|
fixture.detectChanges();
|
||||||
|
component.ngOnChanges({ appName });
|
||||||
|
fixture.detectChanges();
|
||||||
|
|
||||||
|
expect(await loader.hasHarness(MatProgressSpinnerHarness)).toBe(false);
|
||||||
|
|
||||||
|
const emptyContent = fixture.debugElement.query(By.css('.adf-empty-content'));
|
||||||
|
expect(emptyContent).toBeFalsy();
|
||||||
|
|
||||||
|
expect(component.rows.length).toEqual(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should hide columns on applying new columns visibility through columns selector', () => {
|
||||||
|
component.showMainDatatableActions = true;
|
||||||
|
spyOn(taskListCloudService, 'getTaskByRequest').and.returnValue(of(fakeGlobalTasks));
|
||||||
|
component.ngAfterContentInit();
|
||||||
|
|
||||||
|
const appName = new SimpleChange(null, 'FAKE-APP-NAME', true);
|
||||||
|
component.ngOnChanges({ appName });
|
||||||
|
|
||||||
|
fixture.detectChanges();
|
||||||
|
|
||||||
|
const mainMenuButton = fixture.debugElement.query(By.css('[data-automation-id="adf-datatable-main-menu-button"]'));
|
||||||
|
mainMenuButton.triggerEventHandler('click', {});
|
||||||
|
fixture.detectChanges();
|
||||||
|
|
||||||
|
const columnSelectorMenu = fixture.debugElement.query(By.css('adf-datatable-column-selector'));
|
||||||
|
expect(columnSelectorMenu).toBeTruthy();
|
||||||
|
|
||||||
|
const columnsSelectorInstance = columnSelectorMenu.componentInstance as ColumnsSelectorComponent;
|
||||||
|
expect(columnsSelectorInstance.columns).toBe(component.columns, 'should pass columns as input');
|
||||||
|
|
||||||
|
const newColumns = (component.columns as DataColumn[]).map((column, index) => ({
|
||||||
|
...column,
|
||||||
|
isHidden: index !== 0 // only first one is shown
|
||||||
|
}));
|
||||||
|
|
||||||
|
columnSelectorMenu.triggerEventHandler('submitColumnsVisibility', newColumns);
|
||||||
|
fixture.detectChanges();
|
||||||
|
|
||||||
|
const displayedColumns = fixture.debugElement.queryAll(By.css('.adf-datatable-cell-header'));
|
||||||
|
expect(displayedColumns.length).toBe(2, 'only column with isHidden set to false and action column should be shown');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return the results if an application name is given', (done) => {
|
||||||
|
spyOn(taskListCloudService, 'getTaskByRequest').and.returnValue(of(fakeGlobalTasks));
|
||||||
|
|
||||||
|
component.success.subscribe((res) => {
|
||||||
|
expect(res).toBeDefined();
|
||||||
|
expect(component.rows).toBeDefined();
|
||||||
|
expect(component.isListEmpty()).not.toBeTruthy();
|
||||||
|
expect(component.rows.length).toEqual(1);
|
||||||
|
|
||||||
|
const expectedTask = {
|
||||||
|
...fakeGlobalTask,
|
||||||
|
variables: fakeGlobalTask.processVariables
|
||||||
|
};
|
||||||
|
|
||||||
|
expect(component.rows[0]).toEqual(expectedTask);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
|
||||||
|
component.reload();
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should NOT reload the task list when no parameters changed', () => {
|
it('should call endpoint when a column visibility gets changed', () => {
|
||||||
spyOn(taskListCloudService, 'getTaskByRequest');
|
spyOn(taskListCloudService, 'getTaskByRequest');
|
||||||
component.rows = null;
|
component.ngAfterContentInit();
|
||||||
|
spyOn(component, 'createDatatableSchema');
|
||||||
|
component.appName = 'fake-app-name';
|
||||||
|
component.reload();
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
|
|
||||||
|
component.onColumnsVisibilityChange(component.columns);
|
||||||
|
|
||||||
|
fixture.detectChanges();
|
||||||
|
|
||||||
|
expect(taskListCloudService.getTaskByRequest).toHaveBeenCalledTimes(1);
|
||||||
|
});
|
||||||
|
describe('component changes', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
component.rows = fakeGlobalTasks.list.entries;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should reload the task list when input parameters changed', () => {
|
||||||
|
const getTaskByRequestSpy = spyOn(taskListCloudService, 'getTaskByRequest').and.returnValue(of(fakeGlobalTasks));
|
||||||
|
component.appName = 'mock-app-name';
|
||||||
|
component.priority = 1;
|
||||||
|
component.status = 'mock-status';
|
||||||
|
component.lastModifiedFrom = 'mock-lastmodified-date';
|
||||||
|
component.owner = 'mock-owner-name';
|
||||||
|
const priorityChange = new SimpleChange(undefined, 1, true);
|
||||||
|
const statusChange = new SimpleChange(undefined, 'mock-status', true);
|
||||||
|
const lastModifiedFromChange = new SimpleChange(undefined, 'mock-lastmodified-date', true);
|
||||||
|
const ownerChange = new SimpleChange(undefined, 'mock-owner-name', true);
|
||||||
|
component.ngOnChanges({
|
||||||
|
priority: priorityChange,
|
||||||
|
status: statusChange,
|
||||||
|
lastModifiedFrom: lastModifiedFromChange,
|
||||||
|
owner: ownerChange
|
||||||
|
});
|
||||||
|
fixture.detectChanges();
|
||||||
|
expect(component.isListEmpty()).toBeFalsy();
|
||||||
|
expect(getTaskByRequestSpy).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should reload task list when sorting on a column changes', () => {
|
||||||
|
const getTaskByRequestSpy = spyOn(taskListCloudService, 'getTaskByRequest').and.returnValue(of(fakeGlobalTasks));
|
||||||
|
component.onSortingChanged(
|
||||||
|
new CustomEvent('sorting-changed', {
|
||||||
|
detail: {
|
||||||
|
key: 'fakeName',
|
||||||
|
direction: 'asc'
|
||||||
|
},
|
||||||
|
bubbles: true
|
||||||
|
})
|
||||||
|
);
|
||||||
|
fixture.detectChanges();
|
||||||
|
expect(component.sorting).toEqual([
|
||||||
|
new TaskListCloudSortingModel({
|
||||||
|
orderBy: 'fakeName',
|
||||||
|
direction: 'ASC'
|
||||||
|
})
|
||||||
|
]);
|
||||||
|
expect(component.formattedSorting).toEqual(['fakeName', 'asc']);
|
||||||
|
expect(component.isListEmpty()).toBeFalsy();
|
||||||
|
expect(getTaskByRequestSpy).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('TASK_SEARCH_API_METHOD_TOKEN injected with POST value', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
configureTestingModule([{ provide: TASK_SEARCH_API_METHOD_TOKEN, useValue: 'POST' }]);
|
||||||
|
component.appName = 'mock-app-name';
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should load spinner and show the content', async () => {
|
||||||
|
spyOn(taskListCloudService, 'fetchTaskList').and.returnValue(of(fakeGlobalTasks));
|
||||||
|
const appName = new SimpleChange(null, 'FAKE-APP-NAME', true);
|
||||||
|
|
||||||
|
fixture.detectChanges();
|
||||||
|
component.ngOnChanges({ appName });
|
||||||
|
fixture.detectChanges();
|
||||||
|
|
||||||
|
expect(await loader.hasHarness(MatProgressSpinnerHarness)).toBe(false);
|
||||||
|
|
||||||
|
const emptyContent = fixture.debugElement.query(By.css('.adf-empty-content'));
|
||||||
|
expect(emptyContent).toBeFalsy();
|
||||||
|
|
||||||
|
expect(component.rows.length).toEqual(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should hide columns on applying new columns visibility through columns selector', () => {
|
||||||
|
component.showMainDatatableActions = true;
|
||||||
|
spyOn(taskListCloudService, 'fetchTaskList').and.returnValue(of(fakeGlobalTasks));
|
||||||
|
component.ngAfterContentInit();
|
||||||
|
|
||||||
|
const appName = new SimpleChange(null, 'FAKE-APP-NAME', true);
|
||||||
|
component.ngOnChanges({ appName });
|
||||||
|
|
||||||
|
fixture.detectChanges();
|
||||||
|
|
||||||
|
const mainMenuButton = fixture.debugElement.query(By.css('[data-automation-id="adf-datatable-main-menu-button"]'));
|
||||||
|
mainMenuButton.triggerEventHandler('click', {});
|
||||||
|
fixture.detectChanges();
|
||||||
|
|
||||||
|
const columnSelectorMenu = fixture.debugElement.query(By.css('adf-datatable-column-selector'));
|
||||||
|
expect(columnSelectorMenu).toBeTruthy();
|
||||||
|
|
||||||
|
const columnsSelectorInstance = columnSelectorMenu.componentInstance as ColumnsSelectorComponent;
|
||||||
|
expect(columnsSelectorInstance.columns).toBe(component.columns, 'should pass columns as input');
|
||||||
|
|
||||||
|
const newColumns = (component.columns as DataColumn[]).map((column, index) => ({
|
||||||
|
...column,
|
||||||
|
isHidden: index !== 0 // only first one is shown
|
||||||
|
}));
|
||||||
|
|
||||||
|
columnSelectorMenu.triggerEventHandler('submitColumnsVisibility', newColumns);
|
||||||
|
fixture.detectChanges();
|
||||||
|
|
||||||
|
const displayedColumns = fixture.debugElement.queryAll(By.css('.adf-datatable-cell-header'));
|
||||||
|
expect(displayedColumns.length).toBe(2, 'only column with isHidden set to false and action column should be shown');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return the results if an application name is given', (done) => {
|
||||||
|
spyOn(taskListCloudService, 'fetchTaskList').and.returnValue(of(fakeGlobalTasks));
|
||||||
|
|
||||||
|
component.success.subscribe((res) => {
|
||||||
|
expect(res).toBeDefined();
|
||||||
|
expect(component.rows).toBeDefined();
|
||||||
|
expect(component.isListEmpty()).not.toBeTruthy();
|
||||||
|
expect(component.rows.length).toEqual(1);
|
||||||
|
|
||||||
|
const expectedTask = {
|
||||||
|
...fakeGlobalTask,
|
||||||
|
variables: fakeGlobalTask.processVariables
|
||||||
|
};
|
||||||
|
|
||||||
|
expect(component.rows[0]).toEqual(expectedTask);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
|
||||||
|
component.reload();
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should call endpoint when a column visibility gets changed', () => {
|
||||||
|
const fetchTaskListSpy = spyOn(taskListCloudService, 'fetchTaskList').and.returnValue(of(fakeGlobalTasks));
|
||||||
|
component.ngAfterContentInit();
|
||||||
|
spyOn(component, 'createDatatableSchema');
|
||||||
|
component.appName = 'fake-app-name';
|
||||||
|
component.reload();
|
||||||
|
fixture.detectChanges();
|
||||||
|
|
||||||
|
component.onColumnsVisibilityChange(component.columns);
|
||||||
|
|
||||||
|
fixture.detectChanges();
|
||||||
|
|
||||||
|
expect(fetchTaskListSpy).toHaveBeenCalledTimes(1);
|
||||||
|
});
|
||||||
|
describe('component changes', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
component.rows = fakeGlobalTasks.list.entries;
|
||||||
|
component.appName = 'mock-app-name';
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should reload the task list when input parameters changed', () => {
|
||||||
|
const fetchTaskListSpy = spyOn(taskListCloudService, 'fetchTaskList').and.returnValue(of(fakeGlobalTasks));
|
||||||
|
component.appName = 'mock-app-name';
|
||||||
|
component.priorities = ['1', '2'];
|
||||||
|
component.statuses = ['mock-status-1', 'mock-status-2'];
|
||||||
|
component.lastModifiedFrom = 'mock-lastmodified-date';
|
||||||
|
const prioritiesChange = new SimpleChange(undefined, ['1'], true);
|
||||||
|
const statusesChange = new SimpleChange(undefined, ['mock-status'], true);
|
||||||
|
const lastModifiedFromChange = new SimpleChange(undefined, 'mock-lastmodified-date', true);
|
||||||
|
component.ngOnChanges({
|
||||||
|
priorities: prioritiesChange,
|
||||||
|
statuses: statusesChange,
|
||||||
|
lastModifiedFrom: lastModifiedFromChange
|
||||||
|
});
|
||||||
|
fixture.detectChanges();
|
||||||
|
expect(component.isListEmpty()).toBeFalsy();
|
||||||
|
expect(fetchTaskListSpy).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should reload task list when sorting on a column changes', () => {
|
||||||
|
const fetchTaskListSpy = spyOn(taskListCloudService, 'fetchTaskList').and.returnValue(of(fakeGlobalTasks));
|
||||||
|
fixture.detectChanges();
|
||||||
|
component.onSortingChanged(
|
||||||
|
new CustomEvent('sorting-changed', {
|
||||||
|
detail: {
|
||||||
|
key: 'fakeName',
|
||||||
|
direction: 'asc'
|
||||||
|
},
|
||||||
|
bubbles: true
|
||||||
|
})
|
||||||
|
);
|
||||||
|
fixture.detectChanges();
|
||||||
|
expect(component.sorting).toEqual([
|
||||||
|
new TaskListCloudSortingModel({
|
||||||
|
orderBy: 'fakeName',
|
||||||
|
direction: 'ASC'
|
||||||
|
})
|
||||||
|
]);
|
||||||
|
expect(component.formattedSorting).toEqual(['fakeName', 'asc']);
|
||||||
|
expect(component.isListEmpty()).toBeFalsy();
|
||||||
|
expect(fetchTaskListSpy).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('API agnostic', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
configureTestingModule([]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should be able to inject TaskListCloudService instance', () => {
|
||||||
|
fixture.detectChanges();
|
||||||
|
|
||||||
|
expect(component.taskListCloudService instanceof TaskListCloudService).toBeTruthy();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should use the default schemaColumn as default', () => {
|
||||||
|
component.ngAfterContentInit();
|
||||||
|
expect(component.columns).toBeDefined();
|
||||||
|
expect(component.columns.length).toEqual(3);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should display empty content when process list is empty', async () => {
|
||||||
|
const emptyList = { list: { entries: [] } };
|
||||||
|
spyOn(taskListCloudService, 'getTaskByRequest').and.returnValue(of(emptyList));
|
||||||
|
fixture.detectChanges();
|
||||||
|
|
||||||
|
const appName = new SimpleChange(null, 'FAKE-APP-NAME', true);
|
||||||
|
component.ngOnChanges({ appName });
|
||||||
|
fixture.detectChanges();
|
||||||
|
|
||||||
|
expect(await loader.hasHarness(MatProgressSpinnerHarness)).toBe(false);
|
||||||
|
|
||||||
|
const emptyContent = fixture.debugElement.query(By.css('.adf-empty-content'));
|
||||||
|
expect(emptyContent.nativeElement).toBeDefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should use the custom schemaColumn from app.config.json', () => {
|
||||||
|
component.presetColumn = 'fakeCustomSchema';
|
||||||
|
component.ngAfterContentInit();
|
||||||
|
fixture.detectChanges();
|
||||||
|
expect(component.columns).toEqual(fakeCustomSchema);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should fetch custom schemaColumn when the input presetColumn is defined', () => {
|
||||||
|
component.presetColumn = 'fakeCustomSchema';
|
||||||
|
fixture.detectChanges();
|
||||||
|
expect(component.columns).toBeDefined();
|
||||||
|
expect(component.columns.length).toEqual(2);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return an empty task list when no input parameters are passed', () => {
|
||||||
|
component.ngAfterContentInit();
|
||||||
|
expect(component.rows).toBeDefined();
|
||||||
expect(component.isListEmpty()).toBeTruthy();
|
expect(component.isListEmpty()).toBeTruthy();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should reload the task list when input parameters changed', () => {
|
it('should emit row click event', (done) => {
|
||||||
const getTaskByRequestSpy = spyOn(taskListCloudService, 'getTaskByRequest').and.returnValue(of(fakeGlobalTasks));
|
const row = new ObjectDataRow({ id: '999' });
|
||||||
component.appName = 'mock-app-name';
|
const rowEvent = new DataRowEvent(row, null);
|
||||||
component.priority = 1;
|
component.rowClick.subscribe((taskId) => {
|
||||||
component.status = 'mock-status';
|
expect(taskId).toEqual('999');
|
||||||
component.lastModifiedFrom = 'mock-lastmodified-date';
|
expect(component.currentInstanceId).toEqual('999');
|
||||||
component.owner = 'mock-owner-name';
|
|
||||||
const priorityChange = new SimpleChange(undefined, 1, true);
|
|
||||||
const statusChange = new SimpleChange(undefined, 'mock-status', true);
|
|
||||||
const lastModifiedFromChange = new SimpleChange(undefined, 'mock-lastmodified-date', true);
|
|
||||||
const ownerChange = new SimpleChange(undefined, 'mock-owner-name', true);
|
|
||||||
component.ngOnChanges({
|
|
||||||
priority: priorityChange,
|
|
||||||
status: statusChange,
|
|
||||||
lastModifiedFrom: lastModifiedFromChange,
|
|
||||||
owner: ownerChange
|
|
||||||
});
|
|
||||||
fixture.detectChanges();
|
|
||||||
expect(component.isListEmpty()).toBeFalsy();
|
|
||||||
expect(getTaskByRequestSpy).toHaveBeenCalled();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should set formattedSorting if sorting input changes', () => {
|
|
||||||
spyOn(taskListCloudService, 'getTaskByRequest').and.returnValue(of(fakeGlobalTasks));
|
|
||||||
spyOn(component, 'formatSorting').and.callThrough();
|
|
||||||
|
|
||||||
component.appName = 'mock-app-name';
|
|
||||||
const mockSort = [
|
|
||||||
new TaskListCloudSortingModel({
|
|
||||||
orderBy: 'startDate',
|
|
||||||
direction: 'DESC'
|
|
||||||
})
|
|
||||||
];
|
|
||||||
const sortChange = new SimpleChange(undefined, mockSort, true);
|
|
||||||
component.ngOnChanges({
|
|
||||||
sorting: sortChange
|
|
||||||
});
|
|
||||||
fixture.detectChanges();
|
|
||||||
expect(component.formatSorting).toHaveBeenCalledWith(mockSort);
|
|
||||||
expect(component.formattedSorting).toEqual(['startDate', 'desc']);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should reload task list when sorting on a column changes', () => {
|
|
||||||
const getTaskByRequestSpy = spyOn(taskListCloudService, 'getTaskByRequest').and.returnValue(of(fakeGlobalTasks));
|
|
||||||
component.onSortingChanged(
|
|
||||||
new CustomEvent('sorting-changed', {
|
|
||||||
detail: {
|
|
||||||
key: 'fakeName',
|
|
||||||
direction: 'asc'
|
|
||||||
},
|
|
||||||
bubbles: true
|
|
||||||
})
|
|
||||||
);
|
|
||||||
fixture.detectChanges();
|
|
||||||
expect(component.sorting).toEqual([
|
|
||||||
new TaskListCloudSortingModel({
|
|
||||||
orderBy: 'fakeName',
|
|
||||||
direction: 'ASC'
|
|
||||||
})
|
|
||||||
]);
|
|
||||||
expect(component.formattedSorting).toEqual(['fakeName', 'asc']);
|
|
||||||
expect(component.isListEmpty()).toBeFalsy();
|
|
||||||
expect(getTaskByRequestSpy).toHaveBeenCalled();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should reset pagination when resetPaginationValues is called', (done) => {
|
|
||||||
spyOn(taskListCloudService, 'getTaskByRequest').and.returnValue(of(fakeGlobalTasks));
|
|
||||||
|
|
||||||
const size = component.size;
|
|
||||||
const skipCount = component.skipCount;
|
|
||||||
component.pagination.pipe(skip(3)).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();
|
done();
|
||||||
});
|
});
|
||||||
|
component.onRowClick(rowEvent);
|
||||||
const pagination = {
|
|
||||||
maxItems: 250,
|
|
||||||
skipCount: 200
|
|
||||||
};
|
|
||||||
component.updatePagination(pagination);
|
|
||||||
|
|
||||||
component.resetPagination();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should set pagination and reload when updatePagination is called', (done) => {
|
it('should re-create columns when a column width gets changed', () => {
|
||||||
spyOn(taskListCloudService, 'getTaskByRequest').and.returnValue(of(fakeGlobalTasks));
|
component.reload();
|
||||||
spyOn(component, 'reload').and.stub();
|
fixture.detectChanges();
|
||||||
|
|
||||||
const pagination = {
|
const newColumns = [...component.columns];
|
||||||
maxItems: 250,
|
newColumns[0].width = 120;
|
||||||
skipCount: 200
|
component.onColumnsWidthChanged(newColumns);
|
||||||
};
|
|
||||||
component.pagination.pipe(skip(1)).subscribe((updatedPagination) => {
|
expect(component.columns[0].width).toBe(120);
|
||||||
fixture.detectChanges();
|
});
|
||||||
expect(component.size).toBe(pagination.maxItems);
|
|
||||||
expect(component.skipCount).toBe(pagination.skipCount);
|
it('should update columns widths when a column width gets changed', () => {
|
||||||
expect(updatedPagination.maxItems).toEqual(pagination.maxItems);
|
component.appName = 'fake-app-name';
|
||||||
expect(updatedPagination.skipCount).toEqual(pagination.skipCount);
|
component.reload();
|
||||||
done();
|
fixture.detectChanges();
|
||||||
|
|
||||||
|
const newColumns = [...component.columns];
|
||||||
|
newColumns[0].width = 120;
|
||||||
|
component.onColumnsWidthChanged(newColumns);
|
||||||
|
|
||||||
|
expect(component.columns[0].width).toBe(120);
|
||||||
|
expect(preferencesService.updatePreference).toHaveBeenCalledWith('fake-app-name', 'tasks-list-cloud-columns-widths', {
|
||||||
|
name: 120
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should update columns widths while preserving previously saved widths when a column width gets changed', () => {
|
||||||
|
component.appName = 'fake-app-name';
|
||||||
|
component.reload();
|
||||||
|
fixture.detectChanges();
|
||||||
|
|
||||||
|
const newColumns = [...component.columns];
|
||||||
|
newColumns[0].width = 120;
|
||||||
|
component.onColumnsWidthChanged(newColumns);
|
||||||
|
|
||||||
|
expect(component.columns[0].width).toBe(120);
|
||||||
|
expect(preferencesService.updatePreference).toHaveBeenCalledWith('fake-app-name', 'tasks-list-cloud-columns-widths', {
|
||||||
|
name: 120
|
||||||
});
|
});
|
||||||
|
|
||||||
component.updatePagination(pagination);
|
newColumns[1].width = 150;
|
||||||
|
component.onColumnsWidthChanged(newColumns);
|
||||||
|
|
||||||
|
expect(component.columns[0].width).toBe(120);
|
||||||
|
expect(component.columns[1].width).toBe(150);
|
||||||
|
expect(preferencesService.updatePreference).toHaveBeenCalledWith('fake-app-name', 'tasks-list-cloud-columns-widths', {
|
||||||
|
name: 120,
|
||||||
|
created: 150
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should re-create columns when a column order gets changed', () => {
|
||||||
|
component.reload();
|
||||||
|
fixture.detectChanges();
|
||||||
|
|
||||||
|
expect(component.columns[0].title).toBe('ADF_CLOUD_TASK_LIST.PROPERTIES.NAME');
|
||||||
|
expect(component.columns[1].title).toBe('ADF_CLOUD_TASK_LIST.PROPERTIES.CREATED');
|
||||||
|
expect(component.columns[2].title).toBe('ADF_CLOUD_TASK_LIST.PROPERTIES.ASSIGNEE');
|
||||||
|
|
||||||
|
component.onColumnOrderChanged([component.columns[1], ...component.columns]);
|
||||||
|
fixture.detectChanges();
|
||||||
|
|
||||||
|
expect(component.columns[0].title).toBe('ADF_CLOUD_TASK_LIST.PROPERTIES.CREATED');
|
||||||
|
expect(component.columns[1].title).toBe('ADF_CLOUD_TASK_LIST.PROPERTIES.NAME');
|
||||||
|
expect(component.columns[2].title).toBe('ADF_CLOUD_TASK_LIST.PROPERTIES.ASSIGNEE');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create datatable schema when a column visibility gets changed', () => {
|
||||||
|
component.ngAfterContentInit();
|
||||||
|
spyOn(component, 'createDatatableSchema');
|
||||||
|
|
||||||
|
component.onColumnsVisibilityChange(component.columns);
|
||||||
|
|
||||||
|
fixture.detectChanges();
|
||||||
|
|
||||||
|
expect(component.createDatatableSchema).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('component changes', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
component.rows = fakeGlobalTasks.list.entries;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should NOT reload the task list when no parameters changed', () => {
|
||||||
|
spyOn(taskListCloudService, 'getTaskByRequest');
|
||||||
|
component.rows = null;
|
||||||
|
fixture.detectChanges();
|
||||||
|
expect(component.isListEmpty()).toBeTruthy();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should set formattedSorting if sorting input changes', () => {
|
||||||
|
spyOn(taskListCloudService, 'getTaskByRequest').and.returnValue(of(fakeGlobalTasks));
|
||||||
|
spyOn(component, 'formatSorting').and.callThrough();
|
||||||
|
|
||||||
|
component.appName = 'mock-app-name';
|
||||||
|
const mockSort = [
|
||||||
|
new TaskListCloudSortingModel({
|
||||||
|
orderBy: 'startDate',
|
||||||
|
direction: 'DESC'
|
||||||
|
})
|
||||||
|
];
|
||||||
|
const sortChange = new SimpleChange(undefined, mockSort, true);
|
||||||
|
component.ngOnChanges({
|
||||||
|
sorting: sortChange
|
||||||
|
});
|
||||||
|
fixture.detectChanges();
|
||||||
|
expect(component.formatSorting).toHaveBeenCalledWith(mockSort);
|
||||||
|
expect(component.formattedSorting).toEqual(['startDate', 'desc']);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should reset pagination when resetPaginationValues is called', (done) => {
|
||||||
|
spyOn(taskListCloudService, 'getTaskByRequest').and.returnValue(of(fakeGlobalTasks));
|
||||||
|
|
||||||
|
const size = component.size;
|
||||||
|
const skipCount = component.skipCount;
|
||||||
|
component.pagination.pipe(skip(3)).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,
|
||||||
|
skipCount: 200
|
||||||
|
};
|
||||||
|
component.updatePagination(pagination);
|
||||||
|
|
||||||
|
component.resetPagination();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should set pagination and reload when updatePagination is called', (done) => {
|
||||||
|
spyOn(taskListCloudService, 'getTaskByRequest').and.returnValue(of(fakeGlobalTasks));
|
||||||
|
spyOn(component, 'reload').and.stub();
|
||||||
|
|
||||||
|
const pagination = {
|
||||||
|
maxItems: 250,
|
||||||
|
skipCount: 200
|
||||||
|
};
|
||||||
|
component.pagination.pipe(skip(1)).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);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -505,6 +666,7 @@ describe('TaskListCloudComponent: Injecting custom colums for tasklist - CustomT
|
|||||||
});
|
});
|
||||||
taskListCloudService = TestBed.inject(TASK_LIST_CLOUD_TOKEN);
|
taskListCloudService = TestBed.inject(TASK_LIST_CLOUD_TOKEN);
|
||||||
spyOn(taskListCloudService, 'getTaskByRequest').and.returnValue(of(fakeGlobalTasks));
|
spyOn(taskListCloudService, 'getTaskByRequest').and.returnValue(of(fakeGlobalTasks));
|
||||||
|
spyOn(taskListCloudService, 'fetchTaskList').and.returnValue(of(fakeGlobalTasks));
|
||||||
fixtureCustom = TestBed.createComponent(CustomTaskListComponent);
|
fixtureCustom = TestBed.createComponent(CustomTaskListComponent);
|
||||||
copyFixture = TestBed.createComponent(CustomCopyContentTaskListComponent);
|
copyFixture = TestBed.createComponent(CustomCopyContentTaskListComponent);
|
||||||
fixtureCustom.detectChanges();
|
fixtureCustom.detectChanges();
|
||||||
@ -559,6 +721,7 @@ describe('TaskListCloudComponent: Creating an empty custom template - EmptyTempl
|
|||||||
taskListCloudService = TestBed.inject(TASK_LIST_CLOUD_TOKEN);
|
taskListCloudService = TestBed.inject(TASK_LIST_CLOUD_TOKEN);
|
||||||
const emptyList = { list: { entries: [] } };
|
const emptyList = { list: { entries: [] } };
|
||||||
spyOn(taskListCloudService, 'getTaskByRequest').and.returnValue(of(emptyList));
|
spyOn(taskListCloudService, 'getTaskByRequest').and.returnValue(of(emptyList));
|
||||||
|
spyOn(taskListCloudService, 'fetchTaskList').and.returnValue(of(fakeGlobalTasks));
|
||||||
|
|
||||||
fixtureEmpty = TestBed.createComponent(EmptyTemplateComponent);
|
fixtureEmpty = TestBed.createComponent(EmptyTemplateComponent);
|
||||||
fixtureEmpty.detectChanges();
|
fixtureEmpty.detectChanges();
|
||||||
@ -578,7 +741,8 @@ describe('TaskListCloudComponent: Creating an empty custom template - EmptyTempl
|
|||||||
});
|
});
|
||||||
|
|
||||||
describe('TaskListCloudComponent: Copy cell content directive from app.config specifications', () => {
|
describe('TaskListCloudComponent: Copy cell content directive from app.config specifications', () => {
|
||||||
let taskSpy: jasmine.Spy;
|
let getTaskByRequestSpy: jasmine.Spy;
|
||||||
|
let fetchTaskListSpy: jasmine.Spy;
|
||||||
let appConfig: AppConfigService;
|
let appConfig: AppConfigService;
|
||||||
let taskListCloudService: TaskListCloudServiceInterface;
|
let taskListCloudService: TaskListCloudServiceInterface;
|
||||||
let component: TaskListCloudComponent;
|
let component: TaskListCloudComponent;
|
||||||
@ -619,7 +783,8 @@ describe('TaskListCloudComponent: Copy cell content directive from app.config sp
|
|||||||
});
|
});
|
||||||
fixture = TestBed.createComponent(TaskListCloudComponent);
|
fixture = TestBed.createComponent(TaskListCloudComponent);
|
||||||
component = fixture.componentInstance;
|
component = fixture.componentInstance;
|
||||||
taskSpy = spyOn(taskListCloudService, 'getTaskByRequest').and.returnValue(of(fakeGlobalTasks));
|
getTaskByRequestSpy = spyOn(taskListCloudService, 'getTaskByRequest').and.returnValue(of(fakeGlobalTasks));
|
||||||
|
fetchTaskListSpy = spyOn(taskListCloudService, 'fetchTaskList').and.returnValue(of(fakeGlobalTasks));
|
||||||
component.isColumnSchemaCreated$ = of(true);
|
component.isColumnSchemaCreated$ = of(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -628,7 +793,6 @@ describe('TaskListCloudComponent: Copy cell content directive from app.config sp
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should show tooltip if config copyContent flag is true', () => {
|
it('should show tooltip if config copyContent flag is true', () => {
|
||||||
taskSpy.and.returnValue(of(fakeGlobalTasks));
|
|
||||||
component.presetColumn = 'fakeCustomSchema';
|
component.presetColumn = 'fakeCustomSchema';
|
||||||
|
|
||||||
component.reload();
|
component.reload();
|
||||||
@ -643,19 +807,18 @@ describe('TaskListCloudComponent: Copy cell content directive from app.config sp
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should replace priority values', () => {
|
it('should replace priority values', () => {
|
||||||
taskSpy.and.returnValue(of(fakeGlobalTasks));
|
|
||||||
component.presetColumn = 'fakeCustomSchema';
|
component.presetColumn = 'fakeCustomSchema';
|
||||||
|
|
||||||
component.reload();
|
component.reload();
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
|
|
||||||
const cell = fixture.debugElement.query(By.css('[data-automation-id="text_ADF_CLOUD_TASK_LIST.PROPERTIES.PRIORITY_VALUES.NONE"]'));
|
const cell = fixture.debugElement.query(By.css('[data-automation-id="text_ADF_CLOUD_TASK_LIST.PROPERTIES.PRIORITY_VALUES.NONE"]'));
|
||||||
expect(cell.nativeElement.textContent).toEqual('ADF_CLOUD_TASK_LIST.PROPERTIES.PRIORITY_VALUES.NONE');
|
expect(cell.nativeElement.textContent).toEqual('ADF_CLOUD_TASK_LIST.PROPERTIES.PRIORITY_VALUES.NONE');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('replacePriorityValues should return undefined when no rows defined', () => {
|
it('replacePriorityValues should return undefined when no rows defined', () => {
|
||||||
const emptyList = { list: { entries: [] } };
|
const emptyList = { list: { entries: [] } };
|
||||||
taskSpy.and.returnValue(of(emptyList));
|
getTaskByRequestSpy.and.returnValue(of(emptyList));
|
||||||
|
fetchTaskListSpy.and.returnValue(of(emptyList));
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
|
|
||||||
const appName = new SimpleChange(null, 'FAKE-APP-NAME', true);
|
const appName = new SimpleChange(null, 'FAKE-APP-NAME', true);
|
||||||
@ -681,7 +844,6 @@ describe('TaskListCloudComponent: Copy cell content directive from app.config sp
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('replacePriorityValues should return replaced value when rows are defined', () => {
|
it('replacePriorityValues should return replaced value when rows are defined', () => {
|
||||||
taskSpy.and.returnValue(of(fakeGlobalTasks));
|
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
|
|
||||||
const appName = new SimpleChange(null, 'FAKE-APP-NAME', true);
|
const appName = new SimpleChange(null, 'FAKE-APP-NAME', true);
|
||||||
|
@ -15,16 +15,16 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { Component, ViewEncapsulation, Input, Inject, OnDestroy } from '@angular/core';
|
import { Component, ViewEncapsulation, Input, Inject, OnDestroy, Optional } from '@angular/core';
|
||||||
import { AppConfigService, UserPreferencesService } from '@alfresco/adf-core';
|
import { AppConfigService, UserPreferencesService } from '@alfresco/adf-core';
|
||||||
import { TaskQueryCloudRequestModel } from '../../../models/filter-cloud-model';
|
import { TaskListRequestModel, TaskQueryCloudRequestModel } from '../../../models/filter-cloud-model';
|
||||||
import { BaseTaskListCloudComponent } from './base-task-list-cloud.component';
|
import { BaseTaskListCloudComponent } from './base-task-list-cloud.component';
|
||||||
import { TaskCloudService } from '../../services/task-cloud.service';
|
import { TaskCloudService } from '../../services/task-cloud.service';
|
||||||
import { TASK_LIST_CLOUD_TOKEN, TASK_LIST_PREFERENCES_SERVICE_TOKEN } from '../../../services/cloud-token.service';
|
import { TASK_LIST_CLOUD_TOKEN, TASK_LIST_PREFERENCES_SERVICE_TOKEN, TASK_SEARCH_API_METHOD_TOKEN } from '../../../services/cloud-token.service';
|
||||||
import { PreferenceCloudServiceInterface } from '../../../services/preference-cloud.interface';
|
import { PreferenceCloudServiceInterface } from '../../../services/preference-cloud.interface';
|
||||||
import { TaskListCloudServiceInterface } from '../../../services/task-list-cloud.service.interface';
|
import { TaskListCloudServiceInterface } from '../../../services/task-list-cloud.service.interface';
|
||||||
import { Subject, of, BehaviorSubject, combineLatest } from 'rxjs';
|
import { Subject, BehaviorSubject, combineLatest } from 'rxjs';
|
||||||
import { map, switchMap, takeUntil, tap } from 'rxjs/operators';
|
import { filter, map, switchMap, take, takeUntil } from 'rxjs/operators';
|
||||||
import { VariableMapperService } from '../../../services/variable-mapper.sevice';
|
import { VariableMapperService } from '../../../services/variable-mapper.sevice';
|
||||||
import { ProcessListDataColumnCustomData } from '../../../models/data-column-custom-data';
|
import { ProcessListDataColumnCustomData } from '../../../models/data-column-custom-data';
|
||||||
import { TaskCloudModel } from '../../../models/task-cloud.model';
|
import { TaskCloudModel } from '../../../models/task-cloud.model';
|
||||||
@ -145,6 +145,48 @@ export class TaskListCloudComponent extends BaseTaskListCloudComponent<ProcessLi
|
|||||||
@Input()
|
@Input()
|
||||||
candidateGroupId: string = '';
|
candidateGroupId: string = '';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Filter the tasks. Display only tasks with names matching any of the supplied strings.
|
||||||
|
* This input will be used only if TASK_SEARCH_API_METHOD_TOKEN is provided with 'POST' value.
|
||||||
|
*/
|
||||||
|
@Input()
|
||||||
|
names: string[] = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Filter the tasks. Display only tasks with assignees whose usernames are present in the array.
|
||||||
|
* This input will be used only if TASK_SEARCH_API_METHOD_TOKEN is provided with 'POST' value.
|
||||||
|
*/
|
||||||
|
@Input()
|
||||||
|
assignees: string[] = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Filter the tasks. Display only tasks with provided statuses.
|
||||||
|
* This input will be used only if TASK_SEARCH_API_METHOD_TOKEN is provided with 'POST' value.
|
||||||
|
*/
|
||||||
|
@Input()
|
||||||
|
statuses: string[] = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Filter the tasks. Display only tasks under provided processes.
|
||||||
|
* This input will be used only if TASK_SEARCH_API_METHOD_TOKEN is provided with 'POST' value.
|
||||||
|
*/
|
||||||
|
@Input()
|
||||||
|
processDefinitionNames: string[] = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Filter the tasks. Display only tasks with provided priorities.
|
||||||
|
* This input will be used only if TASK_SEARCH_API_METHOD_TOKEN is provided with 'POST' value.
|
||||||
|
*/
|
||||||
|
@Input()
|
||||||
|
priorities: string[] = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Filter the tasks. Display only tasks completed by users whose usernames are present in the array.
|
||||||
|
* This input will be used only if TASK_SEARCH_API_METHOD_TOKEN is provided with 'POST' value.
|
||||||
|
*/
|
||||||
|
@Input()
|
||||||
|
completedByUsers: string[] = [];
|
||||||
|
|
||||||
private onDestroyTaskList$ = new Subject<boolean>();
|
private onDestroyTaskList$ = new Subject<boolean>();
|
||||||
|
|
||||||
rows: TaskInstanceCloudListViewModel[] = [];
|
rows: TaskInstanceCloudListViewModel[] = [];
|
||||||
@ -156,6 +198,7 @@ export class TaskListCloudComponent extends BaseTaskListCloudComponent<ProcessLi
|
|||||||
);
|
);
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
|
@Inject(TASK_SEARCH_API_METHOD_TOKEN) @Optional() private searchMethod: 'GET' | 'POST',
|
||||||
@Inject(TASK_LIST_CLOUD_TOKEN) public taskListCloudService: TaskListCloudServiceInterface,
|
@Inject(TASK_LIST_CLOUD_TOKEN) public taskListCloudService: TaskListCloudServiceInterface,
|
||||||
appConfigService: AppConfigService,
|
appConfigService: AppConfigService,
|
||||||
taskCloudService: TaskCloudService,
|
taskCloudService: TaskCloudService,
|
||||||
@ -176,13 +219,22 @@ export class TaskListCloudComponent extends BaseTaskListCloudComponent<ProcessLi
|
|||||||
|
|
||||||
this.isColumnSchemaCreated$
|
this.isColumnSchemaCreated$
|
||||||
.pipe(
|
.pipe(
|
||||||
switchMap(() => of(this.createRequestNode())),
|
filter((isColumnSchemaCreated) => !!isColumnSchemaCreated),
|
||||||
tap((requestNode) => (this.requestNode = requestNode)),
|
take(1),
|
||||||
switchMap((requestNode) => this.taskListCloudService.getTaskByRequest(requestNode)),
|
switchMap(() => {
|
||||||
|
if (this.searchMethod === 'POST') {
|
||||||
|
const requestNode = this.createTaskListRequestNode();
|
||||||
|
return this.taskListCloudService.fetchTaskList(requestNode).pipe(take(1));
|
||||||
|
} else {
|
||||||
|
const requestNode = this.createRequestNode();
|
||||||
|
this.requestNode = requestNode;
|
||||||
|
return this.taskListCloudService.getTaskByRequest(requestNode);
|
||||||
|
}
|
||||||
|
}),
|
||||||
takeUntil(this.onDestroyTaskList$)
|
takeUntil(this.onDestroyTaskList$)
|
||||||
)
|
)
|
||||||
.subscribe(
|
.subscribe({
|
||||||
(tasks: { list: PaginatedEntries<TaskCloudModel> }) => {
|
next: (tasks: { list: PaginatedEntries<TaskCloudModel> }) => {
|
||||||
const tasksWithVariables = tasks.list.entries.map((task) => ({
|
const tasksWithVariables = tasks.list.entries.map((task) => ({
|
||||||
...task,
|
...task,
|
||||||
variables: task.processVariables
|
variables: task.processVariables
|
||||||
@ -196,14 +248,43 @@ export class TaskListCloudComponent extends BaseTaskListCloudComponent<ProcessLi
|
|||||||
this.isReloadingSubject$.next(false);
|
this.isReloadingSubject$.next(false);
|
||||||
this.pagination.next(tasks.list.pagination);
|
this.pagination.next(tasks.list.pagination);
|
||||||
},
|
},
|
||||||
(error) => {
|
error: (error) => {
|
||||||
this.error.emit(error);
|
this.error.emit(error);
|
||||||
this.isReloadingSubject$.next(false);
|
this.isReloadingSubject$.next(false);
|
||||||
}
|
}
|
||||||
);
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
createRequestNode(): TaskQueryCloudRequestModel {
|
private createTaskListRequestNode(): TaskListRequestModel {
|
||||||
|
const requestNode: TaskListRequestModel = {
|
||||||
|
appName: this.appName,
|
||||||
|
pagination: {
|
||||||
|
maxItems: this.size,
|
||||||
|
skipCount: this.skipCount
|
||||||
|
},
|
||||||
|
sorting: this.sorting,
|
||||||
|
onlyStandalone: this.standalone,
|
||||||
|
name: this.names,
|
||||||
|
processDefinitionName: this.processDefinitionNames,
|
||||||
|
priority: this.priorities,
|
||||||
|
status: this.statuses,
|
||||||
|
completedBy: this.completedByUsers,
|
||||||
|
assignee: this.assignees,
|
||||||
|
createdFrom: this.createdFrom,
|
||||||
|
createdTo: this.createdTo,
|
||||||
|
lastModifiedFrom: this.lastModifiedFrom,
|
||||||
|
lastModifiedTo: this.lastModifiedTo,
|
||||||
|
dueDateFrom: this.dueDateFrom,
|
||||||
|
dueDateTo: this.dueDateTo,
|
||||||
|
completedFrom: this.completedFrom,
|
||||||
|
completedTo: this.completedTo,
|
||||||
|
variableKeys: this.getRequestNodeVariables()
|
||||||
|
};
|
||||||
|
|
||||||
|
return new TaskListRequestModel(requestNode);
|
||||||
|
}
|
||||||
|
|
||||||
|
private createRequestNode(): TaskQueryCloudRequestModel {
|
||||||
const requestNode = {
|
const requestNode = {
|
||||||
appName: this.appName,
|
appName: this.appName,
|
||||||
assignee: this.assignee,
|
assignee: this.assignee,
|
||||||
|
@ -17,9 +17,10 @@
|
|||||||
|
|
||||||
import { TestBed } from '@angular/core/testing';
|
import { TestBed } from '@angular/core/testing';
|
||||||
import { TaskListCloudService } from './task-list-cloud.service';
|
import { TaskListCloudService } from './task-list-cloud.service';
|
||||||
import { TaskQueryCloudRequestModel } from '../../../models/filter-cloud-model';
|
import { TaskListRequestModel, TaskQueryCloudRequestModel } from '../../../models/filter-cloud-model';
|
||||||
import { ProcessServiceCloudTestingModule } from '../../../testing/process-service-cloud.testing.module';
|
import { ProcessServiceCloudTestingModule } from '../../../testing/process-service-cloud.testing.module';
|
||||||
import { AdfHttpClient } from '@alfresco/adf-core/api';
|
import { AdfHttpClient } from '@alfresco/adf-core/api';
|
||||||
|
import { catchError, firstValueFrom, of } from 'rxjs';
|
||||||
|
|
||||||
describe('TaskListCloudService', () => {
|
describe('TaskListCloudService', () => {
|
||||||
let service: TaskListCloudService;
|
let service: TaskListCloudService;
|
||||||
@ -39,59 +40,126 @@ describe('TaskListCloudService', () => {
|
|||||||
requestSpy = spyOn(adfHttpClient, 'request');
|
requestSpy = spyOn(adfHttpClient, 'request');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should append to the call all the parameters', (done) => {
|
describe('getTaskByRequest', () => {
|
||||||
const taskRequest = { appName: 'fakeName', skipCount: 0, maxItems: 20, service: 'fake-service' } as TaskQueryCloudRequestModel;
|
it('should append to the call all the parameters', async () => {
|
||||||
requestSpy.and.callFake(returnCallQueryParameters);
|
const taskRequest = {
|
||||||
service.getTaskByRequest(taskRequest).subscribe((res) => {
|
appName: 'fakeName',
|
||||||
|
skipCount: 0,
|
||||||
|
maxItems: 20,
|
||||||
|
service: 'fake-service'
|
||||||
|
} as TaskQueryCloudRequestModel;
|
||||||
|
requestSpy.and.callFake(returnCallQueryParameters);
|
||||||
|
|
||||||
|
const res = await firstValueFrom(service.getTaskByRequest(taskRequest));
|
||||||
|
|
||||||
expect(res).toBeDefined();
|
expect(res).toBeDefined();
|
||||||
expect(res).not.toBeNull();
|
expect(res).not.toBeNull();
|
||||||
expect(res.skipCount).toBe(0);
|
expect(res.skipCount).toBe(0);
|
||||||
expect(res.maxItems).toBe(20);
|
expect(res.maxItems).toBe(20);
|
||||||
expect(res.service).toBe('fake-service');
|
expect(res.service).toBe('fake-service');
|
||||||
done();
|
|
||||||
});
|
});
|
||||||
});
|
|
||||||
|
|
||||||
it('should concat the app name to the request url', (done) => {
|
it('should concat the app name to the request url', async () => {
|
||||||
const taskRequest = { appName: 'fakeName', skipCount: 0, maxItems: 20, service: 'fake-service' } as TaskQueryCloudRequestModel;
|
const taskRequest = {
|
||||||
requestSpy.and.callFake(returnCallUrl);
|
appName: 'fakeName',
|
||||||
service.getTaskByRequest(taskRequest).subscribe((requestUrl) => {
|
skipCount: 0,
|
||||||
|
maxItems: 20,
|
||||||
|
service: 'fake-service'
|
||||||
|
} as TaskQueryCloudRequestModel;
|
||||||
|
requestSpy.and.callFake(returnCallUrl);
|
||||||
|
|
||||||
|
const requestUrl = await firstValueFrom(service.getTaskByRequest(taskRequest));
|
||||||
|
|
||||||
expect(requestUrl).toBeDefined();
|
expect(requestUrl).toBeDefined();
|
||||||
expect(requestUrl).not.toBeNull();
|
expect(requestUrl).not.toBeNull();
|
||||||
expect(requestUrl).toContain('/fakeName/query/v1/tasks');
|
expect(requestUrl).toContain('/fakeName/query/v1/tasks');
|
||||||
done();
|
|
||||||
});
|
});
|
||||||
});
|
|
||||||
|
|
||||||
it('should concat the sorting to append as parameters', (done) => {
|
it('should concat the sorting to append as parameters', async () => {
|
||||||
const taskRequest = {
|
const taskRequest = {
|
||||||
appName: 'fakeName',
|
appName: 'fakeName',
|
||||||
skipCount: 0,
|
skipCount: 0,
|
||||||
maxItems: 20,
|
maxItems: 20,
|
||||||
service: 'fake-service',
|
service: 'fake-service',
|
||||||
sorting: [
|
sorting: [
|
||||||
{ orderBy: 'NAME', direction: 'DESC' },
|
{ orderBy: 'NAME', direction: 'DESC' },
|
||||||
{ orderBy: 'TITLE', direction: 'ASC' }
|
{ orderBy: 'TITLE', direction: 'ASC' }
|
||||||
]
|
]
|
||||||
} as TaskQueryCloudRequestModel;
|
} as TaskQueryCloudRequestModel;
|
||||||
requestSpy.and.callFake(returnCallQueryParameters);
|
requestSpy.and.callFake(returnCallQueryParameters);
|
||||||
service.getTaskByRequest(taskRequest).subscribe((res) => {
|
|
||||||
|
const res = await firstValueFrom(service.getTaskByRequest(taskRequest));
|
||||||
|
|
||||||
expect(res).toBeDefined();
|
expect(res).toBeDefined();
|
||||||
expect(res).not.toBeNull();
|
expect(res).not.toBeNull();
|
||||||
expect(res.sort).toBe('NAME,DESC&TITLE,ASC');
|
expect(res.sort).toBe('NAME,DESC&TITLE,ASC');
|
||||||
done();
|
});
|
||||||
|
|
||||||
|
it('should return an error when app name is not specified', async () => {
|
||||||
|
const taskRequest = { appName: null } as TaskQueryCloudRequestModel;
|
||||||
|
requestSpy.and.callFake(returnCallUrl);
|
||||||
|
|
||||||
|
const res = await firstValueFrom(service.getTaskByRequest(taskRequest).pipe(catchError((error) => of(error))));
|
||||||
|
|
||||||
|
expect(res).toBe('Appname not configured');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should return an error when app name is not specified', (done) => {
|
describe('fetchTaskList', () => {
|
||||||
const taskRequest = { appName: null } as TaskQueryCloudRequestModel;
|
it('should append to the call all the parameters', async () => {
|
||||||
requestSpy.and.callFake(returnCallUrl);
|
const taskRequest = {
|
||||||
service.getTaskByRequest(taskRequest).subscribe(
|
appName: 'fakeName',
|
||||||
() => {},
|
pagination: { skipCount: 0, maxItems: 20 }
|
||||||
(error) => {
|
} as TaskListRequestModel;
|
||||||
expect(error).toBe('Appname not configured');
|
requestSpy.and.callFake(returnCallQueryParameters);
|
||||||
done();
|
|
||||||
}
|
const res = await firstValueFrom(service.fetchTaskList(taskRequest));
|
||||||
);
|
|
||||||
|
expect(res).toBeDefined();
|
||||||
|
expect(res).not.toBeNull();
|
||||||
|
expect(res.skipCount).toBe(0);
|
||||||
|
expect(res.maxItems).toBe(20);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should concat the app name to the request url', async () => {
|
||||||
|
const taskRequest = {
|
||||||
|
appName: 'fakeName',
|
||||||
|
pagination: { skipCount: 0, maxItems: 20 }
|
||||||
|
} as TaskListRequestModel;
|
||||||
|
requestSpy.and.callFake(returnCallUrl);
|
||||||
|
|
||||||
|
const res = await firstValueFrom(service.fetchTaskList(taskRequest));
|
||||||
|
|
||||||
|
expect(res).toBeDefined();
|
||||||
|
expect(res).not.toBeNull();
|
||||||
|
expect(res).toContain('/fakeName/query/v1/tasks/search');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should concat the sorting to append as parameters', async () => {
|
||||||
|
const taskRequest = {
|
||||||
|
appName: 'fakeName',
|
||||||
|
pagination: { skipCount: 0, maxItems: 20 },
|
||||||
|
sorting: [
|
||||||
|
{ orderBy: 'NAME', direction: 'DESC' },
|
||||||
|
{ orderBy: 'TITLE', direction: 'ASC' }
|
||||||
|
]
|
||||||
|
} as TaskListRequestModel;
|
||||||
|
requestSpy.and.callFake(returnCallQueryParameters);
|
||||||
|
|
||||||
|
const res = await firstValueFrom(service.fetchTaskList(taskRequest));
|
||||||
|
|
||||||
|
expect(res).toBeDefined();
|
||||||
|
expect(res).not.toBeNull();
|
||||||
|
expect(res.sort).toBe('NAME,DESC&TITLE,ASC');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return an error when app name is not specified', async () => {
|
||||||
|
const taskRequest = { appName: null } as TaskListRequestModel;
|
||||||
|
requestSpy.and.callFake(returnCallUrl);
|
||||||
|
|
||||||
|
const res = await firstValueFrom(service.fetchTaskList(taskRequest).pipe(catchError((error) => of(error.message))));
|
||||||
|
|
||||||
|
expect(res).toBe('Appname not configured');
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -16,7 +16,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { Injectable } from '@angular/core';
|
import { Injectable } from '@angular/core';
|
||||||
import { TaskQueryCloudRequestModel } from '../../../models/filter-cloud-model';
|
import { TaskQueryCloudRequestModel, TaskListRequestModel } from '../../../models/filter-cloud-model';
|
||||||
import { Observable, throwError } from 'rxjs';
|
import { Observable, throwError } from 'rxjs';
|
||||||
import { TaskListCloudSortingModel } from '../../../models/task-list-sorting.model';
|
import { TaskListCloudSortingModel } from '../../../models/task-list-sorting.model';
|
||||||
import { BaseCloudService } from '../../../services/base-cloud.service';
|
import { BaseCloudService } from '../../../services/base-cloud.service';
|
||||||
@ -29,6 +29,7 @@ export class TaskListCloudService extends BaseCloudService implements TaskListCl
|
|||||||
/**
|
/**
|
||||||
* Finds a task using an object with optional query properties.
|
* Finds a task using an object with optional query properties.
|
||||||
*
|
*
|
||||||
|
* @deprecated From Activiti 8.7.0 forward, use TaskListCloudService.fetchTaskList instead.
|
||||||
* @param requestNode Query object
|
* @param requestNode Query object
|
||||||
* @param queryUrl Query url
|
* @param queryUrl Query url
|
||||||
* @returns Task information
|
* @returns Task information
|
||||||
@ -56,6 +57,78 @@ export class TaskListCloudService extends BaseCloudService implements TaskListCl
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Available from Activiti version 8.7.0 onwards.
|
||||||
|
* Retrieves a list of tasks using an object with optional query properties.
|
||||||
|
*
|
||||||
|
* @param requestNode Query object
|
||||||
|
* @param queryUrl Query url
|
||||||
|
* @returns List of tasks
|
||||||
|
*/
|
||||||
|
fetchTaskList(requestNode: TaskListRequestModel, queryUrl?: string): Observable<any> {
|
||||||
|
if (!requestNode?.appName) {
|
||||||
|
return throwError(() => new Error('Appname not configured'));
|
||||||
|
}
|
||||||
|
|
||||||
|
queryUrl = queryUrl || `${this.getBasePath(requestNode.appName)}/query/v1/tasks/search`;
|
||||||
|
|
||||||
|
const queryParams = {
|
||||||
|
maxItems: requestNode.pagination?.maxItems || 25,
|
||||||
|
skipCount: requestNode.pagination?.skipCount || 0,
|
||||||
|
sort: this.buildSortingParam(requestNode.sorting || [])
|
||||||
|
};
|
||||||
|
|
||||||
|
const queryData = this.buildQueryData(requestNode);
|
||||||
|
|
||||||
|
return this.post<any, TaskCloudNodePaging>(queryUrl, queryData, queryParams).pipe(
|
||||||
|
map((response) => {
|
||||||
|
const entries = response.list?.entries;
|
||||||
|
if (entries) {
|
||||||
|
response.list.entries = entries.map((entryData) => entryData.entry) as any;
|
||||||
|
}
|
||||||
|
return response;
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
getTaskListCounter(requestNode: TaskListRequestModel): Observable<number> {
|
||||||
|
if (!requestNode.appName) {
|
||||||
|
return throwError(() => new Error('Appname not configured'));
|
||||||
|
}
|
||||||
|
return this.fetchTaskList(requestNode).pipe(map((tasks) => tasks.list.pagination.totalItems));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected buildQueryData(requestNode: TaskListRequestModel) {
|
||||||
|
const variableKeys = requestNode.variableKeys?.length > 0 ? requestNode.variableKeys.join(',') : undefined;
|
||||||
|
|
||||||
|
const queryData: any = {
|
||||||
|
status: requestNode.status,
|
||||||
|
processDefinitionName: requestNode.processDefinitionName,
|
||||||
|
assignee: requestNode.assignee,
|
||||||
|
priority: requestNode.priority,
|
||||||
|
name: requestNode.name,
|
||||||
|
completedBy: requestNode.completedBy,
|
||||||
|
completedFrom: requestNode.completedFrom,
|
||||||
|
completedTo: requestNode.completedTo,
|
||||||
|
createdFrom: requestNode.createdFrom,
|
||||||
|
createdTo: requestNode.createdTo,
|
||||||
|
dueDateFrom: requestNode.dueDateFrom,
|
||||||
|
dueDateTo: requestNode.dueDateTo,
|
||||||
|
variableKeys
|
||||||
|
};
|
||||||
|
|
||||||
|
Object.keys(queryData).forEach((key) => {
|
||||||
|
const value = queryData[key];
|
||||||
|
const isValueEmpty = !value;
|
||||||
|
const isValueArrayWithEmptyValue = Array.isArray(value) && (value.length === 0 || value[0] === null);
|
||||||
|
if (isValueEmpty || isValueArrayWithEmptyValue) {
|
||||||
|
delete queryData[key];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return queryData;
|
||||||
|
}
|
||||||
|
|
||||||
protected buildQueryParams(requestNode: TaskQueryCloudRequestModel): any {
|
protected buildQueryParams(requestNode: TaskQueryCloudRequestModel): any {
|
||||||
const queryParam: any = {};
|
const queryParam: any = {};
|
||||||
for (const propertyKey in requestNode) {
|
for (const propertyKey in requestNode) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user