more control over task details header (#1688)

- toggle task details header
- toggle visibility of involve/comments/checklist
- readme updates
This commit is contained in:
Denys Vuika
2017-03-04 17:29:48 +00:00
committed by Mario Romano
parent 4d8abee892
commit 861393de60
6 changed files with 133 additions and 71 deletions

View File

@@ -41,11 +41,11 @@
#activititasklist></activiti-tasklist> #activititasklist></activiti-tasklist>
</div> </div>
<div class="mdl-cell mdl-cell--7-col task-column mdl-shadow--2dp"> <div class="mdl-cell mdl-cell--7-col task-column mdl-shadow--2dp">
<span><h5>Task Details</h5></span> <activiti-task-details #activitidetails
<hr> [taskId]="currentTaskId"
<activiti-task-details [taskId]="currentTaskId" (formCompleted)="onFormCompleted($event)" (formCompleted)="onFormCompleted($event)"
(taskCreated)="onTaskCreated($event)" (taskCreated)="onTaskCreated($event)">
#activitidetails></activiti-task-details> </activiti-task-details>
</div> </div>
</div> </div>
</div> </div>

View File

@@ -117,8 +117,8 @@ This component renders a list containing all the tasks matched by the parameters
Usage example of this component : Usage example of this component :
**main.ts** **main.ts**
```ts
```ts
import { NgModule, Component } from '@angular/core'; import { NgModule, Component } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser'; import { BrowserModule } from '@angular/platform-browser';
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
@@ -129,34 +129,35 @@ import { ObjectDataTableAdapter, DataSorting } from 'ng2-alfresco-datatable';
@Component({ @Component({
selector: 'alfresco-app-demo', selector: 'alfresco-app-demo',
template: `<activiti-tasklist [appId]="appId" [state]="state" [assignment]="assignment" [data]="dataTasks"></activiti-tasklist>` template: `
<activiti-tasklist
[appId]="appId"
[state]="state"
[assignment]="assignment"
[data]="dataTasks">
</activiti-tasklist>
`
}) })
class MyDemoApp { class MyDemoApp {
dataTasks: ObjectDataTableAdapter; dataTasks: ObjectDataTableAdapter;
appId: string = '1'; appId: string = '1';
assignment: string = 'assignee'; assignment: string = 'assignee';
state: string = 'open'; state: string = 'open';
constructor(private authService: AlfrescoAuthenticationService, private settingsService: AlfrescoSettingsService) { constructor(private authService: AlfrescoAuthenticationService,
private settingsService: AlfrescoSettingsService) {
settingsService.bpmHost = 'http://localhost:9999'; settingsService.bpmHost = 'http://localhost:9999';
this.authService.login('admin', 'admin').subscribe( this.authService.login('admin', 'admin').subscribe(
ticket => { ticket => console.log(ticket),
console.log(ticket); error => console.log(error)
}, );
error => {
console.log(error);
});
this.dataTasks = new ObjectDataTableAdapter([], [ this.dataTasks = new ObjectDataTableAdapter([], [
{type: 'text', key: 'name', title: 'Name', cssClass: 'full-width name-column', sortable: true}, {type: 'text', key: 'name', title: 'Name', cssClass: 'full-width name-column', sortable: true},
{type: 'text', key: 'started', title: 'Started', cssClass: 'hidden', sortable: true} {type: 'text', key: 'started', title: 'Started', cssClass: 'hidden', sortable: true}
] ]);
);
this.dataTasks.setSorting(new DataSorting('started', 'desc')); this.dataTasks.setSorting(new DataSorting('started', 'desc'));
} }
} }
@@ -170,12 +171,9 @@ class MyDemoApp {
declarations: [MyDemoApp], declarations: [MyDemoApp],
bootstrap: [MyDemoApp] bootstrap: [MyDemoApp]
}) })
export class AppModule { export class AppModule {}
}
platformBrowserDynamic().bootstrapModule(AppModule); platformBrowserDynamic().bootstrapModule(AppModule);
``` ```
#### Events #### Events
@@ -216,6 +214,24 @@ The component shows the details of the task id passed in input
<activiti-task-details [taskId]="taskId"></activiti-task-details> <activiti-task-details [taskId]="taskId"></activiti-task-details>
``` ```
#### Properties
| Name | Type | Default | Description |
| --- | --- | --- | --- |
| `taskId` | string | | (**required**) The id of the task details that we are asking for. |
| `showNextTask` | boolean | true | Automatically render the next one, when the task is completed. |
| `showFormTitle` | boolean | true | Toggle rendering of the form title. |
| `readOnlyForm` | boolean | false | Toggle readonly state of the form. Enforces all form widgets render readonly if enabled. |
| `showFormRefreshButton` | true | optional | Toggle rendering of the `Refresh` button. |
| `showFormSaveButton` | true | optional | Toggle rendering of the `Save` outcome button. |
| `showFormCompleteButton` | true | optional | Toggle rendering of the Form `Complete` outcome button |
| `peopleIconImageUrl` | string | | Define a custom people icon image |
| `showHeader` | boolean | true | Toggle task details Header component |
| `showHeaderContent` | boolean | true | Toggle collapsed/expanded state of the Header component |
| `showInvolvePeople` | boolean | true | Toggle `Involve People` feature for Header component |
| `showComments` | boolean | true | Toggle `Comments` feature for Header component |
| `showChecklist` | boolean | true | Toggle `Checklist` feature for Header component |
#### Events #### Events
| Name | Description | | Name | Description |
@@ -227,25 +243,13 @@ The component shows the details of the task id passed in input
| `executeOutcome` | Invoked when any outcome is executed, default behaviour can be prevented via `event.preventDefault()` | | `executeOutcome` | Invoked when any outcome is executed, default behaviour can be prevented via `event.preventDefault()` |
| `onError` | Invoked at any error | | `onError` | Invoked at any error |
#### Options
| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `taskId` | {string} | required | The id of the task details that we are asking for. |
| `showNextTask` | {boolean} | optional | Automatically render the next one, when the task is completed. |
| `showFormTitle` | {boolean} | optional | Toggle rendering of the form title. |
| `readOnlyForm` | {boolean} | optional | Toggle readonly state of the form. Enforces all form widgets render readonly if enabled. |
| `showFormRefreshButton` | {boolean} | optional | Toggle rendering of the `Refresh` button. |
| `showFormSaveButton` | {boolean} | optional | Toggle rendering of the `Save` outcome button. |
| `showFormCompleteButton` | {boolean} | optional | Toggle rendering of the Form `Complete` outcome button |
| `peopleIconImageUrl` | {string} | optional | Define a custom people icon image |
### Custom 'empty Activiti Task Details' template ### Custom 'empty Activiti Task Details' template
By default the Activiti Task Details provides the following message for the empty task details: By default the Activiti Task Details provides the following message for the empty task details:
'No Tasks' ```
No Tasks
```
This can be changed by adding the following custom html template: This can be changed by adding the following custom html template:
@@ -260,6 +264,8 @@ This can be changed by adding the following custom html template:
</activiti-task-details> </activiti-task-details>
``` ```
Note that can put any HTML content as part of the template, includuing other Angualr components.
## Basic usage example Activiti Apps ## Basic usage example Activiti Apps
The component shows all the available apps. The component shows all the available apps.

View File

@@ -21,6 +21,7 @@ import { DataTableModule } from 'ng2-alfresco-datatable';
import { ActivitiFormModule } from 'ng2-activiti-form'; import { ActivitiFormModule } from 'ng2-activiti-form';
import { ActivitiPeopleService } from './src/services/activiti-people.service'; import { ActivitiPeopleService } from './src/services/activiti-people.service';
import { ActivitiTaskListService } from './src/services/activiti-tasklist.service'; import { ActivitiTaskListService } from './src/services/activiti-tasklist.service';
import { MaterialModule } from '@angular/material';
import { import {
ActivitiApps, ActivitiApps,
@@ -63,7 +64,8 @@ export const ACTIVITI_TASKLIST_PROVIDERS: any[] = [
imports: [ imports: [
CoreModule, CoreModule,
DataTableModule, DataTableModule,
ActivitiFormModule ActivitiFormModule,
MaterialModule
], ],
declarations: [ declarations: [
...ACTIVITI_TASKLIST_DIRECTIVES ...ACTIVITI_TASKLIST_DIRECTIVES

View File

@@ -5,3 +5,22 @@
.error-dialog h3 { .error-dialog h3 {
margin: 16px 0; margin: 16px 0;
} }
.activiti-task-details__header {
align-self: flex-end;
display: flex;
font-size: 24px;
font-weight: 300;
line-height: normal;
overflow: hidden;
margin: 0;
cursor: pointer;
user-select: none;
-moz-user-select: none;
-webkit-user-select: none;
-ms-user-select: none;
}
.activiti-task-details__action-button {
text-transform: uppercase;
}

View File

@@ -1,6 +1,5 @@
<div *ngIf="!taskDetails"> <div *ngIf="!taskDetails">
<template *ngIf="noTaskDetailsTemplateComponent" ngFor [ngForOf]="[data]" <template *ngIf="noTaskDetailsTemplateComponent" ngFor [ngForOf]="[data]" [ngForTemplate]="noTaskDetailsTemplateComponent">
[ngForTemplate]="noTaskDetailsTemplateComponent">
{{ 'TASK_DETAILS.MESSAGES.NONE' | translate }} {{ 'TASK_DETAILS.MESSAGES.NONE' | translate }}
</template> </template>
<div *ngIf="!noTaskDetailsTemplateComponent"> <div *ngIf="!noTaskDetailsTemplateComponent">
@@ -8,44 +7,61 @@
</div> </div>
</div> </div>
<div *ngIf="taskDetails"> <div *ngIf="taskDetails">
<h2 class="mdl-card__title-text">{{taskDetails.name}}</h2> <div *ngIf="showHeader">
<activiti-task-header <h2 class="activiti-task-details__header" (click)="toggleHeaderContent()">
<md-icon *ngIf="!showHeaderContent">expand_more</md-icon>
<md-icon *ngIf="showHeaderContent">expand_less</md-icon>
<span>{{taskDetails.name || 'No name'}}</span>
</h2>
<activiti-task-header *ngIf="showHeaderContent"
[taskDetails]="taskDetails" [taskDetails]="taskDetails"
[formName]="taskFormName" [formName]="taskFormName"
(claim)="onClaimTask($event)"></activiti-task-header> (claim)="onClaimTask($event)">
<div class="mdl-grid"> </activiti-task-header>
<div class="mdl-cell mdl-cell--4-col"> <div *ngIf="showHeaderContent" class="mdl-grid">
<activiti-people [iconImageUrl]="peopleIconImageUrl" [people]="taskPeople" [readOnly]="readOnlyForm" <div *ngIf="showInvolvePeople" class="mdl-cell mdl-cell--4-col">
[taskId]="taskDetails.id"></activiti-people> <activiti-people
</div> [iconImageUrl]="peopleIconImageUrl"
<div class="mdl-cell mdl-cell--4-col"> [people]="taskPeople"
<activiti-comments [readOnly]="readOnlyForm" [taskId]="taskDetails.id" [readOnly]="readOnlyForm"
#activiticomments></activiti-comments> [taskId]="taskDetails.id">
</div> </activiti-people>
<div class="mdl-cell mdl-cell--4-col"> </div>
<activiti-checklist [readOnly]="readOnlyForm" [taskId]="taskDetails.id" [assignee]="taskDetails?.assignee?.id" <div *ngIf="showComments" class="mdl-cell mdl-cell--4-col">
(checklistTaskCreated)="onChecklistTaskCreated($event)" #activitichecklist></activiti-checklist> <activiti-comments #activiticomments
[readOnly]="readOnlyForm"
[taskId]="taskDetails.id">
</activiti-comments>
</div>
<div *ngIf="showChecklist" class="mdl-cell mdl-cell--4-col">
<activiti-checklist #activitichecklist
[readOnly]="readOnlyForm"
[taskId]="taskDetails.id"
[assignee]="taskDetails?.assignee?.id"
(checklistTaskCreated)="onChecklistTaskCreated($event)">
</activiti-checklist>
</div>
</div> </div>
</div> </div>
<div *ngIf="isAssignedToMe()"> <div *ngIf="isAssignedToMe()">
<activiti-form *ngIf="hasFormKey()" [taskId]="taskDetails.id" <activiti-form *ngIf="hasFormKey()" #activitiForm
[showTitle]="showFormTitle" [taskId]="taskDetails.id"
[showRefreshButton]="showFormRefreshButton" [showTitle]="showFormTitle"
[showCompleteButton]="showFormCompleteButton" [showRefreshButton]="showFormRefreshButton"
[showSaveButton]="showFormSaveButton" [showCompleteButton]="showFormCompleteButton"
[readOnly]="readOnlyForm" [showSaveButton]="showFormSaveButton"
(formSaved)='onFormSaved($event)' [readOnly]="readOnlyForm"
(formCompleted)='onFormCompleted($event)' (formSaved)='onFormSaved($event)'
(formLoaded)='onFormLoaded($event)' (formCompleted)='onFormCompleted($event)'
(onError)='onFormError($event)' (formLoaded)='onFormLoaded($event)'
(executeOutcome)='onFormExecuteOutcome($event)' (onError)='onFormError($event)'
#activitiForm> (executeOutcome)='onFormExecuteOutcome($event)'>
</activiti-form> </activiti-form>
</div> </div>
<div *ngIf="!isAssignedToMe()"> <div *ngIf="!isAssignedToMe()">
{{ 'TASK_DETAILS.MESSAGES.CLAIM' | translate }} {{ 'TASK_DETAILS.MESSAGES.CLAIM' | translate }}
</div> </div>
<button type="button" class="mdl-button" *ngIf="!hasFormKey() && isTaskActive()" (click)="onComplete()"> <button md-raised-button class="activiti-task-details__action-button" *ngIf="!hasFormKey() && isTaskActive()" (click)="onComplete()">
{{ 'TASK_DETAILS.BUTTON.COMPLETE' | translate }} {{ 'TASK_DETAILS.BUTTON.COMPLETE' | translate }}
</button> </button>
<dialog class="mdl-dialog error-dialog" #errorDialog> <dialog class="mdl-dialog error-dialog" #errorDialog>

View File

@@ -46,6 +46,21 @@ export class ActivitiTaskDetails implements OnInit, OnChanges {
@Input() @Input()
showNextTask: boolean = true; showNextTask: boolean = true;
@Input()
showHeader: boolean = true;
@Input()
showHeaderContent: boolean = true;
@Input()
showInvolvePeople: boolean = true;
@Input()
showComments: boolean = true;
@Input()
showChecklist: boolean = true;
@Input() @Input()
showFormTitle: boolean = true; showFormTitle: boolean = true;
@@ -250,4 +265,8 @@ export class ActivitiTaskDetails implements OnInit, OnChanges {
onClaimTask(taskId: string) { onClaimTask(taskId: string) {
this.loadDetails(taskId); this.loadDetails(taskId);
} }
toggleHeaderContent() {
this.showHeaderContent = !this.showHeaderContent;
}
} }