mirror of
https://github.com/Alfresco/alfresco-ng2-components.git
synced 2025-07-24 17:32:15 +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:
committed by
Maurizio Vitale
parent
7d36400dbd
commit
3c1097fb84
@@ -50,7 +50,7 @@ export class ProcessHeaderCloudComponent implements OnChanges {
|
||||
}
|
||||
|
||||
ngOnChanges() {
|
||||
if ((this.appName || this.appName === '') && this.processInstanceId) {
|
||||
if (this.appName && this.processInstanceId) {
|
||||
this.loadProcessInstanceDetails(this.appName, this.processInstanceId);
|
||||
}
|
||||
}
|
||||
|
@@ -45,7 +45,7 @@ export class ProcessHeaderCloudService extends BaseCloudService {
|
||||
* @returns Process instance details
|
||||
*/
|
||||
getProcessInstanceById(appName: string, processInstanceId: string): Observable<ProcessInstanceCloud> {
|
||||
if ((appName || appName === '') && processInstanceId) {
|
||||
if (appName && processInstanceId) {
|
||||
const queryUrl = `${this.getBasePath(appName)}/query/v1/process-instances/${processInstanceId}`;
|
||||
return from(this.alfrescoApiService.getInstance()
|
||||
.oauth2Auth.callCustomApi(queryUrl, 'GET',
|
||||
|
@@ -185,7 +185,7 @@ export class ProcessListCloudComponent extends DataTableSchema implements OnChan
|
||||
|
||||
reload() {
|
||||
this.requestNode = this.createRequestNode();
|
||||
if (this.requestNode.appName || this.requestNode.appName === '') {
|
||||
if (this.requestNode.appName) {
|
||||
this.load(this.requestNode);
|
||||
} else {
|
||||
this.rows = [];
|
||||
|
@@ -39,7 +39,7 @@ export class ProcessListCloudService extends BaseCloudService {
|
||||
* @returns Process information
|
||||
*/
|
||||
getProcessByRequest(requestNode: ProcessQueryCloudRequestModel): Observable<any> {
|
||||
if (requestNode.appName || requestNode.appName === '') {
|
||||
if (requestNode.appName) {
|
||||
const queryUrl = this.buildQueryUrl(requestNode);
|
||||
const queryParams = this.buildQueryParams(requestNode);
|
||||
const sortingParams = this.buildSortingParam(requestNode.sorting);
|
||||
|
@@ -48,7 +48,7 @@ export class StartProcessCloudService extends BaseCloudService {
|
||||
*/
|
||||
getProcessDefinitions(appName: string): Observable<ProcessDefinitionCloud[]> {
|
||||
|
||||
if (appName || appName === '') {
|
||||
if (appName) {
|
||||
const queryUrl = `${this.getBasePath(appName)}/rb/v1/process-definitions`;
|
||||
|
||||
return from(this.alfrescoApiService.getInstance()
|
||||
|
@@ -41,7 +41,7 @@ export class UserPreferenceCloudService extends BaseCloudService implements Pref
|
||||
* @returns List of user preferences
|
||||
*/
|
||||
getPreferences(appName: string): Observable<any> {
|
||||
if (appName || appName === '') {
|
||||
if (appName) {
|
||||
const uri = this.buildPreferenceServiceUri(appName);
|
||||
return from(this.alfrescoApiService.getInstance()
|
||||
.oauth2Auth.callCustomApi(uri, 'GET',
|
||||
@@ -62,7 +62,7 @@ export class UserPreferenceCloudService extends BaseCloudService implements Pref
|
||||
* @returns Observable of user preference
|
||||
*/
|
||||
getPreferenceByKey(appName: string, key: string): Observable<any> {
|
||||
if (appName || appName === '') {
|
||||
if (appName) {
|
||||
const uri = this.buildPreferenceServiceUri(appName) + '/' + `${key}`;
|
||||
return from(
|
||||
this.alfrescoApiService.getInstance()
|
||||
@@ -85,7 +85,7 @@ export class UserPreferenceCloudService extends BaseCloudService implements Pref
|
||||
* @returns Observable of created user preferences
|
||||
*/
|
||||
createPreference(appName: string, key: string, newPreference: any): Observable<any> {
|
||||
if (appName || appName === '') {
|
||||
if (appName) {
|
||||
const uri = this.buildPreferenceServiceUri(appName) + '/' + `${key}`;
|
||||
const requestPayload = JSON.stringify(newPreference);
|
||||
return from(this.alfrescoApiService.getInstance()
|
||||
@@ -121,7 +121,7 @@ export class UserPreferenceCloudService extends BaseCloudService implements Pref
|
||||
* @returns Observable of delete operation status
|
||||
*/
|
||||
deletePreference(appName: string, key: string): Observable<any> {
|
||||
if (appName || appName === '') {
|
||||
if (appName) {
|
||||
const uri = this.buildPreferenceServiceUri(appName) + '/' + `${key}`;
|
||||
return from(this.alfrescoApiService.getInstance()
|
||||
.oauth2Auth.callCustomApi(uri, 'DELETE',
|
||||
|
@@ -68,7 +68,7 @@ export class ClaimTaskDirective implements OnInit {
|
||||
}
|
||||
|
||||
isAppValid(): boolean {
|
||||
return (this.appName && this.appName.length > 0) || (this.appName === '');
|
||||
return (this.appName && this.appName.length > 0);
|
||||
}
|
||||
|
||||
@HostListener('click')
|
||||
|
@@ -65,7 +65,7 @@ export class CompleteTaskDirective implements OnInit {
|
||||
}
|
||||
|
||||
isAppValid(): boolean {
|
||||
return (this.appName && this.appName.length > 0) || (this.appName === '');
|
||||
return (this.appName && this.appName.length > 0);
|
||||
}
|
||||
|
||||
@HostListener('click')
|
||||
|
@@ -66,7 +66,7 @@ export class UnClaimTaskDirective implements OnInit {
|
||||
}
|
||||
|
||||
isAppValid(): boolean {
|
||||
return (this.appName && this.appName.length > 0) || (this.appName === '');
|
||||
return (this.appName && this.appName.length > 0);
|
||||
}
|
||||
|
||||
@HostListener('click')
|
||||
|
@@ -17,7 +17,7 @@
|
||||
|
||||
import { Injectable } from '@angular/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 { TaskDetailsCloudModel, StartTaskCloudResponseModel } from '../start-task/models/task-details-cloud.model';
|
||||
import { BaseCloudService } from '../../services/base-cloud.service';
|
||||
@@ -32,6 +32,9 @@ export class TaskCloudService extends BaseCloudService {
|
||||
accepts = ['application/json'];
|
||||
returnType = Object;
|
||||
|
||||
private dataChangesDetected = new Subject();
|
||||
dataChangesDetected$: Observable<object>;
|
||||
|
||||
constructor(
|
||||
private apiService: AlfrescoApiService,
|
||||
private appConfigService: AppConfigService,
|
||||
@@ -40,6 +43,7 @@ export class TaskCloudService extends BaseCloudService {
|
||||
) {
|
||||
super();
|
||||
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
|
||||
*/
|
||||
completeTask(appName: string, taskId: string): Observable<TaskDetailsCloudModel> {
|
||||
if ((appName || appName === '') && taskId) {
|
||||
if (appName && taskId) {
|
||||
const queryUrl = this.buildCompleteTaskUrl(appName, taskId);
|
||||
const bodyParam = { 'payloadType': 'CompleteTaskPayload' };
|
||||
const pathParams = {}, queryParams = {}, headerParams = {},
|
||||
@@ -116,7 +120,7 @@ export class TaskCloudService extends BaseCloudService {
|
||||
* @returns Details of the claimed task
|
||||
*/
|
||||
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}`;
|
||||
return from(this.apiService.getInstance()
|
||||
.oauth2Auth.callCustomApi(queryUrl, 'POST',
|
||||
@@ -143,7 +147,7 @@ export class TaskCloudService extends BaseCloudService {
|
||||
* @returns Details of the task that was unclaimed
|
||||
*/
|
||||
unclaimTask(appName: string, taskId: string): Observable<TaskDetailsCloudModel> {
|
||||
if ((appName || appName === '') && taskId) {
|
||||
if (appName && taskId) {
|
||||
const queryUrl = `${this.getBasePath(appName)}/rb/v1/tasks/${taskId}/release`;
|
||||
return from(this.apiService.getInstance()
|
||||
.oauth2Auth.callCustomApi(queryUrl, 'POST',
|
||||
@@ -170,7 +174,7 @@ export class TaskCloudService extends BaseCloudService {
|
||||
* @returns Task details
|
||||
*/
|
||||
getTaskById(appName: string, taskId: string): Observable<TaskDetailsCloudModel> {
|
||||
if ((appName || appName === '') && taskId) {
|
||||
if (appName && taskId) {
|
||||
const queryUrl = `${this.getBasePath(appName)}/query/v1/tasks/${taskId}`;
|
||||
return from(this.apiService.getInstance()
|
||||
.oauth2Auth.callCustomApi(queryUrl, 'GET',
|
||||
@@ -180,6 +184,7 @@ export class TaskCloudService extends BaseCloudService {
|
||||
this.returnType, null, null)
|
||||
).pipe(
|
||||
map((res: any) => {
|
||||
this.dataChangesDetected.next();
|
||||
return new TaskDetailsCloudModel(res.entry);
|
||||
}),
|
||||
catchError((err) => this.handleError(err))
|
||||
@@ -224,7 +229,7 @@ export class TaskCloudService extends BaseCloudService {
|
||||
* @returns Updated task details
|
||||
*/
|
||||
updateTask(appName: string, taskId: string, updatePayload: any): Observable<TaskDetailsCloudModel> {
|
||||
if ((appName || appName === '') && taskId) {
|
||||
if (appName && taskId) {
|
||||
|
||||
updatePayload.payloadType = 'UpdateTaskPayload';
|
||||
const queryUrl = `${this.getBasePath(appName)}/rb/v1/tasks/${taskId}`;
|
||||
@@ -253,7 +258,7 @@ export class TaskCloudService extends BaseCloudService {
|
||||
* @returns Candidate users
|
||||
*/
|
||||
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`;
|
||||
return from(this.apiService.getInstance()
|
||||
.oauth2Auth.callCustomApi(queryUrl, 'GET',
|
||||
@@ -280,7 +285,7 @@ export class TaskCloudService extends BaseCloudService {
|
||||
* @returns Candidate groups
|
||||
*/
|
||||
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`;
|
||||
return from(this.apiService.getInstance()
|
||||
.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">
|
||||
<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 { TaskHeaderCloudModule } from '../task-header-cloud.module';
|
||||
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 { RouterTestingModule } from '@angular/router/testing';
|
||||
import { TaskCloudService } from '../../services/task-cloud.service';
|
||||
@@ -35,7 +35,12 @@ describe('TaskHeaderCloudComponent', () => {
|
||||
let getCandidateGroupsSpy: 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 mockCandidateGroups = ['mockgroup1', 'mockgroup2', 'mockgroup3'];
|
||||
|
||||
@@ -48,200 +53,222 @@ describe('TaskHeaderCloudComponent', () => {
|
||||
providers: [IdentityUserService]
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
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);
|
||||
});
|
||||
describe('Task Details', () => {
|
||||
|
||||
it('should render empty component if no task details provided', async(() => {
|
||||
component.appName = undefined;
|
||||
component.taskId = undefined;
|
||||
fixture.detectChanges();
|
||||
expect(fixture.debugElement.children.length).toBe(2);
|
||||
}));
|
||||
|
||||
it('should display assignee', async(() => {
|
||||
component.ngOnInit();
|
||||
fixture.detectChanges();
|
||||
|
||||
fixture.whenStable().then(() => {
|
||||
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');
|
||||
beforeEach(() => {
|
||||
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 display priority', async(() => {
|
||||
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();
|
||||
it('should render empty component if no task details provided', async(() => {
|
||||
component.appName = undefined;
|
||||
component.taskId = undefined;
|
||||
fixture.detectChanges();
|
||||
expect(fixture.debugElement.children.length).toBe(2);
|
||||
}));
|
||||
|
||||
const formPriorityEl = fixture.debugElement.query(By.css('[data-automation-id="card-textitem-editinput-priority"]'));
|
||||
formPriorityEl.nativeElement.value = 'stringValue';
|
||||
formPriorityEl.nativeElement.dispatchEvent(new Event('input'));
|
||||
it('should display assignee', async(() => {
|
||||
component.ngOnChanges();
|
||||
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(() => {
|
||||
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');
|
||||
const formNameEl = fixture.debugElement.query(By.css('[data-automation-id="card-textitem-value-assignee"] span'));
|
||||
expect(formNameEl.nativeElement.innerText).toBe('AssignedTaskUser');
|
||||
});
|
||||
}));
|
||||
|
||||
it('should show all the default properties if there is no configuration', async(() => {
|
||||
spyOn(appConfigService, 'get').and.returnValue(null);
|
||||
component.ngOnInit();
|
||||
fixture.detectChanges();
|
||||
it('should display placeholder if no assignee', async(() => {
|
||||
component.taskDetails.assignee = null;
|
||||
component.refreshData();
|
||||
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');
|
||||
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 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.
|
||||
*/
|
||||
|
||||
import { Component, Input, OnInit, EventEmitter, Output, OnDestroy } from '@angular/core';
|
||||
import { Component, Input, EventEmitter, Output, OnDestroy, OnChanges, OnInit } from '@angular/core';
|
||||
import {
|
||||
CardViewDateItemModel,
|
||||
CardViewItem,
|
||||
@@ -30,7 +30,7 @@ import {
|
||||
import { TaskDetailsCloudModel, TaskStatusEnum } from '../../start-task/models/task-details-cloud.model';
|
||||
import { Router } from '@angular/router';
|
||||
import { TaskCloudService } from '../../services/task-cloud.service';
|
||||
import { Subject, Observable } from 'rxjs';
|
||||
import { Subject } from 'rxjs';
|
||||
import { NumericFieldValidator } from '../../../validators/numeric-field.validator';
|
||||
import { takeUntil } from 'rxjs/operators';
|
||||
|
||||
@@ -39,7 +39,7 @@ import { takeUntil } from 'rxjs/operators';
|
||||
templateUrl: './task-header-cloud.component.html',
|
||||
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. */
|
||||
@Input()
|
||||
@@ -57,6 +57,10 @@ export class TaskHeaderCloudComponent implements OnInit, OnDestroy {
|
||||
@Output()
|
||||
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();
|
||||
properties: CardViewItem[];
|
||||
inEdit: boolean = false;
|
||||
@@ -79,13 +83,23 @@ export class TaskHeaderCloudComponent implements OnInit, OnDestroy {
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
if ((this.appName || this.appName === '') && this.taskId) {
|
||||
this.taskCloudService.dataChangesDetected$
|
||||
.pipe(takeUntil(this.onDestroy$))
|
||||
.subscribe(() => {
|
||||
this.loadTaskDetailsById(this.appName, this.taskId);
|
||||
}
|
||||
});
|
||||
|
||||
this.cardViewUpdateService.itemUpdated$
|
||||
.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 {
|
||||
@@ -97,7 +111,8 @@ export class TaskHeaderCloudComponent implements OnInit, OnDestroy {
|
||||
} else {
|
||||
this.refreshData();
|
||||
}
|
||||
});
|
||||
},
|
||||
(err) => this.taskError.emit(err), () => {});
|
||||
}
|
||||
|
||||
private initDefaultProperties() {
|
||||
@@ -202,7 +217,7 @@ export class TaskHeaderCloudComponent implements OnInit, OnDestroy {
|
||||
new CardViewArrayItemModel(
|
||||
{
|
||||
label: 'ADF_CLOUD_TASK_HEADER.PROPERTIES.CANDIDATE_USERS',
|
||||
value: this.getCandidateUsers(),
|
||||
value: this.taskCloudService.getCandidateUsers(this.appName, this.taskId),
|
||||
key: 'candidateUsers',
|
||||
icon: 'person',
|
||||
default: this.translationService.instant('ADF_CLOUD_TASK_HEADER.PROPERTIES.CANDIDATE_USERS_DEFAULT'),
|
||||
@@ -212,7 +227,7 @@ export class TaskHeaderCloudComponent implements OnInit, OnDestroy {
|
||||
new CardViewArrayItemModel(
|
||||
{
|
||||
label: 'ADF_CLOUD_TASK_HEADER.PROPERTIES.CANDIDATE_GROUPS',
|
||||
value: this.getCandidateGroups(),
|
||||
value: this.taskCloudService.getCandidateGroups(this.appName, this.taskId),
|
||||
key: 'candidateGroups',
|
||||
icon: 'group',
|
||||
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
|
||||
*/
|
||||
@@ -275,7 +282,7 @@ export class TaskHeaderCloudComponent implements OnInit, OnDestroy {
|
||||
}
|
||||
|
||||
isTaskValid(): boolean {
|
||||
return (this.appName || this.appName === '') && !!this.taskId;
|
||||
return (this.appName) && !!this.taskId;
|
||||
}
|
||||
|
||||
isTaskAssigned(): boolean {
|
||||
|
@@ -233,7 +233,7 @@ export class TaskListCloudComponent extends DataTableSchema implements OnChanges
|
||||
|
||||
reload() {
|
||||
this.requestNode = this.createRequestNode();
|
||||
if (this.requestNode.appName || this.requestNode.appName === '') {
|
||||
if (this.requestNode.appName) {
|
||||
this.load(this.requestNode);
|
||||
} else {
|
||||
this.rows = [];
|
||||
|
@@ -41,7 +41,7 @@ export class TaskListCloudService extends BaseCloudService {
|
||||
*/
|
||||
getTaskByRequest(requestNode: TaskQueryCloudRequestModel): Observable<any> {
|
||||
|
||||
if (requestNode.appName || requestNode.appName === '') {
|
||||
if (requestNode.appName) {
|
||||
const queryUrl = this.buildQueryUrl(requestNode);
|
||||
const queryParams = this.buildQueryParams(requestNode);
|
||||
const sortingParams = this.buildSortingParam(requestNode.sorting);
|
||||
|
Reference in New Issue
Block a user