mirror of
https://github.com/Alfresco/alfresco-ng2-components.git
synced 2025-07-31 17:38:48 +00:00
process details improvements (#1408)
* process details improvements - new: redirect to task instead of opening a dialog (Activiti parity) - fixed: task headers for nameless tasks - fixed: cursor style for task list items - new: stub for ng-1 directive api (Activiti stencils) - code cleanup * error handling fixes
This commit is contained in:
@@ -4,8 +4,10 @@
|
||||
<activiti-process-instance-header [processInstance]="processInstanceDetails"></activiti-process-instance-header>
|
||||
<div class="mdl-card mdl-shadow--2dp activiti-process-container">
|
||||
<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"
|
||||
(taskClick)="onTaskClicked($event)">
|
||||
</activiti-process-instance-tasks>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mdl-cell mdl-cell--4-col" data-automation-id="header-status" *ngIf="isRunning()">
|
||||
|
@@ -21,7 +21,7 @@ import { By } from '@angular/platform-browser';
|
||||
import { Observable } from 'rxjs/Rx';
|
||||
|
||||
import { AlfrescoTranslateService, CoreModule } from 'ng2-alfresco-core';
|
||||
import { ActivitiFormModule, FormModel, FormService } from 'ng2-activiti-form';
|
||||
import { ActivitiFormModule, FormService } from 'ng2-activiti-form';
|
||||
import { ActivitiTaskListModule } from 'ng2-activiti-tasklist';
|
||||
|
||||
import { ActivitiProcessInstanceDetails } from './activiti-process-instance-details.component';
|
||||
@@ -139,20 +139,4 @@ describe('ActivitiProcessInstanceDetails', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('events', () => {
|
||||
|
||||
beforeEach(async(() => {
|
||||
component.processInstanceId = '123';
|
||||
fixture.detectChanges();
|
||||
fixture.whenStable();
|
||||
}));
|
||||
|
||||
it('should emit a task form completed event when task form completed', () => {
|
||||
let emitSpy: jasmine.Spy = spyOn(component.taskFormCompleted, 'emit');
|
||||
component.bubbleTaskFormCompleted(new FormModel());
|
||||
expect(emitSpy).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
@@ -17,13 +17,13 @@
|
||||
|
||||
import { Component, Input, ViewChild, Output, EventEmitter, OnChanges, SimpleChanges } from '@angular/core';
|
||||
import { AlfrescoTranslateService, LogService } from 'ng2-alfresco-core';
|
||||
import { TaskDetailsEvent } from 'ng2-activiti-tasklist';
|
||||
|
||||
import { ActivitiProcessService } from './../services/activiti-process.service';
|
||||
import { ActivitiProcessInstanceHeader } from './activiti-process-instance-header.component';
|
||||
import { ActivitiProcessInstanceTasks } from './activiti-process-instance-tasks.component';
|
||||
import { ProcessInstance } from '../models/process-instance.model';
|
||||
|
||||
declare let componentHandler: any;
|
||||
|
||||
@Component({
|
||||
selector: 'activiti-process-instance-details',
|
||||
moduleId: module.id,
|
||||
@@ -51,7 +51,7 @@ export class ActivitiProcessInstanceDetails implements OnChanges {
|
||||
processCancelled: EventEmitter<any> = new EventEmitter<any>();
|
||||
|
||||
@Output()
|
||||
taskFormCompleted: EventEmitter<any> = new EventEmitter<any>();
|
||||
taskClick: EventEmitter<TaskDetailsEvent> = new EventEmitter<TaskDetailsEvent>();
|
||||
|
||||
processInstanceDetails: ProcessInstance;
|
||||
|
||||
@@ -98,10 +98,6 @@ export class ActivitiProcessInstanceDetails implements OnChanges {
|
||||
}
|
||||
}
|
||||
|
||||
bubbleTaskFormCompleted(data: any) {
|
||||
this.taskFormCompleted.emit(data);
|
||||
}
|
||||
|
||||
isRunning(): boolean {
|
||||
return this.processInstanceDetails && !this.processInstanceDetails.ended;
|
||||
}
|
||||
@@ -114,4 +110,9 @@ export class ActivitiProcessInstanceDetails implements OnChanges {
|
||||
this.logService.error(err);
|
||||
});
|
||||
}
|
||||
|
||||
// bubbles (taskClick) event
|
||||
onTaskClicked(event: TaskDetailsEvent) {
|
||||
this.taskClick.emit(event);
|
||||
}
|
||||
}
|
||||
|
@@ -47,3 +47,7 @@
|
||||
display: block;
|
||||
padding: 12px;
|
||||
}
|
||||
|
||||
.process-tasks__task-item {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
@@ -1,6 +1,5 @@
|
||||
<div *ngIf="showRefreshButton" class="process-tasks-refresh" >
|
||||
<button (click)="onRefreshClicked()"
|
||||
class="mdl-button mdl-button--icon mdl-js-button mdl-js-ripple-effect">
|
||||
<button (click)="onRefreshClicked()" class="mdl-button mdl-button--icon mdl-js-button mdl-js-ripple-effect">
|
||||
<i class="material-icons">refresh</i>
|
||||
</button>
|
||||
</div>
|
||||
@@ -12,11 +11,13 @@
|
||||
|
||||
<div class="menu-container" *ngIf="activeTasks?.length > 0" data-automation-id="active-tasks">
|
||||
<ul class='mdl-list'>
|
||||
<li class="mdl-list__item mdl-list__item--two-line" *ngFor="let task of activeTasks">
|
||||
<li class="mdl-list__item mdl-list__item--two-line process-tasks__task-item" *ngFor="let task of activeTasks">
|
||||
<span class="mdl-list__item-primary-content" (click)="clickTask($event, task)">
|
||||
<i class="material-icons mdl-list__item-icon">assignment</i>
|
||||
<span>{{task.name}}</span>
|
||||
<span class="mdl-list__item-sub-title">{{ 'DETAILS.LABELS.TASK_SUBTITLE' | translate:{user: getUserFullName(task.assignee), created: getFormatDate(task.created, 'mediumDate') } }}</span>
|
||||
<span>{{task.name || 'Nameless task'}}</span>
|
||||
<span class="mdl-list__item-sub-title">
|
||||
{{ 'DETAILS.LABELS.TASK_SUBTITLE' | translate:{user: getUserFullName(task.assignee), created: getFormatDate(task.created, 'mediumDate') } }}
|
||||
</span>
|
||||
</span>
|
||||
</li>
|
||||
</ul>
|
||||
@@ -34,12 +35,13 @@
|
||||
<!--IF START TASK COMPLETED -->
|
||||
<div class="menu-container">
|
||||
<ul class='mdl-list'>
|
||||
<li class="mdl-list__item mdl-list__item--two-line">
|
||||
<li class="mdl-list__item mdl-list__item--two-line process-tasks__task-item">
|
||||
<span class="mdl-list__item-primary-content" (click)="clickStartTask($event)">
|
||||
<i class="material-icons mdl-list__item-icon">assignment</i>
|
||||
<span>{{ 'DETAILS.LABELS.START_FORM'|translate }}</span>
|
||||
<span class="mdl-list__item-sub-title">{{ 'DETAILS.LABELS.TASK_SUBTITLE' | translate:{user:
|
||||
getUserFullName(processInstanceDetails.startedBy), created: getFormatDate(processInstanceDetails.started, 'mediumDate') } }}</span>
|
||||
<span class="mdl-list__item-sub-title">
|
||||
{{ 'DETAILS.LABELS.TASK_SUBTITLE' | translate:{user:getUserFullName(processInstanceDetails.startedBy), created: getFormatDate(processInstanceDetails.started, 'mediumDate') } }}
|
||||
</span>
|
||||
</span>
|
||||
</li>
|
||||
</ul>
|
||||
@@ -53,12 +55,13 @@
|
||||
|
||||
<div class="menu-container" *ngIf="completedTasks?.length > 0" data-automation-id="completed-tasks">
|
||||
<ul class='mdl-list'>
|
||||
<li class="mdl-list__item mdl-list__item--two-line" *ngFor="let task of completedTasks">
|
||||
<li class="mdl-list__item mdl-list__item--two-line process-tasks__task-item" *ngFor="let task of completedTasks">
|
||||
<span class="mdl-list__item-primary-content" (click)="clickTask($event, task)">
|
||||
<i class="material-icons mdl-list__item-icon">assignment</i>
|
||||
<span>{{task.name}}</span>
|
||||
<span class="mdl-list__item-sub-title">{{ 'DETAILS.LABELS.TASK_SUBTITLE' | translate:{user:
|
||||
getUserFullName(task.assignee), created: getFormatDate(task.created, 'mediumDate') } }}</span>
|
||||
<span>{{task.name || 'Nameless task'}}</span>
|
||||
<span class="mdl-list__item-sub-title">
|
||||
{{ 'DETAILS.LABELS.TASK_SUBTITLE' | translate:{user:getUserFullName(task.assignee), created: getFormatDate(task.created, 'mediumDate') } }}
|
||||
</span>
|
||||
</span>
|
||||
</li>
|
||||
</ul>
|
||||
@@ -68,16 +71,6 @@
|
||||
{{ 'DETAILS.TASKS.NO_COMPLETED' | translate }}
|
||||
</div>
|
||||
|
||||
<dialog class="mdl-dialog task-details-dialog" #dialog>
|
||||
<h4 class="mdl-dialog__title">{{ 'DETAILS.TASKS.TASK_DETAILS' | translate }}</h4>
|
||||
<div class="mdl-dialog__content form__size">
|
||||
<activiti-task-details [taskId]="selectedTaskId" (formCompleted)="onTaskFormCompleted()" #taskdetails></activiti-task-details>
|
||||
</div>
|
||||
<div class="mdl-dialog__actions">
|
||||
<button type="button" (click)="closeDialog()" class="mdl-button close" data-automation-id="button-task-close">{{ 'DETAILS.TASKS.TASK_CLOSE' | translate }}</button>
|
||||
</div>
|
||||
</dialog>
|
||||
|
||||
<dialog *ngIf="hasStartFormDefined()" class="mdl-dialog task-details-dialog" #startDialog>
|
||||
<h4 class="mdl-dialog__title">{{ 'DETAILS.LABELS.START_FORM'|translate }}</h4>
|
||||
<div class="mdl-dialog__content form__size">
|
||||
|
@@ -158,51 +158,4 @@ describe('ActivitiProcessInstanceTasks', () => {
|
||||
expect(getProcessTasksSpy).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe('task details', () => {
|
||||
|
||||
let closeSpy;
|
||||
|
||||
beforeEach(async(() => {
|
||||
closeSpy = spyOn(component.dialog.nativeElement, 'close');
|
||||
component.processInstanceDetails = exampleProcessInstance;
|
||||
fixture.detectChanges();
|
||||
fixture.whenStable();
|
||||
component.taskdetails = jasmine.createSpyObj('taskdetails', [
|
||||
'loadDetails'
|
||||
]);
|
||||
}));
|
||||
|
||||
it('should display task details dialog when task clicked', () => {
|
||||
let showModalSpy = spyOn(component.dialog.nativeElement, 'showModal');
|
||||
component.clickTask({}, new TaskDetailsModel(taskDetailsMock));
|
||||
expect(showModalSpy).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should close the task details dialog when close button clicked', () => {
|
||||
component.clickTask({}, new TaskDetailsModel(taskDetailsMock));
|
||||
fixture.detectChanges();
|
||||
let closeButton: DebugElement = debugElement.query(By.css('[data-automation-id="button-task-close"]'));
|
||||
closeButton.triggerEventHandler('click', null);
|
||||
expect(closeSpy).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should output event when task form completed', async(() => {
|
||||
let emitSpy = spyOn(component.taskFormCompleted, 'emit');
|
||||
fixture.detectChanges();
|
||||
component.clickTask({}, new TaskDetailsModel(taskDetailsMock));
|
||||
fixture.detectChanges();
|
||||
component.onTaskFormCompleted();
|
||||
expect(emitSpy).toHaveBeenCalled();
|
||||
}));
|
||||
|
||||
it('should close dialog when task form completed', async(() => {
|
||||
component.clickTask({}, new TaskDetailsModel(taskDetailsMock));
|
||||
fixture.detectChanges();
|
||||
component.onTaskFormCompleted();
|
||||
expect(closeSpy).toHaveBeenCalled();
|
||||
}));
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
@@ -20,7 +20,7 @@ import { DatePipe } from '@angular/common';
|
||||
import { Observable, Observer } from 'rxjs/Rx';
|
||||
import { AlfrescoTranslateService, LogService } from 'ng2-alfresco-core';
|
||||
import { ActivitiProcessService } from './../services/activiti-process.service';
|
||||
import { TaskDetailsModel } from 'ng2-activiti-tasklist';
|
||||
import { TaskDetailsModel, TaskDetailsEvent } from 'ng2-activiti-tasklist';
|
||||
import { ProcessInstance } from '../models/process-instance.model';
|
||||
|
||||
declare let componentHandler: any;
|
||||
@@ -40,9 +40,6 @@ export class ActivitiProcessInstanceTasks implements OnInit, OnChanges {
|
||||
@Input()
|
||||
showRefreshButton: boolean = true;
|
||||
|
||||
@Output()
|
||||
taskFormCompleted = new EventEmitter();
|
||||
|
||||
activeTasks: TaskDetailsModel[] = [];
|
||||
completedTasks: TaskDetailsModel[] = [];
|
||||
|
||||
@@ -53,9 +50,6 @@ export class ActivitiProcessInstanceTasks implements OnInit, OnChanges {
|
||||
completedTask$: Observable<TaskDetailsModel>;
|
||||
|
||||
message: string;
|
||||
|
||||
selectedTaskId: string;
|
||||
|
||||
processId: string;
|
||||
|
||||
@ViewChild('dialog')
|
||||
@@ -67,6 +61,9 @@ export class ActivitiProcessInstanceTasks implements OnInit, OnChanges {
|
||||
@ViewChild('taskdetails')
|
||||
taskdetails: any;
|
||||
|
||||
@Output()
|
||||
taskClick: EventEmitter<TaskDetailsEvent> = new EventEmitter<TaskDetailsEvent>();
|
||||
|
||||
constructor(private translate: AlfrescoTranslateService,
|
||||
private activitiProcess: ActivitiProcessService,
|
||||
private logService: LogService) {
|
||||
@@ -94,12 +91,12 @@ export class ActivitiProcessInstanceTasks implements OnInit, OnChanges {
|
||||
}
|
||||
}
|
||||
|
||||
public load(processId: string) {
|
||||
load(processId: string) {
|
||||
this.loadActive(processId);
|
||||
this.loadCompleted(processId);
|
||||
}
|
||||
|
||||
public loadActive(processId: string) {
|
||||
loadActive(processId: string) {
|
||||
this.activeTasks = [];
|
||||
if (processId) {
|
||||
this.activitiProcess.getProcessTasks(processId, null).subscribe(
|
||||
@@ -117,7 +114,7 @@ export class ActivitiProcessInstanceTasks implements OnInit, OnChanges {
|
||||
}
|
||||
}
|
||||
|
||||
public loadCompleted(processId: string) {
|
||||
loadCompleted(processId: string) {
|
||||
this.completedTasks = [];
|
||||
if (processId) {
|
||||
this.activitiProcess.getProcessTasks(processId, 'completed').subscribe(
|
||||
@@ -157,17 +154,17 @@ export class ActivitiProcessInstanceTasks implements OnInit, OnChanges {
|
||||
}
|
||||
}
|
||||
|
||||
public clickTask($event: any, task: TaskDetailsModel) {
|
||||
this.selectedTaskId = task.id;
|
||||
this.showDialog();
|
||||
clickTask($event: any, task: TaskDetailsModel) {
|
||||
let args = new TaskDetailsEvent(task);
|
||||
this.taskClick.emit(args);
|
||||
}
|
||||
|
||||
public clickStartTask() {
|
||||
clickStartTask() {
|
||||
this.processId = this.processInstanceDetails.id;
|
||||
this.showStartDialog();
|
||||
}
|
||||
|
||||
public showStartDialog() {
|
||||
showStartDialog() {
|
||||
if (!this.startDialog.nativeElement.showModal) {
|
||||
dialogPolyfill.registerDialog(this.startDialog.nativeElement);
|
||||
}
|
||||
@@ -177,35 +174,13 @@ export class ActivitiProcessInstanceTasks implements OnInit, OnChanges {
|
||||
}
|
||||
}
|
||||
|
||||
public showDialog() {
|
||||
if (!this.dialog.nativeElement.showModal) {
|
||||
dialogPolyfill.registerDialog(this.dialog.nativeElement);
|
||||
}
|
||||
if (this.dialog) {
|
||||
this.dialog.nativeElement.showModal();
|
||||
}
|
||||
}
|
||||
|
||||
public closeSartDialog() {
|
||||
closeSartDialog() {
|
||||
if (this.startDialog) {
|
||||
this.startDialog.nativeElement.close();
|
||||
}
|
||||
}
|
||||
|
||||
private closeDialog() {
|
||||
if (this.dialog) {
|
||||
this.dialog.nativeElement.close();
|
||||
}
|
||||
this.selectedTaskId = null;
|
||||
}
|
||||
|
||||
public onTaskFormCompleted() {
|
||||
this.closeDialog();
|
||||
this.load(this.processInstanceDetails.id);
|
||||
this.taskFormCompleted.emit(this.processInstanceDetails.id);
|
||||
}
|
||||
|
||||
public onRefreshClicked() {
|
||||
onRefreshClicked() {
|
||||
this.load(this.processInstanceDetails.id);
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user