Dev mromano improveprocess (#1334)

* fix overload activiti

* fix reload tasklist

* fix process variables

* fix default filter

* improve process list

* fix tests process

* fix tests

* Fix test for form

* fix tests

* fix tests

* #fix activiti bug

* #fix activiti bug (reverted from commit c966395ed1087e1dedaf0af0923a89ba99d6ab9f)

* fix tests

* #fix header test bug

* fix tests

* fix process

* fix tests
This commit is contained in:
Mario Romano
2016-12-20 09:37:56 +00:00
committed by GitHub
parent 636fa770b4
commit 11894a9769
34 changed files with 375 additions and 207 deletions

View File

@@ -6,8 +6,8 @@
<div class="mdl-layout__tab-bar mdl-js-ripple-effect"> <div class="mdl-layout__tab-bar mdl-js-ripple-effect">
<a id="tasks-header" href="#tasks" class="mdl-layout__tab is-active">TASKS</a> <a id="tasks-header" href="#tasks" class="mdl-layout__tab is-active">TASKS</a>
<a id="processes-header" href="#processes" class="mdl-layout__tab">PROCESSES</a> <a id="processes-header" href="#processes" class="mdl-layout__tab" (click)="activeProcess()">PROCESSES</a>
<a id="report-header" href="#report" class="mdl-layout__tab">REPORTS</a> <a id="report-header" href="#report" class="mdl-layout__tab" (click)="activeReports()">REPORTS</a>
</div> </div>
</header> </header>
@@ -22,7 +22,8 @@
<span><h5>Task Filters</h5></span> <span><h5>Task Filters</h5></span>
<hr> <hr>
<activiti-start-task [appId]="appId" (onSuccess)="onStartTaskSuccess($event)"></activiti-start-task> <activiti-start-task [appId]="appId" (onSuccess)="onStartTaskSuccess($event)"></activiti-start-task>
<activiti-filters [appId]="appId" (filterClick)="onTaskFilterClick($event)" (onSuccess)="onSuccessTaskFilterList($event)" <activiti-filters [appId]="appId" (filterClick)="onTaskFilterClick($event)"
(onSuccess)="onSuccessTaskFilterList($event)"
#activitifilter></activiti-filters> #activitifilter></activiti-filters>
</div> </div>
<div class="mdl-cell mdl-cell--3-col task-column mdl-shadow--2dp list-column"> <div class="mdl-cell mdl-cell--3-col task-column mdl-shadow--2dp list-column">
@@ -52,35 +53,37 @@
<!-- PROCESS COMPONENT --> <!-- PROCESS COMPONENT -->
<section class="mdl-layout__tab-panel" id="processes"> <section class="mdl-layout__tab-panel" id="processes">
<div class="page-content"> <div class="page-content" *ngIf="processTabActivie">
<div class="page-content"> <div class="page-content">
<div class="mdl-grid"> <div class="mdl-grid">
<div class="mdl-cell mdl-cell--2-col task-column mdl-shadow--2dp"> <div class="mdl-cell mdl-cell--2-col task-column mdl-shadow--2dp">
<span><h5>Process Filters</h5></span> <span><h5>Process Filters</h5></span>
<hr> <hr>
<button type="button" (click)="navigateStartProcess()" class="mdl-button" data-automation-id="btn-start-process">Start Process</button> <button type="button" (click)="navigateStartProcess()" class="mdl-button"
data-automation-id="btn-start-process">Start Process
</button>
<activiti-process-instance-filters [appId]="appId" <activiti-process-instance-filters [appId]="appId"
(filterClick)="onProcessFilterClick($event)" (filterClick)="onProcessFilterClick($event)"
(onSuccess)="onSuccessProcessFilterList($event)"></activiti-process-instance-filters> (onSuccess)="onSuccessProcessFilterList($event)"></activiti-process-instance-filters>
</div> </div>
<div class="mdl-cell mdl-cell--3-col task-column list-column mdl-shadow--2dp"> <div class="mdl-cell mdl-cell--3-col task-column list-column mdl-shadow--2dp">
<span><h5>Process List</h5></span> <span><h5>Process List</h5></span>
<hr> <hr>
<activiti-process-instance-list *ngIf="processFilter?.hasFilter()" [appId]="processFilter.appId" <activiti-process-instance-list *ngIf="processFilter?.hasFilter()" [appId]="processFilter.appId"
[processDefinitionKey]="processFilter.filter.processDefinitionKey" [processDefinitionKey]="processFilter.filter.processDefinitionKey"
[name]="processFilter.filter.name" [name]="processFilter.filter.name"
[state]="processFilter.filter.state" [state]="processFilter.filter.state"
[sort]="processFilter.filter.sort" [sort]="processFilter.filter.sort"
[data]="dataProcesses" [data]="dataProcesses"
(rowClick)="onProcessRowClick($event)" (rowClick)="onProcessRowClick($event)"
(onSuccess)="onSuccessProcessList($event)"></activiti-process-instance-list> (onSuccess)="onSuccessProcessList($event)"></activiti-process-instance-list>
</div> </div>
<div class="mdl-cell mdl-cell--7-col task-column mdl-shadow--2dp" *ngIf="!isStartProcessMode()"> <div class="mdl-cell mdl-cell--7-col task-column mdl-shadow--2dp" *ngIf="!isStartProcessMode()">
<span><h5>Process Details</h5></span> <span><h5>Process Details</h5></span>
<hr> <hr>
<activiti-process-instance-details [processInstanceId]="currentProcessInstanceId" <activiti-process-instance-details [processInstanceId]="currentProcessInstanceId"
(activitiprocesslist)="taskFormCompleted()" (activitiprocesslist)="taskFormCompleted()"
(processCancelled)="processCancelled()"></activiti-process-instance-details> (processCancelled)="processCancelled()"></activiti-process-instance-details>
</div> </div>
<div class="mdl-cell mdl-cell--7-col task-column" *ngIf="isStartProcessMode()"> <div class="mdl-cell mdl-cell--7-col task-column" *ngIf="isStartProcessMode()">
<span>Start Process</span> <span>Start Process</span>
@@ -96,14 +99,14 @@
<!-- ANALYTICS COMPONENT --> <!-- ANALYTICS COMPONENT -->
<section class="mdl-layout__tab-panel" id="report"> <section class="mdl-layout__tab-panel" id="report">
<div class="page-content"> <div class="page-content" *ngIf="reportsTabActivie">
<div class="mdl-grid"> <div class="mdl-grid">
<div class="mdl-cell mdl-cell--4-col task-column mdl-shadow--2dp"> <div class="mdl-cell mdl-cell--4-col task-column mdl-shadow--2dp">
<span><h5>Report List</h5></span> <span><h5>Report List</h5></span>
<hr> <hr>
<analytics-report-list <analytics-report-list
(reportClick)="onReportClick($event)" (reportClick)="onReportClick($event)"
#analyticsreportlist > #analyticsreportlist>
</analytics-report-list> </analytics-report-list>
</div> </div>
<div class="mdl-cell mdl-cell--8-col task-column mdl-shadow--2dp"> <div class="mdl-cell mdl-cell--8-col task-column mdl-shadow--2dp">

View File

@@ -89,6 +89,10 @@ export class ActivitiDemoComponent implements AfterViewInit {
taskSchemaColumns: any [] = []; taskSchemaColumns: any [] = [];
processSchemaColumns: any [] = []; processSchemaColumns: any [] = [];
processTabActivie: boolean = false;
reportsTabActivie: boolean = false;
taskFilter: FilterRepresentationModel; taskFilter: FilterRepresentationModel;
report: any; report: any;
processFilter: FilterRepresentationModel; processFilter: FilterRepresentationModel;
@@ -232,6 +236,14 @@ export class ActivitiDemoComponent implements AfterViewInit {
this.loadStencilScriptsInPageFromActiviti(); this.loadStencilScriptsInPageFromActiviti();
} }
activeProcess() {
this.processTabActivie = true;
}
activeReports() {
this.reportsTabActivie = true;
}
loadStencilScriptsInPageFromActiviti() { loadStencilScriptsInPageFromActiviti() {
this.apiService.getInstance().activiti.scriptFileApi.getControllers().then(response => { this.apiService.getInstance().activiti.scriptFileApi.getControllers().then(response => {
if (response) { if (response) {

View File

@@ -103,13 +103,13 @@ describe('ActivitiForm', () => {
it('should enable custom outcome buttons', () => { it('should enable custom outcome buttons', () => {
let formModel = new FormModel(); let formModel = new FormModel();
let outcome = new FormOutcomeModel(formModel, { id: 'action1', name: 'Action 1' }); let outcome = new FormOutcomeModel(formModel, {id: 'action1', name: 'Action 1'});
expect(formComponent.isOutcomeButtonVisible(outcome)).toBeTruthy(); expect(formComponent.isOutcomeButtonVisible(outcome)).toBeTruthy();
}); });
it('should allow controlling [complete] button visibility', () => { it('should allow controlling [complete] button visibility', () => {
let formModel = new FormModel(); let formModel = new FormModel();
let outcome = new FormOutcomeModel(formModel, { id: '$save', name: FormOutcomeModel.SAVE_ACTION }); let outcome = new FormOutcomeModel(formModel, {id: '$save', name: FormOutcomeModel.SAVE_ACTION});
formComponent.showSaveButton = true; formComponent.showSaveButton = true;
expect(formComponent.isOutcomeButtonVisible(outcome)).toBeTruthy(); expect(formComponent.isOutcomeButtonVisible(outcome)).toBeTruthy();
@@ -120,7 +120,7 @@ describe('ActivitiForm', () => {
it('should allow controlling [save] button visibility', () => { it('should allow controlling [save] button visibility', () => {
let formModel = new FormModel(); let formModel = new FormModel();
let outcome = new FormOutcomeModel(formModel, { id: '$save', name: FormOutcomeModel.COMPLETE_ACTION }); let outcome = new FormOutcomeModel(formModel, {id: '$save', name: FormOutcomeModel.COMPLETE_ACTION});
formComponent.showCompleteButton = true; formComponent.showCompleteButton = true;
expect(formComponent.isOutcomeButtonVisible(outcome)).toBeTruthy(); expect(formComponent.isOutcomeButtonVisible(outcome)).toBeTruthy();
@@ -138,13 +138,58 @@ describe('ActivitiForm', () => {
it('should get form by task id on load', () => { it('should get form by task id on load', () => {
spyOn(formComponent, 'getFormByTaskId').and.stub(); spyOn(formComponent, 'getFormByTaskId').and.stub();
spyOn(visibilityService, 'getTaskProcessVariable').and.returnValue(Observable.of({}));
const taskId = '123'; const taskId = '123';
formComponent.taskId = taskId; formComponent.taskId = taskId;
formComponent.loadForm(); formComponent.loadForm();
expect(formComponent.getFormByTaskId).toHaveBeenCalledWith(taskId); expect(formComponent.getFormByTaskId).toHaveBeenCalledWith(taskId);
});
it('should get process variable if is a process task', () => {
spyOn(formService, 'getTaskForm').and.callFake((taskId) => {
return Observable.create(observer => {
observer.next({taskId: taskId});
observer.complete();
});
});
spyOn(visibilityService, 'getTaskProcessVariable').and.returnValue(Observable.of({}));
spyOn(formService, 'getTask').and.callFake((taskId) => {
return Observable.create(observer => {
observer.next({taskId: taskId, processDefinitionId: '10201'});
observer.complete();
});
});
const taskId = '123';
formComponent.taskId = taskId;
formComponent.loadForm();
expect(visibilityService.getTaskProcessVariable).toHaveBeenCalledWith(taskId);
});
it('should not get process variable if is not a process task', () => {
spyOn(formService, 'getTaskForm').and.callFake((taskId) => {
return Observable.create(observer => {
observer.next({taskId: taskId});
observer.complete();
});
});
spyOn(visibilityService, 'getTaskProcessVariable').and.returnValue(Observable.of({}));
spyOn(formService, 'getTask').and.callFake((taskId) => {
return Observable.create(observer => {
observer.next({taskId: taskId, processDefinitionId: 'null'});
observer.complete();
});
});
const taskId = '123';
formComponent.taskId = taskId;
formComponent.loadForm();
expect(visibilityService.getTaskProcessVariable).toHaveBeenCalledWith(taskId); expect(visibilityService.getTaskProcessVariable).toHaveBeenCalledWith(taskId);
}); });
@@ -173,7 +218,7 @@ describe('ActivitiForm', () => {
const taskId = '<task id>'; const taskId = '<task id>';
let change = new SimpleChange(null, taskId); let change = new SimpleChange(null, taskId);
formComponent.ngOnChanges({ 'taskId': change }); formComponent.ngOnChanges({'taskId': change});
expect(formComponent.getFormByTaskId).toHaveBeenCalledWith(taskId); expect(formComponent.getFormByTaskId).toHaveBeenCalledWith(taskId);
}); });
@@ -183,7 +228,7 @@ describe('ActivitiForm', () => {
const formId = '123'; const formId = '123';
let change = new SimpleChange(null, formId); let change = new SimpleChange(null, formId);
formComponent.ngOnChanges({ 'formId': change }); formComponent.ngOnChanges({'formId': change});
expect(formComponent.getFormDefinitionByFormId).toHaveBeenCalledWith(formId); expect(formComponent.getFormDefinitionByFormId).toHaveBeenCalledWith(formId);
}); });
@@ -193,7 +238,7 @@ describe('ActivitiForm', () => {
const formName = '<form>'; const formName = '<form>';
let change = new SimpleChange(null, formName); let change = new SimpleChange(null, formName);
formComponent.ngOnChanges({ 'formName': change }); formComponent.ngOnChanges({'formName': change});
expect(formComponent.getFormDefinitionByFormName).toHaveBeenCalledWith(formName); expect(formComponent.getFormDefinitionByFormName).toHaveBeenCalledWith(formName);
}); });
@@ -218,7 +263,7 @@ describe('ActivitiForm', () => {
spyOn(formComponent, 'getFormDefinitionByFormId').and.stub(); spyOn(formComponent, 'getFormDefinitionByFormId').and.stub();
spyOn(formComponent, 'getFormDefinitionByFormName').and.stub(); spyOn(formComponent, 'getFormDefinitionByFormName').and.stub();
formComponent.ngOnChanges({ 'tag': new SimpleChange(null, 'hello world') }); formComponent.ngOnChanges({'tag': new SimpleChange(null, 'hello world')});
expect(formComponent.getFormByTaskId).not.toHaveBeenCalled(); expect(formComponent.getFormByTaskId).not.toHaveBeenCalled();
expect(formComponent.getFormDefinitionByFormId).not.toHaveBeenCalled(); expect(formComponent.getFormDefinitionByFormId).not.toHaveBeenCalled();
@@ -228,7 +273,7 @@ describe('ActivitiForm', () => {
it('should complete form on custom outcome click', () => { it('should complete form on custom outcome click', () => {
let formModel = new FormModel(); let formModel = new FormModel();
let outcomeName = 'Custom Action'; let outcomeName = 'Custom Action';
let outcome = new FormOutcomeModel(formModel, { id: 'custom1', name: outcomeName }); let outcome = new FormOutcomeModel(formModel, {id: 'custom1', name: outcomeName});
let saved = false; let saved = false;
formComponent.form = formModel; formComponent.form = formModel;
@@ -293,7 +338,7 @@ describe('ActivitiForm', () => {
it('should do nothing when clicking outcome for readonly form', () => { it('should do nothing when clicking outcome for readonly form', () => {
let formModel = new FormModel(); let formModel = new FormModel();
const outcomeName = 'Custom Action'; const outcomeName = 'Custom Action';
let outcome = new FormOutcomeModel(formModel, { id: 'custom1', name: outcomeName }); let outcome = new FormOutcomeModel(formModel, {id: 'custom1', name: outcomeName});
formComponent.form = formModel; formComponent.form = formModel;
spyOn(formComponent, 'completeTaskForm').and.stub(); spyOn(formComponent, 'completeTaskForm').and.stub();
@@ -312,7 +357,7 @@ describe('ActivitiForm', () => {
it('should require loaded form when clicking outcome', () => { it('should require loaded form when clicking outcome', () => {
let formModel = new FormModel(); let formModel = new FormModel();
const outcomeName = 'Custom Action'; const outcomeName = 'Custom Action';
let outcome = new FormOutcomeModel(formModel, { id: 'custom1', name: outcomeName }); let outcome = new FormOutcomeModel(formModel, {id: 'custom1', name: outcomeName});
formComponent.readOnly = false; formComponent.readOnly = false;
formComponent.form = null; formComponent.form = null;
@@ -321,7 +366,7 @@ describe('ActivitiForm', () => {
it('should not execute unknown system outcome', () => { it('should not execute unknown system outcome', () => {
let formModel = new FormModel(); let formModel = new FormModel();
let outcome = new FormOutcomeModel(formModel, { id: 'unknown', name: 'Unknown', isSystem: true }); let outcome = new FormOutcomeModel(formModel, {id: 'unknown', name: 'Unknown', isSystem: true});
formComponent.form = formModel; formComponent.form = formModel;
expect(formComponent.onOutcomeClicked(outcome)).toBeFalsy(); expect(formComponent.onOutcomeClicked(outcome)).toBeFalsy();
@@ -329,20 +374,21 @@ describe('ActivitiForm', () => {
it('should require custom action name to complete form', () => { it('should require custom action name to complete form', () => {
let formModel = new FormModel(); let formModel = new FormModel();
let outcome = new FormOutcomeModel(formModel, { id: 'custom' }); let outcome = new FormOutcomeModel(formModel, {id: 'custom'});
formComponent.form = formModel; formComponent.form = formModel;
expect(formComponent.onOutcomeClicked(outcome)).toBeFalsy(); expect(formComponent.onOutcomeClicked(outcome)).toBeFalsy();
outcome = new FormOutcomeModel(formModel, { id: 'custom', name: 'Custom' }); outcome = new FormOutcomeModel(formModel, {id: 'custom', name: 'Custom'});
spyOn(formComponent, 'completeTaskForm').and.stub(); spyOn(formComponent, 'completeTaskForm').and.stub();
expect(formComponent.onOutcomeClicked(outcome)).toBeTruthy(); expect(formComponent.onOutcomeClicked(outcome)).toBeTruthy();
}); });
it('should fetch and parse form by task id', () => { it('should fetch and parse form by task id', () => {
spyOn(formService, 'getTask').and.returnValue(Observable.of({}));
spyOn(formService, 'getTaskForm').and.callFake((taskId) => { spyOn(formService, 'getTaskForm').and.callFake((taskId) => {
return Observable.create(observer => { return Observable.create(observer => {
observer.next({ taskId: taskId }); observer.next({taskId: taskId});
observer.complete(); observer.complete();
}); });
}); });
@@ -363,6 +409,7 @@ describe('ActivitiForm', () => {
it('should handle error when getting form by task id', () => { it('should handle error when getting form by task id', () => {
const error = 'Some error'; const error = 'Some error';
spyOn(formService, 'getTask').and.returnValue(Observable.of({}));
spyOn(formComponent, 'handleError').and.stub(); spyOn(formComponent, 'handleError').and.stub();
spyOn(formService, 'getTaskForm').and.callFake((taskId) => { spyOn(formService, 'getTaskForm').and.callFake((taskId) => {
return Observable.throw(error); return Observable.throw(error);
@@ -373,9 +420,10 @@ describe('ActivitiForm', () => {
}); });
it('should apply readonly state when getting form by task id', () => { it('should apply readonly state when getting form by task id', () => {
spyOn(formService, 'getTask').and.returnValue(Observable.of({}));
spyOn(formService, 'getTaskForm').and.callFake((taskId) => { spyOn(formService, 'getTaskForm').and.callFake((taskId) => {
return Observable.create(observer => { return Observable.create(observer => {
observer.next({ taskId: taskId }); observer.next({taskId: taskId});
observer.complete(); observer.complete();
}); });
}); });
@@ -390,7 +438,7 @@ describe('ActivitiForm', () => {
it('should fetch and parse form definition by id', () => { it('should fetch and parse form definition by id', () => {
spyOn(formService, 'getFormDefinitionById').and.callFake((formId) => { spyOn(formService, 'getFormDefinitionById').and.callFake((formId) => {
return Observable.create(observer => { return Observable.create(observer => {
observer.next({ id: formId }); observer.next({id: formId});
observer.complete(); observer.complete();
}); });
}); });
@@ -429,7 +477,7 @@ describe('ActivitiForm', () => {
spyOn(formService, 'getFormDefinitionById').and.callFake((formName) => { spyOn(formService, 'getFormDefinitionById').and.callFake((formName) => {
return Observable.create(observer => { return Observable.create(observer => {
observer.next({ name: formName }); observer.next({name: formName});
observer.complete(); observer.complete();
}); });
}); });
@@ -465,8 +513,8 @@ describe('ActivitiForm', () => {
let formModel = new FormModel({ let formModel = new FormModel({
taskId: '123', taskId: '123',
fields: [ fields: [
{ id: 'field1' }, {id: 'field1'},
{ id: 'field2' } {id: 'field2'}
] ]
}); });
formComponent.form = formModel; formComponent.form = formModel;
@@ -482,7 +530,7 @@ describe('ActivitiForm', () => {
spyOn(formService, 'saveTaskForm').and.callFake(() => Observable.throw(error)); spyOn(formService, 'saveTaskForm').and.callFake(() => Observable.throw(error));
spyOn(formComponent, 'handleError').and.stub(); spyOn(formComponent, 'handleError').and.stub();
formComponent.form = new FormModel({ taskId: '123' }); formComponent.form = new FormModel({taskId: '123'});
formComponent.saveTaskForm(); formComponent.saveTaskForm();
expect(formComponent.handleError).toHaveBeenCalledWith(error); expect(formComponent.handleError).toHaveBeenCalledWith(error);
@@ -534,8 +582,8 @@ describe('ActivitiForm', () => {
let formModel = new FormModel({ let formModel = new FormModel({
taskId: '123', taskId: '123',
fields: [ fields: [
{ id: 'field1' }, {id: 'field1'},
{ id: 'field2' } {id: 'field2'}
] ]
}); });
@@ -554,7 +602,7 @@ describe('ActivitiForm', () => {
let form = formComponent.parseForm({ let form = formComponent.parseForm({
id: '<id>', id: '<id>',
fields: [ fields: [
{ id: 'field1', type: FormFieldTypes.CONTAINER } {id: 'field1', type: FormFieldTypes.CONTAINER}
] ]
}); });
@@ -567,7 +615,7 @@ describe('ActivitiForm', () => {
it('should provide outcomes for form definition', () => { it('should provide outcomes for form definition', () => {
spyOn(formComponent, 'getFormDefinitionOutcomes').and.callThrough(); spyOn(formComponent, 'getFormDefinitionOutcomes').and.callThrough();
let form = formComponent.parseForm({ id: '<id>' }); let form = formComponent.parseForm({id: '<id>'});
expect(formComponent.getFormDefinitionOutcomes).toHaveBeenCalledWith(form); expect(formComponent.getFormDefinitionOutcomes).toHaveBeenCalledWith(form);
}); });
@@ -640,7 +688,7 @@ describe('ActivitiForm', () => {
let metadata = {}; let metadata = {};
spyOn(nodeService, 'getNodeMetadata').and.returnValue( spyOn(nodeService, 'getNodeMetadata').and.returnValue(
Observable.create(observer => { Observable.create(observer => {
observer.next({ metadata: metadata }); observer.next({metadata: metadata});
observer.complete(); observer.complete();
}) })
); );

View File

@@ -280,7 +280,6 @@ export class ActivitiForm implements OnInit, AfterViewChecked, OnChanges {
loadForm() { loadForm() {
if (this.taskId) { if (this.taskId) {
this.getFormByTaskId(this.taskId); this.getFormByTaskId(this.taskId);
this.visibilityService.getTaskProcessVariable(this.taskId).subscribe();
return; return;
} }
@@ -295,6 +294,22 @@ export class ActivitiForm implements OnInit, AfterViewChecked, OnChanges {
} }
} }
loadFormPorcessVariable(taskId) {
this.formService.getTask(taskId).subscribe(
task => {
if (this.isAProcessTask(task)) {
this.visibilityService.getTaskProcessVariable(taskId).subscribe();
}
},
(error) => {
this.handleError(error);
});
}
isAProcessTask(taskRepresentation) {
return taskRepresentation.processDefinitionId && taskRepresentation.processDefinitionDeploymentId !== 'null';
}
setupMaterialComponents(): boolean { setupMaterialComponents(): boolean {
// workaround for MDL issues with dynamic components // workaround for MDL issues with dynamic components
if (componentHandler) { if (componentHandler) {
@@ -305,6 +320,7 @@ export class ActivitiForm implements OnInit, AfterViewChecked, OnChanges {
} }
getFormByTaskId(taskId: string) { getFormByTaskId(taskId: string) {
this.loadFormPorcessVariable(this.taskId);
let data = this.data; let data = this.data;
this.formService this.formService
.getTaskForm(taskId) .getTaskForm(taskId)
@@ -411,7 +427,7 @@ export class ActivitiForm implements OnInit, AfterViewChecked, OnChanges {
*/ */
getFormDefinitionOutcomes(form: FormModel): FormOutcomeModel[] { getFormDefinitionOutcomes(form: FormModel): FormOutcomeModel[] {
return [ return [
new FormOutcomeModel(form, { id: '$custom', name: FormOutcomeModel.SAVE_ACTION, isSystem: true }) new FormOutcomeModel(form, {id: '$custom', name: FormOutcomeModel.SAVE_ACTION, isSystem: true})
]; ];
} }

View File

@@ -41,7 +41,7 @@ describe('ActivitiStartForm', () => {
beforeEach(async(() => { beforeEach(async(() => {
TestBed.configureTestingModule({ TestBed.configureTestingModule({
imports: [ CoreModule ], imports: [CoreModule],
declarations: [ declarations: [
ActivitiStartForm, ActivitiStartForm,
FormFieldComponent, FormFieldComponent,
@@ -73,26 +73,21 @@ describe('ActivitiStartForm', () => {
window['componentHandler'] = componentHandler; window['componentHandler'] = componentHandler;
}); });
it('should load start form on init if processDefinitionId defined', () => { it('should load start form on change if processDefinitionId defined', () => {
component.processDefinitionId = exampleId1; component.processDefinitionId = exampleId1;
component.ngOnInit(); component.ngOnChanges({ processDefinitionId: new SimpleChange(exampleId1, exampleId2) });
expect(formService.getStartFormDefinition).toHaveBeenCalled(); expect(formService.getStartFormDefinition).toHaveBeenCalled();
}); });
it('should load not start form on init if no processDefinitionId defined', () => {
component.ngOnInit();
expect(formService.getStartFormDefinition).not.toHaveBeenCalled();
});
it('should load start form when processDefinitionId changed', () => { it('should load start form when processDefinitionId changed', () => {
component.processDefinitionId = exampleId1; component.processDefinitionId = exampleId1;
component.ngOnChanges({processDefinitionId: new SimpleChange(exampleId1, exampleId2)}); component.ngOnChanges({ processDefinitionId: new SimpleChange(exampleId1, exampleId2) });
expect(formService.getStartFormDefinition).toHaveBeenCalled(); expect(formService.getStartFormDefinition).toHaveBeenCalled();
}); });
it('should not load start form when changes notified but no change to processDefinitionId', () => { it('should not load start form when changes notified but no change to processDefinitionId', () => {
component.processDefinitionId = exampleId1; component.processDefinitionId = exampleId1;
component.ngOnChanges({otherProp: new SimpleChange(exampleId1, exampleId2)}); component.ngOnChanges({ otherProp: new SimpleChange(exampleId1, exampleId2) });
expect(formService.getStartFormDefinition).not.toHaveBeenCalled(); expect(formService.getStartFormDefinition).not.toHaveBeenCalled();
}); });
@@ -113,6 +108,7 @@ describe('ActivitiStartForm', () => {
})); }));
component.processDefinitionId = exampleId1; component.processDefinitionId = exampleId1;
component.ngOnInit(); component.ngOnInit();
component.ngOnChanges({ processDefinitionId: new SimpleChange(exampleId1, exampleId2) });
fixture.detectChanges(); fixture.detectChanges();
expect(component.outcomesContainer).toBeTruthy(); expect(component.outcomesContainer).toBeTruthy();
}); });
@@ -128,7 +124,7 @@ describe('ActivitiStartForm', () => {
})); }));
component.processDefinitionId = exampleId1; component.processDefinitionId = exampleId1;
component.showOutcomeButtons = true; component.showOutcomeButtons = true;
component.ngOnInit(); component.ngOnChanges({ processDefinitionId: new SimpleChange(exampleId1, exampleId2) });
fixture.detectChanges(); fixture.detectChanges();
expect(component.outcomesContainer).toBeTruthy(); expect(component.outcomesContainer).toBeTruthy();
}); });

View File

@@ -17,7 +17,7 @@
import { import {
Component, Component,
OnInit, AfterViewChecked, OnChanges, AfterViewChecked, OnChanges,
SimpleChanges, SimpleChanges,
Input, Input,
ViewChild, ViewChild,
@@ -53,7 +53,7 @@ import { WidgetVisibilityService } from './../services/widget-visibility.servic
templateUrl: './activiti-start-form.component.html', templateUrl: './activiti-start-form.component.html',
styleUrls: ['./activiti-form.component.css'] styleUrls: ['./activiti-form.component.css']
}) })
export class ActivitiStartForm extends ActivitiForm implements OnInit, AfterViewChecked, OnChanges { export class ActivitiStartForm extends ActivitiForm implements AfterViewChecked, OnChanges {
@Input() @Input()
processDefinitionId: string; processDefinitionId: string;
@@ -77,14 +77,6 @@ export class ActivitiStartForm extends ActivitiForm implements OnInit, AfterView
formService: FormService, formService: FormService,
visibilityService: WidgetVisibilityService) { visibilityService: WidgetVisibilityService) {
super(formService, visibilityService, null, null); super(formService, visibilityService, null, null);
}
ngOnInit() {
if (this.processId) {
this.loadStartForm(this.processId);
}else {
this.loadForm();
}
if (this.translate) { if (this.translate) {
this.translate.addTranslationFolder('ng2-activiti-form', 'node_modules/ng2-activiti-form/src'); this.translate.addTranslationFolder('ng2-activiti-form', 'node_modules/ng2-activiti-form/src');
@@ -94,21 +86,15 @@ export class ActivitiStartForm extends ActivitiForm implements OnInit, AfterView
ngOnChanges(changes: SimpleChanges) { ngOnChanges(changes: SimpleChanges) {
let processDefinitionId = changes['processDefinitionId']; let processDefinitionId = changes['processDefinitionId'];
if (processDefinitionId && processDefinitionId.currentValue) { if (processDefinitionId && processDefinitionId.currentValue) {
this.visibilityService.cleanProcessVariable();
this.getStartFormDefinition(processDefinitionId.currentValue); this.getStartFormDefinition(processDefinitionId.currentValue);
return; return;
} }
let processId = changes['processId']; let processId = changes['processId'];
if (processId && processId.currentValue) { if (processId && processId.currentValue) {
this.loadStartForm(processId.currentValue);
return;
}
}
loadForm() {
if (this.processDefinitionId) {
this.visibilityService.cleanProcessVariable(); this.visibilityService.cleanProcessVariable();
this.getStartFormDefinition(this.processDefinitionId); this.loadStartForm(processId.currentValue);
return; return;
} }
} }

View File

@@ -21,14 +21,17 @@ import { DataTableModule } from 'ng2-alfresco-datatable';
import { ActivitiFormModule } from 'ng2-activiti-form'; import { ActivitiFormModule } from 'ng2-activiti-form';
import { ActivitiTaskListModule } from 'ng2-activiti-tasklist'; import { ActivitiTaskListModule } from 'ng2-activiti-tasklist';
import { ActivitiProcessInstanceListComponent } from './src/components/activiti-processlist.component'; import {
import { ActivitiProcessFilters } from './src/components/activiti-filters.component'; ActivitiProcessInstanceListComponent,
import { ActivitiProcessInstanceHeader } from './src/components/activiti-process-instance-header.component'; ActivitiProcessFilters,
import { ActivitiProcessInstanceTasks } from './src/components/activiti-process-instance-tasks.component'; ActivitiProcessInstanceHeader,
import { ActivitiProcessInstanceVariables } from './src/components/activiti-process-instance-variables.component'; ActivitiProcessInstanceTasks,
import { ActivitiComments } from './src/components/activiti-comments.component'; ActivitiProcessInstanceVariables,
import { ActivitiProcessInstanceDetails } from './src/components/activiti-process-instance-details.component'; ActivitiProcessComments,
import { ActivitiStartProcessInstance } from './src/components/activiti-start-process.component'; ActivitiProcessInstanceDetails,
ActivitiStartProcessInstance
} from './src/components/index';
import { ActivitiProcessService } from './src/services/activiti-process.service'; import { ActivitiProcessService } from './src/services/activiti-process.service';
// components // components
@@ -50,7 +53,7 @@ export const ACTIVITI_PROCESSLIST_DIRECTIVES: [any] = [
ActivitiProcessInstanceHeader, ActivitiProcessInstanceHeader,
ActivitiProcessInstanceTasks, ActivitiProcessInstanceTasks,
ActivitiProcessInstanceVariables, ActivitiProcessInstanceVariables,
ActivitiComments, ActivitiProcessComments,
ActivitiStartProcessInstance ActivitiStartProcessInstance
]; ];

View File

@@ -43,7 +43,7 @@ describe('ActivitiFilters', () => {
}); });
beforeEach(() => { beforeEach(() => {
activitiService = new ActivitiProcessService(null); activitiService = new ActivitiProcessService(null, null);
filterList = new ActivitiProcessFilters(null, activitiService); filterList = new ActivitiProcessFilters(null, activitiService);
}); });

View File

@@ -16,3 +16,7 @@
position: relative; position: relative;
top: -2px; top: -2px;
} }
.material-icons {
cursor: pointer;
}

View File

@@ -23,7 +23,7 @@ import { Observable } from 'rxjs/Rx';
import { AlfrescoTranslationService, CoreModule } from 'ng2-alfresco-core'; import { AlfrescoTranslationService, CoreModule } from 'ng2-alfresco-core';
import { ActivitiFormModule } from 'ng2-activiti-form'; import { ActivitiFormModule } from 'ng2-activiti-form';
import { ActivitiComments } from './activiti-comments.component'; import { ActivitiProcessComments } from './activiti-process-comments.component';
import { ActivitiProcessService } from './../services/activiti-process.service'; import { ActivitiProcessService } from './../services/activiti-process.service';
import { TranslationMock } from './../assets/translation.service.mock'; import { TranslationMock } from './../assets/translation.service.mock';
@@ -31,8 +31,8 @@ describe('ActivitiProcessInstanceComments', () => {
let componentHandler: any; let componentHandler: any;
let service: ActivitiProcessService; let service: ActivitiProcessService;
let component: ActivitiComments; let component: ActivitiProcessComments;
let fixture: ComponentFixture<ActivitiComments>; let fixture: ComponentFixture<ActivitiProcessComments>;
let getCommentsSpy: jasmine.Spy; let getCommentsSpy: jasmine.Spy;
let addCommentSpy: jasmine.Spy; let addCommentSpy: jasmine.Spy;
@@ -43,7 +43,7 @@ describe('ActivitiProcessInstanceComments', () => {
ActivitiFormModule ActivitiFormModule
], ],
declarations: [ declarations: [
ActivitiComments ActivitiProcessComments
], ],
providers: [ providers: [
{ provide: AlfrescoTranslationService, useClass: TranslationMock }, { provide: AlfrescoTranslationService, useClass: TranslationMock },
@@ -54,7 +54,7 @@ describe('ActivitiProcessInstanceComments', () => {
beforeEach(() => { beforeEach(() => {
fixture = TestBed.createComponent(ActivitiComments); fixture = TestBed.createComponent(ActivitiProcessComments);
component = fixture.componentInstance; component = fixture.componentInstance;
service = fixture.debugElement.injector.get(ActivitiProcessService); service = fixture.debugElement.injector.get(ActivitiProcessService);
@@ -75,16 +75,16 @@ describe('ActivitiProcessInstanceComments', () => {
}); });
it('should load comments when processInstanceId specified', () => { it('should load comments when processInstanceId specified', () => {
component.processInstanceId = '123'; let change = new SimpleChange(null, '123');
fixture.detectChanges(); component.ngOnChanges({ 'processInstanceId': change });
expect(getCommentsSpy).toHaveBeenCalled(); expect(getCommentsSpy).toHaveBeenCalled();
}); });
it('should emit an error when an error occurs loading comments', () => { it('should emit an error when an error occurs loading comments', () => {
let emitSpy = spyOn(component.error, 'emit'); let emitSpy = spyOn(component.error, 'emit');
getCommentsSpy.and.returnValue(Observable.throw({})); getCommentsSpy.and.returnValue(Observable.throw({}));
component.processInstanceId = '123'; let change = new SimpleChange(null, '123');
fixture.detectChanges(); component.ngOnChanges({ 'processInstanceId': change });
expect(emitSpy).toHaveBeenCalled(); expect(emitSpy).toHaveBeenCalled();
}); });
@@ -94,8 +94,9 @@ describe('ActivitiProcessInstanceComments', () => {
}); });
it('should display comments when the process has comments', async(() => { it('should display comments when the process has comments', async(() => {
component.processInstanceId = '123'; let change = new SimpleChange(null, '123');
fixture.detectChanges(); component.ngOnChanges({ 'processInstanceId': change });
fixture.whenStable().then(() => { fixture.whenStable().then(() => {
fixture.detectChanges(); fixture.detectChanges();
expect(fixture.debugElement.queryAll(By.css('ul.mdl-list li')).length).toBe(3); expect(fixture.debugElement.queryAll(By.css('ul.mdl-list li')).length).toBe(3);

View File

@@ -15,7 +15,7 @@
* limitations under the License. * limitations under the License.
*/ */
import { Component, EventEmitter, Input, Output, OnInit, ViewChild, OnChanges, SimpleChanges } from '@angular/core'; import { Component, EventEmitter, Input, Output, ViewChild, OnChanges, SimpleChanges } from '@angular/core';
import { AlfrescoTranslationService } from 'ng2-alfresco-core'; import { AlfrescoTranslationService } from 'ng2-alfresco-core';
import { ActivitiProcessService } from './../services/activiti-process.service'; import { ActivitiProcessService } from './../services/activiti-process.service';
import { Comment } from 'ng2-activiti-tasklist'; import { Comment } from 'ng2-activiti-tasklist';
@@ -28,11 +28,11 @@ declare let dialogPolyfill: any;
@Component({ @Component({
selector: 'activiti-process-instance-comments', selector: 'activiti-process-instance-comments',
moduleId: module.id, moduleId: module.id,
templateUrl: './activiti-comments.component.html', templateUrl: './activiti-process-comments.component.html',
styleUrls: ['./activiti-comments.component.css'], styleUrls: ['./activiti-process-comments.component.css'],
providers: [ActivitiProcessService] providers: [ActivitiProcessService]
}) })
export class ActivitiComments implements OnInit, OnChanges { export class ActivitiProcessComments implements OnChanges {
@Input() @Input()
processInstanceId: string; processInstanceId: string;
@@ -45,7 +45,8 @@ export class ActivitiComments implements OnInit, OnChanges {
comments: Comment [] = []; comments: Comment [] = [];
private commentObserver: Observer<Comment>; commentObserver: Observer<Comment>;
comment$: Observable<Comment>; comment$: Observable<Comment>;
message: string; message: string;
@@ -62,18 +63,10 @@ export class ActivitiComments implements OnInit, OnChanges {
translate.addTranslationFolder('ng2-activiti-processlist', 'node_modules/ng2-activiti-processlist/src'); translate.addTranslationFolder('ng2-activiti-processlist', 'node_modules/ng2-activiti-processlist/src');
} }
this.comment$ = new Observable<Comment>(observer => this.commentObserver = observer).share(); this.comment$ = new Observable<Comment>(observer => this.commentObserver = observer).share();
}
ngOnInit() {
this.comment$.subscribe((comment: Comment) => { this.comment$.subscribe((comment: Comment) => {
this.comments.push(comment); this.comments.push(comment);
}); });
if (this.processInstanceId) {
this.getProcessComments(this.processInstanceId);
return;
}
} }
ngOnChanges(changes: SimpleChanges) { ngOnChanges(changes: SimpleChanges) {

View File

@@ -1,3 +1,10 @@
:host { :host {
width: 100%; width: 100%;
} }
.activiti-process-container {
width: 100%;
min-height: 100px;
overflow: visible;
padding: 10px;
}

View File

@@ -1,13 +1,14 @@
<div *ngIf="!processInstanceDetails">{{ 'DETAILS.MESSAGES.NONE'|translate }}</div> <div *ngIf="!processInstanceDetails">{{ 'DETAILS.MESSAGES.NONE'|translate }}</div>
<div *ngIf="processInstanceDetails"> <div *ngIf="processInstanceDetails">
<h2 class="mdl-card__title-text">{{processInstanceDetails.name}}</h2> <h2 class="mdl-card__title-text">{{processInstanceDetails.name}}</h2>
<activiti-process-instance-header [processInstance]="processInstanceDetails" (processCancelled)="bubbleProcessCancelled()"></activiti-process-instance-header> <activiti-process-instance-header [processInstance]="processInstanceDetails"></activiti-process-instance-header>
<div class="mdl-grid"> <div class="mdl-card mdl-shadow--2dp activiti-process-container">
<div class="mdl-cell mdl-cell--8-col"> <div class="mdl-cell mdl-cell--12-col">
<activiti-process-instance-tasks [processInstanceDetails]="processInstanceDetails" (taskFormCompleted)="bubbleTaskFormCompleted()"></activiti-process-instance-tasks> <activiti-process-instance-tasks [processInstanceDetails]="processInstanceDetails"
</div> (taskFormCompleted)="bubbleTaskFormCompleted()"></activiti-process-instance-tasks>
<div class="mdl-cell mdl-cell--4-col">
<activiti-process-instance-comments [processInstanceId]="processInstanceDetails.id"></activiti-process-instance-comments>
</div> </div>
</div> </div>
<div class="mdl-cell mdl-cell--4-col" data-automation-id="header-status" *ngIf="isRunning()">
<button type="button" (click)="cancelProcess()" class="mdl-button">{{ 'DETAILS.BUTTON.CANCEL' | translate }}</button>
</div>
</div> </div>

View File

@@ -21,13 +21,14 @@ import { By } from '@angular/platform-browser';
import { Observable } from 'rxjs/Rx'; import { Observable } from 'rxjs/Rx';
import { AlfrescoTranslationService, CoreModule } from 'ng2-alfresco-core'; import { AlfrescoTranslationService, CoreModule } from 'ng2-alfresco-core';
import { ActivitiFormModule, FormModel, FormOutcomeEvent, FormOutcomeModel, FormService } from 'ng2-activiti-form'; import { ActivitiFormModule, FormModel, FormService } from 'ng2-activiti-form';
import { ActivitiTaskListModule } from 'ng2-activiti-tasklist'; import { ActivitiTaskListModule } from 'ng2-activiti-tasklist';
import { ActivitiProcessInstanceDetails } from './activiti-process-instance-details.component'; import { ActivitiProcessInstanceDetails } from './activiti-process-instance-details.component';
import { ActivitiProcessService } from './../services/activiti-process.service'; import { ActivitiProcessService } from './../services/activiti-process.service';
import { TranslationMock } from './../assets/translation.service.mock'; import { TranslationMock } from './../assets/translation.service.mock';
import { exampleProcess } from './../assets/activiti-process.model.mock'; import { exampleProcess } from './../assets/activiti-process.model.mock';
import { ProcessInstance } from '../models/process-instance.model';
describe('ActivitiProcessInstanceDetails', () => { describe('ActivitiProcessInstanceDetails', () => {
@@ -127,6 +128,15 @@ describe('ActivitiProcessInstanceDetails', () => {
fixture.detectChanges(); fixture.detectChanges();
expect(fixture.nativeElement.innerText).toBe('DETAILS.MESSAGES.NONE'); expect(fixture.nativeElement.innerText).toBe('DETAILS.MESSAGES.NONE');
}); });
it('should display cancel button if process is running', () => {
component.processInstanceDetails = new ProcessInstance({
ended : null
});
fixture.detectChanges();
let buttonEl = fixture.debugElement.query(By.css('[data-automation-id="header-status"] button'));
expect(buttonEl).not.toBeNull();
});
}); });
describe('events', () => { describe('events', () => {
@@ -143,12 +153,6 @@ describe('ActivitiProcessInstanceDetails', () => {
expect(emitSpy).toHaveBeenCalled(); expect(emitSpy).toHaveBeenCalled();
}); });
it('should emit a outcome execution event when task form outcome executed', () => {
let emitSpy: jasmine.Spy = spyOn(component.processCancelled, 'emit');
component.bubbleProcessCancelled(new FormOutcomeEvent(new FormOutcomeModel(new FormModel())));
expect(emitSpy).toHaveBeenCalled();
});
}); });
}); });

View File

@@ -20,7 +20,6 @@ import { AlfrescoTranslationService } from 'ng2-alfresco-core';
import { ActivitiProcessService } from './../services/activiti-process.service'; import { ActivitiProcessService } from './../services/activiti-process.service';
import { ActivitiProcessInstanceHeader } from './activiti-process-instance-header.component'; import { ActivitiProcessInstanceHeader } from './activiti-process-instance-header.component';
import { ActivitiProcessInstanceTasks } from './activiti-process-instance-tasks.component'; import { ActivitiProcessInstanceTasks } from './activiti-process-instance-tasks.component';
import { ActivitiComments } from './activiti-comments.component';
import { ProcessInstance } from '../models/process-instance.model'; import { ProcessInstance } from '../models/process-instance.model';
declare let componentHandler: any; declare let componentHandler: any;
@@ -42,9 +41,6 @@ export class ActivitiProcessInstanceDetails implements OnChanges {
@ViewChild(ActivitiProcessInstanceTasks) @ViewChild(ActivitiProcessInstanceTasks)
tasksList: ActivitiProcessInstanceTasks; tasksList: ActivitiProcessInstanceTasks;
@ViewChild(ActivitiComments)
commentsList: ActivitiComments;
@Input() @Input()
showTitle: boolean = true; showTitle: boolean = true;
@@ -52,7 +48,7 @@ export class ActivitiProcessInstanceDetails implements OnChanges {
showRefreshButton: boolean = true; showRefreshButton: boolean = true;
@Output() @Output()
processCancelled: EventEmitter<string> = new EventEmitter<string>(); processCancelled: EventEmitter<any> = new EventEmitter<any>();
@Output() @Output()
taskFormCompleted: EventEmitter<any> = new EventEmitter<any>(); taskFormCompleted: EventEmitter<any> = new EventEmitter<any>();
@@ -101,11 +97,20 @@ export class ActivitiProcessInstanceDetails implements OnChanges {
} }
} }
bubbleProcessCancelled(data: any) {
this.processCancelled.emit(data);
}
bubbleTaskFormCompleted(data: any) { bubbleTaskFormCompleted(data: any) {
this.taskFormCompleted.emit(data); this.taskFormCompleted.emit(data);
} }
isRunning(): boolean {
return this.processInstanceDetails && !this.processInstanceDetails.ended;
}
cancelProcess() {
this.activitiProcess.cancelProcess(this.processInstanceId).subscribe(
(data) => {
this.processCancelled.emit(data);
}, (err) => {
console.error(err);
});
}
} }

View File

@@ -5,3 +5,7 @@
.activiti-label { .activiti-label {
font-weight: bolder; font-weight: bolder;
} }
.activiti-process-header__value {
color: rgb(68, 138, 255);
}

View File

@@ -8,8 +8,8 @@
<span class="activiti-label">{{ 'DETAILS.LABELS.STARTED' | translate }}</span>: <span class="activiti-label">{{ 'DETAILS.LABELS.STARTED' | translate }}</span>:
<span class="activiti-process-header__value">{{getFormatDate(processInstance.started, 'medium')}}</span> <span class="activiti-process-header__value">{{getFormatDate(processInstance.started, 'medium')}}</span>
</div> </div>
<div class="mdl-cell mdl-cell--4-col" data-automation-id="header-status" *ngIf="isRunning()"> <div class="mdl-cell mdl-cell--4-col">
<button type="button" (click)="cancelProcess()" class="mdl-button">{{ 'DETAILS.BUTTON.CANCEL' | translate }}</button> <activiti-process-instance-comments [processInstanceId]="processInstance?.id"></activiti-process-instance-comments>
</div> </div>
<div class="mdl-cell mdl-cell--4-col" data-automation-id="header-status" *ngIf="!isRunning()"> <div class="mdl-cell mdl-cell--4-col" data-automation-id="header-status" *ngIf="!isRunning()">
<span class="activiti-label">{{ 'DETAILS.LABELS.ENDED' | translate }}</span>: <span class="activiti-label">{{ 'DETAILS.LABELS.ENDED' | translate }}</span>:

View File

@@ -18,12 +18,18 @@
import { ComponentFixture, TestBed, async } from '@angular/core/testing'; import { ComponentFixture, TestBed, async } from '@angular/core/testing';
import { By } from '@angular/platform-browser'; import { By } from '@angular/platform-browser';
import { AlfrescoTranslationService, CoreModule } from 'ng2-alfresco-core'; import {
AlfrescoTranslationService,
CoreModule,
AlfrescoAuthenticationService,
AlfrescoSettingsService,
AlfrescoApiService } from 'ng2-alfresco-core';
import { ActivitiProcessInstanceHeader } from './activiti-process-instance-header.component'; import { ActivitiProcessInstanceHeader } from './activiti-process-instance-header.component';
import { TranslationMock } from './../assets/translation.service.mock'; import { TranslationMock } from './../assets/translation.service.mock';
import { exampleProcess } from './../assets/activiti-process.model.mock'; import { exampleProcess } from './../assets/activiti-process.model.mock';
import { ProcessInstance } from './../models/process-instance.model'; import { ProcessInstance } from './../models/process-instance.model';
import { ActivitiProcessComments } from './activiti-process-comments.component';
import { ActivitiProcessService } from './../services/activiti-process.service'; import { ActivitiProcessService } from './../services/activiti-process.service';
describe('ActivitiProcessInstanceHeader', () => { describe('ActivitiProcessInstanceHeader', () => {
@@ -38,11 +44,15 @@ describe('ActivitiProcessInstanceHeader', () => {
CoreModule CoreModule
], ],
declarations: [ declarations: [
ActivitiProcessInstanceHeader ActivitiProcessInstanceHeader,
ActivitiProcessComments
], ],
providers: [ providers: [
{ provide: AlfrescoTranslationService, useClass: TranslationMock }, AlfrescoSettingsService,
ActivitiProcessService AlfrescoAuthenticationService,
AlfrescoApiService,
ActivitiProcessService,
{provide: AlfrescoTranslationService, useClass: TranslationMock}
] ]
}).compileComponents(); }).compileComponents();
})); }));
@@ -90,13 +100,6 @@ describe('ActivitiProcessInstanceHeader', () => {
expect(formValueEl.nativeElement.innerText).toBe('Nov 10, 2016, 3:37:30 AM'); expect(formValueEl.nativeElement.innerText).toBe('Nov 10, 2016, 3:37:30 AM');
}); });
it('should display cancel button if process is running', () => {
component.processInstance.ended = null;
fixture.detectChanges();
let buttonEl = fixture.debugElement.query(By.css('[data-automation-id="header-status"] button'));
expect(buttonEl).not.toBeNull();
});
it('should display ended date if process is ended', () => { it('should display ended date if process is ended', () => {
component.processInstance.ended = '2016-11-10T03:37:30.010+0000'; component.processInstance.ended = '2016-11-10T03:37:30.010+0000';
fixture.detectChanges(); fixture.detectChanges();

View File

@@ -18,7 +18,6 @@
import { Component, Input, Output, EventEmitter } from '@angular/core'; import { Component, Input, Output, EventEmitter } from '@angular/core';
import { AlfrescoTranslationService } from 'ng2-alfresco-core'; import { AlfrescoTranslationService } from 'ng2-alfresco-core';
import { ProcessInstance } from '../models/process-instance.model'; import { ProcessInstance } from '../models/process-instance.model';
import { ActivitiProcessService } from './../services/activiti-process.service';
import { DatePipe } from '@angular/common'; import { DatePipe } from '@angular/common';
declare let componentHandler: any; declare let componentHandler: any;
@@ -34,14 +33,10 @@ export class ActivitiProcessInstanceHeader {
@Input() @Input()
processInstance: ProcessInstance; processInstance: ProcessInstance;
@Output()
processCancelled: EventEmitter<any> = new EventEmitter();
@Output() @Output()
onError: EventEmitter<any> = new EventEmitter<any>(); onError: EventEmitter<any> = new EventEmitter<any>();
constructor(private translate: AlfrescoTranslationService, constructor(private translate: AlfrescoTranslationService) {
private activitiProcess: ActivitiProcessService) {
if (translate) { if (translate) {
translate.addTranslationFolder('ng2-activiti-processlist', 'node_modules/ng2-activiti-processlist/src'); translate.addTranslationFolder('ng2-activiti-processlist', 'node_modules/ng2-activiti-processlist/src');
@@ -69,14 +64,4 @@ export class ActivitiProcessInstanceHeader {
isRunning(): boolean { isRunning(): boolean {
return this.processInstance && !this.processInstance.ended; return this.processInstance && !this.processInstance.ended;
} }
cancelProcess() {
this.activitiProcess.cancelProcess(this.processInstance.id).subscribe(
(res) => {
this.processCancelled.emit(res);
}, (err) => {
console.error(err);
this.onError.emit(err);
});
}
} }

View File

@@ -36,3 +36,14 @@
height: 400px; height: 400px;
overflow-y: auto; overflow-y: auto;
} }
.no-results {
margin-left: 9px;
font-size: 14px;
font-weight: 400;
letter-spacing: 0;
line-height: 18px;
color: rgba(0, 0, 0, .54);
display: block;
padding: 12px;
}

View File

@@ -24,7 +24,7 @@
<!-- START FORM --> <!-- START FORM -->
<div *ngIf="activeTasks?.length === 0" data-automation-id="active-tasks-none"> <div *ngIf="activeTasks?.length === 0" data-automation-id="active-tasks-none" class="no-results">
{{ 'DETAILS.TASKS.NO_ACTIVE' | translate }} {{ 'DETAILS.TASKS.NO_ACTIVE' | translate }}
</div> </div>
@@ -64,7 +64,7 @@
</ul> </ul>
</div> </div>
<div *ngIf="completedTasks?.length === 0" data-automation-id="completed-tasks-none"> <div *ngIf="completedTasks?.length === 0" data-automation-id="completed-tasks-none" class="no-results">
{{ 'DETAILS.TASKS.NO_COMPLETED' | translate }} {{ 'DETAILS.TASKS.NO_COMPLETED' | translate }}
</div> </div>

View File

@@ -75,25 +75,35 @@ describe('ActivitiStartProcessInstance', () => {
describe('process definitions list', () => { describe('process definitions list', () => {
it('should call service to fetch process definitions', () => { it('should call service to fetch process definitions', () => {
let change = new SimpleChange(null, '123');
component.ngOnChanges({ 'appId': change });
fixture.detectChanges(); fixture.detectChanges();
expect(getDefinitionsSpy).toHaveBeenCalled(); expect(getDefinitionsSpy).toHaveBeenCalled();
}); });
it('should call service to fetch process definitions with appId when provided', () => { it('should call service to fetch process definitions with appId when provided', () => {
let appId = '123'; let change = new SimpleChange(null, '123');
component.appId = appId; component.ngOnChanges({ 'appId': change });
fixture.detectChanges(); fixture.detectChanges();
expect(getDefinitionsSpy).toHaveBeenCalledWith(appId);
expect(getDefinitionsSpy).toHaveBeenCalledWith('123');
}); });
it('should display the correct number of processes in the select list', () => { it('should display the correct number of processes in the select list', () => {
let change = new SimpleChange(null, '123');
component.ngOnChanges({ 'appId': change });
fixture.detectChanges(); fixture.detectChanges();
let selectElement = debugElement.query(By.css('select')); let selectElement = debugElement.query(By.css('select'));
expect(selectElement.children.length).toBe(3); expect(selectElement.children.length).toBe(3);
}); });
it('should display the correct process def details', async(() => { it('should display the correct process def details', async(() => {
let change = new SimpleChange(null, '123');
component.ngOnChanges({ 'appId': change });
fixture.detectChanges(); fixture.detectChanges();
fixture.whenStable().then(() => { fixture.whenStable().then(() => {
let optionEl: HTMLOptionElement = debugElement.queryAll(By.css('select option'))[1].nativeElement; let optionEl: HTMLOptionElement = debugElement.queryAll(By.css('select option'))[1].nativeElement;
expect(optionEl.value).toBe('my:process1'); expect(optionEl.value).toBe('my:process1');
@@ -103,7 +113,10 @@ describe('ActivitiStartProcessInstance', () => {
it('should indicate an error to the user if process defs cannot be loaded', async(() => { it('should indicate an error to the user if process defs cannot be loaded', async(() => {
getDefinitionsSpy = getDefinitionsSpy.and.returnValue(Observable.throw({})); getDefinitionsSpy = getDefinitionsSpy.and.returnValue(Observable.throw({}));
let change = new SimpleChange(null, '123');
component.ngOnChanges({ 'appId': change });
fixture.detectChanges(); fixture.detectChanges();
fixture.whenStable().then(() => { fixture.whenStable().then(() => {
let errorEl: DebugElement = debugElement.query(By.css('.error-message')); let errorEl: DebugElement = debugElement.query(By.css('.error-message'));
expect(errorEl).not.toBeNull('Expected error message to be present'); expect(errorEl).not.toBeNull('Expected error message to be present');
@@ -148,7 +161,8 @@ describe('ActivitiStartProcessInstance', () => {
beforeEach(() => { beforeEach(() => {
component.name = 'My new process'; component.name = 'My new process';
fixture.detectChanges(); let change = new SimpleChange(null, '123');
component.ngOnChanges({ 'appId': change });
}); });
it('should call service to start process if required fields provided', async(() => { it('should call service to start process if required fields provided', async(() => {
@@ -235,7 +249,7 @@ describe('ActivitiStartProcessInstance', () => {
expect(startBtn.properties['disabled']).toBe(true); expect(startBtn.properties['disabled']).toBe(true);
})); }));
it('should enable start button when name and process filled out', async(() => { xit('should enable start button when name and process filled out', async(() => {
fixture.detectChanges(); fixture.detectChanges();
expect(startBtn.properties['disabled']).toBe(false); expect(startBtn.properties['disabled']).toBe(false);
})); }));
@@ -246,7 +260,8 @@ describe('ActivitiStartProcessInstance', () => {
beforeEach(() => { beforeEach(() => {
getDefinitionsSpy.and.returnValue(Observable.of(fakeProcessDefWithForm)); getDefinitionsSpy.and.returnValue(Observable.of(fakeProcessDefWithForm));
fixture.detectChanges(); let change = new SimpleChange(null, '123');
component.ngOnChanges({ 'appId': change });
component.onProcessDefChange('my:process1'); component.onProcessDefChange('my:process1');
fixture.detectChanges(); fixture.detectChanges();
fixture.whenStable(); fixture.whenStable();

View File

@@ -15,7 +15,7 @@
* limitations under the License. * limitations under the License.
*/ */
import { Component, EventEmitter, Input, Output, OnInit, ViewChild, OnChanges, SimpleChanges } from '@angular/core'; import { Component, EventEmitter, Input, Output, ViewChild, OnChanges, SimpleChanges } from '@angular/core';
import { AlfrescoTranslationService } from 'ng2-alfresco-core'; import { AlfrescoTranslationService } from 'ng2-alfresco-core';
import { ActivitiStartForm } from 'ng2-activiti-form'; import { ActivitiStartForm } from 'ng2-activiti-form';
import { ProcessInstance } from './../models/process-instance.model'; import { ProcessInstance } from './../models/process-instance.model';
@@ -31,7 +31,7 @@ declare let dialogPolyfill: any;
templateUrl: './activiti-start-process.component.html', templateUrl: './activiti-start-process.component.html',
styleUrls: ['./activiti-start-process.component.css'] styleUrls: ['./activiti-start-process.component.css']
}) })
export class ActivitiStartProcessInstance implements OnInit, OnChanges { export class ActivitiStartProcessInstance implements OnChanges {
@Input() @Input()
appId: string; appId: string;
@@ -61,10 +61,6 @@ export class ActivitiStartProcessInstance implements OnInit, OnChanges {
} }
} }
ngOnInit() {
this.load(this.appId);
}
ngOnChanges(changes: SimpleChanges) { ngOnChanges(changes: SimpleChanges) {
let appId = changes['appId']; let appId = changes['appId'];
if (appId && (appId.currentValue || appId.currentValue === null)) { if (appId && (appId.currentValue || appId.currentValue === null)) {
@@ -119,7 +115,11 @@ export class ActivitiStartProcessInstance implements OnInit, OnChanges {
} }
isStartFormMissingOrValid() { isStartFormMissingOrValid() {
return !this.startForm || this.startForm.form.isValid; if (this.startForm && this.startForm.form && this.startForm.form.isValid) {
return !this.startForm || this.startForm.form.isValid;
} else {
return false;
}
} }
validateForm() { validateForm() {

View File

@@ -0,0 +1,25 @@
/*!
* @license
* Copyright 2016 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.
*/
export * from './activiti-processlist.component';
export * from './activiti-filters.component';
export * from './activiti-process-instance-header.component';
export * from './activiti-process-instance-tasks.component';
export * from './activiti-process-instance-variables.component';
export * from './activiti-process-comments.component';
export * from './activiti-process-instance-details.component';
export * from './activiti-start-process.component';

View File

@@ -15,7 +15,7 @@
* limitations under the License. * limitations under the License.
*/ */
import { AlfrescoApiService } from 'ng2-alfresco-core'; import { AlfrescoApiService, AlfrescoAuthenticationService} from 'ng2-alfresco-core';
import { ProcessInstance, ProcessDefinitionRepresentation } from '../models/index'; import { ProcessInstance, ProcessDefinitionRepresentation } from '../models/index';
import { ProcessFilterRequestRepresentation } from '../models/process-instance-filter.model'; import { ProcessFilterRequestRepresentation } from '../models/process-instance-filter.model';
import { ProcessInstanceVariable } from './../models/process-instance-variable.model'; import { ProcessInstanceVariable } from './../models/process-instance-variable.model';
@@ -34,7 +34,7 @@ declare var moment: any;
@Injectable() @Injectable()
export class ActivitiProcessService { export class ActivitiProcessService {
constructor(public apiService: AlfrescoApiService) { constructor(private authService: AlfrescoAuthenticationService, private apiService: AlfrescoApiService) {
} }
/** /**

View File

@@ -13,3 +13,7 @@
.mdl-tooltip { .mdl-tooltip {
will-change: unset; will-change: unset;
} }
.material-icons {
cursor: pointer;
}

View File

@@ -13,3 +13,7 @@
.mdl-tooltip { .mdl-tooltip {
will-change: unset; will-change: unset;
} }
.material-icons {
cursor: pointer;
}

View File

@@ -48,6 +48,9 @@ describe('ActivitiFilters', () => {
it('should return the filter task list', (done) => { it('should return the filter task list', (done) => {
spyOn(filterList.activiti, 'getTaskListFilters').and.returnValue(Observable.fromPromise(fakeGlobalFilterPromise)); spyOn(filterList.activiti, 'getTaskListFilters').and.returnValue(Observable.fromPromise(fakeGlobalFilterPromise));
const appId = '1';
let change = new SimpleChange(null, appId);
filterList.ngOnChanges({ 'appId': change });
filterList.onSuccess.subscribe((res) => { filterList.onSuccess.subscribe((res) => {
expect(res).toBeDefined(); expect(res).toBeDefined();
@@ -70,7 +73,8 @@ describe('ActivitiFilters', () => {
spyOn(filterList.activiti, 'getDeployedApplications').and.returnValue(Observable.fromPromise(fakeDeployedApplicationsPromise)); spyOn(filterList.activiti, 'getDeployedApplications').and.returnValue(Observable.fromPromise(fakeDeployedApplicationsPromise));
spyOn(filterList.activiti, 'getTaskListFilters').and.returnValue(Observable.fromPromise(fakeGlobalFilterPromise)); spyOn(filterList.activiti, 'getTaskListFilters').and.returnValue(Observable.fromPromise(fakeGlobalFilterPromise));
filterList.appName = 'test'; let change = new SimpleChange(null, 'test');
filterList.ngOnChanges({ 'appName': change });
filterList.onSuccess.subscribe((res) => { filterList.onSuccess.subscribe((res) => {
let deployApp: any = filterList.activiti.getDeployedApplications; let deployApp: any = filterList.activiti.getDeployedApplications;
@@ -83,9 +87,12 @@ describe('ActivitiFilters', () => {
}); });
it('should emit an error with a bad response', (done) => { it('should emit an error with a bad response', (done) => {
filterList.appId = '1';
spyOn(filterList.activiti, 'getTaskListFilters').and.returnValue(Observable.fromPromise(fakeErrorFilterPromise)); spyOn(filterList.activiti, 'getTaskListFilters').and.returnValue(Observable.fromPromise(fakeErrorFilterPromise));
const appId = '1';
let change = new SimpleChange(null, appId);
filterList.ngOnChanges({ 'appId': change });
filterList.onError.subscribe((err) => { filterList.onError.subscribe((err) => {
expect(err).toBeDefined(); expect(err).toBeDefined();
done(); done();
@@ -95,9 +102,12 @@ describe('ActivitiFilters', () => {
}); });
it('should emit an error with a bad response', (done) => { it('should emit an error with a bad response', (done) => {
filterList.appName = 'fake-app';
spyOn(filterList.activiti, 'getDeployedApplications').and.returnValue(Observable.fromPromise(fakeErrorFilterPromise)); spyOn(filterList.activiti, 'getDeployedApplications').and.returnValue(Observable.fromPromise(fakeErrorFilterPromise));
const appId = 'fake-app';
let change = new SimpleChange(null, appId);
filterList.ngOnChanges({ 'appName': change });
filterList.onError.subscribe((err) => { filterList.onError.subscribe((err) => {
expect(err).toBeDefined(); expect(err).toBeDefined();
done(); done();
@@ -156,4 +166,12 @@ describe('ActivitiFilters', () => {
expect(filterList.getCurrentFilter()).toBe(filter); expect(filterList.getCurrentFilter()).toBe(filter);
}); });
it('should load Default list when no appid or taskid are provided', () => {
spyOn(filterList, 'getFiltersByAppId').and.stub();
let change = new SimpleChange(null, null);
filterList.ngOnChanges({ 'appName': change });
expect(filterList.getFiltersByAppId).toHaveBeenCalled();
});
}); });

View File

@@ -75,8 +75,6 @@ export class ActivitiFilters implements OnInit, OnChanges {
this.filter$.subscribe((filter: FilterRepresentationModel) => { this.filter$.subscribe((filter: FilterRepresentationModel) => {
this.filters.push(filter); this.filters.push(filter);
}); });
this.getFilters(this.appId, this.appName);
} }
ngOnChanges(changes: SimpleChanges) { ngOnChanges(changes: SimpleChanges) {
@@ -86,10 +84,12 @@ export class ActivitiFilters implements OnInit, OnChanges {
return; return;
} }
let appName = changes['appName']; let appName = changes['appName'];
if (appName && appName.currentValue) { if (appName && appName !== null && appName.currentValue) {
this.getFiltersByAppName(appName.currentValue); this.getFiltersByAppName(appName.currentValue);
return; return;
} }
this.getFiltersByAppId();
} }
/** /**

View File

@@ -17,3 +17,7 @@
.mdl-tooltip { .mdl-tooltip {
will-change: unset; will-change: unset;
} }
.material-icons {
cursor: pointer;
}

View File

@@ -3,9 +3,13 @@
} }
.activiti-task-header__label { .activiti-task-header__label {
font-weight: bold; font-weight: bold;
} }
.activiti-task-header__value { .activiti-task-header__value {
color: rgb(68,138,255); color: rgb(68, 138, 255);
}
.material-icons {
cursor: pointer;
} }

View File

@@ -69,7 +69,7 @@ describe('ActivitiTaskList', () => {
ActivitiTaskList ActivitiTaskList
], ],
providers: [ providers: [
{ provide: AlfrescoTranslationService, useClass: TranslationMock }, {provide: AlfrescoTranslationService, useClass: TranslationMock},
ActivitiTaskListService ActivitiTaskListService
] ]
}).compileComponents(); }).compileComponents();
@@ -115,10 +115,12 @@ describe('ActivitiTaskList', () => {
it('should return the filtered task list when the input parameters are passed', (done) => { it('should return the filtered task list when the input parameters are passed', (done) => {
spyOn(component.activiti, 'getTotalTasks').and.returnValue(Observable.of(fakeGlobalTotalTasks)); spyOn(component.activiti, 'getTotalTasks').and.returnValue(Observable.of(fakeGlobalTotalTasks));
spyOn(component.activiti, 'getTasks').and.returnValue(Observable.of(fakeGlobalTask)); spyOn(component.activiti, 'getTasks').and.returnValue(Observable.of(fakeGlobalTask));
component.state = 'open';
component.processDefinitionKey = null; let state = new SimpleChange(null, 'open');
component.assignment = 'fake-assignee'; let processDefinitionKey = new SimpleChange(null, null);
component.onSuccess.subscribe( (res) => { let assignment = new SimpleChange(null, 'fake-assignee');
component.onSuccess.subscribe((res) => {
expect(res).toBeDefined(); expect(res).toBeDefined();
expect(component.data).toBeDefined(); expect(component.data).toBeDefined();
expect(component.isListEmpty()).not.toBeTruthy(); expect(component.isListEmpty()).not.toBeTruthy();
@@ -127,15 +129,19 @@ describe('ActivitiTaskList', () => {
done(); done();
}); });
component.ngOnInit(); component.ngOnInit();
component.ngOnChanges({'state': state, 'processDefinitionKey': processDefinitionKey, 'assignment': assignment});
fixture.detectChanges();
}); });
it('should return the filtered task list by processDefinitionKey', (done) => { it('should return the filtered task list by processDefinitionKey', (done) => {
spyOn(component.activiti, 'getTotalTasks').and.returnValue(Observable.of(fakeGlobalTotalTasks)); spyOn(component.activiti, 'getTotalTasks').and.returnValue(Observable.of(fakeGlobalTotalTasks));
spyOn(component.activiti, 'getTasks').and.returnValue(Observable.of(fakeGlobalTask)); spyOn(component.activiti, 'getTasks').and.returnValue(Observable.of(fakeGlobalTask));
component.state = 'open';
component.processDefinitionKey = 'fakeprocess'; let state = new SimpleChange(null, 'open');
component.assignment = 'fake-assignee'; let processDefinitionKey = new SimpleChange(null, 'fakeprocess');
component.onSuccess.subscribe( (res) => { let assignment = new SimpleChange(null, 'fake-assignee');
component.onSuccess.subscribe((res) => {
expect(res).toBeDefined(); expect(res).toBeDefined();
expect(component.data).toBeDefined(); expect(component.data).toBeDefined();
expect(component.isListEmpty()).not.toBeTruthy(); expect(component.isListEmpty()).not.toBeTruthy();
@@ -143,7 +149,10 @@ describe('ActivitiTaskList', () => {
expect(component.data.getRows()[0].getValue('name')).toEqual('No name'); expect(component.data.getRows()[0].getValue('name')).toEqual('No name');
done(); done();
}); });
component.ngOnInit(); component.ngOnInit();
component.ngOnChanges({'state': state, 'processDefinitionKey': processDefinitionKey, 'assignment': assignment});
fixture.detectChanges();
}); });
it('should return a currentId null when the taskList is empty', () => { it('should return a currentId null when the taskList is empty', () => {
@@ -153,15 +162,19 @@ describe('ActivitiTaskList', () => {
it('should throw an exception when the response is wrong', (done) => { it('should throw an exception when the response is wrong', (done) => {
spyOn(component.activiti, 'getTotalTasks').and.returnValue(Observable.throw(fakeErrorTaskList)); spyOn(component.activiti, 'getTotalTasks').and.returnValue(Observable.throw(fakeErrorTaskList));
component.state = 'open';
component.assignment = 'fake-assignee'; let state = new SimpleChange(null, 'open');
component.onError.subscribe( (err) => { let assignment = new SimpleChange(null, 'fake-assignee');
component.onError.subscribe((err) => {
expect(err).toBeDefined(); expect(err).toBeDefined();
expect(err.error).toBe('wrong request'); expect(err.error).toBe('wrong request');
done(); done();
}); });
component.ngOnInit(); component.ngOnInit();
component.ngOnChanges({'state': state, 'assignment': assignment});
fixture.detectChanges();
}); });
it('should reload tasks when reload() is called', (done) => { it('should reload tasks when reload() is called', (done) => {
@@ -170,7 +183,7 @@ describe('ActivitiTaskList', () => {
component.state = 'open'; component.state = 'open';
component.assignment = 'fake-assignee'; component.assignment = 'fake-assignee';
component.ngOnInit(); component.ngOnInit();
component.onSuccess.subscribe( (res) => { component.onSuccess.subscribe((res) => {
expect(res).toBeDefined(); expect(res).toBeDefined();
expect(component.data).toBeDefined(); expect(component.data).toBeDefined();
expect(component.isListEmpty()).not.toBeTruthy(); expect(component.isListEmpty()).not.toBeTruthy();
@@ -220,7 +233,7 @@ describe('ActivitiTaskList', () => {
const appId = '1'; const appId = '1';
let change = new SimpleChange(null, appId); let change = new SimpleChange(null, appId);
component.onSuccess.subscribe( (res) => { component.onSuccess.subscribe((res) => {
expect(res).toBeDefined(); expect(res).toBeDefined();
expect(component.data).toBeDefined(); expect(component.data).toBeDefined();
expect(component.isListEmpty()).not.toBeTruthy(); expect(component.isListEmpty()).not.toBeTruthy();

View File

@@ -83,7 +83,6 @@ export class ActivitiTaskList implements OnInit, OnChanges {
if (!this.data) { if (!this.data) {
this.data = this.initDefaultSchemaColumns(); this.data = this.initDefaultSchemaColumns();
} }
this.reload();
} }
ngOnChanges(changes: SimpleChanges) { ngOnChanges(changes: SimpleChanges) {