#1259 - checklist task does not appear on tasklist after creation (#1435)

* #1259 - refresh tasklist when checklist is added

* #1259 - updated readme to reflect changes

* #1259 - fixed wrong rebase import
This commit is contained in:
Vito
2017-01-11 06:32:17 -08:00
committed by Maurizio Vitale
parent 6f24ebd6d4
commit 9e0536bca9
11 changed files with 81 additions and 23 deletions

View File

@@ -36,6 +36,7 @@
[state]="taskFilter.filter.state"
[sort]="taskFilter.filter.sort"
[data]="dataTasks"
[landingTaskId]="currentTaskId"
(rowClick)="onTaskRowClick($event)" (onSuccess)="onSuccessTaskList($event)"
#activititasklist></activiti-tasklist>
</div>
@@ -43,6 +44,7 @@
<span><h5>Task Details</h5></span>
<hr>
<activiti-task-details [taskId]="currentTaskId" (formCompleted)="onFormCompleted($event)"
(taskCreated)="onTaskCreated($event)"
#activitidetails></activiti-task-details>
</div>
</div>

View File

@@ -216,6 +216,11 @@ export class ActivitiDemoComponent implements AfterViewInit {
this.currentTaskId = null;
}
onTaskCreated(data: any) {
this.currentTaskId = data.parentTaskId;
this.activititasklist.reload();
}
ngAfterViewInit() {
// workaround for MDL issues with dynamic components
if (componentHandler) {

View File

@@ -218,17 +218,13 @@ platformBrowserDynamic().bootstrapModule(AppModule);
| Name | Description |
| --- | --- |
|`appId`| { appId } The id of the app. |
|`processDefinitionKey`| { processDefinitionKey } The processDefinitionKey of the process. |
|`assignment`| { assignment } The assignment of the process.
Possible values are:
assignee : where the current user is the assignee
candidate: where the current user is a task candidate
group_x: where the task is assigned to a group where the current user is a member of. The groups can be fetched through the profile REST endpoint
no value: where the current user is involved |
|`state`| { state } Define state of the processes. Possible values are: completed, active |
|`sort`| { sort } Define the sort of the processes. Possible values are created-desc, created-asc, due-desc, due-asc |
| `schemaColumn` | { any[] } optional) JSON object that represent the number and the type of the columns that you want show |
|`appId`| { string } The id of the app. |
|`processDefinitionKey`| { string } The processDefinitionKey of the process. |
|`assignment`| { string } The assignment of the process. <ul>Possible values are: <li>assignee : where the current user is the assignee</li> <li>candidate: where the current user is a task candidate </li><li>group_x: where the task is assigned to a group where the current user is a member of.</li> <li>no value: where the current user is involved</li> </ul> |
|`state`| { string } Define state of the processes. Possible values are: completed, active |
|`landingTaskId`| { string } Define which task id should be selected after the reloading. If the task id doesn't exist or nothing is passed it will select the first task |
|`sort`| { string } Define the sort of the processes. Possible values are : created-desc, created-asc, due-desc, due-asc |
| `data` | { DataTableAdapter } (optional) JSON object that represent the number and the type of the columns that you want show |
Example:
@@ -256,6 +252,7 @@ The component shows the details of the task id passed in input
| `formLoaded` | Invoked when form is loaded or reloaded. |
| `formSaved` | Invoked when form is submitted with `Save` or custom outcomes. |
| `formCompleted` | Invoked when form is submitted with `Complete` outcome. |
| `taskCreated` | Invoked when a checklist task is created. |
| `executeOutcome` | Invoked when any outcome is executed, default behaviour can be prevented via `event.preventDefault()` |
| `onError` | Invoked at any error |

View File

@@ -51,7 +51,9 @@ describe('ActivitiChecklist', () => {
}).compileComponents().then(() => {
let translateService = TestBed.get(AlfrescoTranslateService);
spyOn(translateService, 'addTranslationFolder').and.stub();
spyOn(translateService, 'get').and.callFake((key) => { return Observable.of(key); });
spyOn(translateService, 'get').and.callFake((key) => {
return Observable.of(key);
});
fixture = TestBed.createComponent(ActivitiChecklist);
checklistComponent = fixture.componentInstance;
@@ -129,7 +131,7 @@ describe('ActivitiChecklist', () => {
jasmine.Ajax.requests.mostRecent().respondWith({
status: 200,
contentType: 'json',
responseText: {id: 'fake-check-added-id', name: 'fake-check-added-name'}
responseText: { id: 'fake-check-added-id', name: 'fake-check-added-name' }
});
fixture.whenStable().then(() => {
fixture.detectChanges();
@@ -149,7 +151,7 @@ describe('ActivitiChecklist', () => {
jasmine.Ajax.requests.mostRecent().respondWith({
status: 200,
contentType: 'json',
responseText: {data: [{id: 'fake-check-changed-id', name: 'fake-check-changed-name'}]}
responseText: { data: [{ id: 'fake-check-changed-id', name: 'fake-check-changed-name' }] }
});
fixture.whenStable().then(() => {
fixture.detectChanges();
@@ -173,6 +175,25 @@ describe('ActivitiChecklist', () => {
expect(element.querySelector('#checklist-none-message').textContent).toContain('TASK_DETAILS.CHECKLIST.NONE');
});
}));
it('should emit checklist task created event when the checklist is successfully added', (done) => {
checklistComponent.checklistTaskCreated.subscribe((taskAdded: TaskDetailsModel) => {
fixture.detectChanges();
expect(taskAdded.id).toEqual('fake-check-added-id');
expect(taskAdded.name).toEqual('fake-check-added-name');
expect(element.querySelector('#check-fake-check-added-id')).not.toBeNull();
expect(element.querySelector('#check-fake-check-added-id').textContent).toContain('fake-check-added-name');
done();
});
showChecklistDialog.click();
let addButtonDialog = <HTMLElement> element.querySelector('#add-check');
addButtonDialog.click();
jasmine.Ajax.requests.mostRecent().respondWith({
status: 200,
contentType: 'json',
responseText: { id: 'fake-check-added-id', name: 'fake-check-added-name' }
});
});
});
});

View File

@@ -15,11 +15,11 @@
* limitations under the License.
*/
import { Component, Input, OnInit, ViewChild, OnChanges, SimpleChanges } from '@angular/core';
import { Observer, Observable } from 'rxjs/Rx';
import { Component, Input, OnInit, ViewChild, OnChanges, SimpleChanges, EventEmitter, Output } from '@angular/core';
import { AlfrescoTranslateService, LogService } from 'ng2-alfresco-core';
import { ActivitiTaskListService } from './../services/activiti-tasklist.service';
import { TaskDetailsModel } from '../models/task-details.model';
import { Observer, Observable } from 'rxjs/Rx';
declare let dialogPolyfill: any;
@@ -41,6 +41,9 @@ export class ActivitiChecklist implements OnInit, OnChanges {
@Input()
assignee: string;
@Output()
checklistTaskCreated: EventEmitter<TaskDetailsModel> = new EventEmitter<TaskDetailsModel>();
@ViewChild('dialog')
dialog: any;
@@ -116,6 +119,7 @@ export class ActivitiChecklist implements OnInit, OnChanges {
this.activitiTaskList.addTask(newTask).subscribe(
(res: TaskDetailsModel) => {
this.checklist.push(res);
this.checklistTaskCreated.emit(res);
},
(err) => {
this.logService.error(err);

View File

@@ -24,7 +24,7 @@
</div>
<div class="mdl-cell mdl-cell--4-col">
<activiti-checklist [readOnly]="readOnlyForm" [taskId]="taskDetails.id" [assignee]="taskDetails?.assignee?.id"
#activitichecklist></activiti-checklist>
(checklistTaskCreated)="onChecklistTaskCreated($event)" #activitichecklist></activiti-checklist>
</div>
</div>
<div *ngIf="isAssignedToMe()">

View File

@@ -27,6 +27,7 @@ import { ActivitiTaskDetails } from './activiti-task-details.component';
import { ActivitiTaskListService } from './../services/activiti-tasklist.service';
import { ActivitiPeopleService } from './../services/activiti-people.service';
import { taskDetailsMock, taskFormMock, tasksMock, noDataMock } from './../assets/task-details.mock';
import { TaskDetailsModel } from '../models/task-details.model';
describe('ActivitiTaskDetails', () => {
@@ -246,6 +247,13 @@ describe('ActivitiTaskDetails', () => {
expect(closeSpy).toHaveBeenCalled();
});
it('should emit a task created event when checklist task is created', () => {
let emitSpy: jasmine.Spy = spyOn(component.taskCreated, 'emit');
let mockTask = new TaskDetailsModel(taskDetailsMock);
component.onChecklistTaskCreated(mockTask);
expect(emitSpy).toHaveBeenCalled();
});
});
});

View File

@@ -70,6 +70,9 @@ export class ActivitiTaskDetails implements OnInit, OnChanges {
@Output()
formLoaded: EventEmitter<FormModel> = new EventEmitter<FormModel>();
@Output()
taskCreated: EventEmitter<TaskDetailsModel> = new EventEmitter<TaskDetailsModel>();
@Output()
onError: EventEmitter<any> = new EventEmitter<any>();
@@ -224,6 +227,10 @@ export class ActivitiTaskDetails implements OnInit, OnChanges {
this.formLoaded.emit(form);
}
onChecklistTaskCreated(task: TaskDetailsModel) {
this.taskCreated.emit(task);
}
onFormError(error: any) {
this.errorDialog.nativeElement.showModal();
this.onError.emit(error);

View File

@@ -161,7 +161,7 @@ describe('ActivitiTaskList', () => {
});
it('should return a currentId null when the taskList is empty', () => {
component.selectFirst();
component.selectTask(null);
expect(component.getCurrentId()).toBeNull();
});

View File

@@ -49,6 +49,9 @@ export class ActivitiTaskList implements OnInit, OnChanges {
@Input()
name: string;
@Input()
landingTaskId: string;
requestNode: TaskQueryRequestRepresentationModel;
@Input()
@@ -142,7 +145,7 @@ export class ActivitiTaskList implements OnInit, OnChanges {
(response) => {
let instancesRow = this.createDataRow(response);
this.renderInstances(instancesRow);
this.selectFirst();
this.selectTask(requestNode.landingTaskId);
this.onSuccess.emit(response);
}, (error) => {
this.logService.error(error);
@@ -182,16 +185,24 @@ export class ActivitiTaskList implements OnInit, OnChanges {
}
/**
* Select the first instance of a list if present
* Select the task given in input if present
*/
selectFirst() {
selectTask(taskIdToSelect: string) {
if (!this.isListEmpty()) {
this.currentInstanceId = this.data.getRows()[0].getValue('id');
let dataRow = this.data.getRows().find(row => row.getValue('id') === taskIdToSelect);
this.currentInstanceId = dataRow ? dataRow.getValue('id') : this.selectFirst();
} else {
this.currentInstanceId = null;
}
}
/**
* Select the first instance of a list if present
*/
selectFirst() {
return this.data.getRows()[0].getValue('id');
}
/**
* Return the current id
* @returns {string}
@@ -239,7 +250,8 @@ export class ActivitiTaskList implements OnInit, OnChanges {
text: this.name,
assignment: this.assignment,
state: this.state,
sort: this.sort
sort: this.sort,
landingTaskId: this.landingTaskId
};
return new TaskQueryRequestRepresentationModel(requestNode);
}

View File

@@ -116,6 +116,7 @@ export class TaskQueryRequestRepresentationModel {
sort: string;
page: number;
size: number;
landingTaskId: string;
constructor(obj?: any) {
this.appDefinitionId = obj && obj.appDefinitionId || null;
@@ -128,5 +129,6 @@ export class TaskQueryRequestRepresentationModel {
this.sort = obj && obj.sort || null;
this.page = obj && obj.page || 0;
this.size = obj && obj.size || 25;
this.landingTaskId = obj && obj.landingTaskId || '';
}
}