mirror of
https://github.com/Alfresco/alfresco-ng2-components.git
synced 2025-06-30 18:15:11 +00:00
[ADF-4979] Add onChanges detection for Task Header Cloud component (#5208)
* [ADF-4979] Add onChanges detection for Task Header Cloud component * [ADF-4979] Revert licenses.txt changes * [ADF-4979] Documentation added for the taskError Event
This commit is contained in:
parent
7d36400dbd
commit
3c1097fb84
@ -94,6 +94,12 @@
|
|||||||
"TREE_VIEW": "Tree View",
|
"TREE_VIEW": "Tree View",
|
||||||
"ICONS": "Icons",
|
"ICONS": "Icons",
|
||||||
"PEOPLE_GROUPS_CLOUD": "People/Group Cloud",
|
"PEOPLE_GROUPS_CLOUD": "People/Group Cloud",
|
||||||
|
"TASK_HEADER_CLOUD": {
|
||||||
|
"COMPONENT_NAME": "Task Header Cloud",
|
||||||
|
"APP_NAME_INPUT": "App name",
|
||||||
|
"TASK_ID_INPUT": "Task id",
|
||||||
|
"FIND_TASK_BUTTON": "Find Task"
|
||||||
|
},
|
||||||
"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",
|
||||||
|
@ -71,6 +71,7 @@ import { AppsCloudDemoComponent } from './components/cloud/apps-cloud-demo.compo
|
|||||||
import { TasksCloudDemoComponent } from './components/cloud/tasks-cloud-demo.component';
|
import { TasksCloudDemoComponent } from './components/cloud/tasks-cloud-demo.component';
|
||||||
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 { 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';
|
||||||
@ -182,6 +183,7 @@ registerLocaleData(localeSv);
|
|||||||
TasksCloudDemoComponent,
|
TasksCloudDemoComponent,
|
||||||
ProcessesCloudDemoComponent,
|
ProcessesCloudDemoComponent,
|
||||||
TaskDetailsCloudDemoComponent,
|
TaskDetailsCloudDemoComponent,
|
||||||
|
TaskHeaderCloudDemoComponent,
|
||||||
CloudViewerComponent,
|
CloudViewerComponent,
|
||||||
ProcessDetailsCloudDemoComponent,
|
ProcessDetailsCloudDemoComponent,
|
||||||
StartTaskCloudDemoComponent,
|
StartTaskCloudDemoComponent,
|
||||||
|
@ -58,6 +58,7 @@ import { TemplateDemoComponent } from './components/template-list/template-demo.
|
|||||||
import { FormCloudDemoComponent } from './components/app-layout/cloud/form-demo/cloud-form-demo.component';
|
import { FormCloudDemoComponent } from './components/app-layout/cloud/form-demo/cloud-form-demo.component';
|
||||||
import { ConfirmDialogExampleComponent } from './components/confirm-dialog/confirm-dialog-example.component';
|
import { ConfirmDialogExampleComponent } from './components/confirm-dialog/confirm-dialog-example.component';
|
||||||
import { DemoErrorComponent } from './components/error/demo-error.component';
|
import { DemoErrorComponent } from './components/error/demo-error.component';
|
||||||
|
import { TaskHeaderCloudDemoComponent } from './components/cloud/task-header-cloud-demo.component';
|
||||||
export const appRoutes: Routes = [
|
export const appRoutes: Routes = [
|
||||||
{ path: 'login', loadChildren: 'app/components/login/login.module#AppLoginModule' },
|
{ path: 'login', loadChildren: 'app/components/login/login.module#AppLoginModule' },
|
||||||
{ path: 'logout', component: LogoutComponent },
|
{ path: 'logout', component: LogoutComponent },
|
||||||
@ -177,6 +178,10 @@ export const appRoutes: Routes = [
|
|||||||
path: 'people-group-cloud',
|
path: 'people-group-cloud',
|
||||||
component: PeopleGroupCloudDemoComponent
|
component: PeopleGroupCloudDemoComponent
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: 'task-header-cloud',
|
||||||
|
component: TaskHeaderCloudDemoComponent
|
||||||
|
},
|
||||||
{
|
{
|
||||||
path: 'community',
|
path: 'community',
|
||||||
loadChildren: 'app/components/cloud/community/community.module#AppCommunityModule'
|
loadChildren: 'app/components/cloud/community/community.module#AppCommunityModule'
|
||||||
|
@ -48,12 +48,15 @@ export class AppLayoutComponent implements OnInit, OnDestroy {
|
|||||||
{ href: '/node-selector', icon: 'attachment', title: 'APP_LAYOUT.NODE-SELECTOR' },
|
{ href: '/node-selector', icon: 'attachment', title: 'APP_LAYOUT.NODE-SELECTOR' },
|
||||||
{ href: '/sites', icon: 'format_list_bulleted', title: 'APP_LAYOUT.SITES' },
|
{ href: '/sites', icon: 'format_list_bulleted', title: 'APP_LAYOUT.SITES' },
|
||||||
{ href: '/task-list', icon: 'assignment', title: 'APP_LAYOUT.TASK_LIST' },
|
{ href: '/task-list', icon: 'assignment', title: 'APP_LAYOUT.TASK_LIST' },
|
||||||
{ href: '/cloud', icon: 'cloud', title: 'APP_LAYOUT.PROCESS_CLOUD', children: [
|
{
|
||||||
{ href: '/cloud/', icon: 'cloud', title: 'APP_LAYOUT.HOME' },
|
href: '/cloud', icon: 'cloud', title: 'APP_LAYOUT.PROCESS_CLOUD', children: [
|
||||||
{ href: '/cloud/community', icon: 'cloud', title: 'APP_LAYOUT.COMMUNITY' },
|
{ href: '/cloud/', icon: 'cloud', title: 'APP_LAYOUT.HOME' },
|
||||||
{ href: '/form-cloud', icon: 'poll', title: 'APP_LAYOUT.FORM' },
|
{ href: '/cloud/community', icon: 'cloud', title: 'APP_LAYOUT.COMMUNITY' },
|
||||||
{ href: '/cloud/people-group-cloud', icon: 'group', title: 'APP_LAYOUT.PEOPLE_GROUPS_CLOUD' }
|
{ href: '/form-cloud', icon: 'poll', title: 'APP_LAYOUT.FORM' },
|
||||||
]},
|
{ href: '/cloud/people-group-cloud', icon: 'group', title: 'APP_LAYOUT.PEOPLE_GROUPS_CLOUD' },
|
||||||
|
{ href: '/cloud/task-header-cloud', icon: 'cloud', title: 'APP_LAYOUT.TASK_HEADER_CLOUD.COMPONENT_NAME' }
|
||||||
|
]
|
||||||
|
},
|
||||||
{ href: '/activiti', icon: 'device_hub', title: 'APP_LAYOUT.PROCESS_SERVICES', children: [
|
{ href: '/activiti', icon: 'device_hub', title: 'APP_LAYOUT.PROCESS_SERVICES', children: [
|
||||||
{ href: '/activiti', icon: 'vpn_key', title: 'APP_LAYOUT.APP' },
|
{ href: '/activiti', icon: 'vpn_key', title: 'APP_LAYOUT.APP' },
|
||||||
{ href: '/process-list', icon: 'assignment', title: 'APP_LAYOUT.PROCESS_LIST' },
|
{ href: '/process-list', icon: 'assignment', title: 'APP_LAYOUT.PROCESS_LIST' },
|
||||||
|
@ -8,8 +8,6 @@
|
|||||||
[taskId]="taskId"
|
[taskId]="taskId"
|
||||||
(cancelClick)="goBack()"
|
(cancelClick)="goBack()"
|
||||||
(taskCompleted)="onTaskCompleted()"
|
(taskCompleted)="onTaskCompleted()"
|
||||||
(taskClaimed)="onTaskClaimed()"
|
|
||||||
(taskUnclaimed)="onTaskUnclaimed()"
|
|
||||||
(formContentClicked)="onFormContentClicked($event)"
|
(formContentClicked)="onFormContentClicked($event)"
|
||||||
(formSaved)="onFormSaved()">
|
(formSaved)="onFormSaved()">
|
||||||
</adf-cloud-task-form>
|
</adf-cloud-task-form>
|
||||||
|
@ -60,14 +60,6 @@ export class TaskDetailsCloudDemoComponent {
|
|||||||
this.goBack();
|
this.goBack();
|
||||||
}
|
}
|
||||||
|
|
||||||
onTaskClaimed() {
|
|
||||||
this.taskHeader.ngOnInit();
|
|
||||||
}
|
|
||||||
|
|
||||||
onTaskUnclaimed() {
|
|
||||||
this.taskHeader.ngOnInit();
|
|
||||||
}
|
|
||||||
|
|
||||||
onFormContentClicked(resourceClicked: any) {
|
onFormContentClicked(resourceClicked: any) {
|
||||||
this.previewService.showResource(resourceClicked.nodeId);
|
this.previewService.showResource(resourceClicked.nodeId);
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,31 @@
|
|||||||
|
<h2>{{ 'APP_LAYOUT.TASK_HEADER_CLOUD.COMPONENT_NAME' | translate }}</h2>
|
||||||
|
|
||||||
|
<mat-form-field class="app-appName-input">
|
||||||
|
{{ 'APP_LAYOUT.TASK_HEADER_CLOUD.APP_NAME_INPUT' | translate }}
|
||||||
|
<input matInput
|
||||||
|
[type]="'text'"
|
||||||
|
[formControl]="appNameFormControl">
|
||||||
|
</mat-form-field>
|
||||||
|
|
||||||
|
<mat-form-field class="app-taskId-input">
|
||||||
|
{{ 'APP_LAYOUT.TASK_HEADER_CLOUD.TASK_ID_INPUT' | translate }}
|
||||||
|
<input matInput
|
||||||
|
[type]="'text'"
|
||||||
|
[formControl]="taskIdFormControl">
|
||||||
|
</mat-form-field>
|
||||||
|
|
||||||
|
<button mat-button *ngIf="appNameFormControl.value && taskIdFormControl.value"
|
||||||
|
class="app-find-task-button"
|
||||||
|
(click)="updateTaskHeader()">
|
||||||
|
{{ 'APP_LAYOUT.TASK_HEADER_CLOUD.FIND_TASK_BUTTON' | translate }}
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<mat-error *ngIf="errorMessage">{{errorMessage}}</mat-error>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<adf-cloud-task-header #taskHeader
|
||||||
|
[appName]="appName"
|
||||||
|
[taskId]="taskId"
|
||||||
|
(taskError)="onError($event)">
|
||||||
|
</adf-cloud-task-header>
|
||||||
|
</div>
|
@ -0,0 +1,16 @@
|
|||||||
|
.app {
|
||||||
|
|
||||||
|
&-appName-input {
|
||||||
|
width: 500px;
|
||||||
|
margin-right: 50px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-taskId-input {
|
||||||
|
width: 500px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-find-task-button {
|
||||||
|
background-color: #ff9800;
|
||||||
|
margin-left: 30px;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,49 @@
|
|||||||
|
/*!
|
||||||
|
* @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, ViewChild } from '@angular/core';
|
||||||
|
import { TaskHeaderCloudComponent } from '@alfresco/adf-process-services-cloud';
|
||||||
|
import { FormControl, Validators } from '@angular/forms';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
templateUrl: './task-header-cloud-demo.component.html',
|
||||||
|
styleUrls: ['./task-header-cloud-demo.component.scss']
|
||||||
|
})
|
||||||
|
export class TaskHeaderCloudDemoComponent {
|
||||||
|
@ViewChild('taskHeader')
|
||||||
|
taskHeader: TaskHeaderCloudComponent;
|
||||||
|
|
||||||
|
appName: string;
|
||||||
|
taskId: string;
|
||||||
|
|
||||||
|
errorMessage;
|
||||||
|
|
||||||
|
appNameFormControl = new FormControl('', Validators.required);
|
||||||
|
taskIdFormControl = new FormControl('', Validators.required);
|
||||||
|
|
||||||
|
constructor() {}
|
||||||
|
|
||||||
|
updateTaskHeader() {
|
||||||
|
this.errorMessage = undefined;
|
||||||
|
this.appName = this.appNameFormControl.value;
|
||||||
|
this.taskId = this.taskIdFormControl.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
onError(error) {
|
||||||
|
this.errorMessage = error.message;
|
||||||
|
}
|
||||||
|
}
|
@ -35,6 +35,7 @@ Shows all the information related to a task.
|
|||||||
| ---- | ---- | ----------- |
|
| ---- | ---- | ----------- |
|
||||||
| claim | [`EventEmitter`](https://angular.io/api/core/EventEmitter)`<any>` | Emitted when the task is claimed. |
|
| claim | [`EventEmitter`](https://angular.io/api/core/EventEmitter)`<any>` | Emitted when the task is claimed. |
|
||||||
| unclaim | [`EventEmitter`](https://angular.io/api/core/EventEmitter)`<any>` | Emitted when the task is unclaimed (ie, requeued). |
|
| unclaim | [`EventEmitter`](https://angular.io/api/core/EventEmitter)`<any>` | Emitted when the task is unclaimed (ie, requeued). |
|
||||||
|
| taskError | [`EventEmitter`](https://angular.io/api/core/EventEmitter)`<any>` | Emitted when there is an error about the requested task |
|
||||||
|
|
||||||
## Details
|
## Details
|
||||||
|
|
||||||
|
@ -50,7 +50,7 @@ export class ProcessHeaderCloudComponent implements OnChanges {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ngOnChanges() {
|
ngOnChanges() {
|
||||||
if ((this.appName || this.appName === '') && this.processInstanceId) {
|
if (this.appName && this.processInstanceId) {
|
||||||
this.loadProcessInstanceDetails(this.appName, this.processInstanceId);
|
this.loadProcessInstanceDetails(this.appName, this.processInstanceId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -45,7 +45,7 @@ export class ProcessHeaderCloudService extends BaseCloudService {
|
|||||||
* @returns Process instance details
|
* @returns Process instance details
|
||||||
*/
|
*/
|
||||||
getProcessInstanceById(appName: string, processInstanceId: string): Observable<ProcessInstanceCloud> {
|
getProcessInstanceById(appName: string, processInstanceId: string): Observable<ProcessInstanceCloud> {
|
||||||
if ((appName || appName === '') && processInstanceId) {
|
if (appName && processInstanceId) {
|
||||||
const queryUrl = `${this.getBasePath(appName)}/query/v1/process-instances/${processInstanceId}`;
|
const queryUrl = `${this.getBasePath(appName)}/query/v1/process-instances/${processInstanceId}`;
|
||||||
return from(this.alfrescoApiService.getInstance()
|
return from(this.alfrescoApiService.getInstance()
|
||||||
.oauth2Auth.callCustomApi(queryUrl, 'GET',
|
.oauth2Auth.callCustomApi(queryUrl, 'GET',
|
||||||
|
@ -185,7 +185,7 @@ export class ProcessListCloudComponent extends DataTableSchema implements OnChan
|
|||||||
|
|
||||||
reload() {
|
reload() {
|
||||||
this.requestNode = this.createRequestNode();
|
this.requestNode = this.createRequestNode();
|
||||||
if (this.requestNode.appName || this.requestNode.appName === '') {
|
if (this.requestNode.appName) {
|
||||||
this.load(this.requestNode);
|
this.load(this.requestNode);
|
||||||
} else {
|
} else {
|
||||||
this.rows = [];
|
this.rows = [];
|
||||||
|
@ -39,7 +39,7 @@ export class ProcessListCloudService extends BaseCloudService {
|
|||||||
* @returns Process information
|
* @returns Process information
|
||||||
*/
|
*/
|
||||||
getProcessByRequest(requestNode: ProcessQueryCloudRequestModel): Observable<any> {
|
getProcessByRequest(requestNode: ProcessQueryCloudRequestModel): Observable<any> {
|
||||||
if (requestNode.appName || requestNode.appName === '') {
|
if (requestNode.appName) {
|
||||||
const queryUrl = this.buildQueryUrl(requestNode);
|
const queryUrl = this.buildQueryUrl(requestNode);
|
||||||
const queryParams = this.buildQueryParams(requestNode);
|
const queryParams = this.buildQueryParams(requestNode);
|
||||||
const sortingParams = this.buildSortingParam(requestNode.sorting);
|
const sortingParams = this.buildSortingParam(requestNode.sorting);
|
||||||
|
@ -48,7 +48,7 @@ export class StartProcessCloudService extends BaseCloudService {
|
|||||||
*/
|
*/
|
||||||
getProcessDefinitions(appName: string): Observable<ProcessDefinitionCloud[]> {
|
getProcessDefinitions(appName: string): Observable<ProcessDefinitionCloud[]> {
|
||||||
|
|
||||||
if (appName || appName === '') {
|
if (appName) {
|
||||||
const queryUrl = `${this.getBasePath(appName)}/rb/v1/process-definitions`;
|
const queryUrl = `${this.getBasePath(appName)}/rb/v1/process-definitions`;
|
||||||
|
|
||||||
return from(this.alfrescoApiService.getInstance()
|
return from(this.alfrescoApiService.getInstance()
|
||||||
|
@ -41,7 +41,7 @@ export class UserPreferenceCloudService extends BaseCloudService implements Pref
|
|||||||
* @returns List of user preferences
|
* @returns List of user preferences
|
||||||
*/
|
*/
|
||||||
getPreferences(appName: string): Observable<any> {
|
getPreferences(appName: string): Observable<any> {
|
||||||
if (appName || appName === '') {
|
if (appName) {
|
||||||
const uri = this.buildPreferenceServiceUri(appName);
|
const uri = this.buildPreferenceServiceUri(appName);
|
||||||
return from(this.alfrescoApiService.getInstance()
|
return from(this.alfrescoApiService.getInstance()
|
||||||
.oauth2Auth.callCustomApi(uri, 'GET',
|
.oauth2Auth.callCustomApi(uri, 'GET',
|
||||||
@ -62,7 +62,7 @@ export class UserPreferenceCloudService extends BaseCloudService implements Pref
|
|||||||
* @returns Observable of user preference
|
* @returns Observable of user preference
|
||||||
*/
|
*/
|
||||||
getPreferenceByKey(appName: string, key: string): Observable<any> {
|
getPreferenceByKey(appName: string, key: string): Observable<any> {
|
||||||
if (appName || appName === '') {
|
if (appName) {
|
||||||
const uri = this.buildPreferenceServiceUri(appName) + '/' + `${key}`;
|
const uri = this.buildPreferenceServiceUri(appName) + '/' + `${key}`;
|
||||||
return from(
|
return from(
|
||||||
this.alfrescoApiService.getInstance()
|
this.alfrescoApiService.getInstance()
|
||||||
@ -85,7 +85,7 @@ export class UserPreferenceCloudService extends BaseCloudService implements Pref
|
|||||||
* @returns Observable of created user preferences
|
* @returns Observable of created user preferences
|
||||||
*/
|
*/
|
||||||
createPreference(appName: string, key: string, newPreference: any): Observable<any> {
|
createPreference(appName: string, key: string, newPreference: any): Observable<any> {
|
||||||
if (appName || appName === '') {
|
if (appName) {
|
||||||
const uri = this.buildPreferenceServiceUri(appName) + '/' + `${key}`;
|
const uri = this.buildPreferenceServiceUri(appName) + '/' + `${key}`;
|
||||||
const requestPayload = JSON.stringify(newPreference);
|
const requestPayload = JSON.stringify(newPreference);
|
||||||
return from(this.alfrescoApiService.getInstance()
|
return from(this.alfrescoApiService.getInstance()
|
||||||
@ -121,7 +121,7 @@ export class UserPreferenceCloudService extends BaseCloudService implements Pref
|
|||||||
* @returns Observable of delete operation status
|
* @returns Observable of delete operation status
|
||||||
*/
|
*/
|
||||||
deletePreference(appName: string, key: string): Observable<any> {
|
deletePreference(appName: string, key: string): Observable<any> {
|
||||||
if (appName || appName === '') {
|
if (appName) {
|
||||||
const uri = this.buildPreferenceServiceUri(appName) + '/' + `${key}`;
|
const uri = this.buildPreferenceServiceUri(appName) + '/' + `${key}`;
|
||||||
return from(this.alfrescoApiService.getInstance()
|
return from(this.alfrescoApiService.getInstance()
|
||||||
.oauth2Auth.callCustomApi(uri, 'DELETE',
|
.oauth2Auth.callCustomApi(uri, 'DELETE',
|
||||||
|
@ -68,7 +68,7 @@ export class ClaimTaskDirective implements OnInit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
isAppValid(): boolean {
|
isAppValid(): boolean {
|
||||||
return (this.appName && this.appName.length > 0) || (this.appName === '');
|
return (this.appName && this.appName.length > 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@HostListener('click')
|
@HostListener('click')
|
||||||
|
@ -65,7 +65,7 @@ export class CompleteTaskDirective implements OnInit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
isAppValid(): boolean {
|
isAppValid(): boolean {
|
||||||
return (this.appName && this.appName.length > 0) || (this.appName === '');
|
return (this.appName && this.appName.length > 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@HostListener('click')
|
@HostListener('click')
|
||||||
|
@ -66,7 +66,7 @@ export class UnClaimTaskDirective implements OnInit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
isAppValid(): boolean {
|
isAppValid(): boolean {
|
||||||
return (this.appName && this.appName.length > 0) || (this.appName === '');
|
return (this.appName && this.appName.length > 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@HostListener('click')
|
@HostListener('click')
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
|
|
||||||
import { Injectable } from '@angular/core';
|
import { Injectable } from '@angular/core';
|
||||||
import { AlfrescoApiService, LogService, AppConfigService, IdentityUserService } from '@alfresco/adf-core';
|
import { AlfrescoApiService, LogService, AppConfigService, IdentityUserService } from '@alfresco/adf-core';
|
||||||
import { from, throwError, Observable, of } from 'rxjs';
|
import { from, throwError, Observable, of, Subject } from 'rxjs';
|
||||||
import { catchError, map } from 'rxjs/operators';
|
import { catchError, map } from 'rxjs/operators';
|
||||||
import { TaskDetailsCloudModel, StartTaskCloudResponseModel } from '../start-task/models/task-details-cloud.model';
|
import { TaskDetailsCloudModel, StartTaskCloudResponseModel } from '../start-task/models/task-details-cloud.model';
|
||||||
import { BaseCloudService } from '../../services/base-cloud.service';
|
import { BaseCloudService } from '../../services/base-cloud.service';
|
||||||
@ -32,6 +32,9 @@ export class TaskCloudService extends BaseCloudService {
|
|||||||
accepts = ['application/json'];
|
accepts = ['application/json'];
|
||||||
returnType = Object;
|
returnType = Object;
|
||||||
|
|
||||||
|
private dataChangesDetected = new Subject();
|
||||||
|
dataChangesDetected$: Observable<object>;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private apiService: AlfrescoApiService,
|
private apiService: AlfrescoApiService,
|
||||||
private appConfigService: AppConfigService,
|
private appConfigService: AppConfigService,
|
||||||
@ -40,6 +43,7 @@ export class TaskCloudService extends BaseCloudService {
|
|||||||
) {
|
) {
|
||||||
super();
|
super();
|
||||||
this.contextRoot = this.appConfigService.get('bpmHost', '');
|
this.contextRoot = this.appConfigService.get('bpmHost', '');
|
||||||
|
this.dataChangesDetected$ = this.dataChangesDetected.asObservable();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -49,7 +53,7 @@ export class TaskCloudService extends BaseCloudService {
|
|||||||
* @returns Details of the task that was completed
|
* @returns Details of the task that was completed
|
||||||
*/
|
*/
|
||||||
completeTask(appName: string, taskId: string): Observable<TaskDetailsCloudModel> {
|
completeTask(appName: string, taskId: string): Observable<TaskDetailsCloudModel> {
|
||||||
if ((appName || appName === '') && taskId) {
|
if (appName && taskId) {
|
||||||
const queryUrl = this.buildCompleteTaskUrl(appName, taskId);
|
const queryUrl = this.buildCompleteTaskUrl(appName, taskId);
|
||||||
const bodyParam = { 'payloadType': 'CompleteTaskPayload' };
|
const bodyParam = { 'payloadType': 'CompleteTaskPayload' };
|
||||||
const pathParams = {}, queryParams = {}, headerParams = {},
|
const pathParams = {}, queryParams = {}, headerParams = {},
|
||||||
@ -116,7 +120,7 @@ export class TaskCloudService extends BaseCloudService {
|
|||||||
* @returns Details of the claimed task
|
* @returns Details of the claimed task
|
||||||
*/
|
*/
|
||||||
claimTask(appName: string, taskId: string, assignee: string): Observable<TaskDetailsCloudModel> {
|
claimTask(appName: string, taskId: string, assignee: string): Observable<TaskDetailsCloudModel> {
|
||||||
if ((appName || appName === '') && taskId) {
|
if (appName && taskId) {
|
||||||
const queryUrl = `${this.getBasePath(appName)}/rb/v1/tasks/${taskId}/claim?assignee=${assignee}`;
|
const queryUrl = `${this.getBasePath(appName)}/rb/v1/tasks/${taskId}/claim?assignee=${assignee}`;
|
||||||
return from(this.apiService.getInstance()
|
return from(this.apiService.getInstance()
|
||||||
.oauth2Auth.callCustomApi(queryUrl, 'POST',
|
.oauth2Auth.callCustomApi(queryUrl, 'POST',
|
||||||
@ -143,7 +147,7 @@ export class TaskCloudService extends BaseCloudService {
|
|||||||
* @returns Details of the task that was unclaimed
|
* @returns Details of the task that was unclaimed
|
||||||
*/
|
*/
|
||||||
unclaimTask(appName: string, taskId: string): Observable<TaskDetailsCloudModel> {
|
unclaimTask(appName: string, taskId: string): Observable<TaskDetailsCloudModel> {
|
||||||
if ((appName || appName === '') && taskId) {
|
if (appName && taskId) {
|
||||||
const queryUrl = `${this.getBasePath(appName)}/rb/v1/tasks/${taskId}/release`;
|
const queryUrl = `${this.getBasePath(appName)}/rb/v1/tasks/${taskId}/release`;
|
||||||
return from(this.apiService.getInstance()
|
return from(this.apiService.getInstance()
|
||||||
.oauth2Auth.callCustomApi(queryUrl, 'POST',
|
.oauth2Auth.callCustomApi(queryUrl, 'POST',
|
||||||
@ -170,7 +174,7 @@ export class TaskCloudService extends BaseCloudService {
|
|||||||
* @returns Task details
|
* @returns Task details
|
||||||
*/
|
*/
|
||||||
getTaskById(appName: string, taskId: string): Observable<TaskDetailsCloudModel> {
|
getTaskById(appName: string, taskId: string): Observable<TaskDetailsCloudModel> {
|
||||||
if ((appName || appName === '') && taskId) {
|
if (appName && taskId) {
|
||||||
const queryUrl = `${this.getBasePath(appName)}/query/v1/tasks/${taskId}`;
|
const queryUrl = `${this.getBasePath(appName)}/query/v1/tasks/${taskId}`;
|
||||||
return from(this.apiService.getInstance()
|
return from(this.apiService.getInstance()
|
||||||
.oauth2Auth.callCustomApi(queryUrl, 'GET',
|
.oauth2Auth.callCustomApi(queryUrl, 'GET',
|
||||||
@ -180,6 +184,7 @@ export class TaskCloudService extends BaseCloudService {
|
|||||||
this.returnType, null, null)
|
this.returnType, null, null)
|
||||||
).pipe(
|
).pipe(
|
||||||
map((res: any) => {
|
map((res: any) => {
|
||||||
|
this.dataChangesDetected.next();
|
||||||
return new TaskDetailsCloudModel(res.entry);
|
return new TaskDetailsCloudModel(res.entry);
|
||||||
}),
|
}),
|
||||||
catchError((err) => this.handleError(err))
|
catchError((err) => this.handleError(err))
|
||||||
@ -224,7 +229,7 @@ export class TaskCloudService extends BaseCloudService {
|
|||||||
* @returns Updated task details
|
* @returns Updated task details
|
||||||
*/
|
*/
|
||||||
updateTask(appName: string, taskId: string, updatePayload: any): Observable<TaskDetailsCloudModel> {
|
updateTask(appName: string, taskId: string, updatePayload: any): Observable<TaskDetailsCloudModel> {
|
||||||
if ((appName || appName === '') && taskId) {
|
if (appName && taskId) {
|
||||||
|
|
||||||
updatePayload.payloadType = 'UpdateTaskPayload';
|
updatePayload.payloadType = 'UpdateTaskPayload';
|
||||||
const queryUrl = `${this.getBasePath(appName)}/rb/v1/tasks/${taskId}`;
|
const queryUrl = `${this.getBasePath(appName)}/rb/v1/tasks/${taskId}`;
|
||||||
@ -253,7 +258,7 @@ export class TaskCloudService extends BaseCloudService {
|
|||||||
* @returns Candidate users
|
* @returns Candidate users
|
||||||
*/
|
*/
|
||||||
getCandidateUsers(appName: string, taskId: string): Observable<string[]> {
|
getCandidateUsers(appName: string, taskId: string): Observable<string[]> {
|
||||||
if ((appName || appName === '') && taskId) {
|
if (appName && taskId) {
|
||||||
const queryUrl = `${this.getBasePath(appName)}/query/v1/tasks/${taskId}/candidate-users`;
|
const queryUrl = `${this.getBasePath(appName)}/query/v1/tasks/${taskId}/candidate-users`;
|
||||||
return from(this.apiService.getInstance()
|
return from(this.apiService.getInstance()
|
||||||
.oauth2Auth.callCustomApi(queryUrl, 'GET',
|
.oauth2Auth.callCustomApi(queryUrl, 'GET',
|
||||||
@ -280,7 +285,7 @@ export class TaskCloudService extends BaseCloudService {
|
|||||||
* @returns Candidate groups
|
* @returns Candidate groups
|
||||||
*/
|
*/
|
||||||
getCandidateGroups(appName: string, taskId: string): Observable<string[]> {
|
getCandidateGroups(appName: string, taskId: string): Observable<string[]> {
|
||||||
if ((appName || appName === '') && taskId) {
|
if (appName && taskId) {
|
||||||
const queryUrl = `${this.getBasePath(appName)}/query/v1/tasks/${taskId}/candidate-groups`;
|
const queryUrl = `${this.getBasePath(appName)}/query/v1/tasks/${taskId}/candidate-groups`;
|
||||||
return from(this.apiService.getInstance()
|
return from(this.apiService.getInstance()
|
||||||
.oauth2Auth.callCustomApi(queryUrl, 'GET',
|
.oauth2Auth.callCustomApi(queryUrl, 'GET',
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
<h3 class="adf-task-title">{{ taskDetails.name }}</h3>
|
<h3 class="adf-task-title">{{ taskDetails?.name }}</h3>
|
||||||
|
|
||||||
<div class="adf-task-header-container">
|
<div class="adf-task-header-container">
|
||||||
<mat-card *ngIf="isTaskValid()" class="adf-card-container">
|
<mat-card *ngIf="isTaskValid()" class="adf-card-container">
|
||||||
|
@ -21,7 +21,7 @@ import { TaskHeaderCloudComponent } from './task-header-cloud.component';
|
|||||||
import { assignedTaskDetailsCloudMock } from '../mocks/task-details-cloud.mock';
|
import { assignedTaskDetailsCloudMock } from '../mocks/task-details-cloud.mock';
|
||||||
import { TaskHeaderCloudModule } from '../task-header-cloud.module';
|
import { TaskHeaderCloudModule } from '../task-header-cloud.module';
|
||||||
import { By } from '@angular/platform-browser';
|
import { By } from '@angular/platform-browser';
|
||||||
import { of } from 'rxjs';
|
import { of, throwError } from 'rxjs';
|
||||||
import { ProcessServiceCloudTestingModule } from '../../../testing/process-service-cloud.testing.module';
|
import { ProcessServiceCloudTestingModule } from '../../../testing/process-service-cloud.testing.module';
|
||||||
import { RouterTestingModule } from '@angular/router/testing';
|
import { RouterTestingModule } from '@angular/router/testing';
|
||||||
import { TaskCloudService } from '../../services/task-cloud.service';
|
import { TaskCloudService } from '../../services/task-cloud.service';
|
||||||
@ -35,7 +35,12 @@ describe('TaskHeaderCloudComponent', () => {
|
|||||||
let getCandidateGroupsSpy: jasmine.Spy;
|
let getCandidateGroupsSpy: jasmine.Spy;
|
||||||
let getCandidateUsersSpy: jasmine.Spy;
|
let getCandidateUsersSpy: jasmine.Spy;
|
||||||
|
|
||||||
const identityUserMock = { username: 'testuser', firstName: 'fake-identity-first-name', lastName: 'fake-identity-last-name', email: 'fakeIdentity@email.com' };
|
const identityUserMock = {
|
||||||
|
username: 'testuser',
|
||||||
|
firstName: 'fake-identity-first-name',
|
||||||
|
lastName: 'fake-identity-last-name',
|
||||||
|
email: 'fakeIdentity@email.com'
|
||||||
|
};
|
||||||
const mockCandidateUsers = ['mockuser1', 'mockuser2', 'mockuser3'];
|
const mockCandidateUsers = ['mockuser1', 'mockuser2', 'mockuser3'];
|
||||||
const mockCandidateGroups = ['mockgroup1', 'mockgroup2', 'mockgroup3'];
|
const mockCandidateGroups = ['mockgroup1', 'mockgroup2', 'mockgroup3'];
|
||||||
|
|
||||||
@ -48,200 +53,222 @@ describe('TaskHeaderCloudComponent', () => {
|
|||||||
providers: [IdentityUserService]
|
providers: [IdentityUserService]
|
||||||
});
|
});
|
||||||
|
|
||||||
beforeEach(() => {
|
describe('Task Details', () => {
|
||||||
fixture = TestBed.createComponent(TaskHeaderCloudComponent);
|
|
||||||
component = fixture.componentInstance;
|
|
||||||
component.appName = 'myApp';
|
|
||||||
component.taskId = assignedTaskDetailsCloudMock.id;
|
|
||||||
service = TestBed.get(TaskCloudService);
|
|
||||||
identityUserService = TestBed.get(IdentityUserService);
|
|
||||||
appConfigService = TestBed.get(AppConfigService);
|
|
||||||
spyOn(service, 'getTaskById').and.returnValue(of(assignedTaskDetailsCloudMock));
|
|
||||||
getCandidateUsersSpy = spyOn(service, 'getCandidateUsers').and.returnValue(of(mockCandidateUsers));
|
|
||||||
getCandidateGroupsSpy = spyOn(service, 'getCandidateGroups').and.returnValue(of(mockCandidateGroups));
|
|
||||||
spyOn(identityUserService, 'getCurrentUserInfo').and.returnValue(identityUserMock);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should render empty component if no task details provided', async(() => {
|
beforeEach(() => {
|
||||||
component.appName = undefined;
|
fixture = TestBed.createComponent(TaskHeaderCloudComponent);
|
||||||
component.taskId = undefined;
|
component = fixture.componentInstance;
|
||||||
fixture.detectChanges();
|
component.appName = 'myApp';
|
||||||
expect(fixture.debugElement.children.length).toBe(2);
|
component.taskId = assignedTaskDetailsCloudMock.id;
|
||||||
}));
|
service = TestBed.get(TaskCloudService);
|
||||||
|
identityUserService = TestBed.get(IdentityUserService);
|
||||||
it('should display assignee', async(() => {
|
appConfigService = TestBed.get(AppConfigService);
|
||||||
component.ngOnInit();
|
spyOn(service, 'getTaskById').and.returnValue(of(assignedTaskDetailsCloudMock));
|
||||||
fixture.detectChanges();
|
getCandidateUsersSpy = spyOn(service, 'getCandidateUsers').and.returnValue(of(mockCandidateUsers));
|
||||||
|
getCandidateGroupsSpy = spyOn(service, 'getCandidateGroups').and.returnValue(of(mockCandidateGroups));
|
||||||
fixture.whenStable().then(() => {
|
spyOn(identityUserService, 'getCurrentUserInfo').and.returnValue(identityUserMock);
|
||||||
const formNameEl = fixture.debugElement.query(By.css('[data-automation-id="card-textitem-value-assignee"] span'));
|
|
||||||
expect(formNameEl.nativeElement.innerText).toBe('AssignedTaskUser');
|
|
||||||
});
|
|
||||||
}));
|
|
||||||
|
|
||||||
it('should display placeholder if no assignee', async(() => {
|
|
||||||
component.ngOnInit();
|
|
||||||
component.taskDetails.assignee = null;
|
|
||||||
fixture.detectChanges();
|
|
||||||
|
|
||||||
fixture.whenStable().then(() => {
|
|
||||||
const valueEl = fixture.debugElement.query(By.css('[data-automation-id="card-textitem-value-assignee"] span'));
|
|
||||||
expect(valueEl.nativeElement.innerText).toBe('ADF_CLOUD_TASK_HEADER.PROPERTIES.ASSIGNEE_DEFAULT');
|
|
||||||
});
|
});
|
||||||
|
|
||||||
}));
|
it('should render empty component if no task details provided', async(() => {
|
||||||
|
component.appName = undefined;
|
||||||
it('should display priority', async(() => {
|
component.taskId = undefined;
|
||||||
component.ngOnInit();
|
|
||||||
fixture.detectChanges();
|
|
||||||
|
|
||||||
fixture.whenStable().then(() => {
|
|
||||||
const formNameEl = fixture.debugElement.query(By.css('[data-automation-id="card-textitem-value-priority"]'));
|
|
||||||
expect(formNameEl.nativeElement.innerText).toBe('5');
|
|
||||||
});
|
|
||||||
}));
|
|
||||||
|
|
||||||
it('should display error if priority is not a number', async(() => {
|
|
||||||
component.ngOnInit();
|
|
||||||
component.taskDetails.assignee = 'testuser';
|
|
||||||
fixture.detectChanges();
|
|
||||||
|
|
||||||
fixture.whenStable().then(() => {
|
|
||||||
const edit = fixture.debugElement.query(By.css('[data-automation-id="card-textitem-edit-icon-priority"]'));
|
|
||||||
edit.nativeElement.click();
|
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
|
expect(fixture.debugElement.children.length).toBe(2);
|
||||||
|
}));
|
||||||
|
|
||||||
const formPriorityEl = fixture.debugElement.query(By.css('[data-automation-id="card-textitem-editinput-priority"]'));
|
it('should display assignee', async(() => {
|
||||||
formPriorityEl.nativeElement.value = 'stringValue';
|
component.ngOnChanges();
|
||||||
formPriorityEl.nativeElement.dispatchEvent(new Event('input'));
|
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
|
|
||||||
const submitEl = fixture.debugElement.query(By.css('[data-automation-id="card-textitem-update-priority"]'));
|
|
||||||
submitEl.nativeElement.click();
|
|
||||||
fixture.detectChanges();
|
|
||||||
|
|
||||||
const errorMessageEl = fixture.debugElement.query(By.css('[data-automation-id="card-textitem-error-priority"]'));
|
|
||||||
expect(errorMessageEl).not.toBeNull();
|
|
||||||
});
|
|
||||||
}));
|
|
||||||
|
|
||||||
it('should display due date', async(() => {
|
|
||||||
component.ngOnInit();
|
|
||||||
fixture.detectChanges();
|
|
||||||
|
|
||||||
fixture.whenStable().then(() => {
|
|
||||||
const valueEl = fixture.debugElement.query(By.css('[data-automation-id="header-dueDate"] .adf-property-value'));
|
|
||||||
expect(valueEl.nativeElement.innerText.trim()).toBe('Dec 18, 2018');
|
|
||||||
});
|
|
||||||
}));
|
|
||||||
|
|
||||||
it('should display placeholder if no due date', async(() => {
|
|
||||||
component.ngOnInit();
|
|
||||||
component.taskDetails.dueDate = null;
|
|
||||||
fixture.detectChanges();
|
|
||||||
|
|
||||||
fixture.whenStable().then(() => {
|
|
||||||
const valueEl = fixture.debugElement.query(By.css('[data-automation-id="header-dueDate"] .adf-property-value'));
|
|
||||||
expect(valueEl.nativeElement.innerText.trim()).toBe('ADF_CLOUD_TASK_HEADER.PROPERTIES.DUE_DATE_DEFAULT');
|
|
||||||
});
|
|
||||||
}));
|
|
||||||
|
|
||||||
it('should display the default parent value if is undefined', async(() => {
|
|
||||||
component.ngOnInit();
|
|
||||||
component.taskDetails.processInstanceId = null;
|
|
||||||
fixture.detectChanges();
|
|
||||||
|
|
||||||
fixture.whenStable().then(() => {
|
|
||||||
const valueEl = fixture.debugElement.query(By.css('[data-automation-id="header-parentName"] .adf-property-value'));
|
|
||||||
expect(valueEl.nativeElement.innerText.trim()).toEqual('ADF_CLOUD_TASK_HEADER.PROPERTIES.PARENT_NAME_DEFAULT');
|
|
||||||
});
|
|
||||||
}));
|
|
||||||
|
|
||||||
it('should display candidate user', async(() => {
|
|
||||||
component.ngOnInit();
|
|
||||||
fixture.detectChanges();
|
|
||||||
|
|
||||||
fixture.whenStable().then(() => {
|
|
||||||
const candidateUser1 = fixture.nativeElement.querySelector('[data-automation-id="card-arrayitem-chip-mockuser1"] span');
|
|
||||||
const candidateUser2 = fixture.nativeElement.querySelector('[data-automation-id="card-arrayitem-chip-mockuser2"] span');
|
|
||||||
expect(getCandidateUsersSpy).toHaveBeenCalled();
|
|
||||||
expect(candidateUser1.innerText).toBe('mockuser1');
|
|
||||||
expect(candidateUser2.innerText).toBe('mockuser2');
|
|
||||||
});
|
|
||||||
}));
|
|
||||||
|
|
||||||
it('should display placeholder if no candidate users', async(() => {
|
|
||||||
component.ngOnInit();
|
|
||||||
getCandidateUsersSpy.and.returnValue(of([]));
|
|
||||||
fixture.detectChanges();
|
|
||||||
|
|
||||||
fixture.whenStable().then(() => {
|
|
||||||
const labelValue = fixture.debugElement.query(By.css('[data-automation-id="card-array-label-candidateUsers"]'));
|
|
||||||
const defaultElement = fixture.debugElement.query(By.css('[data-automation-id="card-arrayitem-default"]'));
|
|
||||||
expect(labelValue.nativeElement.innerText).toBe('ADF_CLOUD_TASK_HEADER.PROPERTIES.CANDIDATE_USERS');
|
|
||||||
expect(defaultElement.nativeElement.innerText).toBe('ADF_CLOUD_TASK_HEADER.PROPERTIES.CANDIDATE_USERS_DEFAULT');
|
|
||||||
});
|
|
||||||
|
|
||||||
}));
|
|
||||||
|
|
||||||
it('should display candidate groups', async(() => {
|
|
||||||
component.ngOnInit();
|
|
||||||
fixture.detectChanges();
|
|
||||||
|
|
||||||
fixture.whenStable().then(() => {
|
|
||||||
const candidateGroup1 = fixture.nativeElement.querySelector('[data-automation-id="card-arrayitem-chip-mockgroup1"] span');
|
|
||||||
const candidateGroup2 = fixture.nativeElement.querySelector('[data-automation-id="card-arrayitem-chip-mockgroup2"] span');
|
|
||||||
expect(getCandidateGroupsSpy).toHaveBeenCalled();
|
|
||||||
expect(candidateGroup1.innerText).toBe('mockgroup1');
|
|
||||||
expect(candidateGroup2.innerText).toBe('mockgroup2');
|
|
||||||
});
|
|
||||||
}));
|
|
||||||
|
|
||||||
it('should display placeholder if no candidate groups', async(() => {
|
|
||||||
component.ngOnInit();
|
|
||||||
getCandidateGroupsSpy.and.returnValue(of([]));
|
|
||||||
fixture.detectChanges();
|
|
||||||
|
|
||||||
fixture.whenStable().then(() => {
|
|
||||||
const labelValue = fixture.debugElement.query(By.css('[data-automation-id="card-array-label-candidateGroups"]'));
|
|
||||||
const defaultElement = fixture.debugElement.query(By.css('[data-automation-id="card-arrayitem-default"]'));
|
|
||||||
expect(labelValue.nativeElement.innerText).toBe('ADF_CLOUD_TASK_HEADER.PROPERTIES.CANDIDATE_GROUPS');
|
|
||||||
expect(defaultElement.nativeElement.innerText).toBe('ADF_CLOUD_TASK_HEADER.PROPERTIES.CANDIDATE_GROUPS_DEFAULT');
|
|
||||||
});
|
|
||||||
|
|
||||||
}));
|
|
||||||
|
|
||||||
describe('Config Filtering', () => {
|
|
||||||
|
|
||||||
it('should show only the properties from the configuration file', async(() => {
|
|
||||||
spyOn(appConfigService, 'get').and.returnValue(['assignee', 'status']);
|
|
||||||
component.ngOnInit();
|
|
||||||
fixture.detectChanges();
|
|
||||||
const propertyList = fixture.debugElement.queryAll(By.css('.adf-property-list .adf-property'));
|
|
||||||
|
|
||||||
fixture.whenStable().then(() => {
|
fixture.whenStable().then(() => {
|
||||||
expect(propertyList).toBeDefined();
|
const formNameEl = fixture.debugElement.query(By.css('[data-automation-id="card-textitem-value-assignee"] span'));
|
||||||
expect(propertyList).not.toBeNull();
|
expect(formNameEl.nativeElement.innerText).toBe('AssignedTaskUser');
|
||||||
expect(propertyList.length).toBe(2);
|
|
||||||
expect(propertyList[0].nativeElement.textContent).toContain('ADF_CLOUD_TASK_HEADER.PROPERTIES.ASSIGNEE');
|
|
||||||
expect(propertyList[1].nativeElement.textContent).toContain('ADF_CLOUD_TASK_HEADER.PROPERTIES.STATUS');
|
|
||||||
});
|
});
|
||||||
}));
|
}));
|
||||||
|
|
||||||
it('should show all the default properties if there is no configuration', async(() => {
|
it('should display placeholder if no assignee', async(() => {
|
||||||
spyOn(appConfigService, 'get').and.returnValue(null);
|
component.taskDetails.assignee = null;
|
||||||
component.ngOnInit();
|
component.refreshData();
|
||||||
fixture.detectChanges();
|
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
|
|
||||||
fixture.whenStable().then(() => {
|
fixture.whenStable().then(() => {
|
||||||
const propertyList = fixture.debugElement.queryAll(By.css('.adf-property-list .adf-property'));
|
const valueEl = fixture.debugElement.query(By.css('[data-automation-id="card-textitem-value-assignee"] span'));
|
||||||
expect(propertyList).toBeDefined();
|
expect(valueEl.nativeElement.innerText).toBe('ADF_CLOUD_TASK_HEADER.PROPERTIES.ASSIGNEE_DEFAULT');
|
||||||
expect(propertyList).not.toBeNull();
|
|
||||||
expect(propertyList.length).toBe(component.properties.length);
|
|
||||||
expect(propertyList[0].nativeElement.textContent).toContain('ADF_CLOUD_TASK_HEADER.PROPERTIES.ASSIGNEE');
|
|
||||||
expect(propertyList[1].nativeElement.textContent).toContain('ADF_CLOUD_TASK_HEADER.PROPERTIES.STATUS');
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
}));
|
||||||
|
|
||||||
|
it('should display priority', async(() => {
|
||||||
|
component.ngOnChanges();
|
||||||
|
fixture.detectChanges();
|
||||||
|
|
||||||
|
fixture.whenStable().then(() => {
|
||||||
|
const formNameEl = fixture.debugElement.query(By.css('[data-automation-id="card-textitem-value-priority"]'));
|
||||||
|
expect(formNameEl.nativeElement.innerText).toBe('5');
|
||||||
|
});
|
||||||
|
}));
|
||||||
|
|
||||||
|
it('should display error if priority is not a number', async(() => {
|
||||||
|
component.ngOnChanges();
|
||||||
|
component.taskDetails.assignee = 'testuser';
|
||||||
|
fixture.detectChanges();
|
||||||
|
|
||||||
|
fixture.whenStable().then(() => {
|
||||||
|
const edit = fixture.debugElement.query(By.css('[data-automation-id="card-textitem-edit-icon-priority"]'));
|
||||||
|
edit.nativeElement.click();
|
||||||
|
fixture.detectChanges();
|
||||||
|
|
||||||
|
const formPriorityEl = fixture.debugElement.query(By.css('[data-automation-id="card-textitem-editinput-priority"]'));
|
||||||
|
formPriorityEl.nativeElement.value = 'stringValue';
|
||||||
|
formPriorityEl.nativeElement.dispatchEvent(new Event('input'));
|
||||||
|
fixture.detectChanges();
|
||||||
|
|
||||||
|
const submitEl = fixture.debugElement.query(By.css('[data-automation-id="card-textitem-update-priority"]'));
|
||||||
|
submitEl.nativeElement.click();
|
||||||
|
fixture.detectChanges();
|
||||||
|
|
||||||
|
const errorMessageEl = fixture.debugElement.query(By.css('[data-automation-id="card-textitem-error-priority"]'));
|
||||||
|
expect(errorMessageEl).not.toBeNull();
|
||||||
|
});
|
||||||
|
}));
|
||||||
|
|
||||||
|
it('should display due date', async(() => {
|
||||||
|
component.ngOnChanges();
|
||||||
|
fixture.detectChanges();
|
||||||
|
|
||||||
|
fixture.whenStable().then(() => {
|
||||||
|
const valueEl = fixture.debugElement.query(By.css('[data-automation-id="header-dueDate"] .adf-property-value'));
|
||||||
|
expect(valueEl.nativeElement.innerText.trim()).toBe('Dec 18, 2018');
|
||||||
|
});
|
||||||
|
}));
|
||||||
|
|
||||||
|
it('should display placeholder if no due date', async(() => {
|
||||||
|
component.taskDetails.dueDate = null;
|
||||||
|
component.refreshData();
|
||||||
|
fixture.detectChanges();
|
||||||
|
|
||||||
|
fixture.whenStable().then(() => {
|
||||||
|
const valueEl = fixture.debugElement.query(By.css('[data-automation-id="header-dueDate"] .adf-property-value'));
|
||||||
|
expect(valueEl.nativeElement.innerText.trim()).toBe('ADF_CLOUD_TASK_HEADER.PROPERTIES.DUE_DATE_DEFAULT');
|
||||||
|
});
|
||||||
|
}));
|
||||||
|
|
||||||
|
it('should display the default parent value if is undefined', async(() => {
|
||||||
|
component.ngOnChanges();
|
||||||
|
component.taskDetails.processInstanceId = null;
|
||||||
|
fixture.detectChanges();
|
||||||
|
|
||||||
|
fixture.whenStable().then(() => {
|
||||||
|
const valueEl = fixture.debugElement.query(By.css('[data-automation-id="header-parentName"] .adf-property-value'));
|
||||||
|
expect(valueEl.nativeElement.innerText.trim()).toEqual('ADF_CLOUD_TASK_HEADER.PROPERTIES.PARENT_NAME_DEFAULT');
|
||||||
|
});
|
||||||
|
}));
|
||||||
|
|
||||||
|
it('should display candidate user', async(() => {
|
||||||
|
component.ngOnChanges();
|
||||||
|
fixture.detectChanges();
|
||||||
|
|
||||||
|
fixture.whenStable().then(() => {
|
||||||
|
const candidateUser1 = fixture.nativeElement.querySelector('[data-automation-id="card-arrayitem-chip-mockuser1"] span');
|
||||||
|
const candidateUser2 = fixture.nativeElement.querySelector('[data-automation-id="card-arrayitem-chip-mockuser2"] span');
|
||||||
|
expect(getCandidateUsersSpy).toHaveBeenCalled();
|
||||||
|
expect(candidateUser1.innerText).toBe('mockuser1');
|
||||||
|
expect(candidateUser2.innerText).toBe('mockuser2');
|
||||||
|
});
|
||||||
|
}));
|
||||||
|
|
||||||
|
it('should display placeholder if no candidate users', async(() => {
|
||||||
|
getCandidateUsersSpy.and.returnValue(of([]));
|
||||||
|
component.refreshData();
|
||||||
|
fixture.detectChanges();
|
||||||
|
|
||||||
|
fixture.whenStable().then(() => {
|
||||||
|
const labelValue = fixture.debugElement.query(By.css('[data-automation-id="card-array-label-candidateUsers"]'));
|
||||||
|
const defaultElement = fixture.debugElement.query(By.css('[data-automation-id="card-arrayitem-default"]'));
|
||||||
|
expect(labelValue.nativeElement.innerText).toBe('ADF_CLOUD_TASK_HEADER.PROPERTIES.CANDIDATE_USERS');
|
||||||
|
expect(defaultElement.nativeElement.innerText).toBe('ADF_CLOUD_TASK_HEADER.PROPERTIES.CANDIDATE_USERS_DEFAULT');
|
||||||
|
});
|
||||||
|
|
||||||
|
}));
|
||||||
|
|
||||||
|
it('should display candidate groups', async(() => {
|
||||||
|
component.ngOnChanges();
|
||||||
|
fixture.detectChanges();
|
||||||
|
|
||||||
|
fixture.whenStable().then(() => {
|
||||||
|
const candidateGroup1 = fixture.nativeElement.querySelector('[data-automation-id="card-arrayitem-chip-mockgroup1"] span');
|
||||||
|
const candidateGroup2 = fixture.nativeElement.querySelector('[data-automation-id="card-arrayitem-chip-mockgroup2"] span');
|
||||||
|
expect(getCandidateGroupsSpy).toHaveBeenCalled();
|
||||||
|
expect(candidateGroup1.innerText).toBe('mockgroup1');
|
||||||
|
expect(candidateGroup2.innerText).toBe('mockgroup2');
|
||||||
|
});
|
||||||
|
}));
|
||||||
|
|
||||||
|
it('should display placeholder if no candidate groups', async(() => {
|
||||||
|
getCandidateGroupsSpy.and.returnValue(of([]));
|
||||||
|
component.refreshData();
|
||||||
|
fixture.detectChanges();
|
||||||
|
|
||||||
|
fixture.whenStable().then(() => {
|
||||||
|
const labelValue = fixture.debugElement.query(By.css('[data-automation-id="card-array-label-candidateGroups"]'));
|
||||||
|
const defaultElement = fixture.debugElement.query(By.css('[data-automation-id="card-arrayitem-default"]'));
|
||||||
|
expect(labelValue.nativeElement.innerText).toBe('ADF_CLOUD_TASK_HEADER.PROPERTIES.CANDIDATE_GROUPS');
|
||||||
|
expect(defaultElement.nativeElement.innerText).toBe('ADF_CLOUD_TASK_HEADER.PROPERTIES.CANDIDATE_GROUPS_DEFAULT');
|
||||||
|
});
|
||||||
|
|
||||||
|
}));
|
||||||
|
|
||||||
|
describe('Config Filtering', () => {
|
||||||
|
|
||||||
|
it('should show only the properties from the configuration file', async(() => {
|
||||||
|
spyOn(appConfigService, 'get').and.returnValue(['assignee', 'status']);
|
||||||
|
component.ngOnChanges();
|
||||||
|
fixture.detectChanges();
|
||||||
|
const propertyList = fixture.debugElement.queryAll(By.css('.adf-property-list .adf-property'));
|
||||||
|
|
||||||
|
fixture.whenStable().then(() => {
|
||||||
|
expect(propertyList).toBeDefined();
|
||||||
|
expect(propertyList).not.toBeNull();
|
||||||
|
expect(propertyList.length).toBe(2);
|
||||||
|
expect(propertyList[0].nativeElement.textContent).toContain('ADF_CLOUD_TASK_HEADER.PROPERTIES.ASSIGNEE');
|
||||||
|
expect(propertyList[1].nativeElement.textContent).toContain('ADF_CLOUD_TASK_HEADER.PROPERTIES.STATUS');
|
||||||
|
});
|
||||||
|
}));
|
||||||
|
|
||||||
|
it('should show all the default properties if there is no configuration', async(() => {
|
||||||
|
spyOn(appConfigService, 'get').and.returnValue(null);
|
||||||
|
component.ngOnChanges();
|
||||||
|
fixture.detectChanges();
|
||||||
|
|
||||||
|
fixture.whenStable().then(() => {
|
||||||
|
const propertyList = fixture.debugElement.queryAll(By.css('.adf-property-list .adf-property'));
|
||||||
|
expect(propertyList).toBeDefined();
|
||||||
|
expect(propertyList).not.toBeNull();
|
||||||
|
expect(propertyList.length).toBe(component.properties.length);
|
||||||
|
expect(propertyList[0].nativeElement.textContent).toContain('ADF_CLOUD_TASK_HEADER.PROPERTIES.ASSIGNEE');
|
||||||
|
expect(propertyList[1].nativeElement.textContent).toContain('ADF_CLOUD_TASK_HEADER.PROPERTIES.STATUS');
|
||||||
|
});
|
||||||
|
}));
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('Task Errors', () => {
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
fixture = TestBed.createComponent(TaskHeaderCloudComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
service = TestBed.get(TaskCloudService);
|
||||||
|
spyOn(service, 'getTaskById').and.returnValue(throwError('Task not found error'));
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should emit an error when getTaskById returns an error', async(() => {
|
||||||
|
const taskErrorSpy = spyOn(component.taskError, 'emit');
|
||||||
|
component.loadTaskDetailsById(component.appName, component.taskId);
|
||||||
|
fixture.detectChanges();
|
||||||
|
expect(taskErrorSpy).toHaveBeenCalledWith('Task not found error');
|
||||||
|
|
||||||
}));
|
}));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { Component, Input, OnInit, EventEmitter, Output, OnDestroy } from '@angular/core';
|
import { Component, Input, EventEmitter, Output, OnDestroy, OnChanges, OnInit } from '@angular/core';
|
||||||
import {
|
import {
|
||||||
CardViewDateItemModel,
|
CardViewDateItemModel,
|
||||||
CardViewItem,
|
CardViewItem,
|
||||||
@ -30,7 +30,7 @@ import {
|
|||||||
import { TaskDetailsCloudModel, TaskStatusEnum } from '../../start-task/models/task-details-cloud.model';
|
import { TaskDetailsCloudModel, TaskStatusEnum } from '../../start-task/models/task-details-cloud.model';
|
||||||
import { Router } from '@angular/router';
|
import { Router } from '@angular/router';
|
||||||
import { TaskCloudService } from '../../services/task-cloud.service';
|
import { TaskCloudService } from '../../services/task-cloud.service';
|
||||||
import { Subject, Observable } from 'rxjs';
|
import { Subject } from 'rxjs';
|
||||||
import { NumericFieldValidator } from '../../../validators/numeric-field.validator';
|
import { NumericFieldValidator } from '../../../validators/numeric-field.validator';
|
||||||
import { takeUntil } from 'rxjs/operators';
|
import { takeUntil } from 'rxjs/operators';
|
||||||
|
|
||||||
@ -39,7 +39,7 @@ import { takeUntil } from 'rxjs/operators';
|
|||||||
templateUrl: './task-header-cloud.component.html',
|
templateUrl: './task-header-cloud.component.html',
|
||||||
styleUrls: ['./task-header-cloud.component.scss']
|
styleUrls: ['./task-header-cloud.component.scss']
|
||||||
})
|
})
|
||||||
export class TaskHeaderCloudComponent implements OnInit, OnDestroy {
|
export class TaskHeaderCloudComponent implements OnInit, OnDestroy, OnChanges {
|
||||||
|
|
||||||
/** (Required) The name of the application. */
|
/** (Required) The name of the application. */
|
||||||
@Input()
|
@Input()
|
||||||
@ -57,6 +57,10 @@ export class TaskHeaderCloudComponent implements OnInit, OnDestroy {
|
|||||||
@Output()
|
@Output()
|
||||||
unclaim: EventEmitter<any> = new EventEmitter<any>();
|
unclaim: EventEmitter<any> = new EventEmitter<any>();
|
||||||
|
|
||||||
|
/** Emitted when the task has not been found. */
|
||||||
|
@Output()
|
||||||
|
taskError: EventEmitter<any> = new EventEmitter<any>();
|
||||||
|
|
||||||
taskDetails: TaskDetailsCloudModel = new TaskDetailsCloudModel();
|
taskDetails: TaskDetailsCloudModel = new TaskDetailsCloudModel();
|
||||||
properties: CardViewItem[];
|
properties: CardViewItem[];
|
||||||
inEdit: boolean = false;
|
inEdit: boolean = false;
|
||||||
@ -79,13 +83,23 @@ export class TaskHeaderCloudComponent implements OnInit, OnDestroy {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
if ((this.appName || this.appName === '') && this.taskId) {
|
this.taskCloudService.dataChangesDetected$
|
||||||
|
.pipe(takeUntil(this.onDestroy$))
|
||||||
|
.subscribe(() => {
|
||||||
this.loadTaskDetailsById(this.appName, this.taskId);
|
this.loadTaskDetailsById(this.appName, this.taskId);
|
||||||
}
|
});
|
||||||
|
|
||||||
this.cardViewUpdateService.itemUpdated$
|
this.cardViewUpdateService.itemUpdated$
|
||||||
.pipe(takeUntil(this.onDestroy$))
|
.pipe(takeUntil(this.onDestroy$))
|
||||||
.subscribe(this.updateTaskDetails.bind(this));
|
.subscribe(this.updateTaskDetails.bind(this)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnChanges() {
|
||||||
|
this.taskDetails = new TaskDetailsCloudModel();
|
||||||
|
if (this.appName && this.taskId) {
|
||||||
|
this.loadTaskDetailsById(this.appName, this.taskId);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
loadTaskDetailsById(appName: string, taskId: string): any {
|
loadTaskDetailsById(appName: string, taskId: string): any {
|
||||||
@ -97,7 +111,8 @@ export class TaskHeaderCloudComponent implements OnInit, OnDestroy {
|
|||||||
} else {
|
} else {
|
||||||
this.refreshData();
|
this.refreshData();
|
||||||
}
|
}
|
||||||
});
|
},
|
||||||
|
(err) => this.taskError.emit(err), () => {});
|
||||||
}
|
}
|
||||||
|
|
||||||
private initDefaultProperties() {
|
private initDefaultProperties() {
|
||||||
@ -202,7 +217,7 @@ export class TaskHeaderCloudComponent implements OnInit, OnDestroy {
|
|||||||
new CardViewArrayItemModel(
|
new CardViewArrayItemModel(
|
||||||
{
|
{
|
||||||
label: 'ADF_CLOUD_TASK_HEADER.PROPERTIES.CANDIDATE_USERS',
|
label: 'ADF_CLOUD_TASK_HEADER.PROPERTIES.CANDIDATE_USERS',
|
||||||
value: this.getCandidateUsers(),
|
value: this.taskCloudService.getCandidateUsers(this.appName, this.taskId),
|
||||||
key: 'candidateUsers',
|
key: 'candidateUsers',
|
||||||
icon: 'person',
|
icon: 'person',
|
||||||
default: this.translationService.instant('ADF_CLOUD_TASK_HEADER.PROPERTIES.CANDIDATE_USERS_DEFAULT'),
|
default: this.translationService.instant('ADF_CLOUD_TASK_HEADER.PROPERTIES.CANDIDATE_USERS_DEFAULT'),
|
||||||
@ -212,7 +227,7 @@ export class TaskHeaderCloudComponent implements OnInit, OnDestroy {
|
|||||||
new CardViewArrayItemModel(
|
new CardViewArrayItemModel(
|
||||||
{
|
{
|
||||||
label: 'ADF_CLOUD_TASK_HEADER.PROPERTIES.CANDIDATE_GROUPS',
|
label: 'ADF_CLOUD_TASK_HEADER.PROPERTIES.CANDIDATE_GROUPS',
|
||||||
value: this.getCandidateGroups(),
|
value: this.taskCloudService.getCandidateGroups(this.appName, this.taskId),
|
||||||
key: 'candidateGroups',
|
key: 'candidateGroups',
|
||||||
icon: 'group',
|
icon: 'group',
|
||||||
default: this.translationService.instant('ADF_CLOUD_TASK_HEADER.PROPERTIES.CANDIDATE_GROUPS_DEFAULT'),
|
default: this.translationService.instant('ADF_CLOUD_TASK_HEADER.PROPERTIES.CANDIDATE_GROUPS_DEFAULT'),
|
||||||
@ -222,14 +237,6 @@ export class TaskHeaderCloudComponent implements OnInit, OnDestroy {
|
|||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
private getCandidateUsers(): Observable<string[]> {
|
|
||||||
return this.taskCloudService.getCandidateUsers(this.appName, this.taskId);
|
|
||||||
}
|
|
||||||
|
|
||||||
private getCandidateGroups(): Observable<string[]> {
|
|
||||||
return this.taskCloudService.getCandidateGroups(this.appName, this.taskId);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Refresh the card data
|
* Refresh the card data
|
||||||
*/
|
*/
|
||||||
@ -275,7 +282,7 @@ export class TaskHeaderCloudComponent implements OnInit, OnDestroy {
|
|||||||
}
|
}
|
||||||
|
|
||||||
isTaskValid(): boolean {
|
isTaskValid(): boolean {
|
||||||
return (this.appName || this.appName === '') && !!this.taskId;
|
return (this.appName) && !!this.taskId;
|
||||||
}
|
}
|
||||||
|
|
||||||
isTaskAssigned(): boolean {
|
isTaskAssigned(): boolean {
|
||||||
|
@ -233,7 +233,7 @@ export class TaskListCloudComponent extends DataTableSchema implements OnChanges
|
|||||||
|
|
||||||
reload() {
|
reload() {
|
||||||
this.requestNode = this.createRequestNode();
|
this.requestNode = this.createRequestNode();
|
||||||
if (this.requestNode.appName || this.requestNode.appName === '') {
|
if (this.requestNode.appName) {
|
||||||
this.load(this.requestNode);
|
this.load(this.requestNode);
|
||||||
} else {
|
} else {
|
||||||
this.rows = [];
|
this.rows = [];
|
||||||
|
@ -41,7 +41,7 @@ export class TaskListCloudService extends BaseCloudService {
|
|||||||
*/
|
*/
|
||||||
getTaskByRequest(requestNode: TaskQueryCloudRequestModel): Observable<any> {
|
getTaskByRequest(requestNode: TaskQueryCloudRequestModel): Observable<any> {
|
||||||
|
|
||||||
if (requestNode.appName || requestNode.appName === '') {
|
if (requestNode.appName) {
|
||||||
const queryUrl = this.buildQueryUrl(requestNode);
|
const queryUrl = this.buildQueryUrl(requestNode);
|
||||||
const queryParams = this.buildQueryParams(requestNode);
|
const queryParams = this.buildQueryParams(requestNode);
|
||||||
const sortingParams = this.buildSortingParam(requestNode.sorting);
|
const sortingParams = this.buildSortingParam(requestNode.sorting);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user