Activiti Tasks List

in Activiti

Angular.js activiti webapp – part II

Introduction

Previously we wrote about angular.js and activiti-rest and we covered users and groups. Now we went even further  and forned the activiti itself in order to create angular.js activiti client.

Here we are going to explain how to manage tasks. Use cases that are covered are

  • Listing tasks of current user as assignee
  • Searching tasks
  • Opening the task details, showing task name, workflow and form properties
  • Creating generic form that can show the task form properties
  • Submitting form data

Workflow

For this we have created on workflow process, really easy one simple approve process with some of custom properties.

Simple Process

Simple Process

Process has two tasks Approval Task and Check outcome task. Approval Task has a form defined that has properties of types

  • Motivation [String]
  • Date [Date]
  • Long [Long]
  • Boolean [Bool]

Form properties can also be read only, in that case activiti will not allow  us to save its new value.

Motivation is in first task ( approval task) editable and allows user to enter text, in second Check outcome task user is not able to change the motivation value.

The End Result

Lets see the end result for tasks list and few ideas that will come up in the future.

Activiti Tasks List

Activiti Tasks List

As you can see we have simple task list, with data that is really important to the user

  • Priority, with bottom border color
  • Assignee, user that is assigned
  • Task name
  • Description
  • Due date

Our user Admin has to be able to interact with the UI and finish his tasks. After user clicking on Approval task row, popup appears. Here is the image for this.

Task preview

Task preview

Popup dialog shows the user information about the task at hand. After user enters required data and clicks Finish Task, data is saved and task is finished, allowing user to select next task.

User is able to see several popups. Each popup would contain one task user can interact with. In the future here we will have task comments allowing user to collaborate.

Angular.js implementation

Anagular.js being a powerful tool, allowed us to create this using minimal lines of code. We have create factories for

  • Listing assigned tasks
  • Listing task with specified taskId
  • Finishing task
  • Loading task form
  • Submitting form
Listing assigned tasks

Task listing is done using service

service/runtime/tasks/{taskId}

There are multiple ways of filtering though the data, setting assignee, candidate user, dueDate and so on. We currently support only assigned tasks.

Lets see how is this achieved in angular.js. Creating a factory like this

angular.module('activitiApp').factory('TasksService', function ($resource) {
  var data = $resource('service/runtime/tasks/:taskId', {taskId: "@taskId"});
  return data;
});

allows us to list all tasks, and one task setting the taskId value.

Loading all tasks for logged in user is done like this

 $scope.loadTasks = function () {
    $scope.tasks = TasksService.get({"size": 1000,"assignee":$rootScope.username});
 }

, our user username object is saved in $rootScope so it can be used in this cases.

Loading one task

Loading one task with userId specified is done using TaskService using next lines of code

TasksService.get({"taskId": task.id}, function (data) {
  //here do our magic with the task data
});

 Activiti forms

In Activiti  you can for each user task specify a form with properties. Each property can be of some type. Types supported are:

  • Text
  • Boolean
  • Long
  • Enum

Each property can have metadata specified for each property, in metadata we can specify

  • Name
  • Value
  • Readable
  • Writable
  • Required
  • Date pattern
  • EnumValues

Enum values holds list of pairs id and value. Property can have any value from that list. So in form this can be rendered as comboBox or dropDown.

Activiti-rest has two services, one for loading task form and other for submitting. For this we have created FormDataService. Specified below.

angular.module('activitiApp').factory('FormDataService', function ($resource) {
   var data = $resource('service/form/form-data?taskId=:taskId', {taskId: "@taskId"});
   return data;
});

Loading task form data is easy as this

    FormDataService.get({"taskId": task.id}, function (data) {
        for (var i = 0; i < data.formProperties.length; i++) {
          //do magic here
        }
    });

Part of response is listed below.

"formProperties":[
   {
 "id":"approved",
 "name":"Decision",
 "type":"enum",
 "value":null,
 "readable":true,
 "writable":true,
 "required":true,
 "datePattern":null,
 "enumValues":[
               {"id":"true","name":"Approve"},{"id":"false","name":"Reject"}
              ]
  }
]
Submitting activiti form data

For submitting form data same FormDataService is used and its save method like specified below

var saveForm = new FormDataService(objectToSave);
 saveForm.$save(function () {
 
 });

We have objectToSave, so lets say that we want to save enum value approved, we would make our objectToSave like this:

{
  "taskId":"5",
  "properties":[
    {
      "id":"approved",
      "value":"true"
    }
  ]
}
Submitting activiti form with dates

If one of the properties type is date then we have line of two more. After loading form date have datePattern, our submitting date value must comply with this pattern. For date formatting we have used moment.js, now they have angular-moment that works great.

Lets see the code for converting string to date and to formated string again.

 var date = new Date(formProperty.value);
 elem.value = moment(date).format(formProperty.datePattern.toUpperCase());
Completing the task without submitting forms

Tasks can also be completed without submitting forms, this is done using TaskService like so

 var action = new TasksService();
 action.action = "complete";
 action.$save({"taskId": detailedTask.id}, function () {
    //after finishing remove the task from the tasks list
 });
Rendering activiti form

Activiti.js has ngIf, really nice directive that can be used here for rendering activiti task form. Each form property is of one of specified type(string, boolean, long, enum), so in case of string we would have next code

  <input ng-if="item.type=='string'"
         ng-visible="item.readable"
         ng-disabled="{{item.writable == false}}"
         ng-required="item.required"
         type="text"
         class="form-control"
         placeholder="{{item.name}}"
         ng-model="detailedTask.propertyForSaving[item.id].value">

propertyForSavig is object that is used to submit form to activiti-rest, that we have explained that before.

Enumeration is a bit tricky, lets dig into the code

 <div ng-if="item.type=='enum'" class="btn-group" dropdown >
    <button type="button"
           class="btn btn-primary dropdown-toggle"
           ng-visible="item.readable"
           ng-enabled="item.writable"
           ng-required="item.required">
             {{detailedTask.propertyForSaving[item.id].value==null?
               "Select":detailedTask.propertyForSaving[item.id].name}}
 <span class="caret"></span>
</button>
 <ul class="dropdown-menu" role="menu">
   <li ng-repeat="enum in item.enumValues">
     <a id="{{enum.id}}" 
        ng-click="setFormEnum(enum,detailedTask.propertyForSaving[item.id])">{{enum.name}}</a>
   </li>
 </ul>
</div>

As we can see for each enum in enum values render one option.

Function setFormEnum is simple as setting the value.

Summary

We have covered a number of things here, like listing tasks, finishing them, loading task forms and submitting them also.

You may be wondering where is the code, it will be deployed to gitHub soon after we reach beta . For that we must finish few things for claiming the tasks, and listing other tasks where user is not directly assigned but has been involved and so on.

You can read first post of activiti-rest angular.js series here.

If you are developing your angular.js application that consumes data from activiti-rest and have problems with Access-Control-Allow-Origin you can find solution here.

To find our third post angularjs activiti module go here.

Don't be shellfish...Tweet about this on TwitterShare on LinkedInShare on Google+Share on RedditShare on Facebook

Was this helpful ?