mirror of
https://github.com/Alfresco/alfresco-ng2-components.git
synced 2025-05-19 17:14:57 +00:00
[AAE-3469] New Service Task Cloud Component (#6161)
* [AAE-3469] New Service Task Lisst Component * Fix unit tests * Add documentation * Add public methods to Data Table Schema * [AAE-3469] New Service Task Cloud Component * Fix comments * Fix comments * Fix unit tests
This commit is contained in:
parent
9b5d0d2a82
commit
e497b31e3e
@ -105,7 +105,8 @@
|
|||||||
"PEOPLE_CLOUD": "People Cloud Component",
|
"PEOPLE_CLOUD": "People Cloud Component",
|
||||||
"GROUPS_CLOUD": "Groups Cloud Component",
|
"GROUPS_CLOUD": "Groups Cloud Component",
|
||||||
"CONFIRM-DIALOG": "Confirmation Dialog",
|
"CONFIRM-DIALOG": "Confirmation Dialog",
|
||||||
"COMMUNITY": "Community"
|
"COMMUNITY": "Community",
|
||||||
|
"SERVICE_TASK_LIST": "Service Task List"
|
||||||
},
|
},
|
||||||
"TRASHCAN": {
|
"TRASHCAN": {
|
||||||
"ACTIONS": {
|
"ACTIONS": {
|
||||||
|
@ -969,6 +969,35 @@
|
|||||||
"delete"
|
"delete"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"adf-edit-service-task-filter": {
|
||||||
|
"filterProperties": [
|
||||||
|
"appName",
|
||||||
|
"serviceTaskId",
|
||||||
|
"activityName",
|
||||||
|
"activityType",
|
||||||
|
"completedDate",
|
||||||
|
"startedDate",
|
||||||
|
"sort",
|
||||||
|
"order",
|
||||||
|
"status",
|
||||||
|
"elementId",
|
||||||
|
"serviceName",
|
||||||
|
"processInstanceId",
|
||||||
|
"processDefinitionId",
|
||||||
|
"serviceName"
|
||||||
|
],
|
||||||
|
"sortProperties": [
|
||||||
|
"id",
|
||||||
|
"activityName",
|
||||||
|
"completedDate",
|
||||||
|
"startedDate"
|
||||||
|
],
|
||||||
|
"actions": [
|
||||||
|
"save",
|
||||||
|
"saveAs",
|
||||||
|
"delete"
|
||||||
|
]
|
||||||
|
},
|
||||||
"adf-edit-process-filter": {
|
"adf-edit-process-filter": {
|
||||||
"filterProperties": [
|
"filterProperties": [
|
||||||
"status",
|
"status",
|
||||||
@ -1066,6 +1095,44 @@
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"adf-cloud-service-task-list": {
|
||||||
|
"presets": {
|
||||||
|
"default": [
|
||||||
|
{
|
||||||
|
"key": "entry.id",
|
||||||
|
"type": "text",
|
||||||
|
"title": "ADF_CLOUD_SERVICE_TASK_LIST.PROPERTIES.ID",
|
||||||
|
"sortable": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "entry.activityName",
|
||||||
|
"type": "text",
|
||||||
|
"title": "ADF_CLOUD_SERVICE_TASK_LIST.PROPERTIES.ACTIVITY_NAME",
|
||||||
|
"sortable": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "entry.status",
|
||||||
|
"type": "text",
|
||||||
|
"title": "ADF_CLOUD_SERVICE_TASK_LIST.PROPERTIES.STATUS",
|
||||||
|
"sortable": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "entry.startedDate",
|
||||||
|
"type": "date",
|
||||||
|
"title": "ADF_CLOUD_SERVICE_TASK_LIST.PROPERTIES.STARTED_DATE",
|
||||||
|
"sortable": true,
|
||||||
|
"format": "timeAgo"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "entry.completedDate",
|
||||||
|
"type": "date",
|
||||||
|
"title": "ADF_CLOUD_SERVICE_TASK_LIST.PROPERTIES.COMPLETED_DATE",
|
||||||
|
"sortable": true,
|
||||||
|
"format": "timeAgo"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
"adf-cloud-process-list": {
|
"adf-cloud-process-list": {
|
||||||
"presets": {
|
"presets": {
|
||||||
"default": [
|
"default": [
|
||||||
|
@ -65,6 +65,7 @@ import { TasksCloudDemoComponent } from './components/cloud/tasks-cloud-demo.com
|
|||||||
import { ProcessesCloudDemoComponent } from './components/cloud/processes-cloud-demo.component';
|
import { ProcessesCloudDemoComponent } from './components/cloud/processes-cloud-demo.component';
|
||||||
import { TaskDetailsCloudDemoComponent } from './components/cloud/task-details-cloud-demo.component';
|
import { TaskDetailsCloudDemoComponent } from './components/cloud/task-details-cloud-demo.component';
|
||||||
import { TaskHeaderCloudDemoComponent } from './components/cloud/task-header-cloud-demo.component';
|
import { TaskHeaderCloudDemoComponent } from './components/cloud/task-header-cloud-demo.component';
|
||||||
|
import { ServiceTaskListCloudDemoComponent } from './components/cloud/service-task-list-cloud-demo.component';
|
||||||
import { CloudViewerComponent } from './components/cloud/cloud-viewer.component';
|
import { CloudViewerComponent } from './components/cloud/cloud-viewer.component';
|
||||||
import { ProcessDetailsCloudDemoComponent } from './components/cloud/process-details-cloud-demo.component';
|
import { ProcessDetailsCloudDemoComponent } from './components/cloud/process-details-cloud-demo.component';
|
||||||
import { StartTaskCloudDemoComponent } from './components/cloud/start-task-cloud-demo.component';
|
import { StartTaskCloudDemoComponent } from './components/cloud/start-task-cloud-demo.component';
|
||||||
@ -193,7 +194,8 @@ registerLocaleData(localeSv);
|
|||||||
ConfirmDialogExampleComponent,
|
ConfirmDialogExampleComponent,
|
||||||
CustomEditorComponent,
|
CustomEditorComponent,
|
||||||
CustomWidgetComponent,
|
CustomWidgetComponent,
|
||||||
ProcessCloudLayoutComponent
|
ProcessCloudLayoutComponent,
|
||||||
|
ServiceTaskListCloudDemoComponent
|
||||||
],
|
],
|
||||||
providers: [
|
providers: [
|
||||||
{
|
{
|
||||||
|
@ -54,6 +54,7 @@ import { DemoErrorComponent } from './components/error/demo-error.component';
|
|||||||
import { TaskHeaderCloudDemoComponent } from './components/cloud/task-header-cloud-demo.component';
|
import { TaskHeaderCloudDemoComponent } from './components/cloud/task-header-cloud-demo.component';
|
||||||
import { FilteredSearchComponent } from './components/files/filtered-search.component';
|
import { FilteredSearchComponent } from './components/files/filtered-search.component';
|
||||||
import { ProcessCloudLayoutComponent } from './components/cloud/process-cloud-layout.component';
|
import { ProcessCloudLayoutComponent } from './components/cloud/process-cloud-layout.component';
|
||||||
|
import { ServiceTaskListCloudDemoComponent } from './components/cloud/service-task-list-cloud-demo.component';
|
||||||
|
|
||||||
export const appRoutes: Routes = [
|
export const appRoutes: Routes = [
|
||||||
{ path: 'login', loadChildren: () => import('./components/login/login.module').then(m => m.AppLoginModule) },
|
{ path: 'login', loadChildren: () => import('./components/login/login.module').then(m => m.AppLoginModule) },
|
||||||
@ -176,22 +177,31 @@ export const appRoutes: Routes = [
|
|||||||
{
|
{
|
||||||
path: 'cloud',
|
path: 'cloud',
|
||||||
canActivate: [AuthGuardSsoRoleService],
|
canActivate: [AuthGuardSsoRoleService],
|
||||||
data: { roles: ['ACTIVITI_USER'], redirectUrl: '/error/403' },
|
data: { roles: ['ACTIVITI_ADMIN', 'ACTIVITI_USER'], redirectUrl: '/error/403' },
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
path: '',
|
path: '',
|
||||||
|
data: { roles: ['ACTIVITI_USER'], redirectUrl: '/error/403' },
|
||||||
component: AppsCloudDemoComponent
|
component: AppsCloudDemoComponent
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'people-group-cloud',
|
path: 'people-group-cloud',
|
||||||
|
data: { roles: ['ACTIVITI_USER'], redirectUrl: '/error/403' },
|
||||||
component: PeopleGroupCloudDemoComponent
|
component: PeopleGroupCloudDemoComponent
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'task-header-cloud',
|
path: 'task-header-cloud',
|
||||||
|
data: { roles: ['ACTIVITI_USER'], redirectUrl: '/error/403' },
|
||||||
component: TaskHeaderCloudDemoComponent
|
component: TaskHeaderCloudDemoComponent
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: 'service-task-list',
|
||||||
|
data: { roles: ['ACTIVITI_ADMIN'], redirectUrl: '/error/403' },
|
||||||
|
component: ServiceTaskListCloudDemoComponent
|
||||||
|
},
|
||||||
{
|
{
|
||||||
path: 'community',
|
path: 'community',
|
||||||
|
data: { roles: ['ACTIVITI_USER'], redirectUrl: '/error/403' },
|
||||||
loadChildren: () => import('./components/cloud/community/community.module').then(m => m.AppCommunityModule)
|
loadChildren: () => import('./components/cloud/community/community.module').then(m => m.AppCommunityModule)
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -55,7 +55,8 @@ export class AppLayoutComponent implements OnInit, OnDestroy {
|
|||||||
{ href: '/cloud/community', icon: 'cloud', title: 'APP_LAYOUT.COMMUNITY' },
|
{ href: '/cloud/community', icon: 'cloud', title: 'APP_LAYOUT.COMMUNITY' },
|
||||||
{ href: '/form-cloud', icon: 'poll', title: 'APP_LAYOUT.FORM' },
|
{ href: '/form-cloud', icon: 'poll', title: 'APP_LAYOUT.FORM' },
|
||||||
{ href: '/cloud/people-group-cloud', icon: 'group', title: 'APP_LAYOUT.PEOPLE_GROUPS_CLOUD' },
|
{ href: '/cloud/people-group-cloud', icon: 'group', title: 'APP_LAYOUT.PEOPLE_GROUPS_CLOUD' },
|
||||||
{ href: '/cloud/task-header-cloud', icon: 'cloud', title: 'APP_LAYOUT.TASK_HEADER_CLOUD.COMPONENT_NAME' }
|
{ href: '/cloud/task-header-cloud', icon: 'cloud', title: 'APP_LAYOUT.TASK_HEADER_CLOUD.COMPONENT_NAME' },
|
||||||
|
{ href: '/cloud/service-task-list', icon: 'cloud', title: 'APP_LAYOUT.SERVICE_TASK_LIST' }
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{ href: '/activiti', icon: 'device_hub', title: 'APP_LAYOUT.PROCESS_SERVICES', children: [
|
{ href: '/activiti', icon: 'device_hub', title: 'APP_LAYOUT.PROCESS_SERVICES', children: [
|
||||||
|
@ -0,0 +1,29 @@
|
|||||||
|
<div fxLayout="column" fxFill fxLayoutGap="2px">
|
||||||
|
<adf-cloud-edit-service-task-filter
|
||||||
|
[id]="'myFilter'"
|
||||||
|
[filterProperties]="taskFilterProperties.filterProperties"
|
||||||
|
[sortProperties]="taskFilterProperties.sortProperties"
|
||||||
|
[actions]="taskFilterProperties.actions"
|
||||||
|
(filterChange)="onFilterChange($event)">
|
||||||
|
</adf-cloud-edit-service-task-filter>
|
||||||
|
<div fxLayout="column" fxFlex fxLayoutAlign="space-between" *ngIf="editedFilter">
|
||||||
|
<adf-cloud-service-task-list #taskCloud
|
||||||
|
fxFlex
|
||||||
|
[queryParams]="editedFilter"
|
||||||
|
class="app-cloud-layout-overflow"
|
||||||
|
[appName]="editedFilter.appName"
|
||||||
|
[sorting]="sortArray"
|
||||||
|
[multiselect]="multiselect"
|
||||||
|
[selectionMode]="selectionMode"
|
||||||
|
[stickyHeader]="true"
|
||||||
|
[showActions]="actionMenu"
|
||||||
|
[showContextMenu]="contextMenu">
|
||||||
|
</adf-cloud-service-task-list>
|
||||||
|
<adf-pagination
|
||||||
|
[target]="taskCloud"
|
||||||
|
(changePageSize)="onChangePageSize($event)"
|
||||||
|
(nextPage)="resetSelectedRows()"
|
||||||
|
(prevPage)="resetSelectedRows()">
|
||||||
|
</adf-pagination>
|
||||||
|
</div>
|
||||||
|
</div>
|
@ -0,0 +1,101 @@
|
|||||||
|
/*!
|
||||||
|
* @license
|
||||||
|
* Copyright 2019 Alfresco Software, Ltd.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { Component, OnInit, OnDestroy, ViewChild } from '@angular/core';
|
||||||
|
import { TaskListCloudSortingModel, ServiceTaskListCloudComponent, ServiceTaskFilterCloudModel } from '@alfresco/adf-process-services-cloud';
|
||||||
|
import { UserPreferencesService, AppConfigService, PaginationModel } from '@alfresco/adf-core';
|
||||||
|
import { CloudLayoutService, CloudServiceSettings } from './services/cloud-layout.service';
|
||||||
|
import { Subject } from 'rxjs';
|
||||||
|
import { takeUntil } from 'rxjs/operators';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
templateUrl: 'service-task-list-cloud-demo.component.html'
|
||||||
|
})
|
||||||
|
export class ServiceTaskListCloudDemoComponent implements OnInit, OnDestroy {
|
||||||
|
|
||||||
|
public static ACTION_SAVE_AS = 'saveAs';
|
||||||
|
public static ACTION_DELETE = 'delete';
|
||||||
|
static TASK_FILTER_PROPERTY_KEYS = 'adf-edit-service-task-filter';
|
||||||
|
|
||||||
|
@ViewChild('taskCloud')
|
||||||
|
taskCloud: ServiceTaskListCloudComponent;
|
||||||
|
|
||||||
|
isFilterLoaded = false;
|
||||||
|
|
||||||
|
selectedRow: any;
|
||||||
|
|
||||||
|
sortArray: TaskListCloudSortingModel[];
|
||||||
|
editedFilter: ServiceTaskFilterCloudModel;
|
||||||
|
taskFilterProperties: any = { filterProperties: [], sortProperties: [], actions: [] };
|
||||||
|
|
||||||
|
multiselect: boolean;
|
||||||
|
selectedRows: string[] = [];
|
||||||
|
actionMenu: boolean;
|
||||||
|
contextMenu: boolean;
|
||||||
|
actions: any[] = [];
|
||||||
|
selectedAction: { id: number, name: string, actionType: string};
|
||||||
|
selectedContextAction: { id: number, name: string, actionType: string};
|
||||||
|
selectionMode: string;
|
||||||
|
|
||||||
|
private onDestroy$ = new Subject<boolean>();
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
private cloudLayoutService: CloudLayoutService,
|
||||||
|
private userPreference: UserPreferencesService,
|
||||||
|
private appConfig: AppConfigService) {
|
||||||
|
|
||||||
|
const properties = this.appConfig.get<Array<any>>(ServiceTaskListCloudDemoComponent.TASK_FILTER_PROPERTY_KEYS);
|
||||||
|
if (properties === this.taskFilterProperties) {
|
||||||
|
this.taskFilterProperties = properties;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnInit() {
|
||||||
|
this.isFilterLoaded = false;
|
||||||
|
this.cloudLayoutService.settings$
|
||||||
|
.pipe(takeUntil(this.onDestroy$))
|
||||||
|
.subscribe(settings => this.setCurrentSettings(settings));
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnDestroy() {
|
||||||
|
this.onDestroy$.next(true);
|
||||||
|
this.onDestroy$.complete();
|
||||||
|
}
|
||||||
|
|
||||||
|
setCurrentSettings(settings: CloudServiceSettings) {
|
||||||
|
if (settings) {
|
||||||
|
this.multiselect = settings.multiselect;
|
||||||
|
this.selectionMode = settings.selectionMode;
|
||||||
|
this.actionMenu = settings.actionMenu;
|
||||||
|
this.contextMenu = settings.contextMenu;
|
||||||
|
this.actions = settings.actions;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onChangePageSize(event: PaginationModel) {
|
||||||
|
this.userPreference.paginationSize = event.maxItems;
|
||||||
|
}
|
||||||
|
|
||||||
|
resetSelectedRows() {
|
||||||
|
this.selectedRows = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
onFilterChange(filter: ServiceTaskFilterCloudModel) {
|
||||||
|
this.editedFilter = Object.assign({}, filter);
|
||||||
|
this.sortArray = [new TaskListCloudSortingModel({ orderBy: this.editedFilter.sort, direction: this.editedFilter.order })];
|
||||||
|
}
|
||||||
|
}
|
@ -79,4 +79,12 @@ export abstract class DataTableSchema {
|
|||||||
private getDefaultLayoutPreset(): DataColumn[] {
|
private getDefaultLayoutPreset(): DataColumn[] {
|
||||||
return (this.layoutPresets['default']).map((col) => new ObjectDataColumn(col));
|
return (this.layoutPresets['default']).map((col) => new ObjectDataColumn(col));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public setPresetKey(presetKey: string) {
|
||||||
|
this.presetKey = presetKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
public setPresetsModel(presetsModel: any) {
|
||||||
|
this.presetsModel = presetsModel;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -101,11 +101,26 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"ADF_CLOUD_SERVICE_TASK_LIST": {
|
||||||
|
"PROPERTIES": {
|
||||||
|
"ACTIVITY_NAME": "Activity name",
|
||||||
|
"ACTIVITY_TYPE": "Status",
|
||||||
|
"ID": "Id",
|
||||||
|
"COMPLETED_DATE": "Completed date",
|
||||||
|
"STARTED_DATE": "Started date",
|
||||||
|
"STATUS": "Status"
|
||||||
|
}
|
||||||
|
},
|
||||||
"ADF_CLOUD_TASK_FILTERS": {
|
"ADF_CLOUD_TASK_FILTERS": {
|
||||||
"MY_TASKS": "My Tasks",
|
"MY_TASKS": "My Tasks",
|
||||||
"QUEUED_TASKS": "Queued Tasks",
|
"QUEUED_TASKS": "Queued Tasks",
|
||||||
"COMPLETED_TASKS": "Completed Tasks"
|
"COMPLETED_TASKS": "Completed Tasks"
|
||||||
},
|
},
|
||||||
|
"ADF_CLOUD_SERVICE_TASK_FILTERS": {
|
||||||
|
"ALL_SERVICE_TASKS": "All Service Tasks",
|
||||||
|
"ERRORED_TASKS": "Errored Tasks",
|
||||||
|
"COMPLETED_TASKS": "Completed Tasks"
|
||||||
|
},
|
||||||
"ADF_CLOUD_PROCESS_FILTERS": {
|
"ADF_CLOUD_PROCESS_FILTERS": {
|
||||||
"ALL_PROCESSES": "All",
|
"ALL_PROCESSES": "All",
|
||||||
"RUNNING_PROCESSES": "Running",
|
"RUNNING_PROCESSES": "Running",
|
||||||
@ -153,6 +168,24 @@
|
|||||||
"CANCEL": "CANCEL"
|
"CANCEL": "CANCEL"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"ADF_CLOUD_EDIT_SERVICE_TASK_FILTER": {
|
||||||
|
"LABEL": {
|
||||||
|
"APP_NAME": "ApplicationName",
|
||||||
|
"SERVICE_TASK_ID": "ServiceTaskId",
|
||||||
|
"SERVICE_NAME": "ServiceName",
|
||||||
|
"ELEMENT_ID": "ElementId",
|
||||||
|
"PROCESS_DEF_NAME": "ProcessDefinitionName",
|
||||||
|
"PROCESS_DEF_ID": "ProcessDefinitionId",
|
||||||
|
"PROCESS_INSTANCE_ID": "ProcessInstanceId",
|
||||||
|
"STATUS": "Status",
|
||||||
|
"DIRECTION": "Direction",
|
||||||
|
"ACTIVITY_NAME": "ActivityName",
|
||||||
|
"ACTIVITY_TYPE": "ActivityType",
|
||||||
|
"SORT": "Sort",
|
||||||
|
"STARTED_DATE": "StartedDate",
|
||||||
|
"COMPLETED_DATE": "CompletedDate"
|
||||||
|
}
|
||||||
|
},
|
||||||
"ADF_CLOUD_EDIT_PROCESS_FILTER": {
|
"ADF_CLOUD_EDIT_PROCESS_FILTER": {
|
||||||
"TITLE": "Customize your filter",
|
"TITLE": "Customize your filter",
|
||||||
"LABEL": {
|
"LABEL": {
|
||||||
|
@ -6,8 +6,8 @@
|
|||||||
@import './../process/process-filters/components/edit-process-filter-cloud.component.scss';
|
@import './../process/process-filters/components/edit-process-filter-cloud.component.scss';
|
||||||
@import './../task/task-form/components/task-form-cloud.component';
|
@import './../task/task-form/components/task-form-cloud.component';
|
||||||
@import './../task/start-task/components/start-task-cloud.component.scss';
|
@import './../task/start-task/components/start-task-cloud.component.scss';
|
||||||
@import './../task/task-filters/components/edit-task-filter-cloud.component.scss';
|
@import './../task/task-filters/components/edit-task-filters/base-edit-task-filter-cloud.component.scss';
|
||||||
@import './../task/task-filters/components/task-filters-cloud.component.scss';
|
@import './../task/task-filters/components/base-task-filters-cloud.component.scss';
|
||||||
@import './../process/start-process/components/start-process-cloud.component';
|
@import './../process/start-process/components/start-process-cloud.component';
|
||||||
@import './../form/components/widgets/attach-file/attach-file-cloud-widget.component.scss';
|
@import './../form/components/widgets/attach-file/attach-file-cloud-widget.component.scss';
|
||||||
|
|
||||||
|
@ -0,0 +1,54 @@
|
|||||||
|
/*!
|
||||||
|
* @license
|
||||||
|
* Copyright 2019 Alfresco Software, Ltd.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { EventEmitter, Input, Output, OnDestroy, Directive } from '@angular/core';
|
||||||
|
import { Subject } from 'rxjs';
|
||||||
|
import { FilterParamsModel } from '../models/filter-cloud.model';
|
||||||
|
|
||||||
|
@Directive()
|
||||||
|
// tslint:disable-next-line: directive-class-suffix
|
||||||
|
export abstract class BaseTaskFiltersCloudComponent implements OnDestroy {
|
||||||
|
/** Display filters available to the current user for the application with the specified name. */
|
||||||
|
@Input()
|
||||||
|
appName: string = '';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parameters to use for the task filter cloud. If there is no match then the default filter
|
||||||
|
* (the first one in the list) is selected.
|
||||||
|
*/
|
||||||
|
@Input()
|
||||||
|
filterParam: FilterParamsModel;
|
||||||
|
|
||||||
|
/** Toggles display of the filter's icons. */
|
||||||
|
@Input()
|
||||||
|
showIcons: boolean = false;
|
||||||
|
|
||||||
|
/** Emitted when the list is loaded. */
|
||||||
|
@Output()
|
||||||
|
success: EventEmitter<any> = new EventEmitter<any>();
|
||||||
|
|
||||||
|
/** Emitted when an error occurs during loading. */
|
||||||
|
@Output()
|
||||||
|
error: EventEmitter<any> = new EventEmitter<any>();
|
||||||
|
|
||||||
|
protected onDestroy$ = new Subject<boolean>();
|
||||||
|
|
||||||
|
ngOnDestroy() {
|
||||||
|
this.onDestroy$.next(true);
|
||||||
|
this.onDestroy$.complete();
|
||||||
|
}
|
||||||
|
}
|
@ -1,91 +0,0 @@
|
|||||||
<mat-accordion [hideToggle]="isLoading">
|
|
||||||
<mat-expansion-panel (afterExpand)="onExpand()" (closed)="onClose()">
|
|
||||||
<mat-expansion-panel-header *ngIf="taskFilter" id="adf-edit-task-filter-expansion-header">
|
|
||||||
<ng-container *ngIf="!isLoading; else loadingTemplate">
|
|
||||||
<mat-panel-title *ngIf="showTaskFilterName" fxLayoutAlign="space-between center" id="adf-edit-task-filter-title-id">{{taskFilter.name | translate}}</mat-panel-title>
|
|
||||||
<mat-panel-description fxLayoutAlign="space-between center" id="adf-edit-task-filter-sub-title-id">
|
|
||||||
<span *ngIf="showTitle">{{ 'ADF_CLOUD_EDIT_TASK_FILTER.TITLE' | translate}}</span>
|
|
||||||
<div *ngIf="showActions()" class="adf-cloud-edit-task-filter-actions">
|
|
||||||
<ng-container *ngIf="toggleFilterActions">
|
|
||||||
<button *ngFor="let filterAction of taskFilterActions" mat-icon-button matTooltip="{{ filterAction.tooltip | translate}}" [attr.data-automation-id]="'adf-filter-action-' + filterAction.actionType" [disabled]="isDisabledAction(filterAction)" (click)="executeFilterActions(filterAction)">
|
|
||||||
<mat-icon>{{filterAction.icon}}</mat-icon>
|
|
||||||
</button>
|
|
||||||
</ng-container>
|
|
||||||
</div>
|
|
||||||
</mat-panel-description>
|
|
||||||
</ng-container>
|
|
||||||
<ng-template #loadingTemplate>
|
|
||||||
<div class="adf-cloud-edit-task-filter-loading-margin">
|
|
||||||
<mat-spinner [diameter]="30"></mat-spinner>
|
|
||||||
</div>
|
|
||||||
</ng-template>
|
|
||||||
</mat-expansion-panel-header>
|
|
||||||
<ng-container *ngIf="!isLoading;">
|
|
||||||
<form [formGroup]="editTaskFilterForm" *ngIf="editTaskFilterForm">
|
|
||||||
<div fxLayout="row wrap" fxLayout.xs="column" fxLayoutGap="10px" fxLayoutAlign="start center">
|
|
||||||
<ng-container *ngFor="let taskFilterProperty of taskFilterProperties">
|
|
||||||
<mat-form-field fxFlex="23%" *ngIf="isSelectType(taskFilterProperty)" [attr.data-automation-id]="taskFilterProperty.key">
|
|
||||||
<mat-select
|
|
||||||
placeholder="{{taskFilterProperty.label | translate}}"
|
|
||||||
[formControlName]="taskFilterProperty.key"
|
|
||||||
[attr.data-automation-id]="'adf-cloud-edit-task-property-' + taskFilterProperty.key">
|
|
||||||
<mat-option *ngFor="let propertyOption of taskFilterProperty.options" [value]="propertyOption.value" [attr.data-automation-id]="'adf-cloud-edit-task-property-options-' + taskFilterProperty.key">
|
|
||||||
{{ propertyOption.label }}
|
|
||||||
</mat-option>
|
|
||||||
</mat-select>
|
|
||||||
</mat-form-field>
|
|
||||||
<mat-form-field fxFlex="23%" *ngIf="isTextType(taskFilterProperty)" [attr.data-automation-id]="taskFilterProperty.key">
|
|
||||||
<input matInput
|
|
||||||
[formControlName]="taskFilterProperty.key"
|
|
||||||
type="text"
|
|
||||||
placeholder="{{taskFilterProperty.label | translate}}"
|
|
||||||
[attr.data-automation-id]="'adf-cloud-edit-task-property-' + taskFilterProperty.key"/>
|
|
||||||
</mat-form-field>
|
|
||||||
<mat-form-field fxFlex="23%" *ngIf="isDateType(taskFilterProperty)" [attr.data-automation-id]="taskFilterProperty.key">
|
|
||||||
<mat-label>{{taskFilterProperty.label | translate}}</mat-label>
|
|
||||||
<input
|
|
||||||
matInput
|
|
||||||
(keyup)="onDateChanged($event.srcElement.value, taskFilterProperty)"
|
|
||||||
(dateChange)="onDateChanged($event.value, taskFilterProperty)"
|
|
||||||
[matDatepicker]="dateController"
|
|
||||||
placeholder="{{taskFilterProperty.label | translate}}"
|
|
||||||
[attr.data-automation-id]="'adf-cloud-edit-task-`perty-' + taskFilterProperty.key">
|
|
||||||
<mat-datepicker-toggle matSuffix [for]="dateController" [attr.data-automation-id]="'adf-cloud-edit-task-property-date-toggle-' + taskFilterProperty.key"></mat-datepicker-toggle>
|
|
||||||
<mat-datepicker #dateController [attr.data-automation-id]="'adf-cloud-edit-task-property-date-picker-' + taskFilterProperty.key"></mat-datepicker>
|
|
||||||
<div class="adf-edit-task-filter-date-error-container">
|
|
||||||
<div *ngIf="hasError(taskFilterProperty)">
|
|
||||||
<div class="adf-error-text">{{'ADF_TASK_LIST.START_TASK.FORM.ERROR.DATE'|translate}}</div>
|
|
||||||
<mat-icon class="adf-error-icon">warning</mat-icon>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</mat-form-field>
|
|
||||||
<div class="adf-edit-task-filter-checkbox" *ngIf="isCheckBoxType(taskFilterProperty)">
|
|
||||||
<mat-checkbox
|
|
||||||
color="primary"
|
|
||||||
[formControlName]="taskFilterProperty.key"
|
|
||||||
[attr.data-automation-id]="taskFilterProperty.key">
|
|
||||||
{{taskFilterProperty.label | translate}}
|
|
||||||
</mat-checkbox>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<adf-cloud-date-range-filter *ngIf="isDateRangeType(taskFilterProperty)"
|
|
||||||
[processFilterProperty]="taskFilterProperty"
|
|
||||||
[options]="taskFilterProperty.dateFilterOptions"
|
|
||||||
(dateTypeChange)="onDateTypeChange($event, taskFilterProperty)"
|
|
||||||
(dateChanged)="onDateRangeFilterChanged($event, taskFilterProperty)"></adf-cloud-date-range-filter>
|
|
||||||
|
|
||||||
<div fxFlex="23%" class="adf-edit-task-filter-checkbox" *ngIf="isUserSelectType(taskFilterProperty)">
|
|
||||||
<adf-cloud-people
|
|
||||||
[preSelectUsers]="taskFilterProperty.value | async"
|
|
||||||
[title]="taskFilterProperty.label"
|
|
||||||
[validate]="true"
|
|
||||||
[appName]="appName"
|
|
||||||
[mode]="taskFilterProperty.selectionMode"
|
|
||||||
(changedUsers)="onChangedUser($event, taskFilterProperty)"></adf-cloud-people>
|
|
||||||
</div>
|
|
||||||
</ng-container>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
</ng-container>
|
|
||||||
</mat-expansion-panel>
|
|
||||||
</mat-accordion>
|
|
@ -1,719 +0,0 @@
|
|||||||
/*!
|
|
||||||
* @license
|
|
||||||
* Copyright 2019 Alfresco Software, Ltd.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
import { Component, OnChanges, Input, Output, EventEmitter, SimpleChanges, OnInit, OnDestroy } from '@angular/core';
|
|
||||||
import { AbstractControl, FormGroup, FormBuilder } from '@angular/forms';
|
|
||||||
import { DateAdapter } from '@angular/material/core';
|
|
||||||
import { MatDialog } from '@angular/material/dialog';
|
|
||||||
import { debounceTime, filter, takeUntil, finalize, switchMap } from 'rxjs/operators';
|
|
||||||
import { Subject, Observable, of } from 'rxjs';
|
|
||||||
import moment from 'moment-es6';
|
|
||||||
import { Moment } from 'moment';
|
|
||||||
|
|
||||||
import { TaskFilterCloudModel, TaskFilterProperties, FilterOptions, TaskFilterAction } from './../models/filter-cloud.model';
|
|
||||||
import { TaskFilterCloudService } from '../services/task-filter-cloud.service';
|
|
||||||
import { TaskFilterDialogCloudComponent } from './task-filter-dialog-cloud.component';
|
|
||||||
import { TranslationService, UserPreferencesService, UserPreferenceValues, IdentityUserModel, IdentityUserService } from '@alfresco/adf-core';
|
|
||||||
import { AppsProcessCloudService } from '../../../app/services/apps-process-cloud.service';
|
|
||||||
import { ApplicationInstanceModel } from '../../../app/models/application-instance.model';
|
|
||||||
import { DateCloudFilterType, DateRangeFilter } from '../../../models/date-cloud-filter.model';
|
|
||||||
import { ProcessDefinitionCloud } from '../../../models/process-definition-cloud.model';
|
|
||||||
import { TaskCloudService } from '../../services/task-cloud.service';
|
|
||||||
|
|
||||||
@Component({
|
|
||||||
selector: 'adf-cloud-edit-task-filter',
|
|
||||||
templateUrl: './edit-task-filter-cloud.component.html',
|
|
||||||
styleUrls: ['./edit-task-filter-cloud.component.scss']
|
|
||||||
})
|
|
||||||
export class EditTaskFilterCloudComponent implements OnInit, OnChanges, OnDestroy {
|
|
||||||
|
|
||||||
public static ACTION_SAVE = 'save';
|
|
||||||
public static ACTION_SAVE_AS = 'saveAs';
|
|
||||||
public static ACTION_DELETE = 'delete';
|
|
||||||
public static APP_RUNNING_STATUS: string = 'RUNNING';
|
|
||||||
public static APPLICATION_NAME: string = 'appName';
|
|
||||||
public static PROCESS_DEFINITION_NAME: string = 'processDefinitionName';
|
|
||||||
public static LAST_MODIFIED: string = 'lastModified';
|
|
||||||
public static SORT: string = 'sort';
|
|
||||||
public static ORDER: string = 'order';
|
|
||||||
public static DEFAULT_TASK_FILTER_PROPERTIES = ['status', 'assignee', 'sort', 'order'];
|
|
||||||
public static DEFAULT_SORT_PROPERTIES = ['id', 'name', 'createdDate', 'priority'];
|
|
||||||
public static DEFAULT_ACTIONS = ['save', 'saveAs', 'delete'];
|
|
||||||
public FORMAT_DATE: string = 'DD/MM/YYYY';
|
|
||||||
|
|
||||||
/** (required) Name of the app. */
|
|
||||||
@Input()
|
|
||||||
appName: string = '';
|
|
||||||
|
|
||||||
/** user role. */
|
|
||||||
@Input()
|
|
||||||
role: string = '';
|
|
||||||
|
|
||||||
/** (required) ID of the task filter. */
|
|
||||||
@Input()
|
|
||||||
id: string;
|
|
||||||
|
|
||||||
/** List of task filter properties to display. */
|
|
||||||
@Input()
|
|
||||||
filterProperties: string[] = EditTaskFilterCloudComponent.DEFAULT_TASK_FILTER_PROPERTIES;
|
|
||||||
|
|
||||||
/** List of sort properties to display. */
|
|
||||||
@Input()
|
|
||||||
sortProperties: string[] = EditTaskFilterCloudComponent.DEFAULT_SORT_PROPERTIES;
|
|
||||||
|
|
||||||
/** List of task filter actions. */
|
|
||||||
@Input()
|
|
||||||
actions: string[] = EditTaskFilterCloudComponent.DEFAULT_ACTIONS;
|
|
||||||
|
|
||||||
/** Toggles the filter actions. */
|
|
||||||
@Input()
|
|
||||||
showFilterActions = true;
|
|
||||||
|
|
||||||
/** Toggles the title. */
|
|
||||||
@Input()
|
|
||||||
showTitle = true;
|
|
||||||
|
|
||||||
/** Toggles display of task filter name */
|
|
||||||
@Input()
|
|
||||||
showTaskFilterName = true;
|
|
||||||
|
|
||||||
/** Emitted when a task filter property changes. */
|
|
||||||
@Output()
|
|
||||||
filterChange: EventEmitter<TaskFilterCloudModel> = new EventEmitter();
|
|
||||||
|
|
||||||
/** Emitted when a filter action occurs (i.e Save, Save As, Delete). */
|
|
||||||
@Output()
|
|
||||||
action: EventEmitter<TaskFilterAction> = new EventEmitter();
|
|
||||||
|
|
||||||
taskFilter: TaskFilterCloudModel;
|
|
||||||
changedTaskFilter: TaskFilterCloudModel;
|
|
||||||
|
|
||||||
status = [
|
|
||||||
{ label: 'ALL', value: '' },
|
|
||||||
{ label: 'CREATED', value: 'CREATED' },
|
|
||||||
{ label: 'ASSIGNED', value: 'ASSIGNED' },
|
|
||||||
{ label: 'SUSPENDED', value: 'SUSPENDED' },
|
|
||||||
{ label: 'CANCELLED', value: 'CANCELLED' },
|
|
||||||
{ label: 'COMPLETED', value: 'COMPLETED' }
|
|
||||||
];
|
|
||||||
|
|
||||||
directions = [
|
|
||||||
{ label: 'ASC', value: 'ASC' },
|
|
||||||
{ label: 'DESC', value: 'DESC' }
|
|
||||||
];
|
|
||||||
actionDisabledForDefault = [
|
|
||||||
EditTaskFilterCloudComponent.ACTION_SAVE,
|
|
||||||
EditTaskFilterCloudComponent.ACTION_DELETE
|
|
||||||
];
|
|
||||||
allProcessDefinitionNamesOption = { label: 'All', value: '' };
|
|
||||||
|
|
||||||
private applicationNames: any[] = [];
|
|
||||||
private processDefinitionNames: any[] = [];
|
|
||||||
private formHasBeenChanged = false;
|
|
||||||
editTaskFilterForm: FormGroup;
|
|
||||||
taskFilterProperties: TaskFilterProperties[] = [];
|
|
||||||
taskFilterActions: TaskFilterAction[] = [];
|
|
||||||
toggleFilterActions: boolean = false;
|
|
||||||
|
|
||||||
private onDestroy$ = new Subject<boolean>();
|
|
||||||
isLoading: boolean = false;
|
|
||||||
|
|
||||||
constructor(
|
|
||||||
private formBuilder: FormBuilder,
|
|
||||||
public dialog: MatDialog,
|
|
||||||
private translateService: TranslationService,
|
|
||||||
private taskFilterCloudService: TaskFilterCloudService,
|
|
||||||
private dateAdapter: DateAdapter<Moment>,
|
|
||||||
private userPreferencesService: UserPreferencesService,
|
|
||||||
private appsProcessCloudService: AppsProcessCloudService,
|
|
||||||
private identityUserService: IdentityUserService,
|
|
||||||
private taskCloudService: TaskCloudService) {
|
|
||||||
}
|
|
||||||
|
|
||||||
ngOnInit() {
|
|
||||||
this.userPreferencesService
|
|
||||||
.select(UserPreferenceValues.Locale)
|
|
||||||
.pipe(takeUntil(this.onDestroy$))
|
|
||||||
.subscribe(locale => this.dateAdapter.setLocale(locale));
|
|
||||||
}
|
|
||||||
|
|
||||||
ngOnChanges(changes: SimpleChanges) {
|
|
||||||
const id = changes['id'];
|
|
||||||
if (id && id.currentValue !== id.previousValue) {
|
|
||||||
this.retrieveTaskFilterAndBuildForm();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ngOnDestroy() {
|
|
||||||
this.onDestroy$.next(true);
|
|
||||||
this.onDestroy$.complete();
|
|
||||||
}
|
|
||||||
|
|
||||||
buildForm(taskFilterProperties: TaskFilterProperties[]) {
|
|
||||||
this.formHasBeenChanged = false;
|
|
||||||
this.editTaskFilterForm = this.formBuilder.group(this.getFormControlsConfig(taskFilterProperties));
|
|
||||||
this.onFilterChange();
|
|
||||||
}
|
|
||||||
|
|
||||||
getFormControlsConfig(taskFilterProperties: TaskFilterProperties[]): any {
|
|
||||||
const properties = taskFilterProperties.map((property: TaskFilterProperties) => {
|
|
||||||
if (!!property.attributes) {
|
|
||||||
return this.getAttributesControlConfig(property);
|
|
||||||
} else {
|
|
||||||
return { [property.key]: property.value };
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return properties.reduce(((result, current) => Object.assign(result, current)), {});
|
|
||||||
}
|
|
||||||
|
|
||||||
private getAttributesControlConfig(property: TaskFilterProperties) {
|
|
||||||
return Object.values(property.attributes).reduce((result, key) => {
|
|
||||||
result[key] = property.value[key];
|
|
||||||
return result;
|
|
||||||
}, {});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check for edit task filter form changes
|
|
||||||
*/
|
|
||||||
onFilterChange() {
|
|
||||||
this.editTaskFilterForm.valueChanges
|
|
||||||
.pipe(
|
|
||||||
debounceTime(200),
|
|
||||||
filter(() => this.isFormValid()),
|
|
||||||
takeUntil(this.onDestroy$)
|
|
||||||
)
|
|
||||||
.subscribe((formValues: TaskFilterCloudModel) => {
|
|
||||||
this.setLastModifiedToFilter(formValues);
|
|
||||||
this.changedTaskFilter = new TaskFilterCloudModel(Object.assign({}, this.taskFilter, formValues));
|
|
||||||
this.formHasBeenChanged = !this.compareFilters(this.changedTaskFilter, this.taskFilter);
|
|
||||||
this.filterChange.emit(this.changedTaskFilter);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private setLastModifiedToFilter(formValues: TaskFilterCloudModel) {
|
|
||||||
if (formValues.lastModifiedTo && Date.parse(formValues.lastModifiedTo.toString())) {
|
|
||||||
const lastModifiedToFilterValue = moment(formValues.lastModifiedTo);
|
|
||||||
lastModifiedToFilterValue.set({
|
|
||||||
hour: 23,
|
|
||||||
minute: 59,
|
|
||||||
second: 59
|
|
||||||
});
|
|
||||||
formValues.lastModifiedTo = lastModifiedToFilterValue.toDate();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fetches task filter by application name and filter id and creates filter properties, build form
|
|
||||||
*/
|
|
||||||
retrieveTaskFilterAndBuildForm() {
|
|
||||||
this.isLoading = true;
|
|
||||||
this.taskFilterCloudService.getTaskFilterById(this.appName, this.id)
|
|
||||||
.pipe(
|
|
||||||
finalize(() => this.isLoading = false),
|
|
||||||
takeUntil(this.onDestroy$)
|
|
||||||
)
|
|
||||||
.subscribe(response => {
|
|
||||||
this.taskFilter = new TaskFilterCloudModel(response);
|
|
||||||
this.taskFilterProperties = this.createAndFilterProperties();
|
|
||||||
this.taskFilterActions = this.createAndFilterActions();
|
|
||||||
this.buildForm(this.taskFilterProperties);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
createAndFilterProperties() {
|
|
||||||
this.checkMandatoryFilterProperties();
|
|
||||||
|
|
||||||
if (this.checkForProperty(EditTaskFilterCloudComponent.APPLICATION_NAME)) {
|
|
||||||
this.applicationNames = [];
|
|
||||||
this.getRunningApplications();
|
|
||||||
}
|
|
||||||
if (this.checkForProperty(EditTaskFilterCloudComponent.PROCESS_DEFINITION_NAME)) {
|
|
||||||
this.processDefinitionNames = [];
|
|
||||||
this.getProcessDefinitions();
|
|
||||||
}
|
|
||||||
|
|
||||||
const defaultProperties = this.createTaskFilterProperties(this.taskFilter);
|
|
||||||
let filteredProperties = defaultProperties.filter((filterProperty: TaskFilterProperties) => this.isValidProperty(this.filterProperties, filterProperty));
|
|
||||||
|
|
||||||
if (!this.hasSortProperty()) {
|
|
||||||
filteredProperties = this.removeOrderProperty(filteredProperties);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.hasLastModifiedProperty()) {
|
|
||||||
filteredProperties = [...filteredProperties, ...this.createLastModifiedProperty()];
|
|
||||||
}
|
|
||||||
return filteredProperties;
|
|
||||||
}
|
|
||||||
|
|
||||||
checkMandatoryFilterProperties() {
|
|
||||||
if (this.filterProperties === undefined || this.filterProperties.length === 0) {
|
|
||||||
this.filterProperties = EditTaskFilterCloudComponent.DEFAULT_TASK_FILTER_PROPERTIES;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private isValidProperty(filterProperties: string[], filterProperty: any): boolean {
|
|
||||||
return filterProperties ? filterProperties.indexOf(filterProperty.key) >= 0 : true;
|
|
||||||
}
|
|
||||||
|
|
||||||
checkForProperty(property: string): boolean {
|
|
||||||
return this.filterProperties ? this.filterProperties.indexOf(property) >= 0 : false;
|
|
||||||
}
|
|
||||||
|
|
||||||
hasSortProperty(): boolean {
|
|
||||||
return this.filterProperties.indexOf(EditTaskFilterCloudComponent.SORT) >= 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
removeOrderProperty(filteredProperties: TaskFilterProperties[]): TaskFilterProperties[] {
|
|
||||||
if (filteredProperties && filteredProperties.length > 0) {
|
|
||||||
return filteredProperties.filter(property => property.key !== EditTaskFilterCloudComponent.ORDER);
|
|
||||||
}
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
|
|
||||||
hasLastModifiedProperty(): boolean {
|
|
||||||
return this.filterProperties.indexOf(EditTaskFilterCloudComponent.LAST_MODIFIED) >= 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
get createSortProperties(): any {
|
|
||||||
this.checkMandatorySortProperties();
|
|
||||||
const sortProperties = this.sortProperties.map((property: string) => {
|
|
||||||
return <FilterOptions> { label: property.charAt(0).toUpperCase() + property.slice(1), value: property };
|
|
||||||
});
|
|
||||||
return sortProperties;
|
|
||||||
}
|
|
||||||
|
|
||||||
checkMandatorySortProperties(): void {
|
|
||||||
if (this.sortProperties === undefined || this.sortProperties.length === 0) {
|
|
||||||
this.sortProperties = EditTaskFilterCloudComponent.DEFAULT_SORT_PROPERTIES;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
createAndFilterActions(): TaskFilterAction[] {
|
|
||||||
this.checkMandatoryActions();
|
|
||||||
return this.createFilterActions()
|
|
||||||
.filter(action => this.isValidAction(this.actions, action));
|
|
||||||
}
|
|
||||||
|
|
||||||
checkMandatoryActions(): void {
|
|
||||||
if (this.actions === undefined || this.actions.length === 0) {
|
|
||||||
this.actions = EditTaskFilterCloudComponent.DEFAULT_ACTIONS;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private isValidAction(actions: string[], action: any): boolean {
|
|
||||||
return actions ? actions.indexOf(action.actionType) >= 0 : true;
|
|
||||||
}
|
|
||||||
|
|
||||||
isFormValid(): boolean {
|
|
||||||
return this.editTaskFilterForm.valid;
|
|
||||||
}
|
|
||||||
|
|
||||||
getPropertyController(property: TaskFilterProperties): AbstractControl {
|
|
||||||
return this.editTaskFilterForm.get(property.key);
|
|
||||||
}
|
|
||||||
|
|
||||||
onDateChanged(newDateValue: any, dateProperty: TaskFilterProperties) {
|
|
||||||
if (newDateValue) {
|
|
||||||
const momentDate = moment(newDateValue, this.FORMAT_DATE, true);
|
|
||||||
|
|
||||||
if (momentDate.isValid()) {
|
|
||||||
this.getPropertyController(dateProperty).setValue(momentDate.toDate());
|
|
||||||
this.getPropertyController(dateProperty).setErrors(null);
|
|
||||||
} else {
|
|
||||||
this.getPropertyController(dateProperty).setErrors({invalid: true});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
onDateTypeChange(dateType: DateCloudFilterType, property: TaskFilterProperties) {
|
|
||||||
this.editTaskFilterForm.get(property.attributes.dateType).setValue(dateType);
|
|
||||||
}
|
|
||||||
|
|
||||||
onDateRangeFilterChanged(dateRange: DateRangeFilter, property: TaskFilterProperties) {
|
|
||||||
this.editTaskFilterForm.get(property.attributes?.from).setValue(
|
|
||||||
dateRange.startDate ? dateRange.startDate.toISOString() : null
|
|
||||||
);
|
|
||||||
this.editTaskFilterForm.get(property.attributes?.to).setValue(
|
|
||||||
dateRange.endDate ? dateRange.endDate.toISOString() : null
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
onChangedUser(users: IdentityUserModel[], userProperty: TaskFilterProperties) {
|
|
||||||
this.getPropertyController(userProperty).setValue(users[0]?.username);
|
|
||||||
}
|
|
||||||
|
|
||||||
hasError(property: TaskFilterProperties): boolean {
|
|
||||||
return this.getPropertyController(property).errors && this.getPropertyController(property).errors.invalid;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return true if both filters are same
|
|
||||||
* @param editedQuery, @param currentQuery
|
|
||||||
*/
|
|
||||||
compareFilters(editedQuery: TaskFilterCloudModel, currentQuery: TaskFilterCloudModel): boolean {
|
|
||||||
return JSON.stringify(editedQuery).toLowerCase() === JSON.stringify(currentQuery).toLowerCase();
|
|
||||||
}
|
|
||||||
|
|
||||||
getRunningApplications() {
|
|
||||||
this.appsProcessCloudService
|
|
||||||
.getDeployedApplicationsByStatus(EditTaskFilterCloudComponent.APP_RUNNING_STATUS, this.role)
|
|
||||||
.pipe(takeUntil(this.onDestroy$))
|
|
||||||
.subscribe((applications: ApplicationInstanceModel[]) => {
|
|
||||||
if (applications && applications.length > 0) {
|
|
||||||
applications.map((application) => {
|
|
||||||
this.applicationNames.push({ label: application.name, value: application.name });
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
getProcessDefinitions() {
|
|
||||||
this.taskCloudService.getProcessDefinitions(this.appName)
|
|
||||||
.pipe(takeUntil(this.onDestroy$))
|
|
||||||
.subscribe((processDefinitions: ProcessDefinitionCloud[]) => {
|
|
||||||
if (processDefinitions && processDefinitions.length > 0) {
|
|
||||||
this.processDefinitionNames.push(this.allProcessDefinitionNamesOption);
|
|
||||||
processDefinitions.map((processDefinition) => {
|
|
||||||
this.processDefinitionNames.push({ label: processDefinition.name, value: processDefinition.name });
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
executeFilterActions(action: TaskFilterAction): void {
|
|
||||||
if (action.actionType === EditTaskFilterCloudComponent.ACTION_SAVE) {
|
|
||||||
this.save(action);
|
|
||||||
} else if (action.actionType === EditTaskFilterCloudComponent.ACTION_SAVE_AS) {
|
|
||||||
this.saveAs(action);
|
|
||||||
} else if (action.actionType === EditTaskFilterCloudComponent.ACTION_DELETE) {
|
|
||||||
this.delete(action);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
save(saveAction: TaskFilterAction): void {
|
|
||||||
this.taskFilterCloudService
|
|
||||||
.updateFilter(this.changedTaskFilter)
|
|
||||||
.pipe(takeUntil(this.onDestroy$))
|
|
||||||
.subscribe(() => {
|
|
||||||
saveAction.filter = this.changedTaskFilter;
|
|
||||||
this.action.emit(saveAction);
|
|
||||||
this.formHasBeenChanged = this.compareFilters(this.changedTaskFilter, this.taskFilter);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
delete(deleteAction: TaskFilterAction): void {
|
|
||||||
this.taskFilterCloudService
|
|
||||||
.deleteFilter(this.taskFilter)
|
|
||||||
.pipe(
|
|
||||||
filter((filters) => {
|
|
||||||
deleteAction.filter = this.taskFilter;
|
|
||||||
this.action.emit(deleteAction);
|
|
||||||
return filters.length === 0;
|
|
||||||
}),
|
|
||||||
switchMap(() => this.restoreDefaultTaskFilters()),
|
|
||||||
takeUntil(this.onDestroy$))
|
|
||||||
.subscribe(() => {});
|
|
||||||
}
|
|
||||||
|
|
||||||
saveAs(saveAsAction: TaskFilterAction): void {
|
|
||||||
const dialogRef = this.dialog.open(TaskFilterDialogCloudComponent, {
|
|
||||||
data: {
|
|
||||||
name: this.translateService.instant(this.taskFilter.name)
|
|
||||||
},
|
|
||||||
height: 'auto',
|
|
||||||
minWidth: '30%'
|
|
||||||
});
|
|
||||||
dialogRef.afterClosed().subscribe((result) => {
|
|
||||||
if (result && result.action === TaskFilterDialogCloudComponent.ACTION_SAVE) {
|
|
||||||
const filterId = Math.random().toString(36).substr(2, 9);
|
|
||||||
const filterKey = this.getSanitizeFilterName(result.name);
|
|
||||||
const newFilter = {
|
|
||||||
name: result.name,
|
|
||||||
icon: result.icon,
|
|
||||||
id: filterId,
|
|
||||||
key: 'custom-' + filterKey
|
|
||||||
};
|
|
||||||
const resultFilter: TaskFilterCloudModel = Object.assign({}, this.changedTaskFilter, newFilter);
|
|
||||||
this.taskFilterCloudService.addFilter(resultFilter)
|
|
||||||
.pipe(takeUntil(this.onDestroy$)).subscribe(() => {
|
|
||||||
saveAsAction.filter = resultFilter;
|
|
||||||
this.action.emit(saveAsAction);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return filter name
|
|
||||||
* @param filterName
|
|
||||||
*/
|
|
||||||
getSanitizeFilterName(filterName: string): string {
|
|
||||||
const nameWithHyphen = this.replaceSpaceWithHyphen(filterName.trim());
|
|
||||||
return nameWithHyphen.toLowerCase();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return name with hyphen
|
|
||||||
* @param name
|
|
||||||
*/
|
|
||||||
replaceSpaceWithHyphen(name: string): string {
|
|
||||||
const regExt = new RegExp(' ', 'g');
|
|
||||||
return name.replace(regExt, '-');
|
|
||||||
}
|
|
||||||
|
|
||||||
restoreDefaultTaskFilters(): Observable<TaskFilterCloudModel[]> {
|
|
||||||
return this.taskFilterCloudService.getTaskListFilters(this.appName);
|
|
||||||
}
|
|
||||||
|
|
||||||
showActions(): boolean {
|
|
||||||
return this.showFilterActions;
|
|
||||||
}
|
|
||||||
|
|
||||||
onExpand(): void {
|
|
||||||
this.toggleFilterActions = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
onClose(): void {
|
|
||||||
this.toggleFilterActions = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
isDateType(property: TaskFilterProperties): boolean {
|
|
||||||
return property.type === 'date';
|
|
||||||
}
|
|
||||||
|
|
||||||
isDateRangeType(property: TaskFilterProperties): boolean {
|
|
||||||
return property.type === 'date-range';
|
|
||||||
}
|
|
||||||
|
|
||||||
isSelectType(property: TaskFilterProperties): boolean {
|
|
||||||
return property.type === 'select';
|
|
||||||
}
|
|
||||||
|
|
||||||
isTextType(property: TaskFilterProperties): boolean {
|
|
||||||
return property.type === 'text';
|
|
||||||
}
|
|
||||||
|
|
||||||
isCheckBoxType(property: TaskFilterProperties): boolean {
|
|
||||||
return property.type === 'checkbox';
|
|
||||||
}
|
|
||||||
|
|
||||||
isUserSelectType(property: TaskFilterProperties): boolean {
|
|
||||||
return property.type === 'people';
|
|
||||||
}
|
|
||||||
|
|
||||||
isDisabledAction(action: TaskFilterAction): boolean {
|
|
||||||
return this.isDisabledForDefaultFilters(action) ? true : this.hasFormChanged(action);
|
|
||||||
}
|
|
||||||
|
|
||||||
isDisabledForDefaultFilters(action: TaskFilterAction): boolean {
|
|
||||||
return (
|
|
||||||
this.taskFilterCloudService.isDefaultFilter(this.taskFilter.name) &&
|
|
||||||
this.actionDisabledForDefault.includes(action.actionType)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
hasFormChanged(action: TaskFilterAction): boolean {
|
|
||||||
if (action.actionType === EditTaskFilterCloudComponent.ACTION_SAVE) {
|
|
||||||
return !this.formHasBeenChanged;
|
|
||||||
}
|
|
||||||
if (action.actionType === EditTaskFilterCloudComponent.ACTION_SAVE_AS) {
|
|
||||||
return !this.formHasBeenChanged;
|
|
||||||
}
|
|
||||||
if (action.actionType === EditTaskFilterCloudComponent.ACTION_DELETE) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
getUserByUsername(username: string): Observable<IdentityUserModel[]> {
|
|
||||||
if (username) {
|
|
||||||
return this.identityUserService.findUserByUsername(username);
|
|
||||||
}
|
|
||||||
return of([]);
|
|
||||||
}
|
|
||||||
|
|
||||||
createFilterActions(): TaskFilterAction[] {
|
|
||||||
return [
|
|
||||||
new TaskFilterAction({
|
|
||||||
actionType: EditTaskFilterCloudComponent.ACTION_SAVE,
|
|
||||||
icon: 'save',
|
|
||||||
tooltip: 'ADF_CLOUD_EDIT_TASK_FILTER.TOOL_TIP.SAVE'
|
|
||||||
}),
|
|
||||||
new TaskFilterAction({
|
|
||||||
actionType: EditTaskFilterCloudComponent.ACTION_SAVE_AS,
|
|
||||||
icon: 'unarchive',
|
|
||||||
tooltip: 'ADF_CLOUD_EDIT_TASK_FILTER.TOOL_TIP.SAVE_AS'
|
|
||||||
}),
|
|
||||||
new TaskFilterAction({
|
|
||||||
actionType: EditTaskFilterCloudComponent.ACTION_DELETE,
|
|
||||||
icon: 'delete',
|
|
||||||
tooltip: 'ADF_CLOUD_EDIT_TASK_FILTER.TOOL_TIP.DELETE'
|
|
||||||
})
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
createLastModifiedProperty(): TaskFilterProperties[] {
|
|
||||||
return [
|
|
||||||
new TaskFilterProperties({
|
|
||||||
label: 'ADF_CLOUD_EDIT_TASK_FILTER.LABEL.LAST_MODIFIED_FROM',
|
|
||||||
type: 'date',
|
|
||||||
key: 'lastModifiedFrom',
|
|
||||||
value: ''
|
|
||||||
}),
|
|
||||||
|
|
||||||
new TaskFilterProperties({
|
|
||||||
label: 'ADF_CLOUD_EDIT_TASK_FILTER.LABEL.LAST_MODIFIED_TO',
|
|
||||||
type: 'date',
|
|
||||||
key: 'lastModifiedTo',
|
|
||||||
value: ''
|
|
||||||
})
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
createTaskFilterProperties(currentTaskFilter: TaskFilterCloudModel): TaskFilterProperties[] {
|
|
||||||
return [
|
|
||||||
new TaskFilterProperties({
|
|
||||||
label: 'ADF_CLOUD_EDIT_TASK_FILTER.LABEL.APP_NAME',
|
|
||||||
type: 'select',
|
|
||||||
key: 'appName',
|
|
||||||
value: currentTaskFilter.appName || '',
|
|
||||||
options: this.applicationNames
|
|
||||||
}),
|
|
||||||
new TaskFilterProperties({
|
|
||||||
label: 'ADF_CLOUD_EDIT_TASK_FILTER.LABEL.TASK_ID',
|
|
||||||
type: 'text',
|
|
||||||
key: 'taskId',
|
|
||||||
value: ''
|
|
||||||
}),
|
|
||||||
new TaskFilterProperties({
|
|
||||||
label: 'ADF_CLOUD_EDIT_TASK_FILTER.LABEL.STATUS',
|
|
||||||
type: 'select',
|
|
||||||
key: 'status',
|
|
||||||
value: currentTaskFilter.status || this.status[0].value,
|
|
||||||
options: this.status
|
|
||||||
}),
|
|
||||||
new TaskFilterProperties({
|
|
||||||
label: 'ADF_CLOUD_EDIT_TASK_FILTER.LABEL.ASSIGNMENT',
|
|
||||||
type: 'text',
|
|
||||||
key: 'assignee',
|
|
||||||
value: currentTaskFilter.assignee || ''
|
|
||||||
}),
|
|
||||||
new TaskFilterProperties({
|
|
||||||
label: 'ADF_CLOUD_EDIT_TASK_FILTER.LABEL.PROCESS_DEF_NAME',
|
|
||||||
type: 'select',
|
|
||||||
key: 'processDefinitionName',
|
|
||||||
value: currentTaskFilter.processDefinitionName || '',
|
|
||||||
options: this.processDefinitionNames
|
|
||||||
}),
|
|
||||||
new TaskFilterProperties({
|
|
||||||
label: 'ADF_CLOUD_EDIT_TASK_FILTER.LABEL.PROCESS_INSTANCE_ID',
|
|
||||||
type: 'text',
|
|
||||||
key: 'processInstanceId',
|
|
||||||
value: currentTaskFilter.processInstanceId || ''
|
|
||||||
}),
|
|
||||||
new TaskFilterProperties({
|
|
||||||
label: 'ADF_CLOUD_EDIT_TASK_FILTER.LABEL.PROCESS_DEF_ID',
|
|
||||||
type: 'text',
|
|
||||||
key: 'processDefinitionId',
|
|
||||||
value: currentTaskFilter.processDefinitionId || ''
|
|
||||||
}),
|
|
||||||
new TaskFilterProperties({
|
|
||||||
label: 'ADF_CLOUD_EDIT_TASK_FILTER.LABEL.TASK_NAME',
|
|
||||||
type: 'text',
|
|
||||||
key: 'taskName',
|
|
||||||
value: currentTaskFilter.taskName || ''
|
|
||||||
}),
|
|
||||||
new TaskFilterProperties({
|
|
||||||
label: 'ADF_CLOUD_EDIT_TASK_FILTER.LABEL.PARENT_TASK_ID',
|
|
||||||
type: 'text',
|
|
||||||
key: 'parentTaskId',
|
|
||||||
value: currentTaskFilter.parentTaskId || ''
|
|
||||||
}),
|
|
||||||
new TaskFilterProperties({
|
|
||||||
label: 'ADF_CLOUD_EDIT_TASK_FILTER.LABEL.PRIORITY',
|
|
||||||
type: 'text',
|
|
||||||
key: 'priority',
|
|
||||||
value: currentTaskFilter.priority || ''
|
|
||||||
}),
|
|
||||||
new TaskFilterProperties({
|
|
||||||
label: 'ADF_CLOUD_EDIT_TASK_FILTER.LABEL.OWNER',
|
|
||||||
type: 'text',
|
|
||||||
key: 'owner',
|
|
||||||
value: currentTaskFilter.owner || ''
|
|
||||||
}),
|
|
||||||
new TaskFilterProperties({
|
|
||||||
label: 'ADF_CLOUD_EDIT_TASK_FILTER.LABEL.CREATED_DATE',
|
|
||||||
type: 'date',
|
|
||||||
key: 'createdDate',
|
|
||||||
value: ''
|
|
||||||
}),
|
|
||||||
new TaskFilterProperties({
|
|
||||||
label: 'ADF_CLOUD_EDIT_TASK_FILTER.LABEL.DUE_DATE',
|
|
||||||
type: 'date',
|
|
||||||
key: 'dueDate',
|
|
||||||
value: ''
|
|
||||||
}),
|
|
||||||
new TaskFilterProperties({
|
|
||||||
label: 'ADF_CLOUD_EDIT_TASK_FILTER.LABEL.SORT',
|
|
||||||
type: 'select',
|
|
||||||
key: 'sort',
|
|
||||||
value: currentTaskFilter.sort || this.createSortProperties[0].value,
|
|
||||||
options: this.createSortProperties
|
|
||||||
}),
|
|
||||||
new TaskFilterProperties({
|
|
||||||
label: 'ADF_CLOUD_EDIT_TASK_FILTER.LABEL.DIRECTION',
|
|
||||||
type: 'select',
|
|
||||||
key: 'order',
|
|
||||||
value: currentTaskFilter.order || this.directions[0].value,
|
|
||||||
options: this.directions
|
|
||||||
}),
|
|
||||||
new TaskFilterProperties({
|
|
||||||
label: 'ADF_CLOUD_EDIT_TASK_FILTER.LABEL.STAND_ALONE',
|
|
||||||
type: 'checkbox',
|
|
||||||
key: 'standalone',
|
|
||||||
value: currentTaskFilter.standalone || false
|
|
||||||
}),
|
|
||||||
new TaskFilterProperties({
|
|
||||||
label: 'ADF_CLOUD_EDIT_TASK_FILTER.LABEL.DUE_DATE',
|
|
||||||
type: 'date-range',
|
|
||||||
key: 'dueDateRange',
|
|
||||||
attributes: { dateType: 'dueDateType', from: '_dueDateFrom', to: '_dueDateTo'},
|
|
||||||
value: {
|
|
||||||
dueDateType: currentTaskFilter.dueDateType || null,
|
|
||||||
_dueDateFrom: currentTaskFilter.dueDateFrom || null,
|
|
||||||
_dueDateTo: currentTaskFilter.dueDateTo || null
|
|
||||||
},
|
|
||||||
dateFilterOptions: [
|
|
||||||
DateCloudFilterType.NO_DATE,
|
|
||||||
DateCloudFilterType.TODAY,
|
|
||||||
DateCloudFilterType.TOMORROW,
|
|
||||||
DateCloudFilterType.NEXT_7_DAYS,
|
|
||||||
DateCloudFilterType.RANGE
|
|
||||||
]
|
|
||||||
}),
|
|
||||||
new TaskFilterProperties({
|
|
||||||
label: 'ADF_CLOUD_EDIT_TASK_FILTER.LABEL.COMPLETED_BY',
|
|
||||||
type: 'people',
|
|
||||||
key: 'completedBy',
|
|
||||||
value: this.getUserByUsername(currentTaskFilter.completedBy),
|
|
||||||
selectionMode: 'single'
|
|
||||||
})
|
|
||||||
];
|
|
||||||
}
|
|
||||||
}
|
|
@ -0,0 +1,109 @@
|
|||||||
|
<mat-accordion [hideToggle]="isLoading">
|
||||||
|
<mat-expansion-panel (afterExpand)="onExpand()"
|
||||||
|
(closed)="onClose()">
|
||||||
|
<mat-expansion-panel-header *ngIf="taskFilter"
|
||||||
|
id="adf-edit-task-filter-expansion-header">
|
||||||
|
<ng-container *ngIf="!isLoading; else loadingTemplate">
|
||||||
|
<mat-panel-title *ngIf="showTaskFilterName"
|
||||||
|
fxLayoutAlign="space-between center"
|
||||||
|
id="adf-edit-task-filter-title-id">{{taskFilter.name | translate}}</mat-panel-title>
|
||||||
|
<mat-panel-description fxLayoutAlign="space-between center"
|
||||||
|
id="adf-edit-task-filter-sub-title-id">
|
||||||
|
<span *ngIf="showTitle">{{ 'ADF_CLOUD_EDIT_TASK_FILTER.TITLE' | translate}}</span>
|
||||||
|
<div *ngIf="showFilterActions"
|
||||||
|
class="adf-cloud-edit-task-filter-actions">
|
||||||
|
<ng-container *ngIf="toggleFilterActions">
|
||||||
|
<button *ngFor="let filterAction of taskFilterActions"
|
||||||
|
mat-icon-button
|
||||||
|
matTooltip="{{ filterAction.tooltip | translate}}"
|
||||||
|
[attr.data-automation-id]="'adf-filter-action-' + filterAction.actionType"
|
||||||
|
[disabled]="isDisabledAction(filterAction)"
|
||||||
|
(click)="executeFilterActions(filterAction)">
|
||||||
|
<mat-icon>{{filterAction.icon}}</mat-icon>
|
||||||
|
</button>
|
||||||
|
</ng-container>
|
||||||
|
</div>
|
||||||
|
</mat-panel-description>
|
||||||
|
</ng-container>
|
||||||
|
<ng-template #loadingTemplate>
|
||||||
|
<div class="adf-cloud-edit-task-filter-loading-margin">
|
||||||
|
<mat-spinner [diameter]="30"></mat-spinner>
|
||||||
|
</div>
|
||||||
|
</ng-template>
|
||||||
|
</mat-expansion-panel-header>
|
||||||
|
<ng-container *ngIf="!isLoading;">
|
||||||
|
<form [formGroup]="editTaskFilterForm"
|
||||||
|
*ngIf="editTaskFilterForm">
|
||||||
|
<div fxLayout="row wrap"
|
||||||
|
fxLayout.xs="column"
|
||||||
|
fxLayoutGap="10px"
|
||||||
|
fxLayoutAlign="start center">
|
||||||
|
<ng-container *ngFor="let taskFilterProperty of taskFilterProperties">
|
||||||
|
<mat-form-field fxFlex="23%"
|
||||||
|
*ngIf="isSelectType(taskFilterProperty)"
|
||||||
|
[attr.data-automation-id]="taskFilterProperty.key">
|
||||||
|
<mat-select placeholder="{{taskFilterProperty.label | translate}}"
|
||||||
|
[formControlName]="taskFilterProperty.key"
|
||||||
|
[attr.data-automation-id]="'adf-cloud-edit-task-property-' + taskFilterProperty.key">
|
||||||
|
<mat-option *ngFor="let propertyOption of taskFilterProperty.options"
|
||||||
|
[value]="propertyOption.value"
|
||||||
|
[attr.data-automation-id]="'adf-cloud-edit-task-property-options-' + taskFilterProperty.key">
|
||||||
|
{{ propertyOption.label }}
|
||||||
|
</mat-option>
|
||||||
|
</mat-select>
|
||||||
|
</mat-form-field>
|
||||||
|
<mat-form-field fxFlex="23%"
|
||||||
|
*ngIf="isTextType(taskFilterProperty)"
|
||||||
|
[attr.data-automation-id]="taskFilterProperty.key">
|
||||||
|
<input matInput
|
||||||
|
[formControlName]="taskFilterProperty.key"
|
||||||
|
type="text"
|
||||||
|
placeholder="{{taskFilterProperty.label | translate}}"
|
||||||
|
[attr.data-automation-id]="'adf-cloud-edit-task-property-' + taskFilterProperty.key" />
|
||||||
|
</mat-form-field>
|
||||||
|
<mat-form-field fxFlex="23%"
|
||||||
|
*ngIf="isDateType(taskFilterProperty)"
|
||||||
|
[attr.data-automation-id]="taskFilterProperty.key">
|
||||||
|
<mat-label>{{taskFilterProperty.label | translate}}</mat-label>
|
||||||
|
<input matInput
|
||||||
|
(keyup)="onDateChanged($event.srcElement.value, taskFilterProperty)"
|
||||||
|
(dateChange)="onDateChanged($event.value, taskFilterProperty)"
|
||||||
|
[matDatepicker]="dateController"
|
||||||
|
placeholder="{{taskFilterProperty.label | translate}}"
|
||||||
|
[attr.data-automation-id]="'adf-cloud-edit-task-`perty-' + taskFilterProperty.key">
|
||||||
|
<mat-datepicker-toggle matSuffix
|
||||||
|
[for]="dateController"
|
||||||
|
[attr.data-automation-id]="'adf-cloud-edit-task-property-date-toggle-' + taskFilterProperty.key">
|
||||||
|
</mat-datepicker-toggle>
|
||||||
|
<mat-datepicker #dateController
|
||||||
|
[attr.data-automation-id]="'adf-cloud-edit-task-property-date-picker-' + taskFilterProperty.key">
|
||||||
|
</mat-datepicker>
|
||||||
|
<div class="adf-edit-task-filter-date-error-container">
|
||||||
|
<div *ngIf="hasError(taskFilterProperty)">
|
||||||
|
<div class="adf-error-text">{{'ADF_TASK_LIST.START_TASK.FORM.ERROR.DATE'|translate}}
|
||||||
|
</div>
|
||||||
|
<mat-icon class="adf-error-icon">warning</mat-icon>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</mat-form-field>
|
||||||
|
<div class="adf-edit-task-filter-checkbox"
|
||||||
|
*ngIf="isCheckBoxType(taskFilterProperty)">
|
||||||
|
<mat-checkbox color="primary"
|
||||||
|
[formControlName]="taskFilterProperty.key"
|
||||||
|
[attr.data-automation-id]="taskFilterProperty.key">
|
||||||
|
{{taskFilterProperty.label | translate}}
|
||||||
|
</mat-checkbox>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<adf-cloud-date-range-filter *ngIf="isDateRangeType(taskFilterProperty)"
|
||||||
|
[processFilterProperty]="taskFilterProperty"
|
||||||
|
[options]="taskFilterProperty.dateFilterOptions"
|
||||||
|
(dateTypeChange)="onDateTypeChange($event, taskFilterProperty)"
|
||||||
|
(dateChanged)="onDateRangeFilterChanged($event, taskFilterProperty)">
|
||||||
|
</adf-cloud-date-range-filter>
|
||||||
|
</ng-container>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</ng-container>
|
||||||
|
</mat-expansion-panel>
|
||||||
|
</mat-accordion>
|
@ -0,0 +1,410 @@
|
|||||||
|
/*!
|
||||||
|
* @license
|
||||||
|
* Copyright 2019 Alfresco Software, Ltd.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { OnChanges, SimpleChanges, OnInit, OnDestroy, Directive, Input, Output, EventEmitter } from '@angular/core';
|
||||||
|
import { FilterOptions, TaskFilterAction, TaskFilterProperties } from '../../models/filter-cloud.model';
|
||||||
|
import { TaskCloudService } from './../../../services/task-cloud.service';
|
||||||
|
import { AppsProcessCloudService } from './../../../../app/services/apps-process-cloud.service';
|
||||||
|
import { ApplicationInstanceModel } from './../../../../app/models/application-instance.model';
|
||||||
|
import { ProcessDefinitionCloud } from './../../../../models/process-definition-cloud.model';
|
||||||
|
import { DateCloudFilterType, DateRangeFilter } from '../../../../models/date-cloud-filter.model';
|
||||||
|
import moment, { Moment } from 'moment';
|
||||||
|
import { AbstractControl, FormBuilder, FormGroup } from '@angular/forms';
|
||||||
|
import { debounceTime, filter, takeUntil } from 'rxjs/operators';
|
||||||
|
import { Subject } from 'rxjs';
|
||||||
|
import { DateAdapter } from '@angular/material/core';
|
||||||
|
import { UserPreferencesService, UserPreferenceValues } from '@alfresco/adf-core';
|
||||||
|
|
||||||
|
@Directive()
|
||||||
|
// tslint:disable-next-line: directive-class-suffix
|
||||||
|
export abstract class BaseEditTaskFilterCloudComponent implements OnInit, OnChanges, OnDestroy {
|
||||||
|
|
||||||
|
public static ACTION_SAVE = 'save';
|
||||||
|
public static ACTION_SAVE_AS = 'saveAs';
|
||||||
|
public static ACTION_DELETE = 'delete';
|
||||||
|
public static APP_RUNNING_STATUS: string = 'RUNNING';
|
||||||
|
public static APPLICATION_NAME: string = 'appName';
|
||||||
|
public static PROCESS_DEFINITION_NAME: string = 'processDefinitionName';
|
||||||
|
public static LAST_MODIFIED: string = 'lastModified';
|
||||||
|
public static SORT: string = 'sort';
|
||||||
|
public static ORDER: string = 'order';
|
||||||
|
public static DEFAULT_ACTIONS = ['save', 'saveAs', 'delete'];
|
||||||
|
public static FORMAT_DATE: string = 'DD/MM/YYYY';
|
||||||
|
public static DIRECTIONS = [
|
||||||
|
{ label: 'ASC', value: 'ASC' },
|
||||||
|
{ label: 'DESC', value: 'DESC' }
|
||||||
|
];
|
||||||
|
public static ACTIONS_DISABLED_BY_DEFAULT = [
|
||||||
|
BaseEditTaskFilterCloudComponent.ACTION_SAVE,
|
||||||
|
BaseEditTaskFilterCloudComponent.ACTION_DELETE
|
||||||
|
];
|
||||||
|
|
||||||
|
/** (required) Name of the app. */
|
||||||
|
@Input()
|
||||||
|
appName: string = '';
|
||||||
|
|
||||||
|
/** (required) ID of the task filter. */
|
||||||
|
@Input()
|
||||||
|
id: string;
|
||||||
|
|
||||||
|
/** Toggles the title. */
|
||||||
|
@Input()
|
||||||
|
showTitle = true;
|
||||||
|
|
||||||
|
/** Toggles display of task filter name */
|
||||||
|
@Input()
|
||||||
|
showTaskFilterName = true;
|
||||||
|
|
||||||
|
/** List of task filter properties to display. */
|
||||||
|
@Input()
|
||||||
|
filterProperties: string[] = [];
|
||||||
|
|
||||||
|
/** user role. */
|
||||||
|
@Input()
|
||||||
|
role: string = '';
|
||||||
|
|
||||||
|
/** Toggles the filter actions. */
|
||||||
|
@Input()
|
||||||
|
showFilterActions = true;
|
||||||
|
|
||||||
|
/** List of task filter actions. */
|
||||||
|
@Input()
|
||||||
|
actions: string[] = BaseEditTaskFilterCloudComponent.DEFAULT_ACTIONS;
|
||||||
|
|
||||||
|
/** List of sort properties to display. */
|
||||||
|
@Input()
|
||||||
|
sortProperties: string[] = [];
|
||||||
|
|
||||||
|
/** Emitted when a filter action occurs (i.e Save, Save As, Delete). */
|
||||||
|
@Output()
|
||||||
|
action: EventEmitter<TaskFilterAction> = new EventEmitter();
|
||||||
|
|
||||||
|
protected applicationNames: any[] = [];
|
||||||
|
protected processDefinitionNames: any[] = [];
|
||||||
|
protected formHasBeenChanged = false;
|
||||||
|
editTaskFilterForm: FormGroup;
|
||||||
|
taskFilterProperties: TaskFilterProperties[] = [];
|
||||||
|
taskFilterActions: TaskFilterAction[] = [];
|
||||||
|
toggleFilterActions: boolean = false;
|
||||||
|
allProcessDefinitionNamesOption = { label: 'All', value: '' };
|
||||||
|
|
||||||
|
protected onDestroy$ = new Subject<boolean>();
|
||||||
|
isLoading: boolean = false;
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
protected formBuilder: FormBuilder,
|
||||||
|
protected dateAdapter: DateAdapter<Moment>,
|
||||||
|
protected userPreferencesService: UserPreferencesService,
|
||||||
|
protected appsProcessCloudService: AppsProcessCloudService,
|
||||||
|
protected taskCloudService: TaskCloudService) {
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnInit() {
|
||||||
|
this.userPreferencesService
|
||||||
|
.select(UserPreferenceValues.Locale)
|
||||||
|
.pipe(takeUntil(this.onDestroy$))
|
||||||
|
.subscribe(locale => this.dateAdapter.setLocale(locale));
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnChanges(changes: SimpleChanges) {
|
||||||
|
const id = changes['id'];
|
||||||
|
if (id && id.currentValue !== id.previousValue) {
|
||||||
|
this.retrieveTaskFilterAndBuildForm();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnDestroy() {
|
||||||
|
this.onDestroy$.next(true);
|
||||||
|
this.onDestroy$.complete();
|
||||||
|
}
|
||||||
|
|
||||||
|
createFilterActions(): TaskFilterAction[] {
|
||||||
|
return [
|
||||||
|
new TaskFilterAction({
|
||||||
|
actionType: BaseEditTaskFilterCloudComponent.ACTION_SAVE,
|
||||||
|
icon: 'save',
|
||||||
|
tooltip: 'ADF_CLOUD_EDIT_TASK_FILTER.TOOL_TIP.SAVE'
|
||||||
|
}),
|
||||||
|
new TaskFilterAction({
|
||||||
|
actionType: BaseEditTaskFilterCloudComponent.ACTION_SAVE_AS,
|
||||||
|
icon: 'unarchive',
|
||||||
|
tooltip: 'ADF_CLOUD_EDIT_TASK_FILTER.TOOL_TIP.SAVE_AS'
|
||||||
|
}),
|
||||||
|
new TaskFilterAction({
|
||||||
|
actionType: BaseEditTaskFilterCloudComponent.ACTION_DELETE,
|
||||||
|
icon: 'delete',
|
||||||
|
tooltip: 'ADF_CLOUD_EDIT_TASK_FILTER.TOOL_TIP.DELETE'
|
||||||
|
})
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
hasFormChanged(action: TaskFilterAction): boolean {
|
||||||
|
if (action.actionType === BaseEditTaskFilterCloudComponent.ACTION_SAVE) {
|
||||||
|
return !this.formHasBeenChanged;
|
||||||
|
}
|
||||||
|
if (action.actionType === BaseEditTaskFilterCloudComponent.ACTION_SAVE_AS) {
|
||||||
|
return !this.formHasBeenChanged;
|
||||||
|
}
|
||||||
|
if (action.actionType === BaseEditTaskFilterCloudComponent.ACTION_DELETE) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
onExpand(): void {
|
||||||
|
this.toggleFilterActions = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
onClose(): void {
|
||||||
|
this.toggleFilterActions = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
isDateType(property: TaskFilterProperties): boolean {
|
||||||
|
return property.type === 'date';
|
||||||
|
}
|
||||||
|
|
||||||
|
isDateRangeType(property: TaskFilterProperties): boolean {
|
||||||
|
return property.type === 'date-range';
|
||||||
|
}
|
||||||
|
|
||||||
|
isSelectType(property: TaskFilterProperties): boolean {
|
||||||
|
return property.type === 'select';
|
||||||
|
}
|
||||||
|
|
||||||
|
isTextType(property: TaskFilterProperties): boolean {
|
||||||
|
return property.type === 'text';
|
||||||
|
}
|
||||||
|
|
||||||
|
isCheckBoxType(property: TaskFilterProperties): boolean {
|
||||||
|
return property.type === 'checkbox';
|
||||||
|
}
|
||||||
|
|
||||||
|
isDisabledAction(action: TaskFilterAction): boolean {
|
||||||
|
return this.isDisabledForDefaultFilters(action) ? true : this.hasFormChanged(action);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return filter name
|
||||||
|
* @param filterName
|
||||||
|
*/
|
||||||
|
getSanitizeFilterName(filterName: string): string {
|
||||||
|
const nameWithHyphen = this.replaceSpaceWithHyphen(filterName.trim());
|
||||||
|
return nameWithHyphen.toLowerCase();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return name with hyphen
|
||||||
|
* @param name
|
||||||
|
*/
|
||||||
|
replaceSpaceWithHyphen(name: string): string {
|
||||||
|
const regExt = new RegExp(' ', 'g');
|
||||||
|
return name.replace(regExt, '-');
|
||||||
|
}
|
||||||
|
|
||||||
|
executeFilterActions(action: TaskFilterAction): void {
|
||||||
|
if (action.actionType === BaseEditTaskFilterCloudComponent.ACTION_SAVE) {
|
||||||
|
this.save(action);
|
||||||
|
} else if (action.actionType === BaseEditTaskFilterCloudComponent.ACTION_SAVE_AS) {
|
||||||
|
this.saveAs(action);
|
||||||
|
} else if (action.actionType === BaseEditTaskFilterCloudComponent.ACTION_DELETE) {
|
||||||
|
this.delete(action);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
getRunningApplications() {
|
||||||
|
this.appsProcessCloudService
|
||||||
|
.getDeployedApplicationsByStatus(BaseEditTaskFilterCloudComponent.APP_RUNNING_STATUS, this.role)
|
||||||
|
.pipe(takeUntil(this.onDestroy$))
|
||||||
|
.subscribe((applications: ApplicationInstanceModel[]) => {
|
||||||
|
if (applications && applications.length > 0) {
|
||||||
|
applications.map((application) => {
|
||||||
|
this.applicationNames.push({ label: application.name, value: application.name });
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
getProcessDefinitions() {
|
||||||
|
this.taskCloudService.getProcessDefinitions(this.appName)
|
||||||
|
.pipe(takeUntil(this.onDestroy$))
|
||||||
|
.subscribe((processDefinitions: ProcessDefinitionCloud[]) => {
|
||||||
|
if (processDefinitions && processDefinitions.length > 0) {
|
||||||
|
this.processDefinitionNames.push(this.allProcessDefinitionNamesOption);
|
||||||
|
processDefinitions.map((processDefinition) => {
|
||||||
|
this.processDefinitionNames.push({ label: processDefinition.name, value: processDefinition.name });
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
checkMandatoryActions(): void {
|
||||||
|
if (this.actions === undefined || this.actions.length === 0) {
|
||||||
|
this.actions = BaseEditTaskFilterCloudComponent.DEFAULT_ACTIONS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private isValidAction(actions: string[], action: any): boolean {
|
||||||
|
return actions ? actions.indexOf(action.actionType) >= 0 : true;
|
||||||
|
}
|
||||||
|
|
||||||
|
isFormValid(): boolean {
|
||||||
|
return this.editTaskFilterForm.valid;
|
||||||
|
}
|
||||||
|
|
||||||
|
getPropertyController(property: TaskFilterProperties): AbstractControl {
|
||||||
|
return this.editTaskFilterForm.get(property.key);
|
||||||
|
}
|
||||||
|
|
||||||
|
onDateChanged(newDateValue: any, dateProperty: TaskFilterProperties) {
|
||||||
|
if (newDateValue) {
|
||||||
|
const momentDate = moment(newDateValue, BaseEditTaskFilterCloudComponent.FORMAT_DATE, true);
|
||||||
|
|
||||||
|
if (momentDate.isValid()) {
|
||||||
|
this.getPropertyController(dateProperty).setValue(momentDate.toDate());
|
||||||
|
this.getPropertyController(dateProperty).setErrors(null);
|
||||||
|
} else {
|
||||||
|
this.getPropertyController(dateProperty).setErrors({ invalid: true });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onDateRangeFilterChanged(dateRange: DateRangeFilter, property: TaskFilterProperties) {
|
||||||
|
this.editTaskFilterForm.get(property.attributes?.from).setValue(
|
||||||
|
dateRange.startDate ? dateRange.startDate.toISOString() : null
|
||||||
|
);
|
||||||
|
this.editTaskFilterForm.get(property.attributes?.to).setValue(
|
||||||
|
dateRange.endDate ? dateRange.endDate.toISOString() : null
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
hasError(property: TaskFilterProperties): boolean {
|
||||||
|
return this.getPropertyController(property).errors && this.getPropertyController(property).errors.invalid;
|
||||||
|
}
|
||||||
|
|
||||||
|
hasLastModifiedProperty(): boolean {
|
||||||
|
return this.filterProperties.indexOf(BaseEditTaskFilterCloudComponent.LAST_MODIFIED) >= 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
get createSortProperties(): FilterOptions[] {
|
||||||
|
this.checkMandatorySortProperties();
|
||||||
|
const sortProperties = this.sortProperties.map((property: string) => {
|
||||||
|
return <FilterOptions> { label: property.charAt(0).toUpperCase() + property.slice(1), value: property };
|
||||||
|
});
|
||||||
|
return sortProperties;
|
||||||
|
}
|
||||||
|
|
||||||
|
createAndFilterActions(): TaskFilterAction[] {
|
||||||
|
this.checkMandatoryActions();
|
||||||
|
return this.createFilterActions().filter(action => this.isValidAction(this.actions, action));
|
||||||
|
}
|
||||||
|
|
||||||
|
isValidProperty(filterProperties: string[], filterProperty: any): boolean {
|
||||||
|
return filterProperties ? filterProperties.indexOf(filterProperty.key) >= 0 : true;
|
||||||
|
}
|
||||||
|
|
||||||
|
checkForProperty(property: string): boolean {
|
||||||
|
return this.filterProperties ? this.filterProperties.indexOf(property) >= 0 : false;
|
||||||
|
}
|
||||||
|
|
||||||
|
hasSortProperty(): boolean {
|
||||||
|
return this.filterProperties.indexOf(BaseEditTaskFilterCloudComponent.SORT) >= 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
removeOrderProperty(filteredProperties: TaskFilterProperties[]): TaskFilterProperties[] {
|
||||||
|
if (filteredProperties && filteredProperties.length > 0) {
|
||||||
|
return filteredProperties.filter(property => property.key !== BaseEditTaskFilterCloudComponent.ORDER);
|
||||||
|
}
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
createAndFilterProperties() {
|
||||||
|
this.checkMandatoryFilterProperties();
|
||||||
|
|
||||||
|
if (this.checkForProperty(BaseEditTaskFilterCloudComponent.APPLICATION_NAME)) {
|
||||||
|
this.applicationNames = [];
|
||||||
|
this.getRunningApplications();
|
||||||
|
}
|
||||||
|
if (this.checkForProperty(BaseEditTaskFilterCloudComponent.PROCESS_DEFINITION_NAME)) {
|
||||||
|
this.processDefinitionNames = [];
|
||||||
|
this.getProcessDefinitions();
|
||||||
|
}
|
||||||
|
|
||||||
|
const defaultProperties = this.createTaskFilterProperties();
|
||||||
|
let filteredProperties = defaultProperties.filter((filterProperty: TaskFilterProperties) => this.isValidProperty(this.filterProperties, filterProperty));
|
||||||
|
|
||||||
|
if (!this.hasSortProperty()) {
|
||||||
|
filteredProperties = this.removeOrderProperty(filteredProperties);
|
||||||
|
}
|
||||||
|
|
||||||
|
return filteredProperties;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check for edit task filter form changes
|
||||||
|
*/
|
||||||
|
onFilterChange() {
|
||||||
|
this.editTaskFilterForm.valueChanges
|
||||||
|
.pipe(
|
||||||
|
debounceTime(200),
|
||||||
|
filter(() => this.isFormValid()),
|
||||||
|
takeUntil(this.onDestroy$)
|
||||||
|
)
|
||||||
|
.subscribe((formValues) => {
|
||||||
|
this.assignNewFilter(formValues);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
getFormControlsConfig(taskFilterProperties: TaskFilterProperties[]): any {
|
||||||
|
const properties = taskFilterProperties.map((property: TaskFilterProperties) => {
|
||||||
|
if (!!property.attributes) {
|
||||||
|
return this.getAttributesControlConfig(property);
|
||||||
|
} else {
|
||||||
|
return { [property.key]: property.value };
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return properties.reduce(((result, current) => Object.assign(result, current)), {});
|
||||||
|
}
|
||||||
|
|
||||||
|
private getAttributesControlConfig(property: TaskFilterProperties) {
|
||||||
|
return Object.values(property.attributes).reduce((result, key) => {
|
||||||
|
result[key] = property.value[key];
|
||||||
|
return result;
|
||||||
|
}, {});
|
||||||
|
}
|
||||||
|
|
||||||
|
buildForm(taskFilterProperties: TaskFilterProperties[]) {
|
||||||
|
this.formHasBeenChanged = false;
|
||||||
|
this.editTaskFilterForm = this.formBuilder.group(this.getFormControlsConfig(taskFilterProperties));
|
||||||
|
this.onFilterChange();
|
||||||
|
}
|
||||||
|
|
||||||
|
onDateTypeChange(dateType: DateCloudFilterType, property: TaskFilterProperties) {
|
||||||
|
this.editTaskFilterForm.get(property.attributes.dateType).setValue(dateType);
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract save(action: TaskFilterAction): void;
|
||||||
|
abstract saveAs(action: TaskFilterAction): void;
|
||||||
|
abstract delete(action: TaskFilterAction): void;
|
||||||
|
abstract checkMandatorySortProperties(): void;
|
||||||
|
abstract checkMandatoryFilterProperties(): void;
|
||||||
|
abstract isDisabledForDefaultFilters(action: TaskFilterAction): boolean;
|
||||||
|
abstract createTaskFilterProperties(): TaskFilterProperties[];
|
||||||
|
abstract retrieveTaskFilterAndBuildForm(): void;
|
||||||
|
abstract assignNewFilter(formValues): void;
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,706 @@
|
|||||||
|
/*!
|
||||||
|
* @license
|
||||||
|
* Copyright 2019 Alfresco Software, Ltd.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
import { SimpleChange } from '@angular/core';
|
||||||
|
import { By } from '@angular/platform-browser';
|
||||||
|
import { setupTestBed } from '@alfresco/adf-core';
|
||||||
|
import { MatDialog } from '@angular/material/dialog';
|
||||||
|
import { of } from 'rxjs';
|
||||||
|
import { debounceTime } from 'rxjs/operators';
|
||||||
|
import { TASK_FILTERS_SERVICE_TOKEN } from '../../../../services/cloud-token.service';
|
||||||
|
import { LocalPreferenceCloudService } from '../../../../services/local-preference-cloud.service';
|
||||||
|
import { ProcessServiceCloudTestingModule } from '../../../../testing/process-service-cloud.testing.module';
|
||||||
|
import { AppsProcessCloudService } from '../../../../app/services/apps-process-cloud.service';
|
||||||
|
import { fakeApplicationInstance } from '../../../../app/mock/app-model.mock';
|
||||||
|
import { TaskFiltersCloudModule } from '../../task-filters-cloud.module';
|
||||||
|
import { ServiceTaskFilterCloudService } from '../../services/service-task-filter-cloud.service';
|
||||||
|
import { TaskCloudService } from '../../../services/task-cloud.service';
|
||||||
|
import { fakeServiceFilter } from '../../mock/task-filters-cloud.mock';
|
||||||
|
import { TranslateModule } from '@ngx-translate/core';
|
||||||
|
import { EditServiceTaskFilterCloudComponent } from './edit-service-task-filter-cloud.component';
|
||||||
|
|
||||||
|
describe('EditServiceTaskFilterCloudComponent', () => {
|
||||||
|
let component: EditServiceTaskFilterCloudComponent;
|
||||||
|
let service: ServiceTaskFilterCloudService;
|
||||||
|
let appsService: AppsProcessCloudService;
|
||||||
|
let fixture: ComponentFixture<EditServiceTaskFilterCloudComponent>;
|
||||||
|
let dialog: MatDialog;
|
||||||
|
let getTaskFilterSpy: jasmine.Spy;
|
||||||
|
let getRunningApplicationsSpy: jasmine.Spy;
|
||||||
|
let taskService: TaskCloudService;
|
||||||
|
|
||||||
|
setupTestBed({
|
||||||
|
imports: [
|
||||||
|
TranslateModule.forRoot(),
|
||||||
|
ProcessServiceCloudTestingModule,
|
||||||
|
TaskFiltersCloudModule
|
||||||
|
],
|
||||||
|
providers: [
|
||||||
|
MatDialog,
|
||||||
|
{ provide: TASK_FILTERS_SERVICE_TOKEN, useClass: LocalPreferenceCloudService }
|
||||||
|
]
|
||||||
|
});
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
fixture = TestBed.createComponent(EditServiceTaskFilterCloudComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
service = TestBed.inject(ServiceTaskFilterCloudService);
|
||||||
|
appsService = TestBed.inject(AppsProcessCloudService);
|
||||||
|
taskService = TestBed.inject(TaskCloudService);
|
||||||
|
dialog = TestBed.inject(MatDialog);
|
||||||
|
spyOn(dialog, 'open').and.returnValue({
|
||||||
|
afterClosed: of({
|
||||||
|
action: EditServiceTaskFilterCloudComponent.ACTION_SAVE,
|
||||||
|
icon: 'icon',
|
||||||
|
name: 'fake-name'
|
||||||
|
})
|
||||||
|
});
|
||||||
|
getTaskFilterSpy = spyOn(service, 'getTaskFilterById').and.returnValue(of(fakeServiceFilter));
|
||||||
|
getRunningApplicationsSpy = spyOn(appsService, 'getDeployedApplicationsByStatus').and.returnValue(of(fakeApplicationInstance));
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(() => fixture.destroy());
|
||||||
|
|
||||||
|
it('should fetch task filter by taskId', () => {
|
||||||
|
const taskFilterIdChange = new SimpleChange(undefined, 'mock-task-filter-id', true);
|
||||||
|
component.ngOnChanges({ 'id': taskFilterIdChange });
|
||||||
|
fixture.detectChanges();
|
||||||
|
fixture.whenStable().then(() => {
|
||||||
|
expect(getTaskFilterSpy).toHaveBeenCalled();
|
||||||
|
expect(component.taskFilter.name).toEqual('FakeInvolvedTasks');
|
||||||
|
expect(component.taskFilter.icon).toEqual('adjust');
|
||||||
|
expect(component.taskFilter.status).toEqual('CREATED');
|
||||||
|
expect(component.taskFilter.order).toEqual('ASC');
|
||||||
|
expect(component.taskFilter.sort).toEqual('id');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should fetch process definitions when processDefinitionName filter property is set', async(() => {
|
||||||
|
const processSpy = spyOn(taskService, 'getProcessDefinitions').and.returnValue(of([{ id: 'fake-id', name: 'fake-name' }]));
|
||||||
|
fixture.detectChanges();
|
||||||
|
component.filterProperties = ['processDefinitionName'];
|
||||||
|
fixture.detectChanges();
|
||||||
|
const taskFilterIdChange = new SimpleChange(null, 'mock-process-filter-id', true);
|
||||||
|
component.ngOnChanges({ 'id': taskFilterIdChange });
|
||||||
|
fixture.detectChanges();
|
||||||
|
const controller = component.editTaskFilterForm.get('processDefinitionName');
|
||||||
|
fixture.detectChanges();
|
||||||
|
fixture.whenStable().then(() => {
|
||||||
|
expect(processSpy).toHaveBeenCalled();
|
||||||
|
expect(controller).toBeDefined();
|
||||||
|
});
|
||||||
|
}));
|
||||||
|
|
||||||
|
it('should display filter name as title', async(() => {
|
||||||
|
const taskFilterIdChange = new SimpleChange(undefined, 'mock-task-filter-id', true);
|
||||||
|
component.ngOnChanges({ 'id': taskFilterIdChange });
|
||||||
|
fixture.detectChanges();
|
||||||
|
const title = fixture.debugElement.nativeElement.querySelector('#adf-edit-task-filter-title-id');
|
||||||
|
const subTitle = fixture.debugElement.nativeElement.querySelector('#adf-edit-task-filter-sub-title-id');
|
||||||
|
expect(title.innerText).toEqual('FakeInvolvedTasks');
|
||||||
|
expect(subTitle.innerText.trim()).toEqual('ADF_CLOUD_EDIT_TASK_FILTER.TITLE');
|
||||||
|
}));
|
||||||
|
|
||||||
|
it('should not display filter name if showFilterName is false', async(() => {
|
||||||
|
const taskFilterIdChange = new SimpleChange(null, 'mock-task-filter-id', true);
|
||||||
|
component.showTaskFilterName = false;
|
||||||
|
component.ngOnChanges({ 'id': taskFilterIdChange });
|
||||||
|
fixture.detectChanges();
|
||||||
|
const title = fixture.debugElement.nativeElement.querySelector('#adf-edit-task-filter-title-id');
|
||||||
|
|
||||||
|
fixture.whenStable().then(() => {
|
||||||
|
expect(title).toBeNull();
|
||||||
|
});
|
||||||
|
}));
|
||||||
|
|
||||||
|
it('should not display mat-spinner if isloading set to false', async(() => {
|
||||||
|
const taskFilterIdChange = new SimpleChange(null, 'mock-task-filter-id', true);
|
||||||
|
component.ngOnChanges({ 'id': taskFilterIdChange });
|
||||||
|
fixture.detectChanges();
|
||||||
|
const title = fixture.debugElement.nativeElement.querySelector('#adf-edit-task-filter-title-id');
|
||||||
|
const subTitle = fixture.debugElement.nativeElement.querySelector('#adf-edit-task-filter-sub-title-id');
|
||||||
|
const matSpinnerElement = fixture.debugElement.nativeElement.querySelector('.adf-cloud-edit-task-filter-loading-margin');
|
||||||
|
|
||||||
|
fixture.whenStable().then(() => {
|
||||||
|
expect(matSpinnerElement).toBeNull();
|
||||||
|
expect(title.innerText).toEqual('FakeInvolvedTasks');
|
||||||
|
expect(subTitle.innerText.trim()).toEqual('ADF_CLOUD_EDIT_TASK_FILTER.TITLE');
|
||||||
|
});
|
||||||
|
}));
|
||||||
|
|
||||||
|
it('should display mat-spinner if isloading set to true', async(() => {
|
||||||
|
component.isLoading = true;
|
||||||
|
const taskFilterIdChange = new SimpleChange(null, 'mock-task-filter-id', true);
|
||||||
|
component.ngOnChanges({ 'id': taskFilterIdChange });
|
||||||
|
fixture.detectChanges();
|
||||||
|
|
||||||
|
const matSpinnerElement = fixture.debugElement.nativeElement.querySelector('.adf-cloud-edit-task-filter-loading-margin');
|
||||||
|
|
||||||
|
fixture.whenStable().then(() => {
|
||||||
|
expect(matSpinnerElement).toBeDefined();
|
||||||
|
});
|
||||||
|
}));
|
||||||
|
|
||||||
|
describe('EditServiceTaskFilter form', () => {
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
const taskFilterIdChange = new SimpleChange(undefined, 'mock-task-filter-id', true);
|
||||||
|
component.ngOnChanges({ 'id': taskFilterIdChange });
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should defined editTaskFilter form ', () => {
|
||||||
|
expect(component.editTaskFilterForm).toBeDefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create editTaskFilter form with default user task properties', async(() => {
|
||||||
|
fixture.detectChanges();
|
||||||
|
fixture.whenStable().then(() => {
|
||||||
|
const appNameController = component.editTaskFilterForm.get('appName');
|
||||||
|
const statusController = component.editTaskFilterForm.get('status');
|
||||||
|
const sortController = component.editTaskFilterForm.get('sort');
|
||||||
|
const orderController = component.editTaskFilterForm.get('order');
|
||||||
|
const activityNameController = component.editTaskFilterForm.get('activityName');
|
||||||
|
expect(component.editTaskFilterForm).toBeDefined();
|
||||||
|
expect(appNameController.value).toBe('mock-app-name');
|
||||||
|
expect(statusController.value).toBe('COMPLETED');
|
||||||
|
expect(sortController.value).toBe('id');
|
||||||
|
expect(orderController.value).toBe('ASC');
|
||||||
|
expect(activityNameController.value).toBe('fake-activity');
|
||||||
|
});
|
||||||
|
}));
|
||||||
|
|
||||||
|
describe('Save & Delete buttons', () => {
|
||||||
|
it('should disable save and delete button for default task filters', async(() => {
|
||||||
|
getTaskFilterSpy.and.returnValue(of({
|
||||||
|
name: 'ADF_CLOUD_SERVICE_TASK_FILTERS.ALL_SERVICE_TASKS',
|
||||||
|
id: 'filter-id',
|
||||||
|
key: 'all-fake-task',
|
||||||
|
icon: 'adjust',
|
||||||
|
sort: 'startDate',
|
||||||
|
status: 'ALL',
|
||||||
|
order: 'DESC'
|
||||||
|
}));
|
||||||
|
|
||||||
|
const taskFilterIdChange = new SimpleChange(null, 'filter-id', true);
|
||||||
|
component.ngOnChanges({ 'id': taskFilterIdChange });
|
||||||
|
fixture.detectChanges();
|
||||||
|
|
||||||
|
component.toggleFilterActions = true;
|
||||||
|
const expansionPanel = fixture.debugElement.nativeElement.querySelector('mat-expansion-panel-header');
|
||||||
|
expansionPanel.click();
|
||||||
|
fixture.detectChanges();
|
||||||
|
fixture.whenStable().then(() => {
|
||||||
|
const saveButton = fixture.debugElement.nativeElement.querySelector('[data-automation-id="adf-filter-action-save"]');
|
||||||
|
expect(saveButton.disabled).toBe(true);
|
||||||
|
const deleteButton = fixture.debugElement.nativeElement.querySelector('[data-automation-id="adf-filter-action-delete"]');
|
||||||
|
expect(deleteButton.disabled).toBe(true);
|
||||||
|
});
|
||||||
|
}));
|
||||||
|
|
||||||
|
it('should enable delete button for custom task filters', async(() => {
|
||||||
|
const taskFilterIdChange = new SimpleChange(null, 'mock-task-filter-id', true);
|
||||||
|
component.ngOnChanges({ 'id': taskFilterIdChange });
|
||||||
|
fixture.detectChanges();
|
||||||
|
|
||||||
|
component.toggleFilterActions = true;
|
||||||
|
const expansionPanel = fixture.debugElement.nativeElement.querySelector('mat-expansion-panel-header');
|
||||||
|
expansionPanel.click();
|
||||||
|
fixture.detectChanges();
|
||||||
|
fixture.whenStable().then(() => {
|
||||||
|
const saveButton = fixture.debugElement.nativeElement.querySelector('[data-automation-id="adf-filter-action-save"]');
|
||||||
|
expect(saveButton.disabled).toBe(true);
|
||||||
|
const deleteButton = fixture.debugElement.nativeElement.querySelector('[data-automation-id="adf-filter-action-delete"]');
|
||||||
|
expect(deleteButton.disabled).toBe(false);
|
||||||
|
});
|
||||||
|
}));
|
||||||
|
|
||||||
|
it('should enable save button if the filter is changed for custom task filters', (done) => {
|
||||||
|
const taskFilterIdChange = new SimpleChange(null, 'mock-task-filter-id', true);
|
||||||
|
component.ngOnChanges({ 'id': taskFilterIdChange });
|
||||||
|
fixture.detectChanges();
|
||||||
|
|
||||||
|
component.toggleFilterActions = true;
|
||||||
|
const expansionPanel = fixture.debugElement.nativeElement.querySelector('mat-expansion-panel-header');
|
||||||
|
expansionPanel.click();
|
||||||
|
fixture.detectChanges();
|
||||||
|
|
||||||
|
component.editTaskFilterForm.valueChanges
|
||||||
|
.pipe(debounceTime(300))
|
||||||
|
.subscribe(() => {
|
||||||
|
const saveButton = fixture.debugElement.nativeElement.querySelector('[data-automation-id="adf-filter-action-save"]');
|
||||||
|
fixture.detectChanges();
|
||||||
|
expect(saveButton.disabled).toBe(false);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
|
||||||
|
const stateElement = fixture.debugElement.nativeElement.querySelector('[data-automation-id="adf-cloud-edit-task-property-sort"] .mat-select-trigger');
|
||||||
|
stateElement.click();
|
||||||
|
fixture.detectChanges();
|
||||||
|
const sortOptions = fixture.debugElement.queryAll(By.css('.mat-option-text'));
|
||||||
|
sortOptions[3].nativeElement.click();
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should disable save button if the filter is not changed for custom filter', async(() => {
|
||||||
|
component.toggleFilterActions = true;
|
||||||
|
const expansionPanel = fixture.debugElement.nativeElement.querySelector('mat-expansion-panel-header');
|
||||||
|
expansionPanel.click();
|
||||||
|
fixture.detectChanges();
|
||||||
|
fixture.whenStable().then(() => {
|
||||||
|
const saveButton = fixture.debugElement.nativeElement.querySelector('[data-automation-id="adf-filter-action-save"]');
|
||||||
|
expect(saveButton.disabled).toBe(true);
|
||||||
|
});
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('SaveAs button', () => {
|
||||||
|
it('should disable saveAs button if the process filter is not changed for default filter', async(() => {
|
||||||
|
getTaskFilterSpy.and.returnValue(of({
|
||||||
|
name: 'ADF_CLOUD_TASK_FILTERS.MY_TASKS',
|
||||||
|
id: 'filter-id',
|
||||||
|
key: 'all-fake-task',
|
||||||
|
icon: 'adjust',
|
||||||
|
sort: 'startDate',
|
||||||
|
status: 'ALL',
|
||||||
|
order: 'DESC'
|
||||||
|
}));
|
||||||
|
|
||||||
|
const taskFilterIdChange = new SimpleChange(null, 'filter-id', true);
|
||||||
|
component.ngOnChanges({ 'id': taskFilterIdChange });
|
||||||
|
fixture.detectChanges();
|
||||||
|
|
||||||
|
component.toggleFilterActions = true;
|
||||||
|
const expansionPanel = fixture.debugElement.nativeElement.querySelector('mat-expansion-panel-header');
|
||||||
|
expansionPanel.click();
|
||||||
|
fixture.detectChanges();
|
||||||
|
fixture.whenStable().then(() => {
|
||||||
|
const saveButton = fixture.debugElement.nativeElement.querySelector('[data-automation-id="adf-filter-action-saveAs"]');
|
||||||
|
expect(saveButton.disabled).toEqual(true);
|
||||||
|
});
|
||||||
|
}));
|
||||||
|
|
||||||
|
it('should disable saveAs button if the process filter is not changed for custom filter', async(() => {
|
||||||
|
component.toggleFilterActions = true;
|
||||||
|
const expansionPanel = fixture.debugElement.nativeElement.querySelector('mat-expansion-panel-header');
|
||||||
|
expansionPanel.click();
|
||||||
|
fixture.detectChanges();
|
||||||
|
fixture.whenStable().then(() => {
|
||||||
|
const saveButton = fixture.debugElement.nativeElement.querySelector('[data-automation-id="adf-filter-action-saveAs"]');
|
||||||
|
expect(saveButton.disabled).toEqual(true);
|
||||||
|
});
|
||||||
|
}));
|
||||||
|
|
||||||
|
it('should enable saveAs button if the filter values are changed for default filter', (done) => {
|
||||||
|
getTaskFilterSpy.and.returnValue(of({
|
||||||
|
name: 'ADF_CLOUD_TASK_FILTERS.MY_TASKS',
|
||||||
|
id: 'filter-id',
|
||||||
|
key: 'all-fake-task',
|
||||||
|
icon: 'adjust',
|
||||||
|
sort: 'startDate',
|
||||||
|
status: 'ALL',
|
||||||
|
order: 'DESC'
|
||||||
|
}));
|
||||||
|
|
||||||
|
const taskFilterIdChange = new SimpleChange(null, 'filter-id', true);
|
||||||
|
component.ngOnChanges({ 'id': taskFilterIdChange });
|
||||||
|
fixture.detectChanges();
|
||||||
|
|
||||||
|
component.toggleFilterActions = true;
|
||||||
|
const expansionPanel = fixture.debugElement.nativeElement.querySelector('mat-expansion-panel-header');
|
||||||
|
expansionPanel.click();
|
||||||
|
fixture.detectChanges();
|
||||||
|
|
||||||
|
component.editTaskFilterForm.valueChanges
|
||||||
|
.pipe(debounceTime(300))
|
||||||
|
.subscribe(() => {
|
||||||
|
const saveButton = fixture.debugElement.nativeElement.querySelector('[data-automation-id="adf-filter-action-saveAs"]');
|
||||||
|
fixture.detectChanges();
|
||||||
|
expect(saveButton.disabled).toEqual(false);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
|
||||||
|
const stateElement = fixture.debugElement.nativeElement.querySelector('[data-automation-id="adf-cloud-edit-task-property-sort"] .mat-select-trigger');
|
||||||
|
stateElement.click();
|
||||||
|
fixture.detectChanges();
|
||||||
|
|
||||||
|
const sortOptions = fixture.debugElement.queryAll(By.css('.mat-option-text'));
|
||||||
|
sortOptions[3].nativeElement.click();
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should enable saveAs button if the filter values are changed for custom filter', (done) => {
|
||||||
|
component.toggleFilterActions = true;
|
||||||
|
const expansionPanel = fixture.debugElement.nativeElement.querySelector('mat-expansion-panel-header');
|
||||||
|
expansionPanel.click();
|
||||||
|
fixture.detectChanges();
|
||||||
|
|
||||||
|
component.editTaskFilterForm.valueChanges
|
||||||
|
.pipe(debounceTime(300))
|
||||||
|
.subscribe(() => {
|
||||||
|
const saveButton = fixture.debugElement.nativeElement.querySelector('[data-automation-id="adf-filter-action-saveAs"]');
|
||||||
|
fixture.detectChanges();
|
||||||
|
expect(saveButton.disabled).toEqual(false);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
|
||||||
|
const stateElement = fixture.debugElement.nativeElement.querySelector('[data-automation-id="adf-cloud-edit-task-property-sort"] .mat-select-trigger');
|
||||||
|
stateElement.click();
|
||||||
|
fixture.detectChanges();
|
||||||
|
|
||||||
|
const sortOptions = fixture.debugElement.queryAll(By.css('.mat-option-text'));
|
||||||
|
sortOptions[3].nativeElement.click();
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should display current task filter details', async(() => {
|
||||||
|
fixture.detectChanges();
|
||||||
|
fixture.whenStable().then(() => {
|
||||||
|
const expansionPanel = fixture.debugElement.nativeElement.querySelector('mat-expansion-panel-header');
|
||||||
|
expansionPanel.click();
|
||||||
|
fixture.detectChanges();
|
||||||
|
const stateElement = fixture.debugElement.nativeElement.querySelector('[data-automation-id="adf-cloud-edit-task-property-status"]');
|
||||||
|
const assigneeElement = fixture.debugElement.nativeElement.querySelector('[data-automation-id="adf-cloud-edit-task-property-assignee"]');
|
||||||
|
const sortElement = fixture.debugElement.nativeElement.querySelector('[data-automation-id="adf-cloud-edit-task-property-sort"]');
|
||||||
|
const orderElement = fixture.debugElement.nativeElement.querySelector('[data-automation-id="adf-cloud-edit-task-property-order"]');
|
||||||
|
expect(assigneeElement).toBeDefined();
|
||||||
|
expect(stateElement.textContent.trim()).toBe('COMPLETED');
|
||||||
|
expect(sortElement.textContent.trim()).toBe('Id');
|
||||||
|
expect(orderElement.textContent.trim()).toBe('ASC');
|
||||||
|
});
|
||||||
|
}));
|
||||||
|
|
||||||
|
it('should display all the statuses that are defined in the task filter', async(() => {
|
||||||
|
|
||||||
|
const expansionPanel = fixture.debugElement.nativeElement.querySelector('mat-expansion-panel-header');
|
||||||
|
expansionPanel.click();
|
||||||
|
fixture.detectChanges();
|
||||||
|
|
||||||
|
const stateElement = fixture.debugElement.nativeElement.querySelector('[data-automation-id="adf-cloud-edit-task-property-status"]');
|
||||||
|
stateElement.click();
|
||||||
|
fixture.detectChanges();
|
||||||
|
|
||||||
|
const statusOptions = fixture.debugElement.queryAll(By.css('[data-automation-id="adf-cloud-edit-task-property-options-status"]'));
|
||||||
|
|
||||||
|
expect(statusOptions[0].nativeElement.textContent.trim()).toBe('ALL');
|
||||||
|
expect(statusOptions[1].nativeElement.textContent.trim()).toBe('STARTED');
|
||||||
|
expect(statusOptions[2].nativeElement.textContent.trim()).toBe('COMPLETED');
|
||||||
|
expect(statusOptions[3].nativeElement.textContent.trim()).toBe('CANCELLED');
|
||||||
|
expect(statusOptions[4].nativeElement.textContent.trim()).toBe('ERROR');
|
||||||
|
}));
|
||||||
|
|
||||||
|
it('should display sort drop down', async(() => {
|
||||||
|
fixture.detectChanges();
|
||||||
|
const expansionPanel = fixture.debugElement.nativeElement.querySelector('mat-expansion-panel-header');
|
||||||
|
expansionPanel.click();
|
||||||
|
fixture.detectChanges();
|
||||||
|
const sortElement = fixture.debugElement.nativeElement.querySelector('[data-automation-id="adf-cloud-edit-task-property-sort"]');
|
||||||
|
sortElement.click();
|
||||||
|
fixture.detectChanges();
|
||||||
|
fixture.whenStable().then(() => {
|
||||||
|
const sortOptions = fixture.debugElement.queryAll(By.css('.mat-option-text'));
|
||||||
|
expect(sortOptions.length).toEqual(4);
|
||||||
|
});
|
||||||
|
}));
|
||||||
|
|
||||||
|
it('should display order drop down', async(() => {
|
||||||
|
fixture.detectChanges();
|
||||||
|
const expansionPanel = fixture.debugElement.nativeElement.querySelector('mat-expansion-panel-header');
|
||||||
|
expansionPanel.click();
|
||||||
|
fixture.detectChanges();
|
||||||
|
const orderElement = fixture.debugElement.nativeElement.querySelector('[data-automation-id="adf-cloud-edit-task-property-order"]');
|
||||||
|
orderElement.click();
|
||||||
|
fixture.detectChanges();
|
||||||
|
fixture.whenStable().then(() => {
|
||||||
|
const orderOptions = fixture.debugElement.queryAll(By.css('.mat-option-text'));
|
||||||
|
expect(orderOptions.length).toEqual(2);
|
||||||
|
});
|
||||||
|
}));
|
||||||
|
|
||||||
|
it('should able to build a editTaskFilter form with default properties if input is empty', async(() => {
|
||||||
|
const taskFilterIdChange = new SimpleChange(undefined, 'mock-task-filter-id', true);
|
||||||
|
component.ngOnChanges({ 'id': taskFilterIdChange });
|
||||||
|
component.filterProperties = [];
|
||||||
|
fixture.detectChanges();
|
||||||
|
const stateController = component.editTaskFilterForm.get('status');
|
||||||
|
const sortController = component.editTaskFilterForm.get('sort');
|
||||||
|
const orderController = component.editTaskFilterForm.get('order');
|
||||||
|
const activityNameController = component.editTaskFilterForm.get('activityName');
|
||||||
|
fixture.whenStable().then(() => {
|
||||||
|
fixture.detectChanges();
|
||||||
|
expect(component.taskFilterProperties.length).toBe(5);
|
||||||
|
expect(component.editTaskFilterForm).toBeDefined();
|
||||||
|
expect(stateController.value).toBe('COMPLETED');
|
||||||
|
expect(sortController.value).toBe('id');
|
||||||
|
expect(orderController.value).toBe('ASC');
|
||||||
|
expect(activityNameController.value).toBe('fake-activity');
|
||||||
|
});
|
||||||
|
}));
|
||||||
|
|
||||||
|
it('should able to fetch running applications when appName property defined in the input', async(() => {
|
||||||
|
component.filterProperties = ['appName', 'processInstanceId', 'priority'];
|
||||||
|
fixture.detectChanges();
|
||||||
|
const taskFilterIdChange = new SimpleChange(undefined, 'mock-task-filter-id', true);
|
||||||
|
component.ngOnChanges({ 'id': taskFilterIdChange });
|
||||||
|
const appController = component.editTaskFilterForm.get('appName');
|
||||||
|
fixture.detectChanges();
|
||||||
|
fixture.whenStable().then(() => {
|
||||||
|
expect(getRunningApplicationsSpy).toHaveBeenCalled();
|
||||||
|
expect(appController).toBeDefined();
|
||||||
|
expect(appController.value).toBe('mock-app-name');
|
||||||
|
});
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('sort properties', () => {
|
||||||
|
|
||||||
|
it('should display default sort properties', async(() => {
|
||||||
|
const taskFilterIdChange = new SimpleChange(undefined, 'mock-task-filter-id', true);
|
||||||
|
component.ngOnChanges({ 'id': taskFilterIdChange });
|
||||||
|
fixture.detectChanges();
|
||||||
|
const expansionPanel = fixture.debugElement.nativeElement.querySelector('mat-expansion-panel-header');
|
||||||
|
expansionPanel.click();
|
||||||
|
fixture.detectChanges();
|
||||||
|
const sortElement = fixture.debugElement.nativeElement.querySelector('[data-automation-id="adf-cloud-edit-task-property-sort"]');
|
||||||
|
sortElement.click();
|
||||||
|
fixture.detectChanges();
|
||||||
|
fixture.whenStable().then(() => {
|
||||||
|
const sortController = component.editTaskFilterForm.get('sort');
|
||||||
|
const sortOptions = fixture.debugElement.queryAll(By.css('.mat-option-text'));
|
||||||
|
expect(sortController.value).toBe('id');
|
||||||
|
expect(sortOptions.length).toEqual(4);
|
||||||
|
});
|
||||||
|
}));
|
||||||
|
|
||||||
|
it('should display sort properties when sort properties are specified', async(() => {
|
||||||
|
component.sortProperties = ['id', 'name', 'processInstanceId'];
|
||||||
|
getTaskFilterSpy.and.returnValue(of({
|
||||||
|
sort: 'my-custom-sort',
|
||||||
|
processInstanceId: 'process-instance-id',
|
||||||
|
priority: '12'
|
||||||
|
}));
|
||||||
|
fixture.detectChanges();
|
||||||
|
const taskFilterIdChange = new SimpleChange(undefined, 'mock-task-filter-id', true);
|
||||||
|
component.ngOnChanges({ 'id': taskFilterIdChange });
|
||||||
|
fixture.detectChanges();
|
||||||
|
const expansionPanel = fixture.debugElement.nativeElement.querySelector('mat-expansion-panel-header');
|
||||||
|
expansionPanel.click();
|
||||||
|
fixture.detectChanges();
|
||||||
|
const sortElement = fixture.debugElement.nativeElement.querySelector('[data-automation-id="adf-cloud-edit-task-property-sort"]');
|
||||||
|
sortElement.click();
|
||||||
|
fixture.detectChanges();
|
||||||
|
fixture.whenStable().then(() => {
|
||||||
|
const sortController = component.editTaskFilterForm.get('sort');
|
||||||
|
const sortOptions = fixture.debugElement.queryAll(By.css('.mat-option-text'));
|
||||||
|
expect(component.sortProperties.length).toBe(3);
|
||||||
|
expect(sortController.value).toBe('my-custom-sort');
|
||||||
|
expect(sortOptions.length).toEqual(3);
|
||||||
|
});
|
||||||
|
}));
|
||||||
|
|
||||||
|
it('should display default sort properties if input is empty', async(() => {
|
||||||
|
const taskFilterIdChange = new SimpleChange(undefined, 'mock-task-filter-id', true);
|
||||||
|
component.ngOnChanges({ 'id': taskFilterIdChange });
|
||||||
|
fixture.detectChanges();
|
||||||
|
component.sortProperties = [];
|
||||||
|
fixture.detectChanges();
|
||||||
|
const expansionPanel = fixture.debugElement.nativeElement.querySelector('mat-expansion-panel-header');
|
||||||
|
expansionPanel.click();
|
||||||
|
fixture.detectChanges();
|
||||||
|
const sortElement = fixture.debugElement.nativeElement.querySelector('[data-automation-id="adf-cloud-edit-task-property-sort"]');
|
||||||
|
sortElement.click();
|
||||||
|
fixture.detectChanges();
|
||||||
|
fixture.whenStable().then(() => {
|
||||||
|
const sortController = component.editTaskFilterForm.get('sort');
|
||||||
|
const sortOptions = fixture.debugElement.queryAll(By.css('.mat-option-text'));
|
||||||
|
expect(sortController.value).toBe('id');
|
||||||
|
expect(sortOptions.length).toEqual(4);
|
||||||
|
});
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('filter actions', () => {
|
||||||
|
|
||||||
|
it('should display default filter actions', async(() => {
|
||||||
|
component.toggleFilterActions = true;
|
||||||
|
const taskFilterIdChange = new SimpleChange(undefined, 'mock-task-filter-id', true);
|
||||||
|
component.ngOnChanges({ 'id': taskFilterIdChange });
|
||||||
|
fixture.detectChanges();
|
||||||
|
const expansionPanel = fixture.debugElement.nativeElement.querySelector('mat-expansion-panel-header');
|
||||||
|
expansionPanel.click();
|
||||||
|
fixture.detectChanges();
|
||||||
|
fixture.whenStable().then(() => {
|
||||||
|
const saveAsButton = fixture.debugElement.nativeElement.querySelector('[data-automation-id="adf-filter-action-saveAs"]');
|
||||||
|
const saveButton = fixture.debugElement.nativeElement.querySelector('[data-automation-id="adf-filter-action-save"]');
|
||||||
|
const deleteButton = fixture.debugElement.nativeElement.querySelector('[data-automation-id="adf-filter-action-delete"]');
|
||||||
|
expect(component.taskFilterActions.map(action => action.actionType)).toEqual(['save', 'saveAs', 'delete']);
|
||||||
|
expect(component.taskFilterActions.length).toBe(3);
|
||||||
|
expect(saveButton.disabled).toBe(true);
|
||||||
|
expect(saveAsButton.disabled).toBe(true);
|
||||||
|
expect(deleteButton.disabled).toBe(false);
|
||||||
|
});
|
||||||
|
}));
|
||||||
|
|
||||||
|
it('should display filter actions when input actions are specified', async(() => {
|
||||||
|
component.actions = ['save'];
|
||||||
|
fixture.detectChanges();
|
||||||
|
const taskFilterIdChange = new SimpleChange(undefined, 'mock-task-filter-id', true);
|
||||||
|
component.ngOnChanges({ 'id': taskFilterIdChange });
|
||||||
|
fixture.detectChanges();
|
||||||
|
component.toggleFilterActions = true;
|
||||||
|
fixture.detectChanges();
|
||||||
|
const expansionPanel = fixture.debugElement.nativeElement.querySelector('mat-expansion-panel-header');
|
||||||
|
expansionPanel.click();
|
||||||
|
fixture.detectChanges();
|
||||||
|
fixture.whenStable().then(() => {
|
||||||
|
const saveButton = fixture.debugElement.nativeElement.querySelector('[data-automation-id="adf-filter-action-save"]');
|
||||||
|
expect(component.taskFilterActions.map(action => action.actionType)).toEqual(['save']);
|
||||||
|
expect(component.taskFilterActions.length).toBe(1);
|
||||||
|
expect(saveButton.disabled).toBeTruthy();
|
||||||
|
const saveAsButton = fixture.debugElement.nativeElement.querySelector('[data-automation-id="adf-filter-action-saveAs"]');
|
||||||
|
const deleteButton = fixture.debugElement.nativeElement.querySelector('[data-automation-id="adf-filter-action-delete"]');
|
||||||
|
expect(saveAsButton).toBeFalsy();
|
||||||
|
expect(deleteButton).toBeFalsy();
|
||||||
|
});
|
||||||
|
}));
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('edit filter actions', () => {
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
const taskFilterIdChange = new SimpleChange(undefined, 'mock-task-filter-id', true);
|
||||||
|
component.ngOnChanges({ 'id': taskFilterIdChange });
|
||||||
|
fixture.detectChanges();
|
||||||
|
spyOn(component.action, 'emit').and.callThrough();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should emit save event and save the filter on click save button', async(() => {
|
||||||
|
component.toggleFilterActions = true;
|
||||||
|
spyOn(service, 'updateFilter').and.returnValue(of({}));
|
||||||
|
fixture.detectChanges();
|
||||||
|
const expansionPanel = fixture.debugElement.nativeElement.querySelector('mat-expansion-panel-header');
|
||||||
|
expansionPanel.click();
|
||||||
|
fixture.detectChanges();
|
||||||
|
const stateElement = fixture.debugElement.nativeElement.querySelector('[data-automation-id="adf-cloud-edit-task-property-sort"] .mat-select-trigger');
|
||||||
|
stateElement.click();
|
||||||
|
fixture.detectChanges();
|
||||||
|
const sortOptions = fixture.debugElement.queryAll(By.css('.mat-option-text'));
|
||||||
|
sortOptions[3].nativeElement.click();
|
||||||
|
fixture.detectChanges();
|
||||||
|
const saveButton = fixture.debugElement.nativeElement.querySelector('[data-automation-id="adf-filter-action-save"]');
|
||||||
|
fixture.whenStable().then(() => {
|
||||||
|
fixture.detectChanges();
|
||||||
|
expect(saveButton.disabled).toBe(false);
|
||||||
|
saveButton.click();
|
||||||
|
expect(service.updateFilter).toHaveBeenCalled();
|
||||||
|
expect(component.action.emit).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
}));
|
||||||
|
|
||||||
|
it('should emit delete event and delete the filter on click of delete button', async(() => {
|
||||||
|
component.toggleFilterActions = true;
|
||||||
|
spyOn(service, 'deleteFilter').and.returnValue(of({}));
|
||||||
|
fixture.detectChanges();
|
||||||
|
const expansionPanel = fixture.debugElement.nativeElement.querySelector('mat-expansion-panel-header');
|
||||||
|
expansionPanel.click();
|
||||||
|
fixture.detectChanges();
|
||||||
|
const stateElement = fixture.debugElement.nativeElement.querySelector('[data-automation-id="adf-cloud-edit-task-property-sort"] .mat-select-trigger');
|
||||||
|
stateElement.click();
|
||||||
|
fixture.detectChanges();
|
||||||
|
const deleteButton = fixture.debugElement.nativeElement.querySelector('[data-automation-id="adf-filter-action-delete"]');
|
||||||
|
fixture.whenStable().then(() => {
|
||||||
|
fixture.detectChanges();
|
||||||
|
expect(deleteButton.disabled).toBe(false);
|
||||||
|
deleteButton.click();
|
||||||
|
expect(service.deleteFilter).toHaveBeenCalled();
|
||||||
|
expect(component.action.emit).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
}));
|
||||||
|
|
||||||
|
it('should emit saveAs event and add filter on click saveAs button', async(() => {
|
||||||
|
component.toggleFilterActions = true;
|
||||||
|
spyOn(service, 'addFilter').and.returnValue(of({}));
|
||||||
|
fixture.detectChanges();
|
||||||
|
const expansionPanel = fixture.debugElement.nativeElement.querySelector('mat-expansion-panel-header');
|
||||||
|
expansionPanel.click();
|
||||||
|
fixture.detectChanges();
|
||||||
|
const sortElement = fixture.debugElement.nativeElement.querySelector('[data-automation-id="adf-cloud-edit-task-property-sort"] .mat-select-trigger');
|
||||||
|
sortElement.click();
|
||||||
|
fixture.detectChanges();
|
||||||
|
const sortOptions = fixture.debugElement.queryAll(By.css('.mat-option-text'));
|
||||||
|
sortOptions[2].nativeElement.click();
|
||||||
|
fixture.detectChanges();
|
||||||
|
const saveAsButton = fixture.debugElement.nativeElement.querySelector('[data-automation-id="adf-filter-action-saveAs"]');
|
||||||
|
fixture.whenStable().then(() => {
|
||||||
|
fixture.detectChanges();
|
||||||
|
expect(saveAsButton.disabled).toBe(false);
|
||||||
|
saveAsButton.click();
|
||||||
|
expect(service.addFilter).toHaveBeenCalled();
|
||||||
|
expect(component.action.emit).toHaveBeenCalled();
|
||||||
|
expect(dialog.open).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
}));
|
||||||
|
|
||||||
|
it('should call restore default filters service on deletion of last filter', async(() => {
|
||||||
|
component.toggleFilterActions = true;
|
||||||
|
spyOn(service, 'deleteFilter').and.returnValue(of([]));
|
||||||
|
const restoreDefaultFiltersSpy = spyOn(component, 'restoreDefaultTaskFilters').and.returnValue(of([]));
|
||||||
|
fixture.detectChanges();
|
||||||
|
const expansionPanel = fixture.debugElement.nativeElement.querySelector('mat-expansion-panel-header');
|
||||||
|
expansionPanel.click();
|
||||||
|
fixture.detectChanges();
|
||||||
|
const stateElement = fixture.debugElement.nativeElement.querySelector('[data-automation-id="adf-cloud-edit-task-property-sort"] .mat-select-trigger');
|
||||||
|
stateElement.click();
|
||||||
|
fixture.detectChanges();
|
||||||
|
const deleteButton = fixture.debugElement.nativeElement.querySelector('[data-automation-id="adf-filter-action-delete"]');
|
||||||
|
fixture.whenStable().then(() => {
|
||||||
|
fixture.detectChanges();
|
||||||
|
expect(deleteButton.disabled).toBe(false);
|
||||||
|
deleteButton.click();
|
||||||
|
expect(service.deleteFilter).toHaveBeenCalled();
|
||||||
|
expect(component.action.emit).toHaveBeenCalled();
|
||||||
|
expect(restoreDefaultFiltersSpy).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
}));
|
||||||
|
|
||||||
|
it('should not call restore default filters service on deletion of first filter', async(() => {
|
||||||
|
component.toggleFilterActions = true;
|
||||||
|
spyOn(service, 'deleteFilter').and.returnValue(of([{ name: 'mock-filter-name' }]));
|
||||||
|
const restoreDefaultFiltersSpy = spyOn(component, 'restoreDefaultTaskFilters').and.returnValue(of([]));
|
||||||
|
fixture.detectChanges();
|
||||||
|
const expansionPanel = fixture.debugElement.nativeElement.querySelector('mat-expansion-panel-header');
|
||||||
|
expansionPanel.click();
|
||||||
|
fixture.detectChanges();
|
||||||
|
const stateElement = fixture.debugElement.nativeElement.querySelector('[data-automation-id="adf-cloud-edit-task-property-sort"] .mat-select-trigger');
|
||||||
|
stateElement.click();
|
||||||
|
fixture.detectChanges();
|
||||||
|
const deleteButton = fixture.debugElement.nativeElement.querySelector('[data-automation-id="adf-filter-action-delete"]');
|
||||||
|
fixture.whenStable().then(() => {
|
||||||
|
fixture.detectChanges();
|
||||||
|
expect(deleteButton.disabled).toBe(false);
|
||||||
|
deleteButton.click();
|
||||||
|
expect(service.deleteFilter).toHaveBeenCalled();
|
||||||
|
expect(component.action.emit).toHaveBeenCalled();
|
||||||
|
expect(restoreDefaultFiltersSpy).not.toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
});
|
@ -0,0 +1,267 @@
|
|||||||
|
/*!
|
||||||
|
* @license
|
||||||
|
* Copyright 2019 Alfresco Software, Ltd.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { Component, Output, EventEmitter } from '@angular/core';
|
||||||
|
import { FormBuilder } from '@angular/forms';
|
||||||
|
import { DateAdapter } from '@angular/material/core';
|
||||||
|
import { MatDialog } from '@angular/material/dialog';
|
||||||
|
import { filter, takeUntil, finalize, switchMap } from 'rxjs/operators';
|
||||||
|
import { Observable } from 'rxjs';
|
||||||
|
import { Moment } from 'moment';
|
||||||
|
|
||||||
|
import { TaskFilterProperties, TaskFilterAction, ServiceTaskFilterCloudModel } from '../../models/filter-cloud.model';
|
||||||
|
import { TaskFilterDialogCloudComponent } from '../task-filter-dialog/task-filter-dialog-cloud.component';
|
||||||
|
import { TranslationService, UserPreferencesService } from '@alfresco/adf-core';
|
||||||
|
import { AppsProcessCloudService } from '../../../../app/services/apps-process-cloud.service';
|
||||||
|
import { TaskCloudService } from '../../../services/task-cloud.service';
|
||||||
|
import { ServiceTaskFilterCloudService } from '../../services/service-task-filter-cloud.service';
|
||||||
|
import { BaseEditTaskFilterCloudComponent } from './base-edit-task-filter-cloud.component';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'adf-cloud-edit-service-task-filter',
|
||||||
|
templateUrl: './base-edit-task-filter-cloud.component.html',
|
||||||
|
styleUrls: ['./base-edit-task-filter-cloud.component.scss']
|
||||||
|
})
|
||||||
|
export class EditServiceTaskFilterCloudComponent extends BaseEditTaskFilterCloudComponent {
|
||||||
|
|
||||||
|
public static DEFAULT_TASK_FILTER_PROPERTIES = ['appName', 'activityName', 'status', 'sort', 'order'];
|
||||||
|
public static DEFAULT_TASK_SORT_PROPERTIES = ['id', 'name', 'startedDate', 'completedDate'];
|
||||||
|
public static DEFAULT_TASK_STATUS_PROPERTIES = [
|
||||||
|
{ label: 'ALL', value: '' },
|
||||||
|
{ label: 'STARTED', value: 'STARTED' },
|
||||||
|
{ label: 'COMPLETED', value: 'COMPLETED' },
|
||||||
|
{ label: 'CANCELLED', value: 'CANCELLED' },
|
||||||
|
{ label: 'ERROR', value: 'ERROR' }
|
||||||
|
];
|
||||||
|
|
||||||
|
/** Emitted when a task filter property changes. */
|
||||||
|
@Output()
|
||||||
|
filterChange: EventEmitter<ServiceTaskFilterCloudModel> = new EventEmitter();
|
||||||
|
|
||||||
|
taskFilter: ServiceTaskFilterCloudModel;
|
||||||
|
changedTaskFilter: ServiceTaskFilterCloudModel;
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
protected formBuilder: FormBuilder,
|
||||||
|
public dialog: MatDialog,
|
||||||
|
private translateService: TranslationService,
|
||||||
|
private serviceTaskFilterCloudService: ServiceTaskFilterCloudService,
|
||||||
|
protected dateAdapter: DateAdapter<Moment>,
|
||||||
|
protected userPreferencesService: UserPreferencesService,
|
||||||
|
protected appsProcessCloudService: AppsProcessCloudService,
|
||||||
|
protected taskCloudService: TaskCloudService) {
|
||||||
|
super(formBuilder, dateAdapter, userPreferencesService, appsProcessCloudService, taskCloudService);
|
||||||
|
}
|
||||||
|
|
||||||
|
assignNewFilter(formValues: ServiceTaskFilterCloudModel) {
|
||||||
|
this.changedTaskFilter = Object.assign({}, this.taskFilter, formValues) as ServiceTaskFilterCloudModel;
|
||||||
|
this.formHasBeenChanged = !this.compareFilters(this.changedTaskFilter, this.taskFilter);
|
||||||
|
this.filterChange.emit(this.changedTaskFilter);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetches task filter by application name and filter id and creates filter properties, build form
|
||||||
|
*/
|
||||||
|
retrieveTaskFilterAndBuildForm() {
|
||||||
|
this.isLoading = true;
|
||||||
|
this.serviceTaskFilterCloudService.getTaskFilterById(this.appName, this.id)
|
||||||
|
.pipe(
|
||||||
|
finalize(() => this.isLoading = false),
|
||||||
|
takeUntil(this.onDestroy$)
|
||||||
|
)
|
||||||
|
.subscribe(response => {
|
||||||
|
this.taskFilter = response as ServiceTaskFilterCloudModel;
|
||||||
|
this.taskFilterProperties = this.createAndFilterProperties();
|
||||||
|
this.taskFilterActions = this.createAndFilterActions();
|
||||||
|
this.buildForm(this.taskFilterProperties);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
checkMandatoryFilterProperties() {
|
||||||
|
if (this.filterProperties === undefined || this.filterProperties.length === 0) {
|
||||||
|
this.filterProperties = EditServiceTaskFilterCloudComponent.DEFAULT_TASK_FILTER_PROPERTIES;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
checkMandatorySortProperties(): void {
|
||||||
|
if (this.sortProperties === undefined || this.sortProperties.length === 0) {
|
||||||
|
this.sortProperties = EditServiceTaskFilterCloudComponent.DEFAULT_TASK_SORT_PROPERTIES;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return true if both filters are same
|
||||||
|
* @param editedQuery, @param currentQuery
|
||||||
|
*/
|
||||||
|
compareFilters(
|
||||||
|
editedQuery: ServiceTaskFilterCloudModel,
|
||||||
|
currentQuery: ServiceTaskFilterCloudModel
|
||||||
|
): boolean {
|
||||||
|
return JSON.stringify(editedQuery).toLowerCase() === JSON.stringify(currentQuery).toLowerCase();
|
||||||
|
}
|
||||||
|
|
||||||
|
save(saveAction: TaskFilterAction): void {
|
||||||
|
this.serviceTaskFilterCloudService
|
||||||
|
.updateFilter(this.changedTaskFilter)
|
||||||
|
.pipe(takeUntil(this.onDestroy$))
|
||||||
|
.subscribe(() => {
|
||||||
|
saveAction.filter = this.changedTaskFilter;
|
||||||
|
this.action.emit(saveAction);
|
||||||
|
this.formHasBeenChanged = this.compareFilters(this.changedTaskFilter, this.taskFilter);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
delete(deleteAction: TaskFilterAction): void {
|
||||||
|
this.serviceTaskFilterCloudService
|
||||||
|
.deleteFilter(this.taskFilter)
|
||||||
|
.pipe(
|
||||||
|
filter((filters) => {
|
||||||
|
deleteAction.filter = this.taskFilter;
|
||||||
|
this.action.emit(deleteAction);
|
||||||
|
return filters.length === 0;
|
||||||
|
}),
|
||||||
|
switchMap(() => this.restoreDefaultTaskFilters()),
|
||||||
|
takeUntil(this.onDestroy$))
|
||||||
|
.subscribe(() => { });
|
||||||
|
}
|
||||||
|
|
||||||
|
saveAs(saveAsAction: TaskFilterAction): void {
|
||||||
|
const dialogRef = this.dialog.open(TaskFilterDialogCloudComponent, {
|
||||||
|
data: {
|
||||||
|
name: this.translateService.instant(this.taskFilter.name)
|
||||||
|
},
|
||||||
|
height: 'auto',
|
||||||
|
minWidth: '30%'
|
||||||
|
});
|
||||||
|
dialogRef.afterClosed().subscribe((result) => {
|
||||||
|
if (result && result.action === TaskFilterDialogCloudComponent.ACTION_SAVE) {
|
||||||
|
const filterId = Math.random().toString(36).substr(2, 9);
|
||||||
|
const filterKey = this.getSanitizeFilterName(result.name);
|
||||||
|
const newFilter = {
|
||||||
|
name: result.name,
|
||||||
|
icon: result.icon,
|
||||||
|
id: filterId,
|
||||||
|
key: 'custom-' + filterKey
|
||||||
|
};
|
||||||
|
const resultFilter: ServiceTaskFilterCloudModel = Object.assign({}, this.changedTaskFilter, newFilter);
|
||||||
|
this.serviceTaskFilterCloudService.addFilter(resultFilter)
|
||||||
|
.pipe(takeUntil(this.onDestroy$)).subscribe(() => {
|
||||||
|
saveAsAction.filter = resultFilter;
|
||||||
|
this.action.emit(saveAsAction);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
isDisabledForDefaultFilters(action: TaskFilterAction): boolean {
|
||||||
|
return (
|
||||||
|
this.serviceTaskFilterCloudService.isDefaultFilter(this.taskFilter.name) &&
|
||||||
|
EditServiceTaskFilterCloudComponent.ACTIONS_DISABLED_BY_DEFAULT.includes(action.actionType)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
restoreDefaultTaskFilters(): Observable<ServiceTaskFilterCloudModel[]> {
|
||||||
|
return this.serviceTaskFilterCloudService.getTaskListFilters(this.appName);
|
||||||
|
}
|
||||||
|
|
||||||
|
createTaskFilterProperties(): TaskFilterProperties[] {
|
||||||
|
return [
|
||||||
|
new TaskFilterProperties({
|
||||||
|
label: 'ADF_CLOUD_EDIT_SERVICE_TASK_FILTER.LABEL.APP_NAME',
|
||||||
|
type: 'select',
|
||||||
|
key: 'appName',
|
||||||
|
value: this.taskFilter.appName || '',
|
||||||
|
options: this.applicationNames
|
||||||
|
}),
|
||||||
|
new TaskFilterProperties({
|
||||||
|
label: 'ADF_CLOUD_EDIT_SERVICE_TASK_FILTER.LABEL.SERVICE_TASK_ID',
|
||||||
|
type: 'text',
|
||||||
|
key: 'serviceTaskId',
|
||||||
|
value: this.taskFilter.serviceTaskId || ''
|
||||||
|
}),
|
||||||
|
new TaskFilterProperties({
|
||||||
|
label: 'ADF_CLOUD_EDIT_SERVICE_TASK_FILTER.LABEL.ELEMENT_ID',
|
||||||
|
type: 'text',
|
||||||
|
key: 'elementId',
|
||||||
|
value: this.taskFilter.elementId || ''
|
||||||
|
}),
|
||||||
|
new TaskFilterProperties({
|
||||||
|
label: 'ADF_CLOUD_EDIT_SERVICE_TASK_FILTER.LABEL.ACTIVITY_NAME',
|
||||||
|
type: 'text',
|
||||||
|
key: 'activityName',
|
||||||
|
value: this.taskFilter.activityName || ''
|
||||||
|
}),
|
||||||
|
new TaskFilterProperties({
|
||||||
|
label: 'ADF_CLOUD_EDIT_SERVICE_TASK_FILTER.LABEL.ACTIVITY_TYPE',
|
||||||
|
type: 'text',
|
||||||
|
key: 'activityType',
|
||||||
|
value: this.taskFilter.activityType || ''
|
||||||
|
}),
|
||||||
|
new TaskFilterProperties({
|
||||||
|
label: 'ADF_CLOUD_EDIT_SERVICE_TASK_FILTER.LABEL.SORT',
|
||||||
|
type: 'select',
|
||||||
|
key: 'sort',
|
||||||
|
value: this.taskFilter.sort || this.createSortProperties[0].value,
|
||||||
|
options: this.createSortProperties
|
||||||
|
}),
|
||||||
|
new TaskFilterProperties({
|
||||||
|
label: 'ADF_CLOUD_EDIT_SERVICE_TASK_FILTER.LABEL.DIRECTION',
|
||||||
|
type: 'select',
|
||||||
|
key: 'order',
|
||||||
|
value: this.taskFilter.order || EditServiceTaskFilterCloudComponent.DIRECTIONS[0].value,
|
||||||
|
options: EditServiceTaskFilterCloudComponent.DIRECTIONS
|
||||||
|
}),
|
||||||
|
new TaskFilterProperties({
|
||||||
|
label: 'ADF_CLOUD_EDIT_SERVICE_TASK_FILTER.LABEL.STATUS',
|
||||||
|
type: 'select',
|
||||||
|
key: 'status',
|
||||||
|
value: this.taskFilter.status || EditServiceTaskFilterCloudComponent.DEFAULT_TASK_STATUS_PROPERTIES[0].value,
|
||||||
|
options: EditServiceTaskFilterCloudComponent.DEFAULT_TASK_STATUS_PROPERTIES
|
||||||
|
}),
|
||||||
|
new TaskFilterProperties({
|
||||||
|
label: 'ADF_CLOUD_EDIT_SERVICE_TASK_FILTER.LABEL.STARTED_DATE',
|
||||||
|
type: 'date',
|
||||||
|
key: 'startedDate',
|
||||||
|
value: this.taskFilter.completedDate || false
|
||||||
|
}),
|
||||||
|
new TaskFilterProperties({
|
||||||
|
label: 'ADF_CLOUD_EDIT_SERVICE_TASK_FILTER.LABEL.COMPLETED_DATE',
|
||||||
|
type: 'date',
|
||||||
|
key: 'completedDate',
|
||||||
|
value: this.taskFilter.completedDate || false
|
||||||
|
}),
|
||||||
|
new TaskFilterProperties({
|
||||||
|
label: 'ADF_CLOUD_EDIT_SERVICE_TASK_FILTER.LABEL.PROCESS_INSTANCE_ID',
|
||||||
|
type: 'text',
|
||||||
|
key: 'processInstanceId',
|
||||||
|
value: this.taskFilter.processInstanceId || ''
|
||||||
|
}),
|
||||||
|
new TaskFilterProperties({
|
||||||
|
label: 'ADF_CLOUD_EDIT_SERVICE_TASK_FILTER.LABEL.PROCESS_DEF_ID',
|
||||||
|
type: 'text',
|
||||||
|
key: 'processDefinitionId',
|
||||||
|
value: this.taskFilter.processDefinitionId || ''
|
||||||
|
}),
|
||||||
|
new TaskFilterProperties({
|
||||||
|
label: 'ADF_CLOUD_EDIT_SERVICE_TASK_FILTER.LABEL.SERVICE_NAME',
|
||||||
|
type: 'text',
|
||||||
|
key: 'serviceName',
|
||||||
|
value: this.taskFilter.serviceName || ''
|
||||||
|
})
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
@ -23,21 +23,21 @@ import { setupTestBed } from '@alfresco/adf-core';
|
|||||||
import { MatDialog } from '@angular/material/dialog';
|
import { MatDialog } from '@angular/material/dialog';
|
||||||
import { of } from 'rxjs';
|
import { of } from 'rxjs';
|
||||||
import { debounceTime } from 'rxjs/operators';
|
import { debounceTime } from 'rxjs/operators';
|
||||||
import { TASK_FILTERS_SERVICE_TOKEN } from '../../../services/cloud-token.service';
|
import { TASK_FILTERS_SERVICE_TOKEN } from '../../../../services/cloud-token.service';
|
||||||
import { LocalPreferenceCloudService } from '../../../services/local-preference-cloud.service';
|
import { LocalPreferenceCloudService } from '../../../../services/local-preference-cloud.service';
|
||||||
import { ProcessServiceCloudTestingModule } from '../../../testing/process-service-cloud.testing.module';
|
import { ProcessServiceCloudTestingModule } from '../../../../testing/process-service-cloud.testing.module';
|
||||||
import { AppsProcessCloudService } from '../../../app/services/apps-process-cloud.service';
|
import { AppsProcessCloudService } from '../../../../app/services/apps-process-cloud.service';
|
||||||
import { fakeApplicationInstance } from '../../../app/mock/app-model.mock';
|
import { fakeApplicationInstance } from '../../../../app/mock/app-model.mock';
|
||||||
import { TaskFiltersCloudModule } from '../task-filters-cloud.module';
|
import { TaskFiltersCloudModule } from '../../task-filters-cloud.module';
|
||||||
import { EditTaskFilterCloudComponent } from './edit-task-filter-cloud.component';
|
import { EditTaskFilterCloudComponent } from './edit-task-filter-cloud.component';
|
||||||
import { TaskFilterCloudService } from '../services/task-filter-cloud.service';
|
import { TaskFilterCloudService } from '../../services/task-filter-cloud.service';
|
||||||
import { TaskCloudService } from '../../services/task-cloud.service';
|
import { TaskCloudService } from '../../../services/task-cloud.service';
|
||||||
import { TaskFilterDialogCloudComponent } from './task-filter-dialog-cloud.component';
|
import { fakeFilter } from '../../mock/task-filters-cloud.mock';
|
||||||
import { fakeFilter } from '../mock/task-filters-cloud.mock';
|
|
||||||
import { AbstractControl } from '@angular/forms';
|
import { AbstractControl } from '@angular/forms';
|
||||||
import moment from 'moment-es6';
|
import moment from 'moment-es6';
|
||||||
import { TranslateModule } from '@ngx-translate/core';
|
import { TranslateModule } from '@ngx-translate/core';
|
||||||
import { DateCloudFilterType } from '../../../models/date-cloud-filter.model';
|
import { DateCloudFilterType } from '../../../../models/date-cloud-filter.model';
|
||||||
|
import { TaskFilterCloudModel } from '../../models/filter-cloud.model';
|
||||||
|
|
||||||
describe('EditTaskFilterCloudComponent', () => {
|
describe('EditTaskFilterCloudComponent', () => {
|
||||||
let component: EditTaskFilterCloudComponent;
|
let component: EditTaskFilterCloudComponent;
|
||||||
@ -68,11 +68,13 @@ describe('EditTaskFilterCloudComponent', () => {
|
|||||||
appsService = TestBed.inject(AppsProcessCloudService);
|
appsService = TestBed.inject(AppsProcessCloudService);
|
||||||
taskService = TestBed.inject(TaskCloudService);
|
taskService = TestBed.inject(TaskCloudService);
|
||||||
dialog = TestBed.inject(MatDialog);
|
dialog = TestBed.inject(MatDialog);
|
||||||
spyOn(dialog, 'open').and.returnValue({ afterClosed: of({
|
spyOn(dialog, 'open').and.returnValue({
|
||||||
action: TaskFilterDialogCloudComponent.ACTION_SAVE,
|
afterClosed: of({
|
||||||
|
action: EditTaskFilterCloudComponent.ACTION_SAVE,
|
||||||
icon: 'icon',
|
icon: 'icon',
|
||||||
name: 'fake-name'
|
name: 'fake-name'
|
||||||
}) });
|
})
|
||||||
|
});
|
||||||
getTaskFilterSpy = spyOn(service, 'getTaskFilterById').and.returnValue(of(fakeFilter));
|
getTaskFilterSpy = spyOn(service, 'getTaskFilterById').and.returnValue(of(fakeFilter));
|
||||||
getRunningApplicationsSpy = spyOn(appsService, 'getDeployedApplicationsByStatus').and.returnValue(of(fakeApplicationInstance));
|
getRunningApplicationsSpy = spyOn(appsService, 'getDeployedApplicationsByStatus').and.returnValue(of(fakeApplicationInstance));
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
@ -172,7 +174,7 @@ describe('EditTaskFilterCloudComponent', () => {
|
|||||||
expect(component.editTaskFilterForm).toBeDefined();
|
expect(component.editTaskFilterForm).toBeDefined();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should create editTaskFilter form with default properties', async(() => {
|
it('should create editTaskFilter form with default user task properties', async(() => {
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
fixture.whenStable().then(() => {
|
fixture.whenStable().then(() => {
|
||||||
const stateController = component.editTaskFilterForm.get('status');
|
const stateController = component.editTaskFilterForm.get('status');
|
||||||
@ -657,7 +659,9 @@ describe('EditTaskFilterCloudComponent', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
component.filterChange.subscribe(() => {
|
component.filterChange.subscribe(() => {
|
||||||
|
if (component.changedTaskFilter instanceof TaskFilterCloudModel) {
|
||||||
expect(component.changedTaskFilter.lastModifiedTo.toISOString()).toEqual(lastModifiedToFilter.toISOString());
|
expect(component.changedTaskFilter.lastModifiedTo.toISOString()).toEqual(lastModifiedToFilter.toISOString());
|
||||||
|
}
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
component.onFilterChange();
|
component.onFilterChange();
|
@ -0,0 +1,334 @@
|
|||||||
|
/*!
|
||||||
|
* @license
|
||||||
|
* Copyright 2019 Alfresco Software, Ltd.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { Component, Output, EventEmitter } from '@angular/core';
|
||||||
|
import { FormBuilder } from '@angular/forms';
|
||||||
|
import { DateAdapter } from '@angular/material/core';
|
||||||
|
import { MatDialog } from '@angular/material/dialog';
|
||||||
|
import { filter, takeUntil, finalize, switchMap } from 'rxjs/operators';
|
||||||
|
import { Observable } from 'rxjs';
|
||||||
|
import moment from 'moment-es6';
|
||||||
|
import { Moment } from 'moment';
|
||||||
|
|
||||||
|
import { TaskFilterCloudModel, TaskFilterProperties, TaskFilterAction } from '../../models/filter-cloud.model';
|
||||||
|
import { TaskFilterCloudService } from '../../services/task-filter-cloud.service';
|
||||||
|
import { TaskFilterDialogCloudComponent } from '../task-filter-dialog/task-filter-dialog-cloud.component';
|
||||||
|
import { TranslationService, UserPreferencesService } from '@alfresco/adf-core';
|
||||||
|
import { AppsProcessCloudService } from '../../../../app/services/apps-process-cloud.service';
|
||||||
|
import { DateCloudFilterType } from '../../../../models/date-cloud-filter.model';
|
||||||
|
import { TaskCloudService } from '../../../services/task-cloud.service';
|
||||||
|
import { BaseEditTaskFilterCloudComponent } from './base-edit-task-filter-cloud.component';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'adf-cloud-edit-task-filter',
|
||||||
|
templateUrl: './base-edit-task-filter-cloud.component.html',
|
||||||
|
styleUrls: ['./base-edit-task-filter-cloud.component.scss']
|
||||||
|
})
|
||||||
|
export class EditTaskFilterCloudComponent extends BaseEditTaskFilterCloudComponent {
|
||||||
|
|
||||||
|
public static DEFAULT_TASK_FILTER_PROPERTIES = ['status', 'assignee', 'sort', 'order'];
|
||||||
|
public static DEFAULT_TASK_SORT_PROPERTIES = ['id', 'name', 'createdDate', 'priority'];
|
||||||
|
public static DEFAULT_TASK_STATUS_PROPERTIES = [
|
||||||
|
{ label: 'ALL', value: '' },
|
||||||
|
{ label: 'CREATED', value: 'CREATED' },
|
||||||
|
{ label: 'ASSIGNED', value: 'ASSIGNED' },
|
||||||
|
{ label: 'SUSPENDED', value: 'SUSPENDED' },
|
||||||
|
{ label: 'CANCELLED', value: 'CANCELLED' },
|
||||||
|
{ label: 'COMPLETED', value: 'COMPLETED' }
|
||||||
|
];
|
||||||
|
|
||||||
|
/** Emitted when a task filter property changes. */
|
||||||
|
@Output()
|
||||||
|
filterChange: EventEmitter<TaskFilterCloudModel> = new EventEmitter();
|
||||||
|
|
||||||
|
taskFilter: TaskFilterCloudModel;
|
||||||
|
changedTaskFilter: TaskFilterCloudModel;
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
protected formBuilder: FormBuilder,
|
||||||
|
public dialog: MatDialog,
|
||||||
|
private translateService: TranslationService,
|
||||||
|
private taskFilterCloudService: TaskFilterCloudService,
|
||||||
|
protected dateAdapter: DateAdapter<Moment>,
|
||||||
|
protected userPreferencesService: UserPreferencesService,
|
||||||
|
protected appsProcessCloudService: AppsProcessCloudService,
|
||||||
|
protected taskCloudService: TaskCloudService) {
|
||||||
|
super(formBuilder, dateAdapter, userPreferencesService, appsProcessCloudService, taskCloudService);
|
||||||
|
}
|
||||||
|
|
||||||
|
assignNewFilter(formValues: TaskFilterCloudModel) {
|
||||||
|
this.setLastModifiedToFilter(<TaskFilterCloudModel> formValues);
|
||||||
|
this.changedTaskFilter = new TaskFilterCloudModel(Object.assign({}, this.taskFilter, formValues));
|
||||||
|
this.formHasBeenChanged = !this.compareFilters(this.changedTaskFilter, this.taskFilter);
|
||||||
|
this.filterChange.emit(this.changedTaskFilter);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetches task filter by application name and filter id and creates filter properties, build form
|
||||||
|
*/
|
||||||
|
retrieveTaskFilterAndBuildForm() {
|
||||||
|
this.isLoading = true;
|
||||||
|
this.taskFilterCloudService.getTaskFilterById(this.appName, this.id)
|
||||||
|
.pipe(
|
||||||
|
finalize(() => this.isLoading = false),
|
||||||
|
takeUntil(this.onDestroy$)
|
||||||
|
)
|
||||||
|
.subscribe(response => {
|
||||||
|
this.taskFilter = new TaskFilterCloudModel(response);
|
||||||
|
this.taskFilterProperties = this.createAndFilterProperties();
|
||||||
|
if (this.hasLastModifiedProperty()) {
|
||||||
|
this.taskFilterProperties = [...this.taskFilterProperties, ...this.createLastModifiedProperty()];
|
||||||
|
}
|
||||||
|
this.taskFilterActions = this.createAndFilterActions();
|
||||||
|
this.buildForm(this.taskFilterProperties);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
checkMandatoryFilterProperties() {
|
||||||
|
if (this.filterProperties === undefined || this.filterProperties.length === 0) {
|
||||||
|
this.filterProperties = EditTaskFilterCloudComponent.DEFAULT_TASK_FILTER_PROPERTIES;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
checkMandatorySortProperties(): void {
|
||||||
|
if (this.sortProperties === undefined || this.sortProperties.length === 0) {
|
||||||
|
this.sortProperties = EditTaskFilterCloudComponent.DEFAULT_TASK_SORT_PROPERTIES;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private setLastModifiedToFilter(formValues: TaskFilterCloudModel) {
|
||||||
|
if (formValues.lastModifiedTo && Date.parse(formValues.lastModifiedTo.toString())) {
|
||||||
|
const lastModifiedToFilterValue = moment(formValues.lastModifiedTo);
|
||||||
|
lastModifiedToFilterValue.set({
|
||||||
|
hour: 23,
|
||||||
|
minute: 59,
|
||||||
|
second: 59
|
||||||
|
});
|
||||||
|
formValues.lastModifiedTo = lastModifiedToFilterValue.toDate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return true if both filters are same
|
||||||
|
* @param editedQuery, @param currentQuery
|
||||||
|
*/
|
||||||
|
compareFilters(
|
||||||
|
editedQuery: TaskFilterCloudModel,
|
||||||
|
currentQuery: TaskFilterCloudModel
|
||||||
|
): boolean {
|
||||||
|
return JSON.stringify(editedQuery).toLowerCase() === JSON.stringify(currentQuery).toLowerCase();
|
||||||
|
}
|
||||||
|
|
||||||
|
save(saveAction: TaskFilterAction): void {
|
||||||
|
this.taskFilterCloudService
|
||||||
|
.updateFilter(this.changedTaskFilter)
|
||||||
|
.pipe(takeUntil(this.onDestroy$))
|
||||||
|
.subscribe(() => {
|
||||||
|
saveAction.filter = this.changedTaskFilter;
|
||||||
|
this.action.emit(saveAction);
|
||||||
|
this.formHasBeenChanged = this.compareFilters(this.changedTaskFilter, this.taskFilter);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
delete(deleteAction: TaskFilterAction): void {
|
||||||
|
this.taskFilterCloudService
|
||||||
|
.deleteFilter(this.taskFilter)
|
||||||
|
.pipe(
|
||||||
|
filter((filters) => {
|
||||||
|
deleteAction.filter = this.taskFilter;
|
||||||
|
this.action.emit(deleteAction);
|
||||||
|
return filters.length === 0;
|
||||||
|
}),
|
||||||
|
switchMap(() => this.restoreDefaultTaskFilters()),
|
||||||
|
takeUntil(this.onDestroy$))
|
||||||
|
.subscribe(() => { });
|
||||||
|
}
|
||||||
|
|
||||||
|
saveAs(saveAsAction: TaskFilterAction): void {
|
||||||
|
const dialogRef = this.dialog.open(TaskFilterDialogCloudComponent, {
|
||||||
|
data: {
|
||||||
|
name: this.translateService.instant(this.taskFilter.name)
|
||||||
|
},
|
||||||
|
height: 'auto',
|
||||||
|
minWidth: '30%'
|
||||||
|
});
|
||||||
|
dialogRef.afterClosed().subscribe((result) => {
|
||||||
|
if (result && result.action === TaskFilterDialogCloudComponent.ACTION_SAVE) {
|
||||||
|
const filterId = Math.random().toString(36).substr(2, 9);
|
||||||
|
const filterKey = this.getSanitizeFilterName(result.name);
|
||||||
|
const newFilter = {
|
||||||
|
name: result.name,
|
||||||
|
icon: result.icon,
|
||||||
|
id: filterId,
|
||||||
|
key: 'custom-' + filterKey
|
||||||
|
};
|
||||||
|
const resultFilter: TaskFilterCloudModel = Object.assign({}, this.changedTaskFilter, newFilter);
|
||||||
|
this.taskFilterCloudService.addFilter(resultFilter)
|
||||||
|
.pipe(takeUntil(this.onDestroy$)).subscribe(() => {
|
||||||
|
saveAsAction.filter = resultFilter;
|
||||||
|
this.action.emit(saveAsAction);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
isDisabledForDefaultFilters(action: TaskFilterAction): boolean {
|
||||||
|
return (
|
||||||
|
this.taskFilterCloudService.isDefaultFilter(this.taskFilter.name) &&
|
||||||
|
EditTaskFilterCloudComponent.ACTIONS_DISABLED_BY_DEFAULT.includes(action.actionType)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
restoreDefaultTaskFilters(): Observable<TaskFilterCloudModel[]> {
|
||||||
|
return this.taskFilterCloudService.getTaskListFilters(this.appName);
|
||||||
|
}
|
||||||
|
|
||||||
|
createLastModifiedProperty(): TaskFilterProperties[] {
|
||||||
|
return [
|
||||||
|
new TaskFilterProperties({
|
||||||
|
label: 'ADF_CLOUD_EDIT_TASK_FILTER.LABEL.LAST_MODIFIED_FROM',
|
||||||
|
type: 'date',
|
||||||
|
key: 'lastModifiedFrom',
|
||||||
|
value: ''
|
||||||
|
}),
|
||||||
|
|
||||||
|
new TaskFilterProperties({
|
||||||
|
label: 'ADF_CLOUD_EDIT_TASK_FILTER.LABEL.LAST_MODIFIED_TO',
|
||||||
|
type: 'date',
|
||||||
|
key: 'lastModifiedTo',
|
||||||
|
value: ''
|
||||||
|
})
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
createTaskFilterProperties(): TaskFilterProperties[] {
|
||||||
|
return [
|
||||||
|
new TaskFilterProperties({
|
||||||
|
label: 'ADF_CLOUD_EDIT_TASK_FILTER.LABEL.APP_NAME',
|
||||||
|
type: 'select',
|
||||||
|
key: 'appName',
|
||||||
|
value: this.taskFilter.appName || '',
|
||||||
|
options: this.applicationNames
|
||||||
|
}),
|
||||||
|
new TaskFilterProperties({
|
||||||
|
label: 'ADF_CLOUD_EDIT_TASK_FILTER.LABEL.TASK_ID',
|
||||||
|
type: 'text',
|
||||||
|
key: 'taskId',
|
||||||
|
value: ''
|
||||||
|
}),
|
||||||
|
new TaskFilterProperties({
|
||||||
|
label: 'ADF_CLOUD_EDIT_TASK_FILTER.LABEL.STATUS',
|
||||||
|
type: 'select',
|
||||||
|
key: 'status',
|
||||||
|
value: this.taskFilter.status || EditTaskFilterCloudComponent.DEFAULT_TASK_STATUS_PROPERTIES[0].value,
|
||||||
|
options: EditTaskFilterCloudComponent.DEFAULT_TASK_STATUS_PROPERTIES
|
||||||
|
}),
|
||||||
|
new TaskFilterProperties({
|
||||||
|
label: 'ADF_CLOUD_EDIT_TASK_FILTER.LABEL.ASSIGNMENT',
|
||||||
|
type: 'text',
|
||||||
|
key: 'assignee',
|
||||||
|
value: this.taskFilter.assignee || ''
|
||||||
|
}),
|
||||||
|
new TaskFilterProperties({
|
||||||
|
label: 'ADF_CLOUD_EDIT_TASK_FILTER.LABEL.PROCESS_DEF_NAME',
|
||||||
|
type: 'select',
|
||||||
|
key: 'processDefinitionName',
|
||||||
|
value: this.taskFilter.processDefinitionName || '',
|
||||||
|
options: this.processDefinitionNames
|
||||||
|
}),
|
||||||
|
new TaskFilterProperties({
|
||||||
|
label: 'ADF_CLOUD_EDIT_TASK_FILTER.LABEL.PROCESS_INSTANCE_ID',
|
||||||
|
type: 'text',
|
||||||
|
key: 'processInstanceId',
|
||||||
|
value: this.taskFilter.processInstanceId || ''
|
||||||
|
}),
|
||||||
|
new TaskFilterProperties({
|
||||||
|
label: 'ADF_CLOUD_EDIT_TASK_FILTER.LABEL.PROCESS_DEF_ID',
|
||||||
|
type: 'text',
|
||||||
|
key: 'processDefinitionId',
|
||||||
|
value: this.taskFilter.processDefinitionId || ''
|
||||||
|
}),
|
||||||
|
new TaskFilterProperties({
|
||||||
|
label: 'ADF_CLOUD_EDIT_TASK_FILTER.LABEL.TASK_NAME',
|
||||||
|
type: 'text',
|
||||||
|
key: 'taskName',
|
||||||
|
value: this.taskFilter.taskName || ''
|
||||||
|
}),
|
||||||
|
new TaskFilterProperties({
|
||||||
|
label: 'ADF_CLOUD_EDIT_TASK_FILTER.LABEL.PARENT_TASK_ID',
|
||||||
|
type: 'text',
|
||||||
|
key: 'parentTaskId',
|
||||||
|
value: this.taskFilter.parentTaskId || ''
|
||||||
|
}),
|
||||||
|
new TaskFilterProperties({
|
||||||
|
label: 'ADF_CLOUD_EDIT_TASK_FILTER.LABEL.PRIORITY',
|
||||||
|
type: 'text',
|
||||||
|
key: 'priority',
|
||||||
|
value: this.taskFilter.priority || ''
|
||||||
|
}),
|
||||||
|
new TaskFilterProperties({
|
||||||
|
label: 'ADF_CLOUD_EDIT_TASK_FILTER.LABEL.OWNER',
|
||||||
|
type: 'text',
|
||||||
|
key: 'owner',
|
||||||
|
value: this.taskFilter.owner || ''
|
||||||
|
}),
|
||||||
|
new TaskFilterProperties({
|
||||||
|
label: 'ADF_CLOUD_EDIT_TASK_FILTER.LABEL.CREATED_DATE',
|
||||||
|
type: 'date',
|
||||||
|
key: 'createdDate',
|
||||||
|
value: ''
|
||||||
|
}),
|
||||||
|
new TaskFilterProperties({
|
||||||
|
label: 'ADF_CLOUD_EDIT_TASK_FILTER.LABEL.SORT',
|
||||||
|
type: 'select',
|
||||||
|
key: 'sort',
|
||||||
|
value: this.taskFilter.sort || this.createSortProperties[0].value,
|
||||||
|
options: this.createSortProperties
|
||||||
|
}),
|
||||||
|
new TaskFilterProperties({
|
||||||
|
label: 'ADF_CLOUD_EDIT_TASK_FILTER.LABEL.DIRECTION',
|
||||||
|
type: 'select',
|
||||||
|
key: 'order',
|
||||||
|
value: this.taskFilter.order || EditTaskFilterCloudComponent.DIRECTIONS[0].value,
|
||||||
|
options: EditTaskFilterCloudComponent.DIRECTIONS
|
||||||
|
}),
|
||||||
|
new TaskFilterProperties({
|
||||||
|
label: 'ADF_CLOUD_EDIT_TASK_FILTER.LABEL.STAND_ALONE',
|
||||||
|
type: 'checkbox',
|
||||||
|
key: 'standalone',
|
||||||
|
value: this.taskFilter.standalone || false
|
||||||
|
}),
|
||||||
|
new TaskFilterProperties({
|
||||||
|
label: 'ADF_CLOUD_EDIT_TASK_FILTER.LABEL.DUE_DATE',
|
||||||
|
type: 'date-range',
|
||||||
|
key: 'dueDateRange',
|
||||||
|
attributes: { dateType: 'dueDateType', from: '_dueDateFrom', to: '_dueDateTo'},
|
||||||
|
value: {
|
||||||
|
dueDateType: this.taskFilter.dueDateType || null,
|
||||||
|
_dueDateFrom: this.taskFilter.dueDateFrom || null,
|
||||||
|
_dueDateTo: this.taskFilter.dueDateTo || null
|
||||||
|
},
|
||||||
|
dateFilterOptions: [
|
||||||
|
DateCloudFilterType.NO_DATE,
|
||||||
|
DateCloudFilterType.TOMORROW,
|
||||||
|
DateCloudFilterType.NEXT_7_DAYS,
|
||||||
|
DateCloudFilterType.RANGE
|
||||||
|
]
|
||||||
|
})
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,354 @@
|
|||||||
|
/*!
|
||||||
|
* @license
|
||||||
|
* Copyright 2019 Alfresco Software, Ltd.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { SimpleChange } from '@angular/core';
|
||||||
|
import { ComponentFixture, TestBed, async } from '@angular/core/testing';
|
||||||
|
import { setupTestBed } from '@alfresco/adf-core';
|
||||||
|
import { from, Observable } from 'rxjs';
|
||||||
|
import { TASK_FILTERS_SERVICE_TOKEN } from '../../../services/cloud-token.service';
|
||||||
|
import { LocalPreferenceCloudService } from '../../../services/local-preference-cloud.service';
|
||||||
|
import { FilterParamsModel } from '../models/filter-cloud.model';
|
||||||
|
import { By } from '@angular/platform-browser';
|
||||||
|
import { ProcessServiceCloudTestingModule } from '../../../testing/process-service-cloud.testing.module';
|
||||||
|
import { TaskFiltersCloudModule } from '../task-filters-cloud.module';
|
||||||
|
import { fakeGlobalServiceFilters } from '../mock/task-filters-cloud.mock';
|
||||||
|
import { TranslateModule } from '@ngx-translate/core';
|
||||||
|
import { ServiceTaskFilterCloudService } from '../services/service-task-filter-cloud.service';
|
||||||
|
import { ServiceTaskFiltersCloudComponent } from './service-task-filters-cloud.component';
|
||||||
|
|
||||||
|
describe('ServiceTaskFiltersCloudComponent', () => {
|
||||||
|
|
||||||
|
let serviceTaskFilterCloudService: ServiceTaskFilterCloudService;
|
||||||
|
|
||||||
|
const fakeGlobalFilterObservable =
|
||||||
|
new Observable(function(observer) {
|
||||||
|
observer.next(fakeGlobalServiceFilters);
|
||||||
|
observer.complete();
|
||||||
|
});
|
||||||
|
|
||||||
|
const fakeGlobalFilterPromise = new Promise(function (resolve) {
|
||||||
|
resolve(fakeGlobalServiceFilters);
|
||||||
|
});
|
||||||
|
|
||||||
|
const mockErrorFilterList = {
|
||||||
|
error: 'wrong request'
|
||||||
|
};
|
||||||
|
|
||||||
|
const mockErrorFilterPromise = Promise.reject(mockErrorFilterList);
|
||||||
|
|
||||||
|
let component: ServiceTaskFiltersCloudComponent;
|
||||||
|
let fixture: ComponentFixture<ServiceTaskFiltersCloudComponent>;
|
||||||
|
|
||||||
|
setupTestBed({
|
||||||
|
imports: [
|
||||||
|
TranslateModule.forRoot(),
|
||||||
|
ProcessServiceCloudTestingModule,
|
||||||
|
TaskFiltersCloudModule
|
||||||
|
],
|
||||||
|
providers: [
|
||||||
|
{ provide: TASK_FILTERS_SERVICE_TOKEN, useClass: LocalPreferenceCloudService }
|
||||||
|
]
|
||||||
|
});
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
fixture = TestBed.createComponent(ServiceTaskFiltersCloudComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
|
||||||
|
serviceTaskFilterCloudService = TestBed.inject(ServiceTaskFilterCloudService);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should attach specific icon for each filter if hasIcon is true', async(() => {
|
||||||
|
spyOn(serviceTaskFilterCloudService, 'getTaskListFilters').and.returnValue(fakeGlobalFilterObservable);
|
||||||
|
const change = new SimpleChange(undefined, 'my-app-1', true);
|
||||||
|
component.ngOnChanges({'appName': change});
|
||||||
|
fixture.detectChanges();
|
||||||
|
component.showIcons = true;
|
||||||
|
fixture.whenStable().then(() => {
|
||||||
|
fixture.detectChanges();
|
||||||
|
expect(component.filters.length).toBe(3);
|
||||||
|
const filters = fixture.nativeElement.querySelectorAll('.adf-icon');
|
||||||
|
expect(filters.length).toBe(3);
|
||||||
|
expect(filters[0].innerText).toContain('adjust');
|
||||||
|
expect(filters[1].innerText).toContain('done');
|
||||||
|
expect(filters[2].innerText).toContain('inbox');
|
||||||
|
});
|
||||||
|
}));
|
||||||
|
|
||||||
|
it('should not attach icons for each filter if hasIcon is false', (done) => {
|
||||||
|
spyOn(serviceTaskFilterCloudService, 'getTaskListFilters').and.returnValue(from(fakeGlobalFilterPromise));
|
||||||
|
|
||||||
|
component.showIcons = false;
|
||||||
|
const change = new SimpleChange(undefined, 'my-app-1', true);
|
||||||
|
component.ngOnChanges({'appName': change});
|
||||||
|
fixture.detectChanges();
|
||||||
|
|
||||||
|
fixture.whenStable().then(() => {
|
||||||
|
fixture.detectChanges();
|
||||||
|
const filters: any = fixture.debugElement.queryAll(By.css('.adf-icon'));
|
||||||
|
expect(filters.length).toBe(0);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should display the filters', async(() => {
|
||||||
|
spyOn(serviceTaskFilterCloudService, 'getTaskListFilters').and.returnValue(fakeGlobalFilterObservable);
|
||||||
|
const change = new SimpleChange(undefined, 'my-app-1', true);
|
||||||
|
component.ngOnChanges({'appName': change});
|
||||||
|
fixture.detectChanges();
|
||||||
|
component.showIcons = true;
|
||||||
|
fixture.whenStable().then(() => {
|
||||||
|
fixture.detectChanges();
|
||||||
|
const filters = fixture.debugElement.queryAll(By.css('.adf-filters__entry'));
|
||||||
|
expect(component.filters.length).toBe(3);
|
||||||
|
expect(filters.length).toBe(3);
|
||||||
|
expect(filters[0].nativeElement.innerText).toContain('FakeServiceTasks');
|
||||||
|
expect(filters[1].nativeElement.innerText).toContain('FakeMyServiceTasks1');
|
||||||
|
expect(filters[2].nativeElement.innerText).toContain('FakeMyServiceTasks2');
|
||||||
|
});
|
||||||
|
}));
|
||||||
|
|
||||||
|
it('should emit an error with a bad response', (done) => {
|
||||||
|
spyOn(serviceTaskFilterCloudService, 'getTaskListFilters').and.returnValue(from(mockErrorFilterPromise));
|
||||||
|
|
||||||
|
const appName = 'my-app-1';
|
||||||
|
const change = new SimpleChange(null, appName, true);
|
||||||
|
component.ngOnChanges({'appName': change});
|
||||||
|
|
||||||
|
component.error.subscribe((err) => {
|
||||||
|
expect(err).toBeDefined();
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return the filter task list', (done) => {
|
||||||
|
spyOn(serviceTaskFilterCloudService, 'getTaskListFilters').and.returnValue(from(fakeGlobalFilterPromise));
|
||||||
|
const appName = 'my-app-1';
|
||||||
|
const change = new SimpleChange(null, appName, true);
|
||||||
|
component.ngOnChanges({ 'appName': change });
|
||||||
|
|
||||||
|
component.success.subscribe((res) => {
|
||||||
|
expect(res).toBeDefined();
|
||||||
|
expect(component.filters).toBeDefined();
|
||||||
|
expect(component.filters.length).toEqual(3);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return the filter task list, filtered By Name', (done) => {
|
||||||
|
spyOn(serviceTaskFilterCloudService, 'getTaskListFilters').and.returnValue(from(fakeGlobalFilterPromise));
|
||||||
|
const appName = 'my-app-1';
|
||||||
|
const change = new SimpleChange(null, appName, true);
|
||||||
|
component.ngOnChanges({ 'appName': change });
|
||||||
|
|
||||||
|
component.success.subscribe((res) => {
|
||||||
|
expect(res).toBeDefined();
|
||||||
|
expect(component.filters).toBeDefined();
|
||||||
|
expect(component.filters[0].name).toEqual('FakeServiceTasks');
|
||||||
|
expect(component.filters[1].name).toEqual('FakeMyServiceTasks1');
|
||||||
|
expect(component.filters[2].name).toEqual('FakeMyServiceTasks2');
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should select the first filter as default', async(() => {
|
||||||
|
spyOn(serviceTaskFilterCloudService, 'getTaskListFilters').and.returnValue(fakeGlobalFilterObservable);
|
||||||
|
|
||||||
|
const appName = 'my-app-1';
|
||||||
|
const change = new SimpleChange(null, appName, true);
|
||||||
|
|
||||||
|
fixture.detectChanges();
|
||||||
|
component.ngOnChanges({ 'appName': change });
|
||||||
|
|
||||||
|
component.success.subscribe((res) => {
|
||||||
|
expect(res).toBeDefined();
|
||||||
|
expect(component.currentFilter).toBeDefined();
|
||||||
|
expect(component.currentFilter.name).toEqual('FakeServiceTasks');
|
||||||
|
});
|
||||||
|
|
||||||
|
}));
|
||||||
|
|
||||||
|
it('should select the task filter based on the input by name param', async(() => {
|
||||||
|
spyOn(serviceTaskFilterCloudService, 'getTaskListFilters').and.returnValue(fakeGlobalFilterObservable);
|
||||||
|
|
||||||
|
component.filterParam = new FilterParamsModel({ name: 'FakeMyServiceTasks1' });
|
||||||
|
const appName = 'my-app-1';
|
||||||
|
const change = new SimpleChange(null, appName, true);
|
||||||
|
|
||||||
|
fixture.detectChanges();
|
||||||
|
component.ngOnChanges({ 'appName': change });
|
||||||
|
|
||||||
|
component.success.subscribe((res) => {
|
||||||
|
expect(res).toBeDefined();
|
||||||
|
expect(component.currentFilter).toBeDefined();
|
||||||
|
expect(component.currentFilter.name).toEqual('FakeMyServiceTasks1');
|
||||||
|
});
|
||||||
|
|
||||||
|
}));
|
||||||
|
|
||||||
|
it('should select the default task filter if filter input does not exist', async(() => {
|
||||||
|
spyOn(serviceTaskFilterCloudService, 'getTaskListFilters').and.returnValue(fakeGlobalFilterObservable);
|
||||||
|
|
||||||
|
component.filterParam = new FilterParamsModel({ name: 'UnexistableFilter' });
|
||||||
|
|
||||||
|
const appName = 'my-app-1';
|
||||||
|
const change = new SimpleChange(null, appName, true);
|
||||||
|
|
||||||
|
fixture.detectChanges();
|
||||||
|
component.ngOnChanges({ 'appName': change });
|
||||||
|
|
||||||
|
component.success.subscribe((res) => {
|
||||||
|
expect(res).toBeDefined();
|
||||||
|
expect(component.currentFilter).toBeDefined();
|
||||||
|
expect(component.currentFilter.name).toEqual('FakeServiceTasks');
|
||||||
|
});
|
||||||
|
|
||||||
|
}));
|
||||||
|
|
||||||
|
it('should select the task filter based on the input by index param', async(() => {
|
||||||
|
spyOn(serviceTaskFilterCloudService, 'getTaskListFilters').and.returnValue(fakeGlobalFilterObservable);
|
||||||
|
|
||||||
|
component.filterParam = new FilterParamsModel({ index: 2 });
|
||||||
|
|
||||||
|
const appName = 'my-app-1';
|
||||||
|
const change = new SimpleChange(null, appName, true);
|
||||||
|
|
||||||
|
fixture.detectChanges();
|
||||||
|
component.ngOnChanges({ 'appName': change });
|
||||||
|
|
||||||
|
component.success.subscribe((res) => {
|
||||||
|
expect(res).toBeDefined();
|
||||||
|
expect(component.currentFilter).toBeDefined();
|
||||||
|
expect(component.currentFilter.name).toEqual('FakeMyServiceTasks2');
|
||||||
|
});
|
||||||
|
|
||||||
|
}));
|
||||||
|
|
||||||
|
it('should select the task filter based on the input by id param', async(() => {
|
||||||
|
spyOn(serviceTaskFilterCloudService, 'getTaskListFilters').and.returnValue(fakeGlobalFilterObservable);
|
||||||
|
|
||||||
|
component.filterParam = new FilterParamsModel({ id: 12 });
|
||||||
|
const appName = 'my-app-1';
|
||||||
|
const change = new SimpleChange(null, appName, true);
|
||||||
|
|
||||||
|
fixture.detectChanges();
|
||||||
|
component.ngOnChanges({ 'appName': change });
|
||||||
|
|
||||||
|
component.success.subscribe((res) => {
|
||||||
|
expect(res).toBeDefined();
|
||||||
|
expect(component.currentFilter).toBeDefined();
|
||||||
|
expect(component.currentFilter.name).toEqual('FakeMyServiceTasks2');
|
||||||
|
});
|
||||||
|
|
||||||
|
}));
|
||||||
|
|
||||||
|
it('should emit an event when a filter is selected', async(() => {
|
||||||
|
spyOn(serviceTaskFilterCloudService, 'getTaskListFilters').and.returnValue(fakeGlobalFilterObservable);
|
||||||
|
|
||||||
|
component.filterParam = new FilterParamsModel({ id: 12 });
|
||||||
|
|
||||||
|
const appName = 'my-app-1';
|
||||||
|
const change = new SimpleChange(null, appName, true);
|
||||||
|
component.ngOnChanges({ 'appName': change });
|
||||||
|
|
||||||
|
fixture.detectChanges();
|
||||||
|
spyOn(component, 'selectFilterAndEmit').and.stub();
|
||||||
|
const filterButton = fixture.debugElement.nativeElement.querySelector(`[data-automation-id="${fakeGlobalServiceFilters[1].key}_filter"]`);
|
||||||
|
|
||||||
|
filterButton.click();
|
||||||
|
expect(component.selectFilterAndEmit).toHaveBeenCalledWith(fakeGlobalServiceFilters[1]);
|
||||||
|
}));
|
||||||
|
|
||||||
|
it('should reset the filter when the param is undefined', async(() => {
|
||||||
|
spyOn(serviceTaskFilterCloudService, 'getTaskListFilters').and.returnValue(fakeGlobalFilterObservable);
|
||||||
|
spyOn(component, 'selectFilterAndEmit');
|
||||||
|
component.currentFilter = null;
|
||||||
|
|
||||||
|
const filterName = undefined;
|
||||||
|
const change = new SimpleChange(null, filterName, false);
|
||||||
|
component.ngOnChanges({ 'filterParam': change });
|
||||||
|
|
||||||
|
fixture.detectChanges();
|
||||||
|
expect(component.selectFilterAndEmit).toHaveBeenCalledWith(undefined);
|
||||||
|
expect(component.currentFilter).toEqual(undefined);
|
||||||
|
}));
|
||||||
|
|
||||||
|
it('should reload filters by appName on binding changes', () => {
|
||||||
|
spyOn(component, 'getFilters').and.stub();
|
||||||
|
const appName = 'my-app-1';
|
||||||
|
|
||||||
|
const change = new SimpleChange(null, appName, true);
|
||||||
|
component.ngOnChanges({ 'appName': change });
|
||||||
|
|
||||||
|
expect(component.getFilters).toHaveBeenCalledWith(appName);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should change current filter when filterParam (name) changes', () => {
|
||||||
|
component.filters = fakeGlobalServiceFilters;
|
||||||
|
component.currentFilter = null;
|
||||||
|
|
||||||
|
const change = new SimpleChange(null, { name: fakeGlobalServiceFilters[1].name }, true);
|
||||||
|
component.ngOnChanges({ 'filterParam': change });
|
||||||
|
|
||||||
|
fixture.whenStable().then(() => {
|
||||||
|
expect(component.currentFilter.name).toEqual(fakeGlobalServiceFilters[1].name);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should change current filter when filterParam (key) changes', () => {
|
||||||
|
component.filters = fakeGlobalServiceFilters;
|
||||||
|
component.currentFilter = null;
|
||||||
|
|
||||||
|
const change = new SimpleChange(null, { key: fakeGlobalServiceFilters[2].key }, true);
|
||||||
|
component.ngOnChanges({ 'filterParam': change });
|
||||||
|
|
||||||
|
fixture.whenStable().then(() => {
|
||||||
|
expect(component.currentFilter.key).toEqual(fakeGlobalServiceFilters[2].key);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should change current filter when filterParam (index) changes', () => {
|
||||||
|
component.filters = fakeGlobalServiceFilters;
|
||||||
|
component.currentFilter = null;
|
||||||
|
const position = 1;
|
||||||
|
|
||||||
|
const change = new SimpleChange(null, { index: position }, true);
|
||||||
|
component.ngOnChanges({ 'filterParam': change });
|
||||||
|
|
||||||
|
fixture.whenStable().then(() => {
|
||||||
|
expect(component.currentFilter.name).toEqual(fakeGlobalServiceFilters[position].name);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should reload filters by app name on binding changes', () => {
|
||||||
|
spyOn(component, 'getFilters').and.stub();
|
||||||
|
const appName = 'fake-app-name';
|
||||||
|
|
||||||
|
const change = new SimpleChange(null, appName, true);
|
||||||
|
component.ngOnChanges({ 'appName': change });
|
||||||
|
|
||||||
|
expect(component.getFilters).toHaveBeenCalledWith(appName);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return the current filter after one is selected', () => {
|
||||||
|
const filter = new FilterParamsModel({ name: 'FakeMyServiceTasks2' });
|
||||||
|
component.filters = fakeGlobalServiceFilters;
|
||||||
|
|
||||||
|
expect(component.currentFilter).toBeUndefined();
|
||||||
|
component.selectFilter(filter);
|
||||||
|
expect(component.currentFilter).toBe(fakeGlobalServiceFilters[2]);
|
||||||
|
});
|
||||||
|
});
|
@ -0,0 +1,123 @@
|
|||||||
|
/*!
|
||||||
|
* @license
|
||||||
|
* Copyright 2019 Alfresco Software, Ltd.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { Component, EventEmitter, OnChanges, Output, SimpleChanges, OnInit } from '@angular/core';
|
||||||
|
import { Observable } from 'rxjs';
|
||||||
|
import { FilterParamsModel, ServiceTaskFilterCloudModel } from '../models/filter-cloud.model';
|
||||||
|
import { TranslationService } from '@alfresco/adf-core';
|
||||||
|
import { takeUntil } from 'rxjs/operators';
|
||||||
|
import { BaseTaskFiltersCloudComponent } from './base-task-filters-cloud.component';
|
||||||
|
import { ServiceTaskFilterCloudService } from '../services/service-task-filter-cloud.service';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'adf-cloud-service-task-filters',
|
||||||
|
templateUrl: './base-task-filters-cloud.component.html',
|
||||||
|
styleUrls: ['base-task-filters-cloud.component.scss']
|
||||||
|
})
|
||||||
|
export class ServiceTaskFiltersCloudComponent extends BaseTaskFiltersCloudComponent implements OnInit, OnChanges {
|
||||||
|
|
||||||
|
/** Emitted when a filter in the list is clicked. */
|
||||||
|
@Output()
|
||||||
|
filterClick: EventEmitter<ServiceTaskFilterCloudModel> = new EventEmitter<ServiceTaskFilterCloudModel>();
|
||||||
|
|
||||||
|
filters$: Observable<ServiceTaskFilterCloudModel[]>;
|
||||||
|
filters: ServiceTaskFilterCloudModel[] = [];
|
||||||
|
currentFilter: ServiceTaskFilterCloudModel;
|
||||||
|
|
||||||
|
constructor(private serviceTaskFilterCloudService: ServiceTaskFilterCloudService,
|
||||||
|
private translationService: TranslationService) {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnInit() {
|
||||||
|
this.getFilters(this.appName);
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnChanges(changes: SimpleChanges) {
|
||||||
|
const appName = changes['appName'];
|
||||||
|
const filter = changes['filterParam'];
|
||||||
|
if (appName && appName.currentValue !== appName.previousValue) {
|
||||||
|
this.getFilters(appName.currentValue);
|
||||||
|
} else if (filter && filter.currentValue !== filter.previousValue) {
|
||||||
|
this.selectFilterAndEmit(filter.currentValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the filter list filtered by appName
|
||||||
|
*/
|
||||||
|
getFilters(appName: string) {
|
||||||
|
this.filters$ = this.serviceTaskFilterCloudService.getTaskListFilters(appName);
|
||||||
|
|
||||||
|
this.filters$.pipe(takeUntil(this.onDestroy$)).subscribe(
|
||||||
|
(res: ServiceTaskFilterCloudModel[]) => {
|
||||||
|
this.resetFilter();
|
||||||
|
this.filters = Object.assign([], res);
|
||||||
|
this.selectFilterAndEmit(this.filterParam);
|
||||||
|
this.success.emit(res);
|
||||||
|
},
|
||||||
|
(err: any) => {
|
||||||
|
this.error.emit(err);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public selectFilter(paramFilter: FilterParamsModel) {
|
||||||
|
if (paramFilter) {
|
||||||
|
this.currentFilter = (this.filters as Array<ServiceTaskFilterCloudModel>).find((filter: any, index) =>
|
||||||
|
paramFilter.index === index ||
|
||||||
|
paramFilter.key === filter.key ||
|
||||||
|
paramFilter.id === filter.id ||
|
||||||
|
(paramFilter.name &&
|
||||||
|
(paramFilter.name.toLocaleLowerCase() === this.translationService.instant(filter.name).toLocaleLowerCase())
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public selectFilterAndEmit(newParamFilter: FilterParamsModel) {
|
||||||
|
if (newParamFilter) {
|
||||||
|
this.selectFilter(newParamFilter);
|
||||||
|
this.filterClick.emit(this.currentFilter);
|
||||||
|
} else {
|
||||||
|
this.currentFilter = undefined;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Select as default task filter the first in the list
|
||||||
|
*/
|
||||||
|
public selectDefaultTaskFilter() {
|
||||||
|
if (!this.isFilterListEmpty()) {
|
||||||
|
this.currentFilter = this.filters[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the filter list is empty
|
||||||
|
*/
|
||||||
|
isFilterListEmpty(): boolean {
|
||||||
|
return this.filters === undefined || (this.filters && this.filters.length === 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reset the filters properties
|
||||||
|
*/
|
||||||
|
private resetFilter() {
|
||||||
|
this.filters = [];
|
||||||
|
this.currentFilter = undefined;
|
||||||
|
}
|
||||||
|
}
|
@ -18,9 +18,9 @@
|
|||||||
import { ComponentFixture, TestBed, async } from '@angular/core/testing';
|
import { ComponentFixture, TestBed, async } from '@angular/core/testing';
|
||||||
import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';
|
import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';
|
||||||
import { TaskFilterDialogCloudComponent } from './task-filter-dialog-cloud.component';
|
import { TaskFilterDialogCloudComponent } from './task-filter-dialog-cloud.component';
|
||||||
import { TaskFiltersCloudModule } from '../task-filters-cloud.module';
|
import { TaskFiltersCloudModule } from '../../task-filters-cloud.module';
|
||||||
import { setupTestBed } from '@alfresco/adf-core';
|
import { setupTestBed } from '@alfresco/adf-core';
|
||||||
import { ProcessServiceCloudTestingModule } from '../../../testing/process-service-cloud.testing.module';
|
import { ProcessServiceCloudTestingModule } from '../../../../testing/process-service-cloud.testing.module';
|
||||||
import { TranslateModule } from '@ngx-translate/core';
|
import { TranslateModule } from '@ngx-translate/core';
|
||||||
|
|
||||||
describe('TaskFilterDialogCloudComponent', () => {
|
describe('TaskFilterDialogCloudComponent', () => {
|
@ -349,6 +349,6 @@ describe('TaskFiltersCloudComponent', () => {
|
|||||||
|
|
||||||
expect(component.currentFilter).toBeUndefined();
|
expect(component.currentFilter).toBeUndefined();
|
||||||
component.selectFilter(filter);
|
component.selectFilter(filter);
|
||||||
expect(component.getCurrentFilter()).toBe(fakeGlobalFilter[0]);
|
expect(component.currentFilter).toBe(fakeGlobalFilter[0]);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -15,55 +15,31 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { Component, EventEmitter, Input, OnChanges, Output, SimpleChanges, OnDestroy, OnInit } from '@angular/core';
|
import { Component, EventEmitter, OnChanges, Output, SimpleChanges, OnInit } from '@angular/core';
|
||||||
import { Observable, Subject } from 'rxjs';
|
import { Observable } from 'rxjs';
|
||||||
import { TaskFilterCloudService } from '../services/task-filter-cloud.service';
|
import { TaskFilterCloudService } from '../services/task-filter-cloud.service';
|
||||||
import { TaskFilterCloudModel, FilterParamsModel } from '../models/filter-cloud.model';
|
import { TaskFilterCloudModel, FilterParamsModel } from '../models/filter-cloud.model';
|
||||||
import { TranslationService } from '@alfresco/adf-core';
|
import { TranslationService } from '@alfresco/adf-core';
|
||||||
import { takeUntil } from 'rxjs/operators';
|
import { takeUntil } from 'rxjs/operators';
|
||||||
|
import { BaseTaskFiltersCloudComponent } from './base-task-filters-cloud.component';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'adf-cloud-task-filters',
|
selector: 'adf-cloud-task-filters',
|
||||||
templateUrl: './task-filters-cloud.component.html',
|
templateUrl: './base-task-filters-cloud.component.html',
|
||||||
styleUrls: ['task-filters-cloud.component.scss']
|
styleUrls: ['base-task-filters-cloud.component.scss']
|
||||||
})
|
})
|
||||||
export class TaskFiltersCloudComponent implements OnInit, OnChanges, OnDestroy {
|
export class TaskFiltersCloudComponent extends BaseTaskFiltersCloudComponent implements OnInit, OnChanges {
|
||||||
/** Display filters available to the current user for the application with the specified name. */
|
|
||||||
@Input()
|
|
||||||
appName: string = '';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Parameters to use for the task filter cloud. If there is no match then the default filter
|
|
||||||
* (the first one in the list) is selected.
|
|
||||||
*/
|
|
||||||
@Input()
|
|
||||||
filterParam: FilterParamsModel;
|
|
||||||
|
|
||||||
/** Toggles display of the filter's icons. */
|
|
||||||
@Input()
|
|
||||||
showIcons: boolean = false;
|
|
||||||
|
|
||||||
/** Emitted when a filter in the list is clicked. */
|
/** Emitted when a filter in the list is clicked. */
|
||||||
@Output()
|
@Output()
|
||||||
filterClick: EventEmitter<TaskFilterCloudModel> = new EventEmitter<TaskFilterCloudModel>();
|
filterClick: EventEmitter<TaskFilterCloudModel> = new EventEmitter<TaskFilterCloudModel>();
|
||||||
|
|
||||||
/** Emitted when the list is loaded. */
|
|
||||||
@Output()
|
|
||||||
success: EventEmitter<any> = new EventEmitter<any>();
|
|
||||||
|
|
||||||
/** Emitted when an error occurs during loading. */
|
|
||||||
@Output()
|
|
||||||
error: EventEmitter<any> = new EventEmitter<any>();
|
|
||||||
|
|
||||||
filters$: Observable<TaskFilterCloudModel[]>;
|
filters$: Observable<TaskFilterCloudModel[]>;
|
||||||
|
filters: TaskFilterCloudModel[] = [];
|
||||||
currentFilter: TaskFilterCloudModel;
|
currentFilter: TaskFilterCloudModel;
|
||||||
|
|
||||||
filters: TaskFilterCloudModel [] = [];
|
constructor(private taskFilterCloudService: TaskFilterCloudService,
|
||||||
|
private translationService: TranslationService) {
|
||||||
private onDestroy$ = new Subject<boolean>();
|
super();
|
||||||
|
|
||||||
constructor(private taskFilterCloudService: TaskFilterCloudService, private translationService: TranslationService) {
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
@ -80,11 +56,6 @@ export class TaskFiltersCloudComponent implements OnInit, OnChanges, OnDestroy {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnDestroy() {
|
|
||||||
this.onDestroy$.next(true);
|
|
||||||
this.onDestroy$.complete();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the filter list filtered by appName
|
* Return the filter list filtered by appName
|
||||||
*/
|
*/
|
||||||
@ -106,7 +77,7 @@ export class TaskFiltersCloudComponent implements OnInit, OnChanges, OnDestroy {
|
|||||||
|
|
||||||
public selectFilter(paramFilter: FilterParamsModel) {
|
public selectFilter(paramFilter: FilterParamsModel) {
|
||||||
if (paramFilter) {
|
if (paramFilter) {
|
||||||
this.currentFilter = this.filters.find( (filter: TaskFilterCloudModel, index) =>
|
this.currentFilter = this.filters.find((filter: any, index) =>
|
||||||
paramFilter.index === index ||
|
paramFilter.index === index ||
|
||||||
paramFilter.key === filter.key ||
|
paramFilter.key === filter.key ||
|
||||||
paramFilter.id === filter.id ||
|
paramFilter.id === filter.id ||
|
||||||
@ -134,13 +105,6 @@ export class TaskFiltersCloudComponent implements OnInit, OnChanges, OnDestroy {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the current task
|
|
||||||
*/
|
|
||||||
getCurrentFilter(): TaskFilterCloudModel {
|
|
||||||
return this.currentFilter;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if the filter list is empty
|
* Check if the filter list is empty
|
||||||
*/
|
*/
|
||||||
|
@ -15,9 +15,9 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { TaskFilterCloudModel } from '../models/filter-cloud.model';
|
import { TaskFilterCloudModel, ServiceTaskFilterCloudModel } from '../models/filter-cloud.model';
|
||||||
|
|
||||||
export let fakeGlobalFilter = [
|
export const fakeGlobalFilter = [
|
||||||
new TaskFilterCloudModel({
|
new TaskFilterCloudModel({
|
||||||
name: 'FakeInvolvedTasks',
|
name: 'FakeInvolvedTasks',
|
||||||
key: 'fake-involved-tasks',
|
key: 'fake-involved-tasks',
|
||||||
@ -44,7 +44,31 @@ export let fakeGlobalFilter = [
|
|||||||
})
|
})
|
||||||
];
|
];
|
||||||
|
|
||||||
export let fakeFilter = new TaskFilterCloudModel({
|
export const fakeGlobalServiceFilters = [
|
||||||
|
{
|
||||||
|
name: 'FakeServiceTasks',
|
||||||
|
key: 'fake-involved-tasks',
|
||||||
|
icon: 'adjust',
|
||||||
|
id: '10',
|
||||||
|
status: 'open'
|
||||||
|
} as ServiceTaskFilterCloudModel,
|
||||||
|
{
|
||||||
|
name: 'FakeMyServiceTasks1',
|
||||||
|
key: 'fake-my-tast1',
|
||||||
|
icon: 'done',
|
||||||
|
id: '11',
|
||||||
|
status: 'open'
|
||||||
|
} as ServiceTaskFilterCloudModel,
|
||||||
|
{
|
||||||
|
name: 'FakeMyServiceTasks2',
|
||||||
|
key: 'fake-my-tast2',
|
||||||
|
icon: 'inbox',
|
||||||
|
id: '12',
|
||||||
|
status: 'open'
|
||||||
|
} as ServiceTaskFilterCloudModel
|
||||||
|
];
|
||||||
|
|
||||||
|
export const fakeFilter = new TaskFilterCloudModel({
|
||||||
name: 'FakeInvolvedTasks',
|
name: 'FakeInvolvedTasks',
|
||||||
icon: 'adjust',
|
icon: 'adjust',
|
||||||
id: 'mock-task-filter-id',
|
id: 'mock-task-filter-id',
|
||||||
@ -56,7 +80,19 @@ export let fakeFilter = new TaskFilterCloudModel({
|
|||||||
sort: 'id'
|
sort: 'id'
|
||||||
});
|
});
|
||||||
|
|
||||||
export let fakeAllTaskFilter = new TaskFilterCloudModel({
|
export const fakeServiceFilter = {
|
||||||
|
name: 'FakeInvolvedTasks',
|
||||||
|
icon: 'adjust',
|
||||||
|
id: 'mock-task-filter-id',
|
||||||
|
status: 'COMPLETED',
|
||||||
|
appName: 'mock-app-name',
|
||||||
|
processDefinitionId: 'process-def-id',
|
||||||
|
activityName: 'fake-activity',
|
||||||
|
order: 'ASC',
|
||||||
|
sort: 'id'
|
||||||
|
} as ServiceTaskFilterCloudModel;
|
||||||
|
|
||||||
|
export const fakeAllTaskFilter = new TaskFilterCloudModel({
|
||||||
name: 'AllTasks',
|
name: 'AllTasks',
|
||||||
icon: 'adjust',
|
icon: 'adjust',
|
||||||
id: 'mock-task-filter-id',
|
id: 'mock-task-filter-id',
|
||||||
|
@ -116,6 +116,38 @@ export class TaskFilterCloudModel {
|
|||||||
return !!this.dateRangeFilterService.isDateRangeType(type);
|
return !!this.dateRangeFilterService.isDateRangeType(type);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface ServiceTaskFilterCloudModel {
|
||||||
|
id?: string;
|
||||||
|
name?: string;
|
||||||
|
key?: string;
|
||||||
|
icon?: string;
|
||||||
|
index?: number;
|
||||||
|
appName?: string;
|
||||||
|
status?: string;
|
||||||
|
sort?: string;
|
||||||
|
order?: string;
|
||||||
|
activityName?: string;
|
||||||
|
activityType?: string;
|
||||||
|
completedDate?: Date;
|
||||||
|
elementId?: string;
|
||||||
|
executionId?: string;
|
||||||
|
processDefinitionId?: string;
|
||||||
|
processDefinitionKey?: string;
|
||||||
|
processDefinitionVersion?: number;
|
||||||
|
processInstanceId?: string;
|
||||||
|
serviceTaskId?: string;
|
||||||
|
serviceFullName?: string;
|
||||||
|
serviceName?: string;
|
||||||
|
serviceVersion?: string;
|
||||||
|
startedDate?: Date;
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum TaskType {
|
||||||
|
UserTask = 'userTask',
|
||||||
|
ServiceTask = 'serviceTask'
|
||||||
|
}
|
||||||
|
|
||||||
export class FilterParamsModel {
|
export class FilterParamsModel {
|
||||||
|
|
||||||
id?: string;
|
id?: string;
|
||||||
@ -137,7 +169,7 @@ export class TaskFilterAction {
|
|||||||
actionType: string;
|
actionType: string;
|
||||||
icon: string;
|
icon: string;
|
||||||
tooltip: string;
|
tooltip: string;
|
||||||
filter: TaskFilterCloudModel;
|
filter: TaskFilterCloudModel | ServiceTaskFilterCloudModel;
|
||||||
|
|
||||||
constructor(obj?: any) {
|
constructor(obj?: any) {
|
||||||
if (obj) {
|
if (obj) {
|
||||||
|
@ -16,7 +16,8 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
export * from './components/task-filters-cloud.component';
|
export * from './components/task-filters-cloud.component';
|
||||||
export * from './components/edit-task-filter-cloud.component';
|
export * from './components/edit-task-filters/edit-task-filter-cloud.component';
|
||||||
|
export * from './components/edit-task-filters/edit-service-task-filter-cloud.component';
|
||||||
|
|
||||||
export * from './models/filter-cloud.model';
|
export * from './models/filter-cloud.model';
|
||||||
|
|
||||||
|
@ -0,0 +1,295 @@
|
|||||||
|
/*!
|
||||||
|
* @license
|
||||||
|
* Copyright 2019 Alfresco Software, Ltd.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { IdentityUserService } from '@alfresco/adf-core';
|
||||||
|
import { Injectable, Inject } from '@angular/core';
|
||||||
|
import { Observable, of, BehaviorSubject } from 'rxjs';
|
||||||
|
import { ServiceTaskFilterCloudModel } from '../models/filter-cloud.model';
|
||||||
|
import { switchMap, map } from 'rxjs/operators';
|
||||||
|
import { PreferenceCloudServiceInterface } from '../../../services/preference-cloud.interface';
|
||||||
|
import { TASK_FILTERS_SERVICE_TOKEN } from '../../../services/cloud-token.service';
|
||||||
|
|
||||||
|
@Injectable({
|
||||||
|
providedIn: 'root'
|
||||||
|
})
|
||||||
|
export class ServiceTaskFilterCloudService {
|
||||||
|
private filtersSubject: BehaviorSubject<ServiceTaskFilterCloudModel[]>;
|
||||||
|
filters$: Observable<ServiceTaskFilterCloudModel[]>;
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
private identityUserService: IdentityUserService,
|
||||||
|
@Inject(TASK_FILTERS_SERVICE_TOKEN)
|
||||||
|
public preferenceService: PreferenceCloudServiceInterface
|
||||||
|
) {
|
||||||
|
this.filtersSubject = new BehaviorSubject([]);
|
||||||
|
this.filters$ = this.filtersSubject.asObservable();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates and returns the default task filters for an app.
|
||||||
|
* @param appName Name of the target app
|
||||||
|
* @returns Observable of default filters task filters just created or created filters
|
||||||
|
*/
|
||||||
|
private createDefaultFilters(appName: string) {
|
||||||
|
const key: string = this.prepareKey(appName);
|
||||||
|
this.preferenceService.getPreferences(appName, key).pipe(
|
||||||
|
switchMap((response: any) => {
|
||||||
|
const preferences = (response && response.list && response.list.entries) ? response.list.entries : [];
|
||||||
|
if (!this.hasPreferences(preferences) || !this.hasTaskFilters(preferences, key)) {
|
||||||
|
return this.createTaskFilters(appName, key, this.defaultServiceTaskFilters(appName));
|
||||||
|
} else {
|
||||||
|
return of(this.findFiltersByKeyInPreferences(preferences, key));
|
||||||
|
}
|
||||||
|
})
|
||||||
|
).subscribe((filters) => {
|
||||||
|
this.addFiltersToStream(filters);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks user preference are empty or not
|
||||||
|
* @param preferences User preferences of the target app
|
||||||
|
* @returns Boolean value if the preferences are not empty
|
||||||
|
*/
|
||||||
|
private hasPreferences(preferences: any): boolean {
|
||||||
|
return preferences && preferences.length > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks for task filters in given user preferences
|
||||||
|
* @param preferences User preferences of the target app
|
||||||
|
* @param key Key of the task filters
|
||||||
|
* @param filters Details of create filter
|
||||||
|
* @returns Boolean value if the preference has task filters
|
||||||
|
*/
|
||||||
|
private hasTaskFilters(preferences: any, key: string): boolean {
|
||||||
|
const filters = preferences.find((filter: any) => { return filter.entry.key === key; });
|
||||||
|
return (filters && filters.entry) ? JSON.parse(filters.entry.value).length > 0 : false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calls create preference api to create task filters
|
||||||
|
* @param appName Name of the target app
|
||||||
|
* @param key Key of the task instance filters
|
||||||
|
* @param filters Details of new task filter
|
||||||
|
* @returns Observable of created task filters
|
||||||
|
*/
|
||||||
|
private createTaskFilters(appName: string, key: string, filters: ServiceTaskFilterCloudModel[]): Observable<ServiceTaskFilterCloudModel[]> {
|
||||||
|
return this.preferenceService.createPreference(appName, key, filters);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calls get preference api to get task filter by preference key
|
||||||
|
* @param appName Name of the target app
|
||||||
|
* @param key Key of the task filters
|
||||||
|
* @returns Observable of task filters
|
||||||
|
*/
|
||||||
|
private getTaskFiltersByKey(appName: string, key: string): Observable<ServiceTaskFilterCloudModel[]> {
|
||||||
|
return this.preferenceService.getPreferenceByKey(appName, key);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets all task filters for a task app.
|
||||||
|
* @param appName Name of the target app
|
||||||
|
* @returns Observable of task filter details
|
||||||
|
*/
|
||||||
|
getTaskListFilters(appName?: string): Observable<ServiceTaskFilterCloudModel[]> {
|
||||||
|
this.createDefaultFilters(appName);
|
||||||
|
return this.filters$;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets a task filter.
|
||||||
|
* @param appName Name of the target app
|
||||||
|
* @param id ID of the task
|
||||||
|
* @returns Details of the task filter
|
||||||
|
*/
|
||||||
|
getTaskFilterById(appName: string, id: string): Observable<ServiceTaskFilterCloudModel> {
|
||||||
|
const key: string = this.prepareKey(appName);
|
||||||
|
return this.getTaskFiltersByKey(appName, key).pipe(
|
||||||
|
switchMap((filters: ServiceTaskFilterCloudModel[]) => {
|
||||||
|
if (filters && filters.length === 0) {
|
||||||
|
return this.createTaskFilters(appName, key, this.defaultServiceTaskFilters(appName));
|
||||||
|
} else {
|
||||||
|
return of(filters);
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
map((filters: any) => {
|
||||||
|
return filters.filter((filter: ServiceTaskFilterCloudModel) => {
|
||||||
|
return filter.id === id;
|
||||||
|
})[0];
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a new task filter.
|
||||||
|
* @param filter The new filter to add
|
||||||
|
* @returns Observable of task instance filters with newly added filter
|
||||||
|
*/
|
||||||
|
addFilter(newFilter: ServiceTaskFilterCloudModel): Observable<ServiceTaskFilterCloudModel[]> {
|
||||||
|
const key: string = this.prepareKey(newFilter.appName);
|
||||||
|
return this.getTaskFiltersByKey(newFilter.appName, key).pipe(
|
||||||
|
switchMap((filters: ServiceTaskFilterCloudModel[]) => {
|
||||||
|
if (filters && filters.length === 0) {
|
||||||
|
return this.createTaskFilters(newFilter.appName, key, <ServiceTaskFilterCloudModel[]> [newFilter]);
|
||||||
|
} else {
|
||||||
|
filters.push(newFilter);
|
||||||
|
return this.preferenceService.updatePreference(newFilter.appName, key, filters);
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
map((filters: ServiceTaskFilterCloudModel[]) => {
|
||||||
|
this.addFiltersToStream(filters);
|
||||||
|
return filters;
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private addFiltersToStream(filters: ServiceTaskFilterCloudModel[]) {
|
||||||
|
this.filtersSubject.next(filters);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates a task filter.
|
||||||
|
* @param filter The filter to update
|
||||||
|
* @returns Observable of task instance filters with updated filter
|
||||||
|
*/
|
||||||
|
updateFilter(updatedFilter: ServiceTaskFilterCloudModel): Observable<ServiceTaskFilterCloudModel[]> {
|
||||||
|
const key: string = this.prepareKey(updatedFilter.appName);
|
||||||
|
return this.getTaskFiltersByKey(updatedFilter.appName, key).pipe(
|
||||||
|
switchMap((filters: ServiceTaskFilterCloudModel[]) => {
|
||||||
|
if (filters && filters.length === 0) {
|
||||||
|
return this.createTaskFilters(updatedFilter.appName, key, <ServiceTaskFilterCloudModel[]> [updatedFilter]);
|
||||||
|
} else {
|
||||||
|
const itemIndex = filters.findIndex((filter: ServiceTaskFilterCloudModel) => filter.id === updatedFilter.id);
|
||||||
|
filters[itemIndex] = updatedFilter;
|
||||||
|
return this.updateTaskFilters(updatedFilter.appName, key, filters);
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
map((updatedFilters: ServiceTaskFilterCloudModel[]) => {
|
||||||
|
this.addFiltersToStream(updatedFilters);
|
||||||
|
return updatedFilters;
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deletes a task filter
|
||||||
|
* @param filter The filter to delete
|
||||||
|
* @returns Observable of task instance filters without deleted filter
|
||||||
|
*/
|
||||||
|
deleteFilter(deletedFilter: ServiceTaskFilterCloudModel): Observable<ServiceTaskFilterCloudModel[]> {
|
||||||
|
const key = this.prepareKey(deletedFilter.appName);
|
||||||
|
return this.getTaskFiltersByKey(deletedFilter.appName, key).pipe(
|
||||||
|
switchMap((filters: ServiceTaskFilterCloudModel[]) => {
|
||||||
|
if (filters && filters.length > 0) {
|
||||||
|
filters = filters.filter(filter => filter.id !== deletedFilter.id);
|
||||||
|
return this.updateTaskFilters(deletedFilter.appName, key, filters);
|
||||||
|
}
|
||||||
|
return of([]);
|
||||||
|
}),
|
||||||
|
map(filters => {
|
||||||
|
this.addFiltersToStream(filters);
|
||||||
|
return filters;
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if given filter is a default filter
|
||||||
|
* @param filterName Name of the target task filter
|
||||||
|
* @returns Boolean value for whether the filter is a default filter
|
||||||
|
*/
|
||||||
|
isDefaultFilter(filterName: string): boolean {
|
||||||
|
const defaultFilters = this.defaultServiceTaskFilters();
|
||||||
|
return defaultFilters.findIndex((filter) => filterName === filter.name) !== -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calls update preference api to update task filter
|
||||||
|
* @param appName Name of the target app
|
||||||
|
* @param key Key of the task filters
|
||||||
|
* @param filters Details of update filter
|
||||||
|
* @returns Observable of updated task filters
|
||||||
|
*/
|
||||||
|
private updateTaskFilters(appName: string, key: string, filters: ServiceTaskFilterCloudModel[]): Observable<ServiceTaskFilterCloudModel[]> {
|
||||||
|
return this.preferenceService.updatePreference(appName, key, filters);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a uniq key with appName and username
|
||||||
|
* @param appName Name of the target app
|
||||||
|
* @returns String of task filters preference key
|
||||||
|
*/
|
||||||
|
private prepareKey(appName: string): string {
|
||||||
|
return `task-filters-${appName}-${this.identityUserService.getCurrentUserInfo().username}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finds and returns the task filters from preferences
|
||||||
|
* @param appName Name of the target app
|
||||||
|
* @returns Array of TaskFilterCloudModel
|
||||||
|
*/
|
||||||
|
private findFiltersByKeyInPreferences(preferences: any, key: string): ServiceTaskFilterCloudModel[] {
|
||||||
|
const result = preferences.find((filter: any) => { return filter.entry.key === key; });
|
||||||
|
return result && result.entry ? JSON.parse(result.entry.value) : [];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates and returns the default filters for a task app.
|
||||||
|
* @param appName Name of the target app
|
||||||
|
* @returns Array of TaskFilterCloudModel
|
||||||
|
*/
|
||||||
|
private defaultServiceTaskFilters(appName?: string): ServiceTaskFilterCloudModel[] {
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
id: this.generateRandomId(),
|
||||||
|
name: 'ADF_CLOUD_SERVICE_TASK_FILTERS.ALL_SERVICE_TASKS',
|
||||||
|
key: 'my-service-tasks',
|
||||||
|
icon: 'inbox',
|
||||||
|
appName,
|
||||||
|
status: 'ALL',
|
||||||
|
sort: 'startedDate',
|
||||||
|
order: 'DESC'
|
||||||
|
} as ServiceTaskFilterCloudModel,
|
||||||
|
{
|
||||||
|
id: this.generateRandomId(),
|
||||||
|
name: 'ADF_CLOUD_SERVICE_TASK_FILTERS.COMPLETED_TASKS',
|
||||||
|
key: 'completed-tasks',
|
||||||
|
icon: 'done',
|
||||||
|
appName,
|
||||||
|
status: 'COMPLETED',
|
||||||
|
sort: 'completedDate',
|
||||||
|
order: 'DESC'
|
||||||
|
} as ServiceTaskFilterCloudModel,
|
||||||
|
{
|
||||||
|
id: this.generateRandomId(),
|
||||||
|
name: 'ADF_CLOUD_SERVICE_TASK_FILTERS.ERRORED_TASKS',
|
||||||
|
key: 'errored-service-tasks',
|
||||||
|
icon: 'error',
|
||||||
|
appName,
|
||||||
|
status: 'ERROR',
|
||||||
|
sort: 'startedDate',
|
||||||
|
order: 'DESC'
|
||||||
|
} as ServiceTaskFilterCloudModel
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
generateRandomId(): string {
|
||||||
|
return Math.random().toString(36).substr(2, 9);
|
||||||
|
}
|
||||||
|
}
|
@ -38,6 +38,7 @@ import {
|
|||||||
import { UserPreferenceCloudService } from '../../../services/user-preference-cloud.service';
|
import { UserPreferenceCloudService } from '../../../services/user-preference-cloud.service';
|
||||||
import { PreferenceCloudServiceInterface } from '../../../services/preference-cloud.interface';
|
import { PreferenceCloudServiceInterface } from '../../../services/preference-cloud.interface';
|
||||||
import { HttpClientTestingModule } from '@angular/common/http/testing';
|
import { HttpClientTestingModule } from '@angular/common/http/testing';
|
||||||
|
import { TaskFilterCloudModel } from '../models/filter-cloud.model';
|
||||||
|
|
||||||
describe('TaskFilterCloudService', () => {
|
describe('TaskFilterCloudService', () => {
|
||||||
let service: TaskFilterCloudService;
|
let service: TaskFilterCloudService;
|
||||||
@ -257,7 +258,7 @@ describe('Inject [LocalPreferenceCloudService] into the TaskFilterCloudService',
|
|||||||
|
|
||||||
it('should create default task filters if there are no task filter preferences', (done) => {
|
it('should create default task filters if there are no task filter preferences', (done) => {
|
||||||
const appName = 'fakeAppName';
|
const appName = 'fakeAppName';
|
||||||
service.getTaskListFilters(appName).subscribe((res) => {
|
service.getTaskListFilters(appName).subscribe((res: TaskFilterCloudModel[]) => {
|
||||||
expect(res.length).toEqual(3);
|
expect(res.length).toEqual(3);
|
||||||
|
|
||||||
expect(res[0].name).toEqual('ADF_CLOUD_TASK_FILTERS.MY_TASKS');
|
expect(res[0].name).toEqual('ADF_CLOUD_TASK_FILTERS.MY_TASKS');
|
||||||
|
@ -17,9 +17,9 @@
|
|||||||
|
|
||||||
import { IdentityUserService } from '@alfresco/adf-core';
|
import { IdentityUserService } from '@alfresco/adf-core';
|
||||||
import { Injectable, Inject } from '@angular/core';
|
import { Injectable, Inject } from '@angular/core';
|
||||||
import { Observable, of, BehaviorSubject, throwError } from 'rxjs';
|
import { Observable, of, BehaviorSubject } from 'rxjs';
|
||||||
import { TaskFilterCloudModel } from '../models/filter-cloud.model';
|
import { TaskFilterCloudModel } from '../models/filter-cloud.model';
|
||||||
import { switchMap, map, catchError } from 'rxjs/operators';
|
import { switchMap, map } from 'rxjs/operators';
|
||||||
import { PreferenceCloudServiceInterface } from '../../../services/preference-cloud.interface';
|
import { PreferenceCloudServiceInterface } from '../../../services/preference-cloud.interface';
|
||||||
import { TASK_FILTERS_SERVICE_TOKEN } from '../../../services/cloud-token.service';
|
import { TASK_FILTERS_SERVICE_TOKEN } from '../../../services/cloud-token.service';
|
||||||
|
|
||||||
@ -49,15 +49,12 @@ export class TaskFilterCloudService {
|
|||||||
this.preferenceService.getPreferences(appName, key).pipe(
|
this.preferenceService.getPreferences(appName, key).pipe(
|
||||||
switchMap((response: any) => {
|
switchMap((response: any) => {
|
||||||
const preferences = (response && response.list && response.list.entries) ? response.list.entries : [];
|
const preferences = (response && response.list && response.list.entries) ? response.list.entries : [];
|
||||||
if (!this.hasPreferences(preferences)) {
|
if (!this.hasPreferences(preferences) || !this.hasTaskFilters(preferences, key)) {
|
||||||
return this.createTaskFilters(appName, key, this.defaultTaskFilters(appName));
|
|
||||||
} else if (!this.hasTaskFilters(preferences, key)) {
|
|
||||||
return this.createTaskFilters(appName, key, this.defaultTaskFilters(appName));
|
return this.createTaskFilters(appName, key, this.defaultTaskFilters(appName));
|
||||||
} else {
|
} else {
|
||||||
return of(this.findFiltersByKeyInPreferences(preferences, key));
|
return of(this.findFiltersByKeyInPreferences(preferences, key));
|
||||||
}
|
}
|
||||||
}),
|
})
|
||||||
catchError((err) => this.handleTaskError(err))
|
|
||||||
).subscribe((filters) => {
|
).subscribe((filters) => {
|
||||||
this.addFiltersToStream(filters);
|
this.addFiltersToStream(filters);
|
||||||
});
|
});
|
||||||
@ -131,12 +128,11 @@ export class TaskFilterCloudService {
|
|||||||
return of(filters);
|
return of(filters);
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
map((filters: TaskFilterCloudModel[]) => {
|
map((filters: any) => {
|
||||||
return filters.filter((filter: TaskFilterCloudModel) => {
|
return filters.filter((filter: TaskFilterCloudModel) => {
|
||||||
return filter.id === id;
|
return filter.id === id;
|
||||||
})[0];
|
})[0];
|
||||||
}),
|
})
|
||||||
catchError((err) => this.handleTaskError(err))
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -148,9 +144,9 @@ export class TaskFilterCloudService {
|
|||||||
addFilter(newFilter: TaskFilterCloudModel): Observable<TaskFilterCloudModel[]> {
|
addFilter(newFilter: TaskFilterCloudModel): Observable<TaskFilterCloudModel[]> {
|
||||||
const key: string = this.prepareKey(newFilter.appName);
|
const key: string = this.prepareKey(newFilter.appName);
|
||||||
return this.getTaskFiltersByKey(newFilter.appName, key).pipe(
|
return this.getTaskFiltersByKey(newFilter.appName, key).pipe(
|
||||||
switchMap((filters: TaskFilterCloudModel[]) => {
|
switchMap((filters: any) => {
|
||||||
if (filters && filters.length === 0) {
|
if (filters && filters.length === 0) {
|
||||||
return this.createTaskFilters(newFilter.appName, key, [newFilter]);
|
return this.createTaskFilters(newFilter.appName, key, <TaskFilterCloudModel[]> [newFilter]);
|
||||||
} else {
|
} else {
|
||||||
filters.push(newFilter);
|
filters.push(newFilter);
|
||||||
return this.preferenceService.updatePreference(newFilter.appName, key, filters);
|
return this.preferenceService.updatePreference(newFilter.appName, key, filters);
|
||||||
@ -159,8 +155,7 @@ export class TaskFilterCloudService {
|
|||||||
map((filters: TaskFilterCloudModel[]) => {
|
map((filters: TaskFilterCloudModel[]) => {
|
||||||
this.addFiltersToStream(filters);
|
this.addFiltersToStream(filters);
|
||||||
return filters;
|
return filters;
|
||||||
}),
|
})
|
||||||
catchError((err) => this.handleTaskError(err))
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -176,9 +171,9 @@ export class TaskFilterCloudService {
|
|||||||
updateFilter(updatedFilter: TaskFilterCloudModel): Observable<TaskFilterCloudModel[]> {
|
updateFilter(updatedFilter: TaskFilterCloudModel): Observable<TaskFilterCloudModel[]> {
|
||||||
const key: string = this.prepareKey(updatedFilter.appName);
|
const key: string = this.prepareKey(updatedFilter.appName);
|
||||||
return this.getTaskFiltersByKey(updatedFilter.appName, key).pipe(
|
return this.getTaskFiltersByKey(updatedFilter.appName, key).pipe(
|
||||||
switchMap((filters: any) => {
|
switchMap((filters: TaskFilterCloudModel[]) => {
|
||||||
if (filters && filters.length === 0) {
|
if (filters && filters.length === 0) {
|
||||||
return this.createTaskFilters(updatedFilter.appName, key, [updatedFilter]);
|
return this.createTaskFilters(updatedFilter.appName, key, <TaskFilterCloudModel[]> [updatedFilter]);
|
||||||
} else {
|
} else {
|
||||||
const itemIndex = filters.findIndex((filter: TaskFilterCloudModel) => filter.id === updatedFilter.id);
|
const itemIndex = filters.findIndex((filter: TaskFilterCloudModel) => filter.id === updatedFilter.id);
|
||||||
filters[itemIndex] = updatedFilter;
|
filters[itemIndex] = updatedFilter;
|
||||||
@ -188,8 +183,7 @@ export class TaskFilterCloudService {
|
|||||||
map((updatedFilters: TaskFilterCloudModel[]) => {
|
map((updatedFilters: TaskFilterCloudModel[]) => {
|
||||||
this.addFiltersToStream(updatedFilters);
|
this.addFiltersToStream(updatedFilters);
|
||||||
return updatedFilters;
|
return updatedFilters;
|
||||||
}),
|
})
|
||||||
catchError((err) => this.handleTaskError(err))
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -201,7 +195,7 @@ export class TaskFilterCloudService {
|
|||||||
deleteFilter(deletedFilter: TaskFilterCloudModel): Observable<TaskFilterCloudModel[]> {
|
deleteFilter(deletedFilter: TaskFilterCloudModel): Observable<TaskFilterCloudModel[]> {
|
||||||
const key = this.prepareKey(deletedFilter.appName);
|
const key = this.prepareKey(deletedFilter.appName);
|
||||||
return this.getTaskFiltersByKey(deletedFilter.appName, key).pipe(
|
return this.getTaskFiltersByKey(deletedFilter.appName, key).pipe(
|
||||||
switchMap(filters => {
|
switchMap((filters: TaskFilterCloudModel[]) => {
|
||||||
if (filters && filters.length > 0) {
|
if (filters && filters.length > 0) {
|
||||||
filters = filters.filter(filter => filter.id !== deletedFilter.id);
|
filters = filters.filter(filter => filter.id !== deletedFilter.id);
|
||||||
return this.updateTaskFilters(deletedFilter.appName, key, filters);
|
return this.updateTaskFilters(deletedFilter.appName, key, filters);
|
||||||
@ -211,8 +205,7 @@ export class TaskFilterCloudService {
|
|||||||
map(filters => {
|
map(filters => {
|
||||||
this.addFiltersToStream(filters);
|
this.addFiltersToStream(filters);
|
||||||
return filters;
|
return filters;
|
||||||
}),
|
})
|
||||||
catchError((err) => this.handleTaskError(err))
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -237,22 +230,13 @@ export class TaskFilterCloudService {
|
|||||||
return this.preferenceService.updatePreference(appName, key, filters);
|
return this.preferenceService.updatePreference(appName, key, filters);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the username field from the access token.
|
|
||||||
* @returns Username string
|
|
||||||
*/
|
|
||||||
getUsername(): string {
|
|
||||||
const user = this.identityUserService.getCurrentUserInfo();
|
|
||||||
return user.username;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a uniq key with appName and username
|
* Creates a uniq key with appName and username
|
||||||
* @param appName Name of the target app
|
* @param appName Name of the target app
|
||||||
* @returns String of task filters preference key
|
* @returns String of task filters preference key
|
||||||
*/
|
*/
|
||||||
private prepareKey(appName: string): string {
|
private prepareKey(appName: string): string {
|
||||||
return `task-filters-${appName}-${this.getUsername()}`;
|
return `task-filters-${appName}-${this.identityUserService.getCurrentUserInfo().username}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -265,10 +249,6 @@ export class TaskFilterCloudService {
|
|||||||
return result && result.entry ? JSON.parse(result.entry.value) : [];
|
return result && result.entry ? JSON.parse(result.entry.value) : [];
|
||||||
}
|
}
|
||||||
|
|
||||||
private handleTaskError(error: any) {
|
|
||||||
return throwError(error || 'Server error');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates and returns the default filters for a task app.
|
* Creates and returns the default filters for a task app.
|
||||||
* @param appName Name of the target app
|
* @param appName Name of the target app
|
||||||
@ -282,7 +262,7 @@ export class TaskFilterCloudService {
|
|||||||
icon: 'inbox',
|
icon: 'inbox',
|
||||||
appName,
|
appName,
|
||||||
status: 'ASSIGNED',
|
status: 'ASSIGNED',
|
||||||
assignee: this.getUsername(),
|
assignee: this.identityUserService.getCurrentUserInfo().username,
|
||||||
sort: 'createdDate',
|
sort: 'createdDate',
|
||||||
order: 'DESC'
|
order: 'DESC'
|
||||||
}),
|
}),
|
||||||
|
@ -23,12 +23,14 @@ import { TaskFiltersCloudComponent } from './components/task-filters-cloud.compo
|
|||||||
import { MaterialModule } from '../../material.module';
|
import { MaterialModule } from '../../material.module';
|
||||||
import { CoreModule, MomentDateAdapter, MOMENT_DATE_FORMATS } from '@alfresco/adf-core';
|
import { CoreModule, MomentDateAdapter, MOMENT_DATE_FORMATS } from '@alfresco/adf-core';
|
||||||
import { HttpClientModule } from '@angular/common/http';
|
import { HttpClientModule } from '@angular/common/http';
|
||||||
import { EditTaskFilterCloudComponent } from './components/edit-task-filter-cloud.component';
|
|
||||||
import { TaskFilterDialogCloudComponent } from './components/task-filter-dialog-cloud.component';
|
|
||||||
import { AppListCloudModule } from './../../app/app-list-cloud.module';
|
import { AppListCloudModule } from './../../app/app-list-cloud.module';
|
||||||
import { DateAdapter, MAT_DATE_FORMATS } from '@angular/material/core';
|
import { DateAdapter, MAT_DATE_FORMATS } from '@angular/material/core';
|
||||||
import { ProcessCommonModule } from '../../common/process-common.module';
|
import { ProcessCommonModule } from '../../common/process-common.module';
|
||||||
import { PeopleCloudModule } from '../../people/people-cloud.module';
|
import { PeopleCloudModule } from '../../people/people-cloud.module';
|
||||||
|
import { EditServiceTaskFilterCloudComponent } from './components/edit-task-filters/edit-service-task-filter-cloud.component';
|
||||||
|
import { EditTaskFilterCloudComponent } from './components/edit-task-filters/edit-task-filter-cloud.component';
|
||||||
|
import { TaskFilterDialogCloudComponent } from './components/task-filter-dialog/task-filter-dialog-cloud.component';
|
||||||
|
import { ServiceTaskFiltersCloudComponent } from './components/service-task-filters-cloud.component';
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
imports: [
|
imports: [
|
||||||
@ -43,8 +45,19 @@ import { PeopleCloudModule } from '../../people/people-cloud.module';
|
|||||||
ProcessCommonModule,
|
ProcessCommonModule,
|
||||||
PeopleCloudModule
|
PeopleCloudModule
|
||||||
],
|
],
|
||||||
declarations: [TaskFiltersCloudComponent, EditTaskFilterCloudComponent, TaskFilterDialogCloudComponent],
|
declarations: [
|
||||||
exports: [TaskFiltersCloudComponent, EditTaskFilterCloudComponent],
|
TaskFiltersCloudComponent,
|
||||||
|
ServiceTaskFiltersCloudComponent,
|
||||||
|
EditTaskFilterCloudComponent,
|
||||||
|
EditServiceTaskFilterCloudComponent,
|
||||||
|
TaskFilterDialogCloudComponent
|
||||||
|
],
|
||||||
|
exports: [
|
||||||
|
TaskFiltersCloudComponent,
|
||||||
|
ServiceTaskFiltersCloudComponent,
|
||||||
|
EditTaskFilterCloudComponent,
|
||||||
|
EditServiceTaskFilterCloudComponent
|
||||||
|
],
|
||||||
providers: [
|
providers: [
|
||||||
{ provide: DateAdapter, useClass: MomentDateAdapter },
|
{ provide: DateAdapter, useClass: MomentDateAdapter },
|
||||||
{ provide: MAT_DATE_FORMATS, useValue: MOMENT_DATE_FORMATS }
|
{ provide: MAT_DATE_FORMATS, useValue: MOMENT_DATE_FORMATS }
|
||||||
|
@ -0,0 +1,256 @@
|
|||||||
|
/*!
|
||||||
|
* @license
|
||||||
|
* Copyright 2019 Alfresco Software, Ltd.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { OnChanges, Input, SimpleChanges, Output, EventEmitter, ContentChild, AfterContentInit, OnDestroy, OnInit, Directive } from '@angular/core';
|
||||||
|
import {
|
||||||
|
AppConfigService, UserPreferencesService,
|
||||||
|
DataTableSchema, UserPreferenceValues,
|
||||||
|
PaginatedComponent, PaginationModel,
|
||||||
|
DataRowEvent, CustomEmptyContentTemplateDirective, DataCellEvent, DataRowActionEvent
|
||||||
|
} from '@alfresco/adf-core';
|
||||||
|
import { taskPresetsCloudDefaultModel } from '../models/task-preset-cloud.model';
|
||||||
|
import { TaskQueryCloudRequestModel } from '../models/filter-cloud-model';
|
||||||
|
import { BehaviorSubject, Subject } from 'rxjs';
|
||||||
|
import { TaskListCloudSortingModel } from '../models/task-list-sorting.model';
|
||||||
|
import { takeUntil } from 'rxjs/operators';
|
||||||
|
|
||||||
|
@Directive()
|
||||||
|
// tslint:disable-next-line: directive-class-suffix
|
||||||
|
export abstract class BaseTaskListCloudComponent extends DataTableSchema implements OnChanges, AfterContentInit, PaginatedComponent, OnDestroy, OnInit {
|
||||||
|
|
||||||
|
static ENTRY_PREFIX = 'entry.';
|
||||||
|
|
||||||
|
@ContentChild(CustomEmptyContentTemplateDirective)
|
||||||
|
emptyCustomContent: CustomEmptyContentTemplateDirective;
|
||||||
|
|
||||||
|
/** The name of the application. */
|
||||||
|
@Input()
|
||||||
|
appName: string = '';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Row selection mode. Can be none, `single` or `multiple`. For `multiple` mode,
|
||||||
|
* you can use the Cmd (macOS) or Ctrl (Win) modifier key to toggle selection for
|
||||||
|
* multiple rows.
|
||||||
|
*/
|
||||||
|
@Input()
|
||||||
|
selectionMode: string = 'single'; // none|single|multiple
|
||||||
|
|
||||||
|
/** Toggles multiple row selection, rendering a checkbox at the beginning of each row. */
|
||||||
|
@Input()
|
||||||
|
multiselect: boolean = false;
|
||||||
|
|
||||||
|
/** Toggles the sticky header mode. */
|
||||||
|
@Input()
|
||||||
|
stickyHeader: boolean = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specifies how the table should be sorted. The parameters are for BE sorting.
|
||||||
|
*/
|
||||||
|
@Input()
|
||||||
|
sorting: TaskListCloudSortingModel[];
|
||||||
|
|
||||||
|
/** Toggles the data actions column. */
|
||||||
|
@Input()
|
||||||
|
showActions: boolean = false;
|
||||||
|
|
||||||
|
/** Position of the actions dropdown menu. Can be "left" or "right". */
|
||||||
|
@Input()
|
||||||
|
actionsPosition: string = 'right'; // left|right
|
||||||
|
|
||||||
|
/** Toggles custom context menu for the component. */
|
||||||
|
@Input()
|
||||||
|
showContextMenu: boolean = false;
|
||||||
|
|
||||||
|
/** Emitted before the context menu is displayed for a row. */
|
||||||
|
@Output()
|
||||||
|
showRowContextMenu = new EventEmitter<DataCellEvent>();
|
||||||
|
|
||||||
|
/** Emitted before the actions menu is displayed for a row. */
|
||||||
|
@Output()
|
||||||
|
showRowActionsMenu = new EventEmitter<DataCellEvent>();
|
||||||
|
|
||||||
|
/** Emitted when the user executes a row action. */
|
||||||
|
@Output()
|
||||||
|
executeRowAction = new EventEmitter<DataRowActionEvent>();
|
||||||
|
|
||||||
|
/** Emitted when a task in the list is clicked */
|
||||||
|
@Output()
|
||||||
|
rowClick: EventEmitter<string> = new EventEmitter<string>();
|
||||||
|
|
||||||
|
/** Emitted when rows are selected/unselected */
|
||||||
|
@Output()
|
||||||
|
rowsSelected: EventEmitter<any[]> = new EventEmitter<any[]>();
|
||||||
|
|
||||||
|
/** Emitted when the task list is loaded */
|
||||||
|
@Output()
|
||||||
|
success: EventEmitter<any> = new EventEmitter<any>();
|
||||||
|
|
||||||
|
/** Emitted when an error occurs. */
|
||||||
|
@Output()
|
||||||
|
error: EventEmitter<any> = new EventEmitter<any>();
|
||||||
|
|
||||||
|
pagination: BehaviorSubject<PaginationModel>;
|
||||||
|
|
||||||
|
requestNode: TaskQueryCloudRequestModel;
|
||||||
|
rows: any[] = [];
|
||||||
|
size: number;
|
||||||
|
skipCount: number = 0;
|
||||||
|
currentInstanceId: any;
|
||||||
|
isLoading = true;
|
||||||
|
selectedInstances: any[];
|
||||||
|
formattedSorting: any[];
|
||||||
|
private defaultSorting = { key: 'startDate', direction: 'desc' };
|
||||||
|
|
||||||
|
private onDestroy$ = new Subject<boolean>();
|
||||||
|
|
||||||
|
constructor(appConfigService: AppConfigService,
|
||||||
|
private userPreferences: UserPreferencesService,
|
||||||
|
presetKey: string) {
|
||||||
|
super(appConfigService, presetKey, taskPresetsCloudDefaultModel);
|
||||||
|
this.size = userPreferences.paginationSize;
|
||||||
|
|
||||||
|
this.pagination = new BehaviorSubject<PaginationModel>(<PaginationModel> {
|
||||||
|
maxItems: this.size,
|
||||||
|
skipCount: 0,
|
||||||
|
totalItems: 0
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnInit() {
|
||||||
|
this.userPreferences
|
||||||
|
.select(UserPreferenceValues.PaginationSize)
|
||||||
|
.pipe(takeUntil(this.onDestroy$))
|
||||||
|
.subscribe(pageSize => this.size = pageSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnChanges(changes: SimpleChanges) {
|
||||||
|
if (changes['sorting']) {
|
||||||
|
this.formatSorting(changes['sorting'].currentValue);
|
||||||
|
}
|
||||||
|
this.reload();
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnDestroy() {
|
||||||
|
this.onDestroy$.next(true);
|
||||||
|
this.onDestroy$.complete();
|
||||||
|
}
|
||||||
|
|
||||||
|
ngAfterContentInit() {
|
||||||
|
this.createDatatableSchema();
|
||||||
|
}
|
||||||
|
|
||||||
|
reload() {
|
||||||
|
this.requestNode = this.createRequestNode();
|
||||||
|
if (this.requestNode.appName || this.requestNode.appName === '') {
|
||||||
|
this.load(this.requestNode);
|
||||||
|
} else {
|
||||||
|
this.rows = [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
isListEmpty(): boolean {
|
||||||
|
return !this.rows || this.rows.length === 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resets the pagination values
|
||||||
|
*/
|
||||||
|
resetPagination() {
|
||||||
|
this.skipCount = 0;
|
||||||
|
this.size = this.userPreferences.paginationSize;
|
||||||
|
this.pagination.next({
|
||||||
|
skipCount: 0,
|
||||||
|
maxItems: this.size
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resets the pagination values and
|
||||||
|
* Reloads the task list
|
||||||
|
* @param pagination Pagination values to be set
|
||||||
|
*/
|
||||||
|
updatePagination(pagination: PaginationModel) {
|
||||||
|
this.size = pagination.maxItems;
|
||||||
|
this.skipCount = pagination.skipCount;
|
||||||
|
this.pagination.next(pagination);
|
||||||
|
this.reload();
|
||||||
|
}
|
||||||
|
|
||||||
|
onSortingChanged(event: CustomEvent) {
|
||||||
|
this.setSorting(event.detail);
|
||||||
|
this.formatSorting(this.sorting);
|
||||||
|
this.reload();
|
||||||
|
}
|
||||||
|
|
||||||
|
onRowClick(item: DataRowEvent) {
|
||||||
|
this.currentInstanceId = item.value.getValue('entry.id');
|
||||||
|
this.rowClick.emit(this.currentInstanceId);
|
||||||
|
}
|
||||||
|
|
||||||
|
onRowSelect(event: CustomEvent) {
|
||||||
|
this.selectedInstances = [...event.detail.selection];
|
||||||
|
this.rowsSelected.emit(this.selectedInstances);
|
||||||
|
}
|
||||||
|
|
||||||
|
onRowUnselect(event: CustomEvent) {
|
||||||
|
this.selectedInstances = [...event.detail.selection];
|
||||||
|
this.rowsSelected.emit(this.selectedInstances);
|
||||||
|
}
|
||||||
|
|
||||||
|
onRowKeyUp(event: CustomEvent) {
|
||||||
|
if (event.detail.keyboardEvent.key === 'Enter') {
|
||||||
|
event.preventDefault();
|
||||||
|
this.currentInstanceId = event.detail.row.getValue('entry.id');
|
||||||
|
this.rowClick.emit(this.currentInstanceId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onShowRowActionsMenu(event: DataCellEvent) {
|
||||||
|
this.showRowActionsMenu.emit(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
onShowRowContextMenu(event: DataCellEvent) {
|
||||||
|
this.showRowContextMenu.emit(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
onExecuteRowAction(row: DataRowActionEvent) {
|
||||||
|
this.executeRowAction.emit(row);
|
||||||
|
}
|
||||||
|
|
||||||
|
setSorting(sortDetail) {
|
||||||
|
const sorting = sortDetail ? {
|
||||||
|
orderBy: sortDetail.key.replace(BaseTaskListCloudComponent.ENTRY_PREFIX, ''),
|
||||||
|
direction: sortDetail.direction.toUpperCase()
|
||||||
|
} : { ... this.defaultSorting };
|
||||||
|
this.sorting = [new TaskListCloudSortingModel(sorting)];
|
||||||
|
}
|
||||||
|
|
||||||
|
formatSorting(sorting: TaskListCloudSortingModel[]) {
|
||||||
|
this.formattedSorting = this.isValidSorting(sorting) ? [
|
||||||
|
BaseTaskListCloudComponent.ENTRY_PREFIX + sorting[0].orderBy,
|
||||||
|
sorting[0].direction.toLocaleLowerCase()
|
||||||
|
] : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
isValidSorting(sorting: TaskListCloudSortingModel[]) {
|
||||||
|
return sorting.length && sorting[0].orderBy && sorting[0].direction;
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract load(requestNode);
|
||||||
|
abstract createRequestNode();
|
||||||
|
}
|
@ -0,0 +1,524 @@
|
|||||||
|
/*!
|
||||||
|
* @license
|
||||||
|
* Copyright 2019 Alfresco Software, Ltd.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { Component, SimpleChange, ViewChild } from '@angular/core';
|
||||||
|
import { ComponentFixture, TestBed, async } from '@angular/core/testing';
|
||||||
|
import { By } from '@angular/platform-browser';
|
||||||
|
import { AppConfigService, setupTestBed, DataRowEvent, ObjectDataRow } from '@alfresco/adf-core';
|
||||||
|
import { TaskListCloudService } from '../services/task-list-cloud.service';
|
||||||
|
import { ServiceTaskListCloudComponent } from './service-task-list-cloud.component';
|
||||||
|
import { fakeServiceTask, fakeCustomSchema } from '../mock/fake-task-response.mock';
|
||||||
|
import { of } from 'rxjs';
|
||||||
|
import { ProcessServiceCloudTestingModule } from '../../../testing/process-service-cloud.testing.module';
|
||||||
|
import { Person } from '@alfresco/js-api';
|
||||||
|
import { TranslateModule } from '@ngx-translate/core';
|
||||||
|
import { TaskListCloudSortingModel } from '../models/task-list-sorting.model';
|
||||||
|
import { skip } from 'rxjs/operators';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
template: `
|
||||||
|
<adf-cloud-service-task-list #taskListCloud>
|
||||||
|
<data-columns>
|
||||||
|
<data-column key="activityName" title="ADF_CLOUD_TASK_LIST.PROPERTIES.NAME" class="adf-full-width adf-name-column"></data-column>
|
||||||
|
<data-column key="startedDate" title="ADF_CLOUD_TASK_LIST.PROPERTIES.CREATED" class="adf-hidden"></data-column>
|
||||||
|
</data-columns>
|
||||||
|
</adf-cloud-service-task-list>`
|
||||||
|
})
|
||||||
|
class CustomTaskListComponent {
|
||||||
|
@ViewChild(ServiceTaskListCloudComponent)
|
||||||
|
taskList: ServiceTaskListCloudComponent;
|
||||||
|
|
||||||
|
getFullName(person: Person): string {
|
||||||
|
return `${person.firstName} ${person.lastName}`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@Component({
|
||||||
|
template: `
|
||||||
|
<adf-cloud-service-task-list>
|
||||||
|
<adf-custom-empty-content-template>
|
||||||
|
<p id="custom-id"></p>
|
||||||
|
</adf-custom-empty-content-template>
|
||||||
|
</adf-cloud-service-task-list>
|
||||||
|
`
|
||||||
|
})
|
||||||
|
class EmptyTemplateComponent {
|
||||||
|
}
|
||||||
|
@Component({
|
||||||
|
template: `
|
||||||
|
<adf-cloud-service-task-list>
|
||||||
|
<data-columns>
|
||||||
|
<data-column [copyContent]="true" key="entry.id" title="ADF_CLOUD_TASK_LIST.PROPERTIES.ID"></data-column>
|
||||||
|
<data-column key="entry.activityName" title="ADF_CLOUD_TASK_LIST.PROPERTIES.NAME"></data-column>
|
||||||
|
</data-columns>
|
||||||
|
</adf-cloud-service-task-list>`
|
||||||
|
})
|
||||||
|
class CustomCopyContentTaskListComponent {
|
||||||
|
@ViewChild(ServiceTaskListCloudComponent, { static: true })
|
||||||
|
taskList: ServiceTaskListCloudComponent;
|
||||||
|
}
|
||||||
|
|
||||||
|
describe('ServiceTaskListCloudComponent', () => {
|
||||||
|
let component: ServiceTaskListCloudComponent;
|
||||||
|
let fixture: ComponentFixture<ServiceTaskListCloudComponent>;
|
||||||
|
let appConfig: AppConfigService;
|
||||||
|
let taskListCloudService: TaskListCloudService;
|
||||||
|
|
||||||
|
setupTestBed({
|
||||||
|
imports: [
|
||||||
|
TranslateModule.forRoot(),
|
||||||
|
ProcessServiceCloudTestingModule
|
||||||
|
],
|
||||||
|
declarations: [
|
||||||
|
EmptyTemplateComponent
|
||||||
|
]
|
||||||
|
});
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
appConfig = TestBed.inject(AppConfigService);
|
||||||
|
taskListCloudService = TestBed.inject(TaskListCloudService);
|
||||||
|
fixture = TestBed.createComponent(ServiceTaskListCloudComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
appConfig.config = Object.assign(appConfig.config, {
|
||||||
|
'adf-cloud-service-task-list': {
|
||||||
|
'presets': {
|
||||||
|
'fakeCustomSchema': [
|
||||||
|
{
|
||||||
|
'key': 'fakeName',
|
||||||
|
'type': 'text',
|
||||||
|
'title': 'ADF_CLOUD_TASK_LIST.PROPERTIES.FAKE',
|
||||||
|
'sortable': true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'key': 'fakeTaskName',
|
||||||
|
'type': 'text',
|
||||||
|
'title': 'ADF_CLOUD_TASK_LIST.PROPERTIES.TASK_FAKE',
|
||||||
|
'sortable': true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
fixture.destroy();
|
||||||
|
});
|
||||||
|
|
||||||
|
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', () => {
|
||||||
|
const emptyList = { list: { entries: [] } };
|
||||||
|
spyOn(taskListCloudService, 'getServiceTaskByRequest').and.returnValue(of(emptyList));
|
||||||
|
|
||||||
|
fixture.detectChanges();
|
||||||
|
expect(component.isLoading).toBe(true);
|
||||||
|
let loadingContent = fixture.debugElement.query(By.css('mat-progress-spinner'));
|
||||||
|
expect(loadingContent.nativeElement).toBeDefined();
|
||||||
|
|
||||||
|
const appName = new SimpleChange(null, 'FAKE-APP-NAME', true);
|
||||||
|
component.ngOnChanges({ appName });
|
||||||
|
fixture.detectChanges();
|
||||||
|
|
||||||
|
loadingContent = fixture.debugElement.query(By.css('mat-progress-spinner'));
|
||||||
|
expect(loadingContent).toBeFalsy();
|
||||||
|
|
||||||
|
const emptyContent = fixture.debugElement.query(By.css('.adf-empty-content'));
|
||||||
|
expect(emptyContent.nativeElement).toBeDefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should load spinner and show the content', () => {
|
||||||
|
spyOn(taskListCloudService, 'getServiceTaskByRequest').and.returnValue(of(fakeServiceTask));
|
||||||
|
const appName = new SimpleChange(null, 'FAKE-APP-NAME', true);
|
||||||
|
|
||||||
|
fixture.detectChanges();
|
||||||
|
expect(component.isLoading).toBe(true);
|
||||||
|
let loadingContent = fixture.debugElement.query(By.css('mat-progress-spinner'));
|
||||||
|
expect(loadingContent.nativeElement).toBeDefined();
|
||||||
|
|
||||||
|
component.ngOnChanges({ appName });
|
||||||
|
fixture.detectChanges();
|
||||||
|
|
||||||
|
expect(component.isLoading).toBe(false);
|
||||||
|
loadingContent = fixture.debugElement.query(By.css('mat-progress-spinner'));
|
||||||
|
expect(loadingContent).toBeFalsy();
|
||||||
|
|
||||||
|
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 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, 'getServiceTaskByRequest').and.returnValue(of(fakeServiceTask));
|
||||||
|
const appName = new SimpleChange(null, 'FAKE-APP-NAME', true);
|
||||||
|
component.success.subscribe((res) => {
|
||||||
|
expect(res).toBeDefined();
|
||||||
|
expect(component.rows).toBeDefined();
|
||||||
|
expect(component.isListEmpty()).not.toBeTruthy();
|
||||||
|
expect(component.rows.length).toEqual(1);
|
||||||
|
expect(component.rows[0].entry['appName']).toBe('simpleapp');
|
||||||
|
expect(component.rows[0].entry['activityType']).toBe('serviceTask');
|
||||||
|
expect(component.rows[0].entry['id']).toBe('04fdf69f-4ddd-48ab-9563-da776c9b163c');
|
||||||
|
expect(component.rows[0].entry['elementId']).toBe('ServiceTask_0lszm0x');
|
||||||
|
expect(component.rows[0].entry['executionId']).toBe('2023b099-fced-11ea-b116-62141048995a');
|
||||||
|
expect(component.rows[0].entry['startedDate']).toBe('2020-09-22T16:03:37.444+0000');
|
||||||
|
expect(component.rows[0].entry['completedDate']).toBe('2020-09-22T16:03:37.482+0000');
|
||||||
|
expect(component.rows[0].entry['processDefinitionVersion']).toBe(1);
|
||||||
|
expect(component.rows[0].entry['processDefinitionId']).toBe('Process_24rkVVSR:1:0db78dcd-fc14-11ea-bce0-62141048995a');
|
||||||
|
expect(component.rows[0].entry['processInstanceId']).toBe('2023b097-fced-11ea-b116-62141048995a');
|
||||||
|
expect(component.rows[0].entry['status']).toBe('COMPLETED');
|
||||||
|
expect(component.rows[0].entry['serviceFullName']).toBe('simpleapp-rb');
|
||||||
|
expect(component.rows[0].entry['serviceName']).toBe('simpleapp-rb');
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
component.appName = appName.currentValue;
|
||||||
|
component.ngOnChanges({ 'appName': appName });
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should reload tasks when reload() is called', (done) => {
|
||||||
|
component.appName = 'fake';
|
||||||
|
spyOn(taskListCloudService, 'getServiceTaskByRequest').and.returnValue(of(fakeServiceTask));
|
||||||
|
component.success.subscribe((res) => {
|
||||||
|
expect(res).toBeDefined();
|
||||||
|
expect(component.rows).toBeDefined();
|
||||||
|
expect(component.isListEmpty()).not.toBeTruthy();
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
fixture.detectChanges();
|
||||||
|
component.reload();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should emit row click event', (done) => {
|
||||||
|
const row = new ObjectDataRow({
|
||||||
|
entry: {
|
||||||
|
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);
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('component changes', () => {
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
component.rows = fakeServiceTask.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 reload the task list when input parameters changed', () => {
|
||||||
|
const getServiceTaskByRequestSpy = spyOn(taskListCloudService, 'getServiceTaskByRequest').and.returnValue(of(fakeServiceTask));
|
||||||
|
component.appName = 'mock-app-name';
|
||||||
|
component.queryParams.status = 'mock-status';
|
||||||
|
const queryParams = new SimpleChange(undefined, { status: 'mock-status' }, true);
|
||||||
|
component.ngOnChanges({
|
||||||
|
'queryParams': queryParams
|
||||||
|
});
|
||||||
|
fixture.detectChanges();
|
||||||
|
expect(component.isListEmpty()).toBeFalsy();
|
||||||
|
expect(getServiceTaskByRequestSpy).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should set formattedSorting if sorting input changes', () => {
|
||||||
|
spyOn(taskListCloudService, 'getServiceTaskByRequest').and.returnValue(of(fakeServiceTask));
|
||||||
|
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([ServiceTaskListCloudComponent.ENTRY_PREFIX + 'startDate', 'desc']);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should reload task list when sorting on a column changes', () => {
|
||||||
|
const getServiceTaskByRequestSpy = spyOn(taskListCloudService, 'getServiceTaskByRequest').and.returnValue(of(fakeServiceTask));
|
||||||
|
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(['entry.fakeName', 'asc']);
|
||||||
|
expect(component.isListEmpty()).toBeFalsy();
|
||||||
|
expect(getServiceTaskByRequestSpy).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should reset pagination when resetPaginationValues is called', async (done) => {
|
||||||
|
spyOn(taskListCloudService, 'getServiceTaskByRequest').and.returnValue(of(fakeServiceTask));
|
||||||
|
|
||||||
|
const appName = new SimpleChange(null, 'FAKE-APP-NAME', true);
|
||||||
|
component.ngOnChanges({ appName });
|
||||||
|
fixture.detectChanges();
|
||||||
|
|
||||||
|
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);
|
||||||
|
await fixture.whenStable();
|
||||||
|
component.resetPagination();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should set pagination and reload when updatePagination is called', (done) => {
|
||||||
|
spyOn(taskListCloudService, 'getServiceTaskByRequest').and.returnValue(of(fakeServiceTask));
|
||||||
|
spyOn(component, 'reload').and.stub();
|
||||||
|
const appName = new SimpleChange(null, 'FAKE-APP-NAME', true);
|
||||||
|
component.ngOnChanges({ appName });
|
||||||
|
fixture.detectChanges();
|
||||||
|
|
||||||
|
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);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('Injecting custom colums for tasklist - CustomTaskListComponent', () => {
|
||||||
|
let fixtureCustom: ComponentFixture<CustomTaskListComponent>;
|
||||||
|
let componentCustom: CustomTaskListComponent;
|
||||||
|
let customCopyComponent: CustomCopyContentTaskListComponent;
|
||||||
|
let element: any;
|
||||||
|
let copyFixture: ComponentFixture<CustomCopyContentTaskListComponent>;
|
||||||
|
|
||||||
|
setupTestBed({
|
||||||
|
imports: [
|
||||||
|
TranslateModule.forRoot(),
|
||||||
|
ProcessServiceCloudTestingModule
|
||||||
|
],
|
||||||
|
declarations: [
|
||||||
|
CustomTaskListComponent,
|
||||||
|
CustomCopyContentTaskListComponent
|
||||||
|
]
|
||||||
|
});
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
spyOn(taskListCloudService, 'getServiceTaskByRequest').and.returnValue(of(fakeServiceTask));
|
||||||
|
fixtureCustom = TestBed.createComponent(CustomTaskListComponent);
|
||||||
|
copyFixture = TestBed.createComponent(CustomCopyContentTaskListComponent);
|
||||||
|
fixtureCustom.detectChanges();
|
||||||
|
componentCustom = fixtureCustom.componentInstance;
|
||||||
|
customCopyComponent = copyFixture.componentInstance;
|
||||||
|
element = copyFixture.debugElement.nativeElement;
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
fixtureCustom.destroy();
|
||||||
|
copyFixture.destroy();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should fetch custom schemaColumn from html', () => {
|
||||||
|
fixture.detectChanges();
|
||||||
|
expect(componentCustom.taskList.columnList).toBeDefined();
|
||||||
|
expect(componentCustom.taskList.columns[0]['title']).toEqual('ADF_CLOUD_TASK_LIST.PROPERTIES.NAME');
|
||||||
|
expect(componentCustom.taskList.columns[1]['title']).toEqual('ADF_CLOUD_TASK_LIST.PROPERTIES.CREATED');
|
||||||
|
expect(componentCustom.taskList.columns.length).toEqual(2);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('it should show copy tooltip when key is present in data-colunn', async(() => {
|
||||||
|
copyFixture.detectChanges();
|
||||||
|
const appName = new SimpleChange(null, 'FAKE-APP-NAME', true);
|
||||||
|
copyFixture.whenStable().then(() => {
|
||||||
|
copyFixture.detectChanges();
|
||||||
|
const spanHTMLElement: HTMLInputElement = <HTMLInputElement> element.querySelector('span[title="04fdf69f-4ddd-48ab-9563-da776c9b163c"]');
|
||||||
|
spanHTMLElement.dispatchEvent(new Event('mouseenter'));
|
||||||
|
copyFixture.detectChanges();
|
||||||
|
expect(copyFixture.debugElement.nativeElement.querySelector('.adf-copy-tooltip')).not.toBeNull();
|
||||||
|
});
|
||||||
|
customCopyComponent.taskList.appName = appName.currentValue;
|
||||||
|
customCopyComponent.taskList.ngOnChanges({ 'appName': appName });
|
||||||
|
copyFixture.detectChanges();
|
||||||
|
}));
|
||||||
|
|
||||||
|
it('it should not show copy tooltip when key is not present in data-column', (done) => {
|
||||||
|
const appName = new SimpleChange(null, 'FAKE-APP-NAME', true);
|
||||||
|
customCopyComponent.taskList.success.subscribe(() => {
|
||||||
|
copyFixture.whenStable().then(() => {
|
||||||
|
copyFixture.detectChanges();
|
||||||
|
const spanHTMLElement: HTMLInputElement = <HTMLInputElement> element.querySelector('span[title="serviceTaskName"]');
|
||||||
|
spanHTMLElement.dispatchEvent(new Event('mouseenter'));
|
||||||
|
copyFixture.detectChanges();
|
||||||
|
expect(copyFixture.debugElement.nativeElement.querySelector('.adf-copy-tooltip')).toBeNull();
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
customCopyComponent.taskList.appName = appName.currentValue;
|
||||||
|
customCopyComponent.taskList.ngOnChanges({ 'appName': appName });
|
||||||
|
copyFixture.detectChanges();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('Copy cell content directive from app.config specifications', () => {
|
||||||
|
|
||||||
|
let element: any;
|
||||||
|
let taskSpy: jasmine.Spy;
|
||||||
|
|
||||||
|
setupTestBed({
|
||||||
|
imports: [
|
||||||
|
TranslateModule.forRoot(),
|
||||||
|
ProcessServiceCloudTestingModule
|
||||||
|
]
|
||||||
|
});
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
appConfig = TestBed.inject(AppConfigService);
|
||||||
|
taskListCloudService = TestBed.inject(TaskListCloudService);
|
||||||
|
appConfig.config = Object.assign(appConfig.config, {
|
||||||
|
'adf-cloud-service-task-list': {
|
||||||
|
'presets': {
|
||||||
|
'fakeCustomSchema': [
|
||||||
|
{
|
||||||
|
'key': 'entry.id',
|
||||||
|
'type': 'text',
|
||||||
|
'title': 'ADF_CLOUD_TASK_LIST.PROPERTIES.FAKE',
|
||||||
|
'sortable': true,
|
||||||
|
'copyContent': true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'key': 'entry.activityName',
|
||||||
|
'type': 'text',
|
||||||
|
'title': 'ADF_CLOUD_TASK_LIST.PROPERTIES.TASK_FAKE',
|
||||||
|
'sortable': true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
fixture = TestBed.createComponent(ServiceTaskListCloudComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
element = fixture.debugElement.nativeElement;
|
||||||
|
taskSpy = spyOn(taskListCloudService, 'getServiceTaskByRequest').and.returnValue(of(fakeServiceTask));
|
||||||
|
|
||||||
|
});
|
||||||
|
afterEach(() => {
|
||||||
|
fixture.destroy();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('shoud show tooltip if config copyContent flag is true', async(() => {
|
||||||
|
taskSpy.and.returnValue(of(fakeServiceTask));
|
||||||
|
const appName = new SimpleChange(null, 'FAKE-APP-NAME', true);
|
||||||
|
|
||||||
|
component.success.subscribe(() => {
|
||||||
|
fixture.whenStable().then(() => {
|
||||||
|
fixture.detectChanges();
|
||||||
|
const spanHTMLElement: HTMLInputElement = <HTMLInputElement> element.querySelector('span[title="04fdf69f-4ddd-48ab-9563-da776c9b163c"]');
|
||||||
|
spanHTMLElement.dispatchEvent(new Event('mouseenter'));
|
||||||
|
fixture.detectChanges();
|
||||||
|
expect(fixture.debugElement.nativeElement.querySelector('.adf-copy-tooltip')).not.toBeNull();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
component.presetColumn = 'fakeCustomSchema';
|
||||||
|
component.appName = appName.currentValue;
|
||||||
|
component.ngOnChanges({ 'appName': appName });
|
||||||
|
component.ngAfterContentInit();
|
||||||
|
}));
|
||||||
|
|
||||||
|
it('shoud not show tooltip if config copyContent flag is true', async(() => {
|
||||||
|
taskSpy.and.returnValue(of(fakeServiceTask));
|
||||||
|
const appName = new SimpleChange(null, 'FAKE-APP-NAME', true);
|
||||||
|
component.success.subscribe(() => {
|
||||||
|
fixture.whenStable().then(() => {
|
||||||
|
fixture.detectChanges();
|
||||||
|
const spanHTMLElement: HTMLInputElement = <HTMLInputElement> element.querySelector('span[title="serviceTaskName"]');
|
||||||
|
spanHTMLElement.dispatchEvent(new Event('mouseenter'));
|
||||||
|
fixture.detectChanges();
|
||||||
|
expect(fixture.debugElement.nativeElement.querySelector('.adf-copy-tooltip')).toBeNull();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
component.presetColumn = 'fakeCustomSchema';
|
||||||
|
component.appName = appName.currentValue;
|
||||||
|
component.ngOnChanges({ 'appName': appName });
|
||||||
|
component.ngAfterContentInit();
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
});
|
@ -0,0 +1,69 @@
|
|||||||
|
/*!
|
||||||
|
* @license
|
||||||
|
* Copyright 2019 Alfresco Software, Ltd.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { Component, ViewEncapsulation, Input } from '@angular/core';
|
||||||
|
import {
|
||||||
|
AppConfigService, UserPreferencesService
|
||||||
|
} from '@alfresco/adf-core';
|
||||||
|
import { ServiceTaskQueryCloudRequestModel } from '../models/filter-cloud-model';
|
||||||
|
import { TaskListCloudService } from '../services/task-list-cloud.service';
|
||||||
|
import { BaseTaskListCloudComponent } from './base-task-list-cloud.component';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'adf-cloud-service-task-list',
|
||||||
|
templateUrl: './base-task-list-cloud.component.html',
|
||||||
|
styleUrls: ['./base-task-list-cloud.component.scss'],
|
||||||
|
encapsulation: ViewEncapsulation.None
|
||||||
|
})
|
||||||
|
export class ServiceTaskListCloudComponent extends BaseTaskListCloudComponent {
|
||||||
|
|
||||||
|
static PRESET_KEY = 'adf-cloud-service-task-list.presets';
|
||||||
|
|
||||||
|
@Input()
|
||||||
|
queryParams: { [key: string]: string } = {};
|
||||||
|
|
||||||
|
constructor(private taskListCloudService: TaskListCloudService,
|
||||||
|
appConfigService: AppConfigService,
|
||||||
|
userPreferences: UserPreferencesService) {
|
||||||
|
super(appConfigService, userPreferences, ServiceTaskListCloudComponent.PRESET_KEY);
|
||||||
|
}
|
||||||
|
|
||||||
|
load(requestNode: ServiceTaskQueryCloudRequestModel) {
|
||||||
|
this.isLoading = true;
|
||||||
|
this.taskListCloudService.getServiceTaskByRequest(requestNode).subscribe(
|
||||||
|
(tasks) => {
|
||||||
|
this.rows = tasks.list.entries;
|
||||||
|
this.success.emit(tasks);
|
||||||
|
this.isLoading = false;
|
||||||
|
this.pagination.next(tasks.list.pagination);
|
||||||
|
}, (error) => {
|
||||||
|
this.error.emit(error);
|
||||||
|
this.isLoading = false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
createRequestNode(): ServiceTaskQueryCloudRequestModel {
|
||||||
|
const requestNode = {
|
||||||
|
...this.queryParams,
|
||||||
|
appName: this.appName,
|
||||||
|
maxItems: this.size,
|
||||||
|
skipCount: this.skipCount,
|
||||||
|
sorting: this.sorting
|
||||||
|
};
|
||||||
|
return <ServiceTaskQueryCloudRequestModel> requestNode;
|
||||||
|
}
|
||||||
|
}
|
@ -248,7 +248,7 @@ describe('TaskListCloudComponent', () => {
|
|||||||
const rowEvent = new DataRowEvent(row, null);
|
const rowEvent = new DataRowEvent(row, null);
|
||||||
component.rowClick.subscribe((taskId) => {
|
component.rowClick.subscribe((taskId) => {
|
||||||
expect(taskId).toEqual('999');
|
expect(taskId).toEqual('999');
|
||||||
expect(component.getCurrentId()).toEqual('999');
|
expect(component.currentInstanceId).toEqual('999');
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
component.onRowClick(rowEvent);
|
component.onRowClick(rowEvent);
|
||||||
@ -262,8 +262,8 @@ describe('TaskListCloudComponent', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should NOT reload the task list when no parameters changed', () => {
|
it('should NOT reload the task list when no parameters changed', () => {
|
||||||
|
spyOn(taskListCloudService, 'getTaskByRequest');
|
||||||
component.rows = null;
|
component.rows = null;
|
||||||
component.ngOnChanges({});
|
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
expect(component.isListEmpty()).toBeTruthy();
|
expect(component.isListEmpty()).toBeTruthy();
|
||||||
});
|
});
|
||||||
|
@ -15,36 +15,21 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { Component, ViewEncapsulation, OnChanges, Input, SimpleChanges, Output, EventEmitter, ContentChild, AfterContentInit, OnDestroy, OnInit } from '@angular/core';
|
import { Component, ViewEncapsulation, Input } from '@angular/core';
|
||||||
import { AppConfigService, UserPreferencesService,
|
import { AppConfigService, UserPreferencesService } from '@alfresco/adf-core';
|
||||||
DataTableSchema, UserPreferenceValues,
|
|
||||||
PaginatedComponent, PaginationModel,
|
|
||||||
DataRowEvent, CustomEmptyContentTemplateDirective, DataCellEvent, DataRowActionEvent } from '@alfresco/adf-core';
|
|
||||||
import { taskPresetsCloudDefaultModel } from '../models/task-preset-cloud.model';
|
|
||||||
import { TaskQueryCloudRequestModel } from '../models/filter-cloud-model';
|
import { TaskQueryCloudRequestModel } from '../models/filter-cloud-model';
|
||||||
import { BehaviorSubject, Subject } from 'rxjs';
|
|
||||||
import { TaskListCloudService } from '../services/task-list-cloud.service';
|
import { TaskListCloudService } from '../services/task-list-cloud.service';
|
||||||
import { TaskListCloudSortingModel } from '../models/task-list-sorting.model';
|
import { BaseTaskListCloudComponent } from './base-task-list-cloud.component';
|
||||||
import { takeUntil } from 'rxjs/operators';
|
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'adf-cloud-task-list',
|
selector: 'adf-cloud-task-list',
|
||||||
templateUrl: './task-list-cloud.component.html',
|
templateUrl: './base-task-list-cloud.component.html',
|
||||||
styleUrls: ['./task-list-cloud.component.scss'],
|
styleUrls: ['./base-task-list-cloud.component.scss'],
|
||||||
encapsulation: ViewEncapsulation.None
|
encapsulation: ViewEncapsulation.None
|
||||||
})
|
})
|
||||||
|
export class TaskListCloudComponent extends BaseTaskListCloudComponent {
|
||||||
export class TaskListCloudComponent extends DataTableSchema implements OnChanges, AfterContentInit, PaginatedComponent, OnDestroy, OnInit {
|
|
||||||
|
|
||||||
static PRESET_KEY = 'adf-cloud-task-list.presets';
|
static PRESET_KEY = 'adf-cloud-task-list.presets';
|
||||||
static ENTRY_PREFIX = 'entry.';
|
|
||||||
|
|
||||||
@ContentChild(CustomEmptyContentTemplateDirective)
|
|
||||||
emptyCustomContent: CustomEmptyContentTemplateDirective;
|
|
||||||
|
|
||||||
/** The name of the application. */
|
|
||||||
@Input()
|
|
||||||
appName: string = '';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The assignee of the process. Possible values are: "assignee" (the current user is the assignee),
|
* The assignee of the process. Possible values are: "assignee" (the current user is the assignee),
|
||||||
@ -122,150 +107,15 @@ export class TaskListCloudComponent extends DataTableSchema implements OnChanges
|
|||||||
@Input()
|
@Input()
|
||||||
standalone: boolean = false;
|
standalone: boolean = false;
|
||||||
|
|
||||||
/**
|
|
||||||
* Row selection mode. Can be none, `single` or `multiple`. For `multiple` mode,
|
|
||||||
* you can use the Cmd (macOS) or Ctrl (Win) modifier key to toggle selection for
|
|
||||||
* multiple rows.
|
|
||||||
*/
|
|
||||||
@Input()
|
|
||||||
selectionMode: string = 'single'; // none|single|multiple
|
|
||||||
|
|
||||||
/** Toggles multiple row selection, rendering a checkbox at the beginning of each row. */
|
|
||||||
@Input()
|
|
||||||
multiselect: boolean = false;
|
|
||||||
|
|
||||||
/** Toggles the sticky header mode. */
|
|
||||||
@Input()
|
|
||||||
stickyHeader: boolean = false;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Specifies how the table should be sorted. The parameters are for BE sorting.
|
|
||||||
*/
|
|
||||||
@Input()
|
|
||||||
sorting: TaskListCloudSortingModel[];
|
|
||||||
|
|
||||||
/** Toggles the data actions column. */
|
|
||||||
@Input()
|
|
||||||
showActions: boolean = false;
|
|
||||||
|
|
||||||
/** Position of the actions dropdown menu. Can be "left" or "right". */
|
|
||||||
@Input()
|
|
||||||
actionsPosition: string = 'right'; // left|right
|
|
||||||
|
|
||||||
/** Toggles custom context menu for the component. */
|
|
||||||
@Input()
|
|
||||||
showContextMenu: boolean = false;
|
|
||||||
|
|
||||||
/** Emitted before the context menu is displayed for a row. */
|
|
||||||
@Output()
|
|
||||||
showRowContextMenu = new EventEmitter<DataCellEvent>();
|
|
||||||
|
|
||||||
/** Emitted before the actions menu is displayed for a row. */
|
|
||||||
@Output()
|
|
||||||
showRowActionsMenu = new EventEmitter<DataCellEvent>();
|
|
||||||
|
|
||||||
/** Emitted when the user executes a row action. */
|
|
||||||
@Output()
|
|
||||||
executeRowAction = new EventEmitter<DataRowActionEvent>();
|
|
||||||
|
|
||||||
/** Emitted when a task in the list is clicked */
|
|
||||||
@Output()
|
|
||||||
rowClick: EventEmitter<string> = new EventEmitter<string>();
|
|
||||||
|
|
||||||
/** Emitted when rows are selected/unselected */
|
|
||||||
@Output()
|
|
||||||
rowsSelected: EventEmitter<any[]> = new EventEmitter<any[]>();
|
|
||||||
|
|
||||||
/** Emitted when the task list is loaded */
|
|
||||||
@Output()
|
|
||||||
success: EventEmitter<any> = new EventEmitter<any>();
|
|
||||||
|
|
||||||
/** Emitted when an error occurs. */
|
|
||||||
@Output()
|
|
||||||
error: EventEmitter<any> = new EventEmitter<any>();
|
|
||||||
|
|
||||||
pagination: BehaviorSubject<PaginationModel>;
|
|
||||||
|
|
||||||
requestNode: TaskQueryCloudRequestModel;
|
|
||||||
rows: any[] = [];
|
|
||||||
size: number;
|
|
||||||
skipCount: number = 0;
|
|
||||||
currentInstanceId: any;
|
|
||||||
isLoading = true;
|
|
||||||
selectedInstances: any[];
|
|
||||||
formattedSorting: any[];
|
|
||||||
private defaultSorting = { key: 'startDate', direction: 'desc' };
|
|
||||||
|
|
||||||
private onDestroy$ = new Subject<boolean>();
|
|
||||||
|
|
||||||
constructor(private taskListCloudService: TaskListCloudService,
|
constructor(private taskListCloudService: TaskListCloudService,
|
||||||
appConfigService: AppConfigService,
|
appConfigService: AppConfigService,
|
||||||
private userPreferences: UserPreferencesService) {
|
userPreferences: UserPreferencesService) {
|
||||||
super(appConfigService, TaskListCloudComponent.PRESET_KEY, taskPresetsCloudDefaultModel);
|
super(appConfigService, userPreferences, TaskListCloudComponent.PRESET_KEY);
|
||||||
this.size = userPreferences.paginationSize;
|
|
||||||
|
|
||||||
this.pagination = new BehaviorSubject<PaginationModel>(<PaginationModel> {
|
|
||||||
maxItems: this.size,
|
|
||||||
skipCount: 0,
|
|
||||||
totalItems: 0
|
|
||||||
});
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnInit() {
|
load(requestNode: TaskQueryCloudRequestModel) {
|
||||||
this.userPreferences
|
|
||||||
.select(UserPreferenceValues.PaginationSize)
|
|
||||||
.pipe(takeUntil(this.onDestroy$))
|
|
||||||
.subscribe(pageSize => this.size = pageSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
ngOnChanges(changes: SimpleChanges) {
|
|
||||||
if (this.isPropertyChanged(changes, 'sorting')) {
|
|
||||||
this.formatSorting(changes['sorting'].currentValue);
|
|
||||||
}
|
|
||||||
if (this.isAnyPropertyChanged(changes)) {
|
|
||||||
this.reload();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ngOnDestroy() {
|
|
||||||
this.onDestroy$.next(true);
|
|
||||||
this.onDestroy$.complete();
|
|
||||||
}
|
|
||||||
|
|
||||||
ngAfterContentInit() {
|
|
||||||
this.createDatatableSchema();
|
|
||||||
}
|
|
||||||
|
|
||||||
getCurrentId(): string {
|
|
||||||
return this.currentInstanceId;
|
|
||||||
}
|
|
||||||
|
|
||||||
private isAnyPropertyChanged(changes: SimpleChanges): boolean {
|
|
||||||
for (const property in changes) {
|
|
||||||
if (this.isPropertyChanged(changes, property)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private isPropertyChanged(changes: SimpleChanges, property: string): boolean {
|
|
||||||
return changes.hasOwnProperty(property);
|
|
||||||
}
|
|
||||||
|
|
||||||
reload() {
|
|
||||||
this.requestNode = this.createRequestNode();
|
|
||||||
if (this.requestNode.appName || this.requestNode.appName === '') {
|
|
||||||
this.load(this.requestNode);
|
|
||||||
} else {
|
|
||||||
this.rows = [];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private load(requestNode: TaskQueryCloudRequestModel) {
|
|
||||||
this.isLoading = true;
|
this.isLoading = true;
|
||||||
this.taskListCloudService.getTaskByRequest(requestNode).subscribe(
|
this.taskListCloudService.getTaskByRequest(<TaskQueryCloudRequestModel> requestNode).subscribe(
|
||||||
(tasks) => {
|
(tasks) => {
|
||||||
this.rows = tasks.list.entries;
|
this.rows = tasks.list.entries;
|
||||||
this.success.emit(tasks);
|
this.success.emit(tasks);
|
||||||
@ -277,77 +127,7 @@ export class TaskListCloudComponent extends DataTableSchema implements OnChanges
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
isListEmpty(): boolean {
|
createRequestNode(): TaskQueryCloudRequestModel {
|
||||||
return !this.rows || this.rows.length === 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Resets the pagination values
|
|
||||||
*/
|
|
||||||
resetPagination() {
|
|
||||||
this.skipCount = 0;
|
|
||||||
this.size = this.userPreferences.paginationSize;
|
|
||||||
this.pagination.next({
|
|
||||||
skipCount: 0,
|
|
||||||
maxItems: this.size
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Resets the pagination values and
|
|
||||||
* Reloads the task list
|
|
||||||
* @param pagination Pagination values to be set
|
|
||||||
*/
|
|
||||||
updatePagination(pagination: PaginationModel) {
|
|
||||||
this.size = pagination.maxItems;
|
|
||||||
this.skipCount = pagination.skipCount;
|
|
||||||
this.pagination.next(pagination);
|
|
||||||
this.reload();
|
|
||||||
}
|
|
||||||
|
|
||||||
onSortingChanged(event: CustomEvent) {
|
|
||||||
this.setSorting(event.detail);
|
|
||||||
this.formatSorting(this.sorting);
|
|
||||||
this.reload();
|
|
||||||
}
|
|
||||||
|
|
||||||
onRowClick(item: DataRowEvent) {
|
|
||||||
this.currentInstanceId = item.value.getValue('entry.id');
|
|
||||||
this.rowClick.emit(this.currentInstanceId);
|
|
||||||
}
|
|
||||||
|
|
||||||
onRowSelect(event: CustomEvent) {
|
|
||||||
this.selectedInstances = [...event.detail.selection];
|
|
||||||
this.rowsSelected.emit(this.selectedInstances);
|
|
||||||
}
|
|
||||||
|
|
||||||
onRowUnselect(event: CustomEvent) {
|
|
||||||
this.selectedInstances = [...event.detail.selection];
|
|
||||||
this.rowsSelected.emit(this.selectedInstances);
|
|
||||||
}
|
|
||||||
|
|
||||||
onRowKeyUp(event: CustomEvent) {
|
|
||||||
if (event.detail.keyboardEvent.key === 'Enter') {
|
|
||||||
event.preventDefault();
|
|
||||||
this.currentInstanceId = event.detail.row.getValue('entry.id');
|
|
||||||
this.rowClick.emit(this.currentInstanceId);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
onShowRowActionsMenu(event: DataCellEvent) {
|
|
||||||
this.showRowActionsMenu.emit(event);
|
|
||||||
}
|
|
||||||
|
|
||||||
onShowRowContextMenu(event: DataCellEvent) {
|
|
||||||
this.showRowContextMenu.emit(event);
|
|
||||||
}
|
|
||||||
|
|
||||||
onExecuteRowAction(row: DataRowActionEvent) {
|
|
||||||
this.executeRowAction.emit(row);
|
|
||||||
}
|
|
||||||
|
|
||||||
private createRequestNode() {
|
|
||||||
|
|
||||||
const requestNode = {
|
const requestNode = {
|
||||||
appName: this.appName,
|
appName: this.appName,
|
||||||
assignee: this.assignee,
|
assignee: this.assignee,
|
||||||
@ -374,23 +154,4 @@ export class TaskListCloudComponent extends DataTableSchema implements OnChanges
|
|||||||
};
|
};
|
||||||
return new TaskQueryCloudRequestModel(requestNode);
|
return new TaskQueryCloudRequestModel(requestNode);
|
||||||
}
|
}
|
||||||
|
|
||||||
setSorting(sortDetail) {
|
|
||||||
const sorting = sortDetail ? {
|
|
||||||
orderBy: sortDetail.key.replace(TaskListCloudComponent.ENTRY_PREFIX, ''),
|
|
||||||
direction: sortDetail.direction.toUpperCase()
|
|
||||||
} : { ... this.defaultSorting };
|
|
||||||
this.sorting = [new TaskListCloudSortingModel(sorting)];
|
|
||||||
}
|
|
||||||
|
|
||||||
formatSorting(sorting: TaskListCloudSortingModel[]) {
|
|
||||||
this.formattedSorting = this.isValidSorting(sorting) ? [
|
|
||||||
TaskListCloudComponent.ENTRY_PREFIX + sorting[0].orderBy,
|
|
||||||
sorting[0].direction.toLocaleLowerCase()
|
|
||||||
] : null;
|
|
||||||
}
|
|
||||||
|
|
||||||
isValidSorting(sorting: TaskListCloudSortingModel[]) {
|
|
||||||
return sorting.length && sorting[0].orderBy && sorting[0].direction;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -79,7 +79,7 @@ export const fakeTaskCloudList = {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export let fakeGlobalTask = {
|
export const fakeGlobalTask = {
|
||||||
list: {
|
list: {
|
||||||
entries: [
|
entries: [
|
||||||
{
|
{
|
||||||
@ -117,7 +117,41 @@ export let fakeGlobalTask = {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export let fakeCustomSchema =
|
export const fakeServiceTask = {
|
||||||
|
list: {
|
||||||
|
entries: [
|
||||||
|
{
|
||||||
|
entry: {
|
||||||
|
activityType: 'serviceTask',
|
||||||
|
activityName: 'serviceTaskName',
|
||||||
|
appName: 'simpleapp',
|
||||||
|
completedDate: '2020-09-22T16:03:37.482+0000',
|
||||||
|
elementId: 'ServiceTask_0lszm0x',
|
||||||
|
executionId: '2023b099-fced-11ea-b116-62141048995a',
|
||||||
|
id: '04fdf69f-4ddd-48ab-9563-da776c9b163c',
|
||||||
|
processDefinitionId: 'Process_24rkVVSR:1:0db78dcd-fc14-11ea-bce0-62141048995a',
|
||||||
|
processDefinitionKey: 'Process_24rkVVSR',
|
||||||
|
processDefinitionVersion: 1,
|
||||||
|
processInstanceId: '2023b097-fced-11ea-b116-62141048995a',
|
||||||
|
serviceFullName: 'simpleapp-rb',
|
||||||
|
serviceName: 'simpleapp-rb',
|
||||||
|
serviceVersion: '',
|
||||||
|
startedDate: '2020-09-22T16:03:37.444+0000',
|
||||||
|
status: 'COMPLETED'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
pagination: {
|
||||||
|
skipCount: 0,
|
||||||
|
maxItems: 100,
|
||||||
|
count: 1,
|
||||||
|
hasMoreItems: false,
|
||||||
|
totalItems: 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export const fakeCustomSchema =
|
||||||
[
|
[
|
||||||
new ObjectDataColumn({
|
new ObjectDataColumn({
|
||||||
'key': 'fakeName',
|
'key': 'fakeName',
|
||||||
|
@ -74,3 +74,26 @@ export class TaskQueryCloudRequestModel {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface ServiceTaskQueryCloudRequestModel {
|
||||||
|
appName: string;
|
||||||
|
appVersion?: string;
|
||||||
|
id?: string;
|
||||||
|
status?: string;
|
||||||
|
maxItems: number;
|
||||||
|
skipCount: number;
|
||||||
|
sorting?: TaskListCloudSortingModel[];
|
||||||
|
activityName?: string;
|
||||||
|
activityType?: string;
|
||||||
|
completedDate?: Date;
|
||||||
|
elementId?: string;
|
||||||
|
executionId?: string;
|
||||||
|
processDefinitionId?: string;
|
||||||
|
processDefinitionKey?: string;
|
||||||
|
processDefinitionVersion?: number;
|
||||||
|
processInstanceId?: string;
|
||||||
|
serviceFullName?: string;
|
||||||
|
serviceName?: string;
|
||||||
|
serviceVersion?: string;
|
||||||
|
startedDate?: Date;
|
||||||
|
}
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
export let taskPresetsCloudDefaultModel = {
|
export const taskPresetsCloudDefaultModel = {
|
||||||
'default': [
|
'default': [
|
||||||
{
|
{
|
||||||
'key': 'entry.name',
|
'key': 'entry.name',
|
||||||
@ -39,3 +39,34 @@ export let taskPresetsCloudDefaultModel = {
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const serviceTaskPresetsCloudDefaultModel = {
|
||||||
|
'default': [
|
||||||
|
{
|
||||||
|
'key': 'entry.activityName',
|
||||||
|
'type': 'text',
|
||||||
|
'title': 'ADF_CLOUD_SERVICE_TASK_LIST.PROPERTIES.ACTIVITY_NAME',
|
||||||
|
'sortable': true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'key': 'entry.status',
|
||||||
|
'type': 'text',
|
||||||
|
'title': 'ADF_CLOUD_SERVICE_TASK_LIST.PROPERTIES.STATUS',
|
||||||
|
'sortable': true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'key': 'entry.startedDate',
|
||||||
|
'type': 'text',
|
||||||
|
'title': 'ADF_CLOUD_SERVICE_TASK_LIST.PROPERTIES.STARTED_DATE',
|
||||||
|
'cssClass': 'hidden',
|
||||||
|
'sortable': true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'key': 'entry.completedDate',
|
||||||
|
'type': 'text',
|
||||||
|
'title': 'ADF_CLOUD_SERVICE_TASK_LIST.PROPERTIES.COMPLETED_DATE',
|
||||||
|
'cssClass': 'hidden',
|
||||||
|
'sortable': true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
export * from './components/task-list-cloud.component';
|
export * from './components/task-list-cloud.component';
|
||||||
|
export * from './components/service-task-list-cloud.component';
|
||||||
|
|
||||||
export * from './models/filter-cloud-model';
|
export * from './models/filter-cloud-model';
|
||||||
export * from './models/task-list-sorting.model';
|
export * from './models/task-list-sorting.model';
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
|
|
||||||
import { Injectable } from '@angular/core';
|
import { Injectable } from '@angular/core';
|
||||||
import { AlfrescoApiService, AppConfigService, LogService } from '@alfresco/adf-core';
|
import { AlfrescoApiService, AppConfigService, LogService } from '@alfresco/adf-core';
|
||||||
import { TaskQueryCloudRequestModel } from '../models/filter-cloud-model';
|
import { TaskQueryCloudRequestModel, ServiceTaskQueryCloudRequestModel } from '../models/filter-cloud-model';
|
||||||
import { Observable, throwError } from 'rxjs';
|
import { 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';
|
||||||
@ -51,6 +51,26 @@ export class TaskListCloudService extends BaseCloudService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finds a task using an object with optional query properties.
|
||||||
|
* @param requestNode Query object
|
||||||
|
* @returns Task information
|
||||||
|
*/
|
||||||
|
getServiceTaskByRequest(requestNode: ServiceTaskQueryCloudRequestModel): Observable<any> {
|
||||||
|
if (requestNode.appName || requestNode.appName === '') {
|
||||||
|
const queryUrl = `${this.getBasePath(requestNode.appName)}/query/admin/v1/service-tasks`;
|
||||||
|
const queryParams = this.buildQueryParams(requestNode);
|
||||||
|
const sortingParams = this.buildSortingParam(requestNode.sorting);
|
||||||
|
if (sortingParams) {
|
||||||
|
queryParams['sort'] = sortingParams;
|
||||||
|
}
|
||||||
|
return this.get(queryUrl, queryParams);
|
||||||
|
} else {
|
||||||
|
this.logService.error('Appname is mandatory for querying task');
|
||||||
|
return throwError('Appname not configured');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private buildQueryParams(requestNode: TaskQueryCloudRequestModel): Object {
|
private buildQueryParams(requestNode: TaskQueryCloudRequestModel): Object {
|
||||||
const queryParam: Object = {};
|
const queryParam: Object = {};
|
||||||
for (const property in requestNode) {
|
for (const property in requestNode) {
|
||||||
|
@ -19,6 +19,7 @@ import { NgModule } from '@angular/core';
|
|||||||
import { CommonModule } from '@angular/common';
|
import { CommonModule } from '@angular/common';
|
||||||
import { MaterialModule } from '../../material.module';
|
import { MaterialModule } from '../../material.module';
|
||||||
import { TaskListCloudComponent } from './components/task-list-cloud.component';
|
import { TaskListCloudComponent } from './components/task-list-cloud.component';
|
||||||
|
import { ServiceTaskListCloudComponent } from './components/service-task-list-cloud.component';
|
||||||
import { CoreModule } from '@alfresco/adf-core';
|
import { CoreModule } from '@alfresco/adf-core';
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
@ -27,7 +28,13 @@ import { CoreModule } from '@alfresco/adf-core';
|
|||||||
MaterialModule,
|
MaterialModule,
|
||||||
CoreModule
|
CoreModule
|
||||||
],
|
],
|
||||||
declarations: [TaskListCloudComponent],
|
declarations: [
|
||||||
exports: [TaskListCloudComponent]
|
TaskListCloudComponent,
|
||||||
|
ServiceTaskListCloudComponent
|
||||||
|
],
|
||||||
|
exports: [
|
||||||
|
TaskListCloudComponent,
|
||||||
|
ServiceTaskListCloudComponent
|
||||||
|
]
|
||||||
})
|
})
|
||||||
export class TaskListCloudModule { }
|
export class TaskListCloudModule { }
|
||||||
|
Loading…
x
Reference in New Issue
Block a user