1. Intro

This step-by-step tutorial will help new edoras one modelers get started with defining Apps for the edoras one platform.

It’s a good idea to have read the basic edoras one intro (general guide) as well as the edoras one user guide, both of which can be found here: http://documentation.edorasware.com

1.1. What you will learn

By following this tutorial, step by step, you will learn how to create your own App, including the following:

  • Creating case models

  • Designing forms

  • Designing processes

  • Creating ad-hoc task models

  • Creating email templates

  • Creating documents models

  • Creating queries

  • Customizing dashboards

1.2. Tutorial App

For this tutorial we will use the scenario of building an App to handle travel requests. A person who needs to travel will start a new travel request, and a travel agent will organize all the necessary bookings for the trip.

The request process will be built step by step, adding approvers to the process, modeling a feedback-loop between travel agent and requestor and by adding mail tasks to send out information once the travel has been organized.

Everything around the travel request is modeled within a case, so we can attach any necessary information (such as reservation information or vouchers) directly to the case, as well as having an overview of everything going on while managing the travel request.

2. Basic Travel Request Case and Form

In this chapter you will create the Tutorial App with a new form and case model, deploy it and test the new case model within the user dashboard.

2.1. Creating a new App

In order to get started, go to the modeler dashboard and hit c or click the Create button in the menu and choose Create App.

Type Tutorial App as the name for the App.

Select English as the primary language for the App.

Select any other languages you want as secondary languages.

As an App can be modeled in several languages, you specify a main (primary) language for the App, which will act as the default language, if not all elements are translated. You will be able to design forms and processes with all languages you selected (primary will be default). Now click Create and navigate to the newly created App by clicking on the link in the green success message you see on the top of the screen.
create app 01

2.2. Creating a form to start the travel request

Let’s create a first form by typing again c (shortcut) or clicking the Create button in the menu. Now let’s choose Create Form Model and make sure the Tutorial App is selected as the parent App (meaning the new form model will be created inside that App).

Type Travel Request Form as the name for the new form model and click Create and design in order to create the model and directly go to the form designer.

create form 01

2.2.1. Getting familiar with the basics of the form designer

The form designer consists of three parts: on the left you can find the shape palette, the main canvas for the form design in the middle and on the right-hand side you can find the attributes of the currently selected widget (component) on the canvas.

You can add a new widget to the canvas by simply dragging & dropping it from the shape palette to the canvas. During the drag & drop you will get feedback by the responsive layout manager on where the widget can be dropped.

The layout is responsive, with twelve slots you can use to arrange your widgets. By using the handles on the left or right side of a widget, you can define the span of the widget from one up to twelve slots.

The shape palette has several sections to choose from. Use the predefined widgets if you don’t want to worry about bindings and any other technical issues. The widget section has a wide collection of all the available widgets, which will need configuration through the attributes section.

2.2.2. Add name and description widgets

To start with the design, let’s use two predefined fields: the name and description. These fields are always available and each work item supports them.

Now drag & drop the name and description field from the predefined bindings section on to the empty form. Rename the name label to Travel subject and the description label to Travel notes.

form design 01

2.2.3. Add traveling locations

Now let’s add two fields to enter the origin and destination of the travel. There is no predefined field for location, so let’s use the Text field from the Components section. Name the first one Origin and the second one Destination. By dropping the second field onto the first one, the row will split into two parts with both fields in the same row, each spanning six slots.

Instead of navigating through the shape palette, you can also use the filter functionality to quickly find a specific widget. Click the filter icon in the top right corner of the Shape palette and type the name of the widget into the search field (e.g. text).

To make the fields mandatory, select a field and click the red star icon. Do this for both Fields. You can also achieve the same result by clicking the Required attribute in right side panel.

form design 02

2.2.4. Getting familiar with the data model behind work items

Before we can define the data bindings for the new fields, let’s have a short look at how data is stored and managed within edoras one.

The basic structure to manage anything within edoras one is called a work item. A work item is an object of a particular type (e.g. a case, a task, a process or a document), its behavior is driven by its type and model (e.g. a process work item is driven by its process model, which in our case is modeled with BPMN 2). Besides its behavior, every work item is able to store arbitrary data, called variables. Variables hold different types of data, such as text, numeric value, a date or a boolean value. Variables can even hold lists of data or maps or even lists of maps with unlimited nesting.

In order to enter or display the data of work items, its variables can be mapped (bound) to fields.

2.2.5. Define data bindings for the fields

The next step is to set the binding for the newly added fields. Double-click the field or go to the Value attribute on the right side. Bindings tell the form engine where to save and load the data for a particular field.

Let’s save the origin in a variable named travelOrigin and destination in a variable named travelDestination, respectively. Bindings are specified using expressions, which start with a double curly brace {{ and end with a double curly brace }}.

If we don’t specify any prefix to the variable name, the data is stored and retrieved from the same work item the form is associated with.

form design 03

2.2.6. Add date pickers for the outward and return trip dates

Now let’s add two new fields to pick the starting and ending date for the travel. Drag & drop two Date fields on the form and name them Outward trip date and Return trip date, respectively.

Make the fields mandatory and set the bindings to {{outwardTripDate}} and {{returnTripDate}}.

form design 04

2.2.7. Add validation to the date pickers

As we want to make sure there is no date selected in the past, let’s add a validation rule to the date picker.

You can do so by selecting the date field and then clicking on the Minimum date attribute on the right side under Specific attributes. Select a relative date validation by choosing Today + 0 Days.

form design 05

For the Return trip date we also want to add a validation rule. Here we want to ensure that the selected date is not before the Outward trip date. To achieve this, we simply add {{outwardTripDate}} to the Minimum date attribute of the Return trip date widget.

form design 06

Save the form by clicking the Save icon in the designer menu on the left.

2.3. Create case model

Now switch back to the browser tab where you created the new form (not the form designer) and click the Create button once again and select Create case model.

Fill out the case model form:

  • Set Travel Request as the name

  • Choose the Travel Request Form as both the init form and the work form of the case

  • Everything else can be left as it is by default, we will make changes to that later in the tutorial

Click Create to create the new case model.

create case model 01

2.4. Deploy the App

Done! We have our very first version of the Tutorial App ready to be deployed and used.

Click the Tutorial App link from the previous green success message, or the link within the header of the current case model in order to navigate to the Tutorial App.

In the App, you should now see two models: the Travel Request case model and the Travel Request Form model.

From the list of actions on the right side menu you can select Deploy, opening the deploy dialog. Navigate to the end of the dialog and click OK to deploy the App. This will make it available within the user dashboard, so now we can test it.

app deploy 01

2.5. Test the App

In order to test the newly deployed App, we switch to the user dashboard. You can do so by selecting the User dashboard from the menu of dashboards or use the d shortcut. While modeling and testing, it is also a good practice to have two tabs open constantly, one with the user dashboard and one with the modeler dashboard.

Once in the user dashboard, click Create or type c to open the creation dialog. Select Create Case and choose Travel Request from the selection menu.

Fill out the request init form we’ve just designed. Please note the validation checks within the date picker, specifically notice that you will not be able to enter a date earlier than today.

create case 01

Click the Create button to complete creation of the new case. You will see the newly created case displayed using the same form, as we set it for both the init and the work form. Now you will be able to modify any values and click Save in order to change the data for that case.

create case 02
A copy of the tutorial App at this point is availble in the distribution bundle as ModelerTutorialApp1.zip.

2.6. Getting familiar with basic navigation

On the right side you will find available actions for the current work item (a case currently). The top right area shows the available views of the work item.

case menu 01

Actions, from top to bottom:

Assign

lets you specify the owner and current assignee of the work item

Share

lets you share the work item with one or more groups

Start Process

starts an ad-hoc process within the current case

Archive

closes the current work item and archives it

Views, from left to right:

Search

navigates to the list of children for the current case, where you can find open tasks, documents or whatever the current case is holding

Browse

navigates to the main work form of the current work item

Comments

navigates to the comment section of the current work item, where you can see all existing comments as well as add new comments or reply to existing ones

Edit Entity

(only available to modelers) shows a generic view with all data of the current work item and the ability to change it or even add new variables

Edit Entity JSON

(only available to modelers) shows the JSON representation of the current work item, which can also be modified. Great care needs to be taken as you could break data of the work item by incorrectly modifying its JSON representation.

3. Basic process modeling

In this chapter you will learn how to create your first process, attach it to the case model created previously, and then to start it automatically when a new travel request is created.

3.1. Create new "Travel Request Process" model

Switch back to the modeler dashboard (either through the dashboard switcher or by going to your second tab with the modeler dashboard still open).

Choose the Tutorial App if not yet open and click Create or hit c. Now let’s choose Create Process Model and enter Travel Request Management Process as its name, then click Create and Design to create the process model and immediately open it in the process modeler in one step.

create prc model 01

3.2. Getting familiar with the process modeler

The process modeler is quite similar in its basic functionality to the form designer. On the left-hand side you can find the shape palette with several sections from where you can choose process elements. The middle area is the main canvas area where you design the process. The right-hand side shows the attributes of the currently selected element in the process canvas.

You can add elements to the process by simply dragging and dropping them from the shape palette onto the canvas.

Hint: as you start modeling processes, the spacing tool is a very handy feature to make more space in your current process model:

prc modeler action 01

Activating it will allow you to easily expand sections of the process model or make a section smaller. Give it a try once you have some elements on the canvas and make yourself familiar with using the feature. Simply turn it off by clicking it once again to deselecting it.

3.3. Add a pool and lanes to the process

Let’s start the process model by adding a pool and lanes to it. This is optional in BPMN 2, but is a good practice in order to visualize the different roles, people and groups involved in the process.

Go to the Roles section in the shape palette, drag & drop a Pool onto the canvas and name it Travel Request Process. A single lane has been added automatically, double-click its label (called Lane) and rename it to Requestor.

prc modeling 01

Now let’s add a second lane for the travel agent managing the travel request. Select Lane from the Roles section of the shape palette and drag it to the bottom part of the pool; dropping it will add it as a second lane below the existing one. Name it Travel Agent. Using the spacing tool, it’s easy to make the lanes smaller or larger according to need.

prc modeling 02

3.4. Model two user tasks as the first version of the process

We’ve now created two lanes representing two different types of people involved in the process: the requestor actually creating the travel request, and the travel agent responsible for managing the travel.

Let’s add a start event to the process by dragging the Start event element from the Execution section of the shape palette onto the Requestor lane. When an element is selected, you should see the fast-modeling menu floating next to the element. The start event element should still be selected, so click the user symbol from its fast-modeling menu in order to add a user task immediately after the start event. Name it Manage Travel Request, click on the user symbol again and name the next task Review Travel Bookings, then finally click the thick rounded end event in the fast-modeling menu.

Done! We have our very first process with a start event, two user tasks and an end event, looking something like the following:

prc modeling 03

Now let’s get the tasks into the right lane simply by moving them. Move the Manage Travel Request task into the second lane, as it should be done by the travel agent. Make use of the spacing tool in order to add or remove space between lanes and elements.

prc modeling 04

3.5. Save process model and attach it to the case model

Save the process model by clicking on the Save action in the menu bar (we will add task forms later, so ignore any warning messages for now) and switch to the browser tab with the process model within the Tutorial App (not the designer window).

Navigate to the Tutorial App and select the travel request case model. In the Autostart Processes selection choose the newly created process model and save the case model again.

map prc case model 01

3.6. Re-deploy and test the App

We’ve now created our first, albeit simple, process model and attached it to the existing case model. We can now re-deploy the App by using the Deploy action as we did before and switch to the user dashboard in order to test the changes made.

After successfully deploying the Tutorial App, switch to the user dashboard and click Create then select Create Case. Select the Travel Request template, fill out the form and start the next travel request case.

Did you notice the gray badge in the left top corner of the children view button? It shows you that there is one child work item of the current case, which is the first task being created by the process.

case testing 01

Click the children list view to see that task. The open task should be named Manage Travel Request and behind it you should see the name of the travel request case (the same as in the header).

case testing 02

Navigate to the task by clicking its name. It will take you to the work form of that user task. You can still see the case in the header section of the task and use it to navigate back to the case, or you can also use the browser back button to go back. To navigate to the task, select it as the current work item. As you’ve probably noticed, this will change the available views and actions, always reflecting the possibilities with the currently selected work item.

case testing 03

The user task has a default form with the name of the task and a description field. But let’s have a look at the different options available when working with the task. There is a new view called Preview; selecting it will display the process with a red border highlighting the current task.

case testing 04

Go back to the work form by clicking on the Browse button, add some notes and click Complete. This will complete the task and hand control back to the process engine, continuing with the process execution and, in our case, leading to the second task being created. You can go to the preview again and see that the process execution has now moved to the second task. Complete the second task as well and this will finish the process execution. You can then navigate back to the case by using the case link in the header of the task, and check that the children view doesn’t show the badge anymore, as there are no more opened tasks available.

3.7. Create user task forms for process execution

As we haven’t created specific user task forms yet, you’ll have realized that default forms were used. Of course, this doesn’t make much sense for real use and we can improve the two user tasks by designing task forms for them, showing all necessary information needed to complete each task.

Switch back to the process designer (if still open, otherwise switch to the modeler dashboard, select the process model and click Design to open the process modeler).

Select the Manage Travel Request user task. There are two ways to create or select a form for this user task: either click the Add reference context menu; or, go to the attributes of the task and click the Form reference attribute.

Here, you can choose between selecting an existing form (of course we don’t have any suitable forms yet) or creating a new one. And that’s what we’re going to do, so choose New. The form designer is opened again, ready for a new form to be designed that will be automatically attached to that task.

3.7.1. Understanding the work item hierarchy

Before we start designing the new task form, let’s have a look at how the data is organized in the work item hierarchy. The process is started within the case, making the process instance a child work item of the case. If a user task is created automatically through the process, this task becomes a child element of the process. You can think of this as a hierarchy, where the case is the root, having a process as a child and the process having a task as its child:

WorkObjectHierarchy

You can store data on every work item, and every work item has also access to the data of its parent up to the root. But of course when building form data bindings, you need to be aware of the hierarchy and where the form is actually used. Bindings such as {{foo}} without any prefix are always bound to the work item that form is used with. If you want to store or read data from the case, use the root prefix, for example {{root.foo}} would store or read the data from the case’s variable named foo. You can also use the special parent in order to go up one level in the hierarchy of the current work item. For a user-task, its parent is the process the user-task is part of.

3.7.2. Show task information using an output widget

Now let’s go back to our user task form for managing the travel request. It’s good practice to display helpful information about the current task on the task form. As a first step, we can add an Output textarea to it in order to display the travel request details in a read-only way. Drag and drop an Output textarea from the shape palette onto the form, but don’t enter a label name, just leave it blank.

Double-click the widget on the form, or click the Value attribute, to open the rich editor to edit the content for the widget.

Let’s add something like this:

user task design 01

You can use formatting and add any text you want. Of course, you can also add expressions in the same way we did with the data bindings of fields. Please note that we are now designing the form of a user task and hence we need the root prefix in order to display data that is stored on the case. Make sure you use the same variable names that you used in the case init form.

3.7.3. Add editable information to the form with a rich text area

We want the notes for the travel request not only to be shown, but also to be editable by the travel agent, so let’s include a notes field to the form using the predefined widget named Case description. Drag & drop the Case description field from the Predefined bindings in the shape palette below the output widget on the form and rename its label to Travel notes.

We can now additionally add a hint in the notes field to let the travel agent know that he should enter additional information here. Select the travel notes field and click on the Description attribute on the right side. Enter something like Please add any additional information for the travel in here. You can also directly edit that description by double-clicking it directly in the form widget.

The form should now look like this:

form design 01

Save the form with the name Manage Travel Request Task Form. In order to re-use the output widget with all its configuration details, select the output text area widget and copy it. You can now close the form designer browser tab, which should take you back to the process modeler.

3.7.4. Create second task form

Switch back to the process modeler browser tab and click on the Add reference context menu for the second task, named Review Travel Bookings, and again select New. In the new form designer, paste the output widget we previously copied from the first user task form. Note that copy and paste is supported across models, not only within the same model, which can be quite handy for quickly modifying models.

Double-click the output widget in order to change its content to reflect the current task we want to create the form for. As this is just a review task, we’ll include the traveling notes in there directly rather than using a description field as we did in the previous form.

user task design 02

Now save the task form, name it Review Travel Bookings Task Form and close the form designer browser tab.

3.8. Redeploy the App and test again

We’ve successfully added two new task forms and attached them to the appropriate user tasks in the process. So let’s test it by deploying the App again, creating a new travel request and stepping through the process.

Make sure you save the process model too before you redeploy the App, as we have also changed it to map the newly created forms!

Once you have redeployed the App, create a new case, click on the children view and select the manage travel request task. You should now see the specific task form we designed:

prc testing 01

Add some notes, complete the task and check whether the data in the second task reflects this correctly.

A copy of the tutorial App at this point is provided in the distribution bundle as ModelerTutorialApp2.zip.

4. Improving the forms

In the last two chapters we created a new App, a case model, a case initialization form, a management process, as well as task forms in order to reflect our needs for the travel request case.

In this chapter we will further improve the forms, making them more user-friendly and add an attachment widget to it, then later turn it into a subform and reuse that in other forms.

4.1. Add an attachment widget to the case form

Instead of having to manually upload any booking documents, let’s place an attachment widget directly to the case form for easy access to this capability.

First, switch back to the App in the modeler dashboard, navigate to the Travel Request Form and click Design.

Let’s add a comment on the attachment widget for the user to understand how to use it in our context. Drag & drop an Output textarea to the bottom of the form, don’t add a label, and double-click the widget to open the rich editor and enter something like this:

form design 01

Below the output widget, drag & drop a new Attachment widget from the Component section of the shape palette and name it Attachments / bookings. Like text data bindings, the attachment widget can also be bound to a variable, which will hold all information about any attachments uploaded. Use the binding {{attachments}} this time and your form should look like this:

form design 02

Now let’s fine-tune the widget by selecting it and changing some attributes. First, let’s customize the Select file message by changing the default value to Upload any booking documents here or similar. Set the Preview type to Thumbnail, as we want to include a preview in the attachments, if possible. Set the Thumbnail maximum height to 200 to prevent big pictures from using too much space on the form.

4.2. Redeploy and migrate existing cases to reflect new version

Now save the case form and redeploy the App. Instead of creating a new case straight-away, let’s have a look at how versioning is done while deploying an App.

4.2.1. Understanding App and model versioning

Whenever an App is deployed, all of the models within it will be deployed to the runtime of the edoras one platform, and then they become available within the user dashboard. An App is deployed as a new version every time you deploy it, to make it fully consistent and compatible with all the models it contains. By default, the deployment mechanism uses a safe strategy of not migrating existing instances to the new models, including cases, processes and tasks. This means they will still be mapped to precisely the version they were created with until they are either completed or migrated to a newer version. So, even with an updated form in an App, existing instances of it will continue to display and use the older versions of the form.

4.2.2. Migrate existing travel request cases to latest version

For now, we want our cases to immediately reflect the latest changes within the form (the attachment widget), so go to the Tutorial App and navigate to the Travel Request case model by selecting it. Click the Migrate action in the right side action menu of the case model, and migrate all existing cases to the latest, just redeployed, version of the App.

Switch back to the user form and select one of your previously created travel request cases to make sure they now reflect the latest version. You should see the attachment widget now:

case testing 01

Click the upload icon and attach an image, for example. You will have to save the case form in order to see the preview (thumbnail) of the uploaded image:

case testing 02

4.3. Turn the attachment section into a subform

It so happens that we also want to add the same attachment widget to the task forms. We could do this the same way as we did before using copy and paste, but this time we want to try a new feature of forms, sub forms, a great way for re-using existing parts of forms, either for technical or business reasons.

Go to the Tutorial App and click Create, select Create Form Model and enter Attachment Section Sub Form as its name, then click Create and Design to directly open it in the form designer.

First, go back to the case form designer and select both the output widget and the attachment widget and copy them to the clipboard. Switch back to the new, still empty, subform and paste the widgets there. The subform should now look like this:

form design 03

Save the subform and switch back to the case form designer ready to add it there, but first we need to understand how the binding works for subforms.

4.3.1. Understanding bindings in subforms

In order to use a subform in different forms and therefore different contexts, it is essential to isolate its data bindings and make them configurable outside of the subform where they are used.

Assume a subform has two fields in it with bindings to {{foo}} and {{bar}}. The subform may be used within a case form as well as within a task form, displaying the same data in those different contexts. Or the subform may even be used several times on the same form, but with different meanings (for example, an address subform used once for the main address and again for the billing address). In order to be able to deal with situations like this the subform itself needs a data binding as well, following exactly the same rules as explained earlier in this tutorial. So, for instance, if a subform is bound to {{mySubFormData}}, there will be a variable named mySubFormData, which itself will be a map holding all data contained in that subform.

Example 1:

  • a subform with two fields bound to {{address}} and {{city}}, respectively

  • the same subform is used twice in another form

    • the first representing the main address is bound to {{mainAddress}}

    • the second representing the billing address is bound to {{billingAddress}}

  • the possible expressions (for example within an output widget) include:

    • {{mainAddress.city}} representing the city of the main address

    • {{billingAddress.address}} representing the address data of the billing address

Example 2:

  • a subform with fields {{foo}} and {{bar}}

  • the subform is bound to {{$this}} (a special expression representing the context of wherever the subform is used)

  • this will result in the same behavior as if the two fields had been placed on the form directly rather than within a subform

Example 3:

  • a subform with fields {{foo}} and {{bar}}

  • the subform is used within a case form with binding {{$this}}

  • the same subform is used in a task form

    • we want the subform to always represent the same data of the current case

    • the subform therefore needs a binding {{root}} to map it to the root context to make sure it represents the same data in the task form as it does within the case form

Example 4:

  • same as example 3, but this time the subform binding in the case form is {{myData}}

  • the subform binding within the task form then needs to be {{root.myData}} to represent the same data as within the case form

4.3.2. Understanding different types of subforms

That’s now given us the basics for the binding and isolation of data in subforms. There are also some useful possibilities of dynamically changing which form is actually used as the subform, as well as whether the subform should have one element or is able to show multiple elements.

Single-element or multi-element subform?

Subform widgets can be configured to hold exactly one element (single-element) or can hold zero to multiple elements. There is a difference is how the data is mapped in these configurations. Single-element subforms will store their data in a map directly within the variable they are bound to. Multi-element subforms will store their data into a collection (list) of maps in the variable they are bound to and are able to hold 0 to n (none, one or many) elements.

Single-type or multi-type subform?

There are basically two types of subforms available: single-type or multi-type. A single-type subform will render just one type of form for all entries it is showing. A multi-type subform can hold different types of forms and uses something called a discriminator variable to determine which form should be used for which type in the list. Assume there’s a subform showing a list of selected products. For each entry (each product), there might be a different type of form necessary in order to represent the relevant product information. The discriminator would be mapped to the type of the product, so then the appropriate product form would be used in the subform to represent that specific product the best way.

4.3.3. Adding the subform to the case form

Now having learned more about how subforms are bound to data and the different types of subforms, let’s use it in our case form to change how we represent the attachment section of the request.

Go to the form designer for the Travel Request Form, if not already there, and delete the output textarea and the attachment widget, as now we want to replace them with the subform we just created.

Drag & drop a Single-type subform from the Components section of the shape palette onto the bottom of the case form and label it Attachments.

Click the + button at the bottom of the widget to select the subform we want to use. Choose Reference and then select the Attachment Section Sub Form as the referenced form.

Double-click the subform or click the Value attribute to enter the binding for the subform. As we want the same behavior as we had before without the subform, bind it to {{$this}}, meaning the data in the subform will be directly stored in the case (this also means we’ll even be able to migrate the existing cases without having to migrate any data).

Make sure Multiple elements is turned off in the Specific attributes section. You can choose whether you want a border around the subform or not. Turn it off to be as similar to we had before adding the subform.

Because we entered a label name for the subform (although optional), we might decide to remove the label from the attachment widget to avoid duplicate information on the form. To do so, click the subform-name-link at the bottom of the subform widget to open it directly in the form editor and make the change.

4.3.4. Redeploy, migrate and test again with the subform

Go to the Tutorial App, deploy it again, navigate to the Travel Request case model and migrate the existing cases. Switch to the user dashboard and navigate to one of your previously created cases and you should see pretty much the same as before, but now achieved using a subform:

case testing 03

4.3.5. Add the subform to the task forms as well

Now we have a reuseable subform, let’s add it to both user task forms as well, so we have all the useful information available in the different contexts of the process.

Open both task forms in the form designer. There are different ways to do that:

  • Go back to the process model, open it in the process modeler, select the user task, open the attributes and click on the form reference in the Specific Attributes section. Then select Reference and click the OK button to open the form designer for the task form.

  • Go to the modeler dashboard and select the form in the My Form Models widget.

  • Navigate to the Tutorial App and choose the appropriate forms from there.

Once opened in the form designer, drag & drop a Single-type subform to the bottom of the form and label it Attachments. As we did before with the case form, click the + button at the bottom of the subform and select the Attachment Section Sub Form.

Turn off the border and make sure multiple elements are turned off. Now the binding will need to be slightly different than we used in the case form. Remember that we bound the subform to {{$this}}, meaning its data is directly stored within the case itself. In order to show the same data in the context of the task, we now need to bind it to the case, which can be done using {{root}}.

So, for the travel management task form, it should look like this:

form design 04

For the second user task form, you can simply copy and paste the subform widget from the first task form (not from the case form though, as the binding is different there).

4.3.6. Redeploy, migrate and test again with the subform in the tasks

Go to the Tutorial App, deploy it again, navigate to the Travel Request case model and migrate the existing cases. Switch to the user dashboard and navigate to one of your previously created cases (one that already has at least one attachment).

Now let’s see how we can start the process whenever we want, in an ad-hoc way. Remember that the first time the process was started automatically when we created the case. Now let’s see how this can be done manually.

Click the Start Process action in the right hand action menu and select Travel Request Management Process, then click Start. This will start a new instance of the process in the same case. This is how processes can be manually started as an alternative to automatically starting them during the creation of a case.

As before, the children view of the case shows one task because we started the process again within the case. Navigate to the task and check, whether you see the attachments there too:

case testing 04

5. Ad-hoc tasks and process improvements

In this chapter we will add a requestor <–> agent feedback loop to the process. If the travel agent needs more information, clarification, decisions about which flight or hotel to choose from and the like, we will enable that by adding a feedback-loop to the process.

But first, we’ll find out how this can be done using ad-hoc tasks.

5.1. Getting familiar with ad-hoc tasks

Assuming the problem as described above, there are several options for how the travel agent could solve it:

  • Use the phone, contact the requestor and clarify the open questions

  • Send an email to the requestor and clarify anything

  • Create an ad-hoc task within the case, assign it to the requestor and clarify details

  • Add a feedback-loop to the process for better tracking and audit

The first two options are probably the way we solve many unexpected business situations, but they are not integrated in a way that any new information is automatically available within the case. In a large organization there might be a team of travel agents working together and they would need to share that information somehow, so everyone can always be up to date.

As a first step, let’s create an appropriate ad-hoc task model to support this directly within the case. In parallel to the running process, a user can create ad-hoc tasks at anytime if enabled in the case model (which is the default).

5.2. Create ad-hoc task init form

Ad-hoc tasks can be built with forms in exactly the same way we’ve created forms so far. This time, we’re going to create a different init-form. Go to the Tutorial App, click Create, select Create Form Model and name it Ad-hoc Feedback Init Task Form. Click Create and Design to open the new form in the form designer.

This time we will also learn the difference between an init-form and a work-form. So far we’ve used the same form in the case for both. Additionally, we will use a subform to show the data of the case within the case form itself, a nice way to ensure all the data for a case is shown in another context.

First of all, we want to be able to set a subject for the ad-hoc task (like the subject you would put in an email). We can use one of the predefined widgets, so drag the Name widget from the Predefined bindings section of the shape palette onto the form and rename the label to Task subject.

For the description of the task (the request for additional information, review or whatever) we will also use a predefined widget, so drag & drop the Description widget onto the form and rename its label to Task description. Click the star button of the description widget to make it required, to force the user to specify a task description.

Remember, we’re still designing the init-form of the ad-hoc task, which is only used during the creation of the new task, so we also want to be able to select the assignee for the ad-hoc task. There’s a predefined widget to do exactly that, so drag & drop the Assignee selection widget from the Predefined selections section onto the form and rename its label to Assignee for the task. Let’s also add a due-date for the task (another default field as well), so drag the Due date widget from the Predefined bindings section and drop it onto the assignee field in the right part, splitting the row into two parts, and rename its label to Task due date.

Now the form should look like this:

form design 01

5.3. Create ad-hoc task work form

As mentioned before, this time we want different forms for initializing (creating) a new ad-hoc task and for working on it, so go back to the Tutorial App, select the Ad-hoc Feedback Init Task Form and click the Duplicate action, as we want to create a copy of the form so we only have to change what’s different between the init-form and work-form. In the duplicate name field, write Ad-hoc Feedback Work Task Form and click Ok to copy it. Go back to the Tutorial App (link in the header) and select that newly created duplicate form, then click Design to open it in the form designer.

Now we only have to make a few modifications to suit our needs. It doesn’t make sense to allow the subject and description to be changed, so let’s make them read-only by setting their attributes Editable to false. Next, remove the assignee selection and task due date, as we don’t want to be able to modify them.

As the requestor of the initial case, we want to be able to modify the case data itself, so let’s add that case information by using a subform. Previously we saw how data from the case can be shown in a task form by using an output textarea widget and then manually add all necessary data with appropriate expressions to it. This is one option, now let’s see a more generic way to include the case data in the task form by adding it as a read-only subform, using the very same form as we used for the case itself. This way, we make sure that whenever we add new stuff to the case form, it will automatically show up in this task form as well, because it’s a subform. Additionally, we want to be able to choose to show and hide the case information through a checkbox.

Drag & drop a Checkbox widget to the form, label it Show case information and bind it to {{showCaseInfo}}. Select the Default value attribute and set it to true as the default (so the case info is visible by default).

Now drag & drop a Single-type subform below the checkbox and label it Case information. Click the + button and select Reference and then Travel Request Form, our primary case form. Next, we need the binding for the subform. Remember, we want to show the case information in there, so we use {{root}} for the binding, which will map to the current case within which the ad-hoc task has been created. Last thing to do is to set the Visible (RT) attribute to the same binding as the checkbox {{showCaseInfo}} to make the visibility flag of the subform dependent of the state of the checkbox. Visible (RT) means visible runtime and lets you define an expression that must resolve to either true or false, then the visibility is dynamic based on the expression’s value. Also note that expressions are evaluated in real-time directly within the form engine of edoras one, whenever the data that the expression is based on changes. In our case with the checkbox value, the visibility flag is automatically adjusted appropriately. Make sure we have Show border set to true and Multiple elements to false, as there is exactly one case instance to be shown and we want it in a border to visually indicate its data is coming from somewhere else.

The interesting part now is that we can even modify data in one single form for both the task and the case instance simultaneously, so the user doesn’t even need to be aware of context that data is coming from or being saved.

The ad-hoc task work form now should look similar to this (the attribute section is the one from the selected subform):

form design 02

Now save the form and go back to the Tutorial App for our next step.

5.4. Create ad-hoc task model

Go to the Tutorial App and click Create and choose Create Task Model. Set the name to Travel Feedback Task.

Now select the appropriate init-form and work-form in the Init Form and Work Form selections of the task model and complete creation of the model by clicking Create.

task model 01

5.5. Deploy App and test ad-hoc task

Navigate back to the Tutorial App and deploy it again, which will make our new ad-hoc task available for use.

Switch to the user dashboard and select one of your previously created travel request cases. Now click Create and choose Create Task. If you do that in the context of a currently selected case, it should be automatically preselected in the Parent Case selection. Now choose the Travel Feedback Task Template, fill out a task subject and description, choose yourself as the assignee (so you don’t have to logout and login to complete it) and optionally also choose a due-date.

prc testing 01

Click Create to create the ad-hoc task. If you check Create another before hitting Create, the new task will be created and you will return back to the same init-form so you can quickly create another one.

Going to the newly created ad-hoc task there are several things you should note. First of all, you should be able to show and hide the case information by simply clicking the Show case information checkbox. Also note that the information in there reflects the case information and you are able to modify it directly while in the task. You can test that by changing some case information in there, clicking Save (not Complete yet) and navigating to the case. The data in the case itself should have been updated accordingly.

To complete the task, simply click Complete and it will be finished. By default, completed tasks are not shown in the children list of a case. If you would like to see them, go to the children list of the case and select status All within the search box. Now you will see all work items of the case, even completed ones.

5.6. Add feedback loop to the process

As an alternative to the ad-hoc task approach we just tried, we now want to incorporate the agent <→ requestor feedback loop directly into the management process.

And here is how we can do it:

  • Add a next step selector in the management task form, to let the travel agent choose between different options (need more information, travel organized, and so on)

  • Add a gateway in the process after the user task to take the appropriate sequence flow based on the selected next step

  • Add feedback-task as a new path in the process that loops back to the management task

  • In the review task at the end of the project, add a new checkbox to the form to give the requestor the option to loop back to the agent if he is not happy with how the travel has been organized

5.6.1. Add next step selection option to management task

Navigate to our travel request management process and open it using the Design action (if the process modeler is not already open).

Open the process model in the process modeler, select the Manage Travel Request user task, open the attributes and click on the form reference in the Specific Attributes section. Then select Reference and click the OK button to open the form designer for the task form.

In order to separate the previous form elements from the next one, drag a new Horizontal line from the Component section and drop it right after the Travel notes field.

Drag a Static select widget from the Component section onto the form between the travel notes and the attachment subform, and drop it inbetween. Label it Select next step and bind it to {{parent.nextStep}}. Why did we use the parent prefix? Note that our form is used within a user task created as part of a process. If we want to be able to use the data in the nextStep variable in the process context, we must not store the data in the local task context, but rather in the process context (parent-prefix) or even the case context (root-prefix). As this information is only needed during the lifecycle of the process, we’ll to store it in the parent process and not in the root case context.

Let’s make the selection mandatory by clicking the red star or setting the attribute Required to true. Now open the Options attribute dialog by clicking its attribute value, then enter two options in there:

  • Name: Need more information from requestor, Value: moreInfo

  • Name: Finish organization, travel has been fully organized, Value: finish

The name column defines the label used for that option, while the value column is used to define the variable to store the selection.

If we choose the first option, we want to show a new note field where the agent can describe what kind of information is needed from the requestor. So let’s drag & drop a Rich textarea from the Components section of the shape palette to below the selection widget on the form and label it Information request. Make that field required by clicking the red star, but note that the required-validation will only take place if the field is shown; if it stays hidden, there is obviously nothing to be entered and the validation takes this into account. Bind the field to {{root.infoRequest}}, as we want to keep that information, even after the process has been ended. We’ll store it within the case context and that’s why we’ve used the root prefix instead of parent that we used with the nextStep variable.

As we are already thinking ahead to when the feedback loop returns from the requestor back to the agent, we want to show the information the requestor entered, so let’s add an output textarea showing that information. Drag & drop a new Output textarea below the information request field and leave the label empty. Double-click it and add the following content to it:

form design 03

We only want to show the information request field if the next step selected is moreInfo, so select the Information request field and enter {{parent.nextStep=='moreInfo'}} in the Visible (RT) attribute, making it visible only if we select Need more info… in the next step selection.

The output text area should only be visible if it has content, so let’s enter {{root.infoRequestAnswer}} in the Visible (RT) attribute, making it visible only if the variable root.infoRequestAnswer has content.

The form should now look like this:

form design 04

5.6.2. Add feedback loop to the process model

We now have to add the feedback loop to the process model, so let’s open it in the process designer.

Still remember the spacing tool? We can make use of it now to add some extra space after the management task in order to add the gateway after the user task.

prc design 01

Now drag a new Exclusive gateway from the Execution section of the shape palette and drag it over to the sequence flow after the user task. As soon as the sequence flow becomes green we can drop it, as the modeler has recognized that we want to drop it inbetween the two user tasks.

prc design 02

As you can see, the modeler automatically splits the sequence flow into two and adds the gateway inbetween.

Select the gateway element (if not already selected) and drag & drop the small user task icon to add another outgoing sequence flow with a user task after the gateway:

prc design 03

Name the new user task Answer Info Request and align it right above the gateway and on the same horizontal level as the other requestor task:

prc design 04

Select the new user task and drag the arrow icon next to it onto the Manage Travel Request user task until it turns green, then drop it to connect the two tasks with a sequence flow.

prc design 05

We’ve now successfully modeled the feedback loop after the gateway. Our next step is to tell the engine which flow to use from the gateway by specifying conditions on all outgoing sequence flows.

Select the sequence flow between the gateway and the Answer Info Request user task, then click on the Condition expression attribute and enter #{nextStep=='moreInfo'} as the expression. We’ll explain the different expression syntax in just a minute, but first let’s add a label to the sequence flow. This can be done by clicking the Name attribute and entering the name, or simply by double-clicking the sequence flow directly in the process canvas. Let’s name it more info.

Now select the sequence flow between the gateway and the Review Travel Bookings user task and enter #{nextStep=='finish'} as the Condition expression attribute and name it finish.

It’s good practice to add a label to a gateway element, so double-click the gateway and type Decision?

prc design 06

5.6.3. Getting familiar with frontend and backend expressions

You probably noticed that there is a difference in the syntax for frontend expressions used within forms and backend expressions as we’ve just used in the process model. The difference is down to where they are being evaluated: directly within the browser (frontend / forms), or on the server (backend, everywhere else, such as process, email templates, document templates, and so on). Frontend expressions are limited to whatever the browser and form engine know, in contrast to the expressions on the server side, which could contain your own service calls, functions, any navigation through the work item network and much more. That’s why we use different syntaxes, to make the difference in their evaluation very prominent to the modeler.

But now, back to our sequence flow condition #{nextStep=='moreInfo'}. Why didn’t we use parent.nextStep as we did in the form? It’s very important to always remember in which context an expression will be evaluated. In the user task form we are in the context of a task work item, which is a child element of the process work item. The expression on the sequence flow, however, is evaluated in the context of the process itself and therefore we don’t need the parent prefix that we needed in the task context.

5.6.4. Create user task form for the answer task

We now have to create the user task form for the new task added to the process. If you remember, you can simply click the task ref link icon, select New and it will create a new form, attach it to the user task and open it up within the form designer.

Let’s add an Output textarea to the form so we can add the necessary information in there. Leave the label empty, double-click the widget and add the following content to it:

form design 05

Note that we can include expressions anywhere within the content as we like.

Below the output field, add a new Rich textarea widget, label it Your answer and bind it to {{root.infoRequestAnswer}} (the same expression we already used in the management task form). Additionally, make it required by clicking the red star icon.

The form should now look like this:

form design 06

Save the form, name it Answer Info Request Task Form and close it in order to return back to the process design.

Save the process model as well, with the new feedback loop, in order to test it.

5.7. Redeploy and test process with feedback loop

Go back to the Tutorial App and redeploy it. Now switch to the user dashboard and create a new case with our Travel Request template.

Did you notice the new attachment widget was also visible in the init-form? If you don’t want to be able to upload attachments while starting the travel request, just add {{root.id}} within the Visible (RT) attribute of the subform widget holding the attachment subform in the Travel Request Form. It will not show up as long as the case hasn’t been initialized, because the root.id variable is not available.

If you navigate to the Manage travel request task within the children view of the case you will see the updated management task form. Select Need more information… from the Next step selection and the new Information request field should appear, where you can enter the information you need from the requestor:

prc testing 02

Did you notice the rich text capabilities within the text editor? When selecting part of the text, a toolbox appears that allows you to change the formatting:

prc testing 03

If you now click Complete, the next task will be the answer info request task, where you can provide an answer, after which the process will go back to the management task. You can use this feedback loop as many times as you want. As soon as you choose Finish…, the process goes to the review task and will finish.

Did you notice the pre-selected next step combobox when returning back to the management user task? Remember that we bound the selection of this widget to parent.nextStep, and as the selection is stored in the process it will be remembered the next time that information is used again. As we don’t wont that behavior, let’s go back to the process and add a service task to reset its value before we return to the management task again.

5.7.1. Add service task to initialize variables to the process

Make some more space before the Manage Travel Request user task in order to add a service task there. Afterwards drag a new Initialize variables task from the Service tasks section onto the sequence flow between the start event and the user task, drop it and name it Reset next step selection.

Move the sequence flow connection that’s between the answer and the manage task so it points to the new reset service task by selecting the connection and dragging the green point at the end of the flow arrow, dropping it onto the reset service task. If you want to rearrange the sequence flows, there are several handles available to choose from. There is a red point on every bend of the sequence flow to allow you to move the bend location. Adding a new bend is easy too, simply click anywhere on the sequence flow and drag the red point that appears. You can move a sequence flow in parallel by moving the red rectangle that appears in the middle of the flow.

Your process model should now look like:

prc design 07

Of course, we still need to tell the engine which variables to initialize within the reset service task we just added. Select the service task and click the Init variables attribute, in the dialog that appears, enter the variables we want to initialize or reset for our case.

The first column can be left empty as our nextStep variable is in the process scope. Write nextStep in the variable name column and leave the last column empty as well as we simply want to clear the previous selection value. If you also want to clear the previously entered information request text, add an extra row to the dialog which should then look like the following:

prc design 08

Close the dialog and set the attribute Overwrite if existing to true (checked and green). This is necessary, as we explicitly want the variables to be overwritten if they already exist. If you left that option as false it would only initialize variables that do not exist yet, leaving any existing variable values untouched.

Save the process model and go back to the Tutorial App so you can redeploy it and test the updated behavior.

6. Model responsibilities / assignees

6.1. Getting familiar with responsibilities and sharing

Before we include the responsibilities (assignees) in our process, let’s have a look at the permission concepts behind edoras one. Every work item (a case, task, document, and so on) can have the following information concerning responsibilities and sharing:

Owner

By default, the creator of a new work item becomes its owner, although being the owner does not mean being responsible for working on it, rather more in a sense of being kept in the loop and always informed about what’s happening with that work item.

Assignee

The assignee is the person responsible for working and completing a work item. If manually set, the assignee is typically chosen by the owner of a work item.

Candidate groups

Setting one or more candidate groups makes the work item available to all users that are a member of any of the candidate groups. Assume you have a group named "Support" and use it as the candidate group for a support case. This makes all users who are members of the Support group potential assignees for the support case, and all of these members will have access to the work item.

Candidate users

The candidate users work the same way as the candidate groups, but instead of adding a group of users you can directly add selected users to be candidate users. They too will have access to the work item.

In order to have access to a work item you must either be the owner or the assignee of it, or be a member of one of the candidate groups, alternatively, you must have been added explicitly as a candidate user.

6.2. Getting familiar with account, group and user management

If we want to use groups and users in our App, it is important to also understand how they are managed in edoras one. Go to the Administrator dashboard by selecting it from the Dashboard menu (you need to have administrator permission in order to have access to this dashboard, of course). You will now see an overview of your accounts, groups and users in your tenant.

Accounts

Accounts are used to divide your tenants into organizational units, locations or whatever you want, but usually business units. Groups and users are then created within an account. Currently, the account does not have any impact on the visibility of work items. As we learned in the previous chapter, only groups and users directly control the visibility of work items.
What we can do is apply visual styling with CSS customizations for different accounts. The way to customise an account is by setting the field "CSS class" in the form for an account:

admin 01

Technically, this CSS class will be added to the same div that contains the class .edoras-one.
In custom.css there is a commented line to import the file accounts.css. This file contains an example of how to apply your custom styles. To use account CSS customizations, uncomment this line and replace account-example with the name of the CSS classes defined on your account. You can do this for several accounts by repeating the content and changing the class name. Elements that you do not want to customise can be safely removed from the accounts.css.

For "Cloud" solutions, there are some predefined account CSS classes:

Table 1. Account predefined "Cloud" css classes and colours
CSS Class Main Colour Main Dark Colour

account-brown

account-green

account-teal

account-blue

account-purple

account-pink

(empty/default)

To turn off UI customisation for the Account and use default colours, simply remove your class from the account form, leaving only the "account-" prefix.

To create a new Account, click Create or hit C and choose Create Account from the dialog, fill out the necessary information and create it by clicking Create.

Groups

Groups are used to specify a set of users. The meaning of a Group however, is entirely up to you. It could represent a group of people within your organization (for example, the support team, human resources or sales) or it could be used to represent a role (for example, approver, travel agent). By adding a group to a user, that user becomes a member of the group or role, and as a result will have access to any work item that has this group as a candidate group.
To create a new Group, click Create or hit C and choose Create Group from the dialog, fill out the necessary information and create it by clicking Create.

Users

Users allow people log in to edoras one and participate in the work. All users' settings are managed within their own user profile. A user’s profile can only be edited by the user or any administrator.
To create a new User, click Create or hit C and choose Create User from the dialog, fill out the necessary information and create it by clicking Create. It’s good practice to use their email address as the login name, although this is not mandatory.

Good Practice

Although accounts are not directly used for the visibility of work items, it’s good practice to create a Group for each Account with exactly the same name and use it to share work items with all users in that account. Of course, the users need to be added as members of that group as well.

6.3. Adding a travel agent group and requestor to task responsibilities

As we learned earlier, participants, groups and roles are modeled through pools and lanes in BPMN 2.
We currently have two different participants in our process: the requestor of the travel request, and the travel agent managing the request.

6.3.1. Creating a group for the travel agents

As we want to be able to assign tasks to the travel agent team, let’s first create a new group for it. Go to the Administrator Dashboard and click Create or hit C and choose Create Group from the dialog. Choose the primary account to which the group should be added (not the admin account) and set the group’s name to Travel Agents, and optionally add a description for that group, then hit Create in order to create our new group:

admin 02

Add yourself to the newly created group to make it easier to test the modified process later (so you don’t have to keep logging out and logging in to see and complete the travel agents tasks). In order to do that, choose User profile in the upper right corner menu, choose Manage Groups and select the new Travel Agents group, then hit Ok. You’ve just made yourself a member of the new group!

admin 03

6.3.2. Modeling the initial requestor’s responsibilities

The initiator of the travel request will be responsible for answering any open questions and eventually reviewing the travel bookings. In order to model that, navigate to our travel request management process and open it using the Design action (if the process modeler is not already open). Select the Answer Info Request user task and go to the Assignee (RT) property. RT means Runtime and allows us to use an expression to determine the assignee at runtime rather than a fixed user at design time. As we already know, the owner of a work item is set to the user that created it by default, so we simply can use an expression that references the owner of our root case to set the assignee of this task. Set the expression to #{root.ownerId} to automatically assign this user task to the same user as the owner of our travel request case. Remember that this is a backend expression, so we need #{} to tell the process engine what to do.

Your process should now look like this:

assignee 01

Select the Review Travel Bookings user task and follow the same steps, setting the Assignee (RT) property to #{root.ownerId}.

6.3.3. Modeling the travel agents responsibilities

For the travel agents tasks we will use the candidate group feature. This means the task will not be assigned to a single user directly, but rather to a group of users. This time, we leave the Assignee (RT) property empty but will set the Candidate groups property instead.
Select the Manage Travel Request user task and select Travel Agents from the Candidate groups property selection combobox:

assignee 02

If the Travel Agents group doesn’t appear, you might need to reload the process diagram first (only necessary if you created the new group after you opened the process diagram).

Now save the process model and go back to the tutorial App in order to redeploy it. If you create a new travel request, you should now see that the assignee for the requestor tasks is automatically set to the same user that started the request, and the management task is assigned to the Travel Agents group, so it will appear in all members' task list.

6.3.4. Use current user for future management tasks

In our previous step, we assigned the travel management task to a group rather than direct user assignment. This way, there are potentially several users that could claim the management task and organize the travel request. If there is no direct assignee set, the task will appear in the personal task lists of all users who are members of the group. This has implications later on, as we have a feedback-loop built into the travel request management process. If a travel agent needs some more information and the process goes back to the management task, ideally, we would like it to be automatically assigned to the same travel agent and not the whole travel agent group.
To do that, we’ll need to store the travel agent who completed the management task within the process instance, so we can use them again as the assignee for the management task.

Open the travel request management process (if not yet open) and make some space using the spacing tool after the Manage Travel Request user task. Drag & drop a new Initialize variables service task from the shape palette and drop it onto the sequence flow after the Manage Travel Request user task, naming it Store travel agent user. Whenever the previous user task is completed, this service task is executed and will store the current user ID to a process variable.

In the property section, select Overwrite if existing (true, green mark), so the variable will always be overwritten with the most recent travel agent. Now click the Init variables property and fill in the following information:

assignee 03

Set the first cell to root as we want to store the travel agent within the case context. We’ll use travelAgent as the variable name to store the current user ID. For the value, we can use the #{currentUserId} expression that always returns the ID of the current user, which in our case will be the travel manager who just completed the management task.

Our process should now look like this:

assignee 04

In order to use this new variable, select the Manage Travel Request user task and set #{root.travelAgent} as the 'Assignee (RT)' property, but still leave the candidate group property selected with our Travel Agents group:

assignee 05

What will happen now? Whenever the management task is completed, the current user ID is saved in a case variable named travelAgent, which will then used as the assignee expression if the management task is ever created again. This will result in an automatic assignment to the same travel agent handling the current travel request.

However, we still have a problem: the travelAgent variable is set the first time AFTER the management task, but the expression is used BEFORE that, so we need to add another Initialize variables task at the very beginning of the process to initialize this new variable in the case.
In order to do that, make some space just before the Reset next step selection task and drop a new Initialize variables task onto the sequence flow and name it Initialize travel agent variable. Select the Init variables property and enter the following information:

assignee 06

This time, we leave the value empty as we just want to initialize the variable; we don’t yet know the travel agent at this point of the process.

Now your process should look like this:

assignee 07

Save the process model and go back to the tutorial App in order to redeploy it. If you create a new travel request, use at least one feedback loop to create more than one management user task. You will see that the first one is not assigned to a particular user, but every further management task is assigned to the same user that completed the previous one.

7. Add approvers to the process

In this chapter we want to add optional approvers to the travel request. Let’s assume the travel agent has some regulations to follow, such as if the travel exceeds a certain cost, or if it includes traveling by airplane there must be an approval from one or more approvers.
To keep things easy, we’ll simply add a new option to the Select next step combobox in the Manage Travel Request user task to go into an approval phase of the travel request, so it’s up to the travel agent to decide whether an approval is necessary or not.
As a first step, we’ll just add one single approver and later extend it with as many as necessary. This way, we’ll learn how to use multi-subforms in combination with a multi-instance task to loop over the selected approvers.

7.1. Extend travel management task form for optional approval

First, we need to extend the travel management task form by adding a new possible next step.
Open the Travel Request Management process and click the + sign within the Manage Travel Request user task in order to open the task form.

Select the Select next step combobox and click the Options property. Now add a new option by clicking the Add button. Add the new approval option like the following:

approval 01

You can move the order of the new entry by selecting its row and clicking the up-arrow.

If the user selects this new option, we want to display a text field for them to enter any additional approval notes and, of course, select the approving user.
Drag & drop a new Rich textarea just below the Information request text area, name it Approval notes and bind it to {{root.approvalNotes}}. We only want to show this new field whenever the new step is selected, so set the Visible (RT) property to {{parent.nextStep=='approval'}}.

From the Predefined selections section of the shape palette, choose the User selection widget just below the Approval notes text area and name it Select approver. Change the binding expression to {{root.approver}}, make it required and set the Visible (RT) property to {{parent.nextStep=='approval'}} as well.

Your task form should now look like this:

approval 02

Now save the task form and switch back to the process in order to extend it with this new approval functionality.

7.2. Add approval step to the process

As we will be adding a new role to the process, let’s add a new lane to represent it. Drag & drop a Lane below the Travel Agent lane onto the existing process pool and name it Approver:

approval 03

From the existing gateway, drag a new user task out of it, drop it within the newly added Approver lane and name it Approve Travel Request.
Now select the sequence flow between the gateway and the newly added user task and name it approval. We also need to tell the process engine when to actually use this flow, so set the Condition expression to #{nextStep=='approval'}.

approval 04

Drag a new sequence flow out of the new approval task and connect it to the existing Reset next step selection task.
There are now three incoming sequence flows to that task and it’s good practice to use a joining gateway before that task for better visibility of the flow, although it isn’t necessary by the BPMN 2 standard.
To be able to do that, make some more space (using the spacing tool, if you remember) before the Reset next step selection task and drop a new Exclusive gateway onto the sequence flow. Then you have to re-connect the existing sequence flow leading into the Reset next step selection task to the newly added gateway. You can do so by hovering over the sequence flow you want to re-connect until the green circle handles become visible, then drag & drop it using those green handles to the new gateway.

Your process should now look like this:

approval 05

Next, we need to set the assignee for the approval task to be the person we selected in the management task. Select the Approve Travel Request user task and set the Assignee (RT) property to #{root.approver}.

The only remaining missing thing is the approval task form, so let’s create one. Select the Approve Travel Request user task, open the attributes and click on the form reference in the Specific Attributes section. Then select New and click the OK button to create a new task form.

Drag & drop a new Output textarea to the form in order to add some information for this approval task. Double-click it to open the editor for its content and add the following:

approval 06

Notice the expressions we used in the output widget. First of all, they are frontend expressions using double-curly braces, as they will be rendered in the form engine running on the frontend. {{root.name}} actually renders the travel requests name (case name or root name). {{root.approvalNotes}} is the notes field we added within the management task form to allow the travel agent to add special notes for the approver. Finally, we have {{root.travelAgent}}, which will be automatically set after the management task has been completed by the travel agent, using a Initialize variable task.

When it comes to the decision widget for the approver, we basically have two choices: using a checkbox (for instance, if we have yes / no options) or using a selection combobox, the latter being a little bit more verbose and, of course, can have more than two options.

Drag & drop a Static select widget below the output text area and name it Please make your decision. Then double-click the widget and enter {{root.approvalDecision}} for the data binding (or enter it in the value property). Also, make the field required (by either clicking the red small star of the widget or checking the Required property).

Now click the Options property and enter the following values to the dialog:

approval 07

Finally, let’s add a Rich textarea, name it Decision notes and set the data binding to {{root.approvalDecisionNotes}} to let the approver add any special notes about the decision.

The form should now look like this:

approval 08

Save the form, name it Travel Request Approval Task Form and switch back to the process model and save it too.

What did we do? We added a new option to the Manage Travel Request task for getting approval for the travel request, added the approval user task and routed the process back to the travel agent, who then needs to decide whether to further organize the travel or stop it (if approval wasn’t given). How does the travel agent know about the decision made by the approver? We can add this information back to the management task, so they have everything there.

Let’s go back to the process, select the Manage Travel Request user task, open the attributes and click on the form reference in the Specific Attributes section. Then select Reference and click the OK button to open the task form. You can also switch to the task form, if it is still open.
There are several options for how we could add this information. As it is read-only information, we can display it using another output widget that we only want to show if there is an approval already done.
Add a new Output textarea and drop it below the Travel notes rich textarea, double-click it and set it to this content:

approval 09

We only want to show this widget if the approval has already been given. We can do so by using the Visible (RT) property we’ve used before. Select the output widget and enter {{root.approvalDecision}} in the Visible (RT) property. This way, the widget will only be shown if the approval variable is set, which can only be the case after the approval task has completed.

Save the form and go back to the Tutorial App to redeploy it. Start a new travel request, select the Need approval option, select an approver (yourself, to avoid logging out and logging in again) and you should end up at our new approval task.

approval 10

As we look at the approval task now, we have some room for improvement. First of all, do you see how the expression {{root.travelAgent}} is rendered? It’s some cryptic user ID rather than the users name. The backend could support something like #{root.travelAgent.name} in order to access the name of that user, but the frontend doesn’t currently provide that.
So, what options do we have? Remember the Initialize variable service task we used to store the travel agent ID after the Manage Travel Request user task? Let’s add another variable to hold the travel agents name.
Open the Travel Request Management process and select the Store travel agent user task. Click the Init variables property and add the following variable initialization:

approval 11

Save the process and open the Travel Request Approval Task (or switch to it, if it’s still open). Double-click the output widget at the top of the form and replace {{root.travelAgent}} with {{root.travelAgentName}}, so it uses the user’s name rather than their ID.

Save the form, go back to the Tutorial App, redeploy it and test the process again.

To further improve the process, you can add the approvers name and ID as a variable and render it in the output widget in the management task, to let the travel agent know which approver finally approved or declined the travel request. If you remember how we saved the travel agents ID and name and used it in the approval output widget, hopefully, you should be able to do that on your own now.

If not, here are the basic steps:

  • Add a new Initialize variables task after the Approve Travel Request user task and add root | approverName | #{currentUserId.name} to it

  • In the Manage Travel Request user task, add this information to the output widget (something like The travel request has been {{root.approvalDecision}} by {{root.approverName}}…​).

8. Sending emails from within the process

In this chapter we’re going to learn how to create and use email templates within a process. The basic idea is to send out an email to the requestor and travel manager of a new travel request if it is declined by the approver.
Of course, this might not be the best way to end the process after the travel was declined, but it gives us the opportunity to use email templates in our existing example.

8.1. Create email template

We want to create the email template as the first step, so go to the Tutorial App and hit C or click the Create button and choose Create Mail Model and name it Travel Request Declined Email Template. You can hit Create now and fill in the rest of the template later, or complete the email template within the Create Mail Model form.

Now create the template so it looks like this:

email template 01

8.2. Add gateway for approval decision

As we only want to send the email if the travel request was declined, we need to add a new gateway after the approval user task. Open the Travel Request Management Process and make some space at the bottom of the lane in order to add a new gateway. Reroute the existing sequence flow so the process looks similar to this:

email template 02

After adding the new elements and rerouting the sequence flows accordingly, we need to add the conditions for the new sequence flows leaving our new gateway to tell the engine which flow to take.
Select the sequence flow with the label yes and set the property Condition expression to #{root.approvalDecision=='approved'} and for the no labeled flow use the expression #{root.approvalDecision=='declined'}. After this, whenever a travel request is declined, the process will end directly without any notification.

8.3. Send email if approval was declined

Abruptly ending the travel request process just because a request is not approved isn’t the most friendly solution, so we want to integrate our email template and send out a notification email once the request is declined.
Go to the Travel Request Management Process and make some space between the gateway and the end event, to give us room for a new email task. Now drag & drop a new Send mail service task onto the no sequence flow and name it Send decline notification email.

Select the Travel Request Declined Email Template as the Mail model for the Send mail service task, so this will be used when creating the email subject and body to be sent. We want to send the email to our initial requestor and CC to the travel agent. To do that, we’ll use #{root.ownerId} for the Mail recipient property and #{root.travelAgent} for the Mail CC one.
Your process should now look like the following:

email template 03
As an email recipient you can either specify a fixed email address, like john.doe@mycorp.com, or you can specify an expression that evaluates as an email address, like #{root.useEmail} (where useEmail might be a text field where an email address has already been provided) or you can specify an expression that evaluates as an edoras one user. In the latter case, the email address of that edoras one user is used to send the email to. For our travel request, #{root.ownerId} will resolve to the initial requestor and #{root.travelAgent} will resolve to the last travel agent managing the travel request.

When you are testing the email functionality, please note that it may take several minutes before you receive the email.

9. Create document models

In this chapter we will learn how to create document models, which can be used in a variety of ways, as we’ll see.
First of all, documents can either be created manually, in the same way that ad-hoc tasks are created, or they can be created as part of a process task.

Documents can have properties (metadata), designed using init-forms and work-forms, exactly as we did with task models.

9.1. Create document properties form

A document might have some properties (metadata) stored as variables that can be used to classify it or allow it to be found later. This is done using a form in just the same way as for cases or tasks, to create a document or to manage the metadata of a document.

Go to the Tutorial App and hit C or click Create and select Create Form Model, name it Travel Request Document Form and click Create and design. Drag & drop the Name and Description fields onto the canvas. Let’s assume we want to select an assignee for the document, so drag & drop the Assignee selection widget below the description. To share the document with other groups, we could drag & drop the Share with groups selection widget as well.

If you want to have more metadata for your document, just add more fields to the form; you can design the document form in the same way as for tasks or cases.

The document form should now look like this:

document model 01

If we want to be able to upload content during the creation of the document (init-form), we can add an upload-widget. Drag & drop the Upload widget to the top of the form (before the name field) and name it Upload document. This is a special widget that’s only used for uploading the content of a work item (in this case, a document), so we don’t need any special data binding.

We only want the upload widget, the assignee selection and the share with group field to be visible during the initialization of the document, but we’d like the form to be used as both init-form and work-form. There is a way to achieve this using the Visible (RT) property to show or hide a widget, depending on whether the form is used as an init-form or as a work-form.

Use the expression {{!root.id}} for the Visible (RT) property to show a widget only when the form is used as an init-form. If you want to hide a widget when the form is used as an init-form, use the expression {{root.id}} for the Visible (RT) property. What does {{root.id}} mean? Well, it references the ID of the root work item, typically a case, and when we use a form as the init-form, we don’t have a case yet, so there is no ID. We can use this expression to show or hide the widget based on the existence or not of the root ID.

With that knowledge, let’s add {{!root.id}} as the Visible (RT) property for the Upload widget, as well as for the Assignee and the Share with groups widgets.

The document form should now look like this:

document model 02

Save the form and go back to the tutorial app.

9.2. Document models with content being uploaded

Using the document form we just created, we want to create a new document model within our Tutorial App, so go back to the tutorial app and hit C or click the Create button and select Create Document Model, name it Travel Request Document and select Travel Request Document Form for both the Init form and Work form. Now create it, navigate back to the Tutorial App and deploy it, so we can test our new document model.

9.2.1. Upload new document to a case

Go back to the user dashboard and open one of your previous travel cases. The same way we created an ad-hoc task, we can create or upload a new document in the case by clicking the Create button and select Create document. In the Template selection, choose Travel Request Document and click the Add... button to select a document to upload. It should automatically set the name of your selected document to the form we created, but can you change it if you want.
Also, if you want, you can select an assignee for the document, as well as share it with some groups.

Creating a new document should look similar to this:

document model 03

After creating it, you will notice the assignee, share with groups and upload widget are no longer visible. As you’ll remember, we used the Visible (RT) flag to hide it for the work-form but show it within the init-form.

9.2.2. Getting familiar with the document views and actions

document model 04

Having created our new document, let’s look at the different views and actions a document provides.
The first view (eye-icon) is a preview of the document, which is currently provided for images, PDFs, OpenOffice and Microsoft Office documents (Word, Excel and Powerpoint). The second view is the work form for the document, similar to the forms for any work item (such as cases or tasks). Then we have the comment view where you can see and add comments for the work item. The last two views are for developers or modelers, allowing you to see all the data of the work item in a generic form or represented in JSON.

Here is the list of actions:

  • Assign lets you change the owner and assignee of the work item (document, in this case)

  • Share lets you share the work item with groups of users

  • Move to move the current work item to another case

  • Update Placeholders will update the content of placeholders within a document, if it was created from a template (more on this later)

  • Upload Document allows you to upload, optionally overwriting the current content with a new document.

  • Download allows you to download the content of the document to your local machine

  • Archive will close and archive the document

To manage the actions available in the document model form, select the document model in the Tutorial App, click Edit Entity and scroll to the section Allowed Actions.

9.3. Document models with a file template

We’ve learned how we can create and use a document work item from uploadable content. In our next step, we will attach a file template, also called a skeleton, to the document model. Go back to the tutorial app and select the Travel Request Document and click the Upload skeleton button. You can now upload a document that will be used as the template whenever we create a new document based on that model. Choose an empty Word document for now, and we will use it again later with placeholders.
After having uploaded the document, you will see it in the preview (even if it is a Word document).

document model 05

Now have a file template attached to the document model, we really don’t need the upload widget in the init-form anymore, so go to the Travel Request Document Form, remove the Upload widget and save the form.

Go back to the Tutorial App, redeploy it, switch back to the user dashboard and navigate into one of your previous cases. Click Create, select Create Document, select Travel Request Document, choose any name you want for the document and click Create. If you go to the Preview (eye icon), you will see a document that looks the same as you used for the skeleton in the document model.

Whenever there is a skeleton file attached to a document model in an App, it will create a copy of it and store it in the case in which the document was created.

9.4. Document models with a file template containing placeholders

We’ve learned how document skeletons can be used as the template that is copied when a new document is created. In our next step, we will add placeholder fields in the document so we can automatically fill in data from the root case of the document.
Go back to the Tutorial App, select our Travel Request Document and click Edit skeleton, which should open the document in Microsoft Word. If the Java plugin for the Office integration is not supported in your browser, you can just use the Download skeleton button, save it to your desktop and open the document from there.

Now write your travel request document template and use text fields for the placeholders (you typically find them in the developer tools of Microsoft Word). Your document could now look like this:

document model 06

Double-clicking a placeholder opens up its details:

document model 07

The important information is the text marker name, which we will use later for data binding. We’re using the expression we’re going to map to afterwards as the standard text, but this is not mandatory, only good practice to see where data will be filled in.

I used the following placeholder information:

  • caseName, will later be bound to #{root.name}

  • travelOrigin, will later be bound to #{root.travelOrigin}

  • travelDestination, will later be bound to #{root.travelDestination}

  • outwardTripDate, will later be bound to #{root.outwardTripDate}

  • returnTripDate, will later be bound to #{root.returnTripDate}

  • approverName, will later be bound to #{root.approverName}

  • approvalDecision, will later be bound to #{root.approvalDecision}

It’s good practice to use the same name for the text field as for the variable name that the field will be bound to later, although this is not strictly required.

Now save the Word document. You need to use the Upload skeleton action and upload the saved Word document again.

Navigate to the Tutorial App and redeploy it, then switch to the user dashboard, select one of your previously created cases and create a new document the same way we did before.

Your document in the case should now look similar to this:

document model 08

As you can see, the request name has not been properly set within the title, which is because we used caseName as the name of the marker and this is not a variable name that’s available in our travel request case. Not only that, we’d really like to change the formatting of the dates as well, so let’s see how we can do that.

9.4.1. Mapping expressions to placeholder names in a document template

If we do not want to use a direct mapping by using the same name for the text marker as the name of the variable to be filled in, we can create a mapping using an expression. To do that, go back to our Travel Request Document model in the Tutorial App and navigate to the work-form view (the preview is active by default).

At the bottom of the view, you will see a section labelled Placeholders from where you can add mappings by clicking the Add Placeholder button for each mapping you want to configure. For every placeholder with a mapping, the engine will first evaluate your expression and then use this as the value to substitute in the text field.

Add the following placeholder configurations to the document template:

  • caseName with expression #{root.name}

  • outwardTripDate with expression #{formatDate(root.outwardTripDate, 'dd.MM.yyyy')}

  • returnTripDate with expression #{formatDate(root.returnTripDate, 'dd.MM.yyyy')}

The placeholder section should now look like this:

document model 09
We used a function in our expression, formatDate(date, format), which takes a date object as its first parameter and a date formatting string as the second. Please refer to the reference documentation to see further functions and what you can do with the expression language.

Now save the document model, go to the Tutorial App, redeploy it and create another document in your case which should look similar to this:

document model 10

9.5. Create documents from within a process

We’ve so far learned how to create a document model, use skeletons and further improve them with placeholders (optionally with placeholder mappings using expressions). Our next step takes us back to the process model, where we want to automatically create our document as part of the process. Go to the Tutorial App and open the Travel Request Management Process.

Drag & drop a new Create document service task onto the sequence flow, right after the last Review Travel Bookings user task, and name it Create Travel Doc. In the property Document model, choose our recently created Travel Request Document model and use root.travelDoc as the Document id variable name property. You can optionally specify the name for the document using the Document name variable, so we’ll set it to #{root.name}.docx.

Your process should now look like this:

document model 11
Using a variable name for the document ID will give us the ability to reference this specific document later by using that variable.

You can now save the process model, redeploy the app and start a new travel request or start the travel management process within an existing case again. By the end of the process, our document will have been created from the template using the data from the case, and stored within the case.

9.6. Send documents as attachments to an email

As a final step, we want to send a document from our case as an attachment to an email. Go back to our Travel Request Management Process and make some space before the Send decline notification email task. Before we can use the document as the attachment in that email, we first have to create it using the same task we added in our last step. We could add a new Create document task again or we can copy & paste our existing one, so we don’t have to enter all properties again. You can do so by selecting the existing Create Travel Doc task, using the Copy button or hit Ctrl-C to copy it and then the Paste button or Ctrl-V to paste it. Drag this copy and drop it onto the sequence flow just before the Send decline notification email task.

Your process should now look like this:

document model 12

Select the Send decline notification email task, click the Attachment ids property and enter #{root.travelDoc} in the property dialog.

Save the process, redeploy the app and start the process again or create a new travel request. Make sure to use the approval path and decline it in order to send an email with the document as an attachment.

10. Create convenience queries

Queries are a kind of work item that allow the saving and optional sharing of a custom query, which when executed acts like a filter that returns a list of work items. If you’re familiar with the search in edoras one, then you’re almost there, as a query is nothing other than a saved search request that can be executed at any time later.

And that’s exactly how you can actually create a new query: simply type some search terms in the search box, hit Enter and then use the Create Query button to save it.

You can use a simple search just by entering words to search for. More powerfully, you can use advanced search terms, so for example, type:CAS or for:me would search for cases only assigned to the current user.

10.1. Create query to return all open travel request cases

If we want to get a list of all open travel request cases, here’s the way to create an appropriate query item:

  • click the search box and enter type:CAS and hit Enter to see a list of cases

  • now add state:open as a second term and hit Enter to see only open cases

  • add model:'Travel Request' as a next term and hit Enter to just see open travel request cases

You probably noticed that some of the terms are being removed from the search box and represented using the predefined, simple search selection, for example the state and type terms or even the sort term.

Once you have the results in the way you want them, click the Create Query button, add a name for it and click Create. If you go back to the user dashboard, you will see the new query item in the list of My Queries.
If you wish, you can share a query item with others by using the Share action. This will mean other users will have the opportunity to see and use that query in their own dashboards.

10.2. Execute and change an existing query item

Once you’ve created a query item, it’s simple to use it by just clicking it in the user dashboard. It will then be executed and return a list of work items matching the query terms.
If you select the Work Form view at a later time, you can change the name and query term for the item and save it the same way you would with a case or task item. Alternatively, you can use the Share action to add some groups you want to share the query item with.

10.3. Exporting the data returned by a query item

Once you’ve execute a query item, you can export its results and data by clicking the Export Query Data button. This will create an Excel file containing all data from the returned work items.
Currently, you can’t configure what data is exported, so the Excel file can become quite large.

11. Create your own dashboard

In this chapter, we are going to create our own dashboard and we will learn how to set it in our user profile to be used as our default dashboard.
Currently, there’s not a specific confugration feature for custom user dashboards, so we’ll be using one of the general customization capabilities of the edora one platform.

11.1. Using a case model to represent our own dashboard

We are going to model and design a case to act as our dashboard. Since we can design a working form for a case, we can design it in such a way that it could act as our dashboard. We can’t use it directly, so we need to create an instance of the case and find its unique URL, then store this URL as the default one in our user profile and we’re done!

11.2. Designing the form for our dashboard

This is exactly the same as we’ve done many times now in this tutorial, so go to the Tutorial App, hit C or click the Create button and select Create Form Model to create our dashboard view. Name the form Dashboard View as it’s more a view than a form, then click Create and Design to directly create the form model and open it in edoras vis to design it.

Drag & drop an Output textarea on to the top of the form, so we can add some information about the dashboard. Double-click it and add something like this to it:

dashboard 01

We want to add some lists of information to the dashboard, so drag & drop a new List widget onto the form and remove the label by deleting its predefined text. Lists show work items retrieved using a query term. Still remember the query items from our last chapter? A list widget is based on exactly the same query terms and uses the same search functionality as a query item or the global search action in edoras one.

Now select the newly added List widget and set the Title property to Open travel requests.

With the Format property we can specify how the labels of the items in the list will be displayed. By default, it will use the name of the work item. We would like to also include the original requestor of the travel request, so let’s set the Format property to {{item.name}} (Requestor: {{item.owner.name}}), which will include the name of the requestor after the name of the travel request case.

Set the Query property to the following search term: type:CAS state:open model:'Travel Request' sort:creation:desc

We can limit the height of the list widget by setting the property Maximum number of rows, for example, to 10.

Your form should now look like this:

dashboard 02

We would like to add two more lists, one of them only showing the Manage Travel Request user tasks, and the other showing all open tasks, regardless the type of case or app.
First the management tasks: drag & drop another List widget to the right-hand side of the existing list and configure the following properties:

  • set the Label property to an empty value to hide it (we’ll use the Title property instead)

  • set the Query property to type:TSK state:open for:me name:'Manage Travel Request' sort:creation:asc

  • set the Title property to My open management tasks

  • set the Format property to {{item.name}} ({{item.root.name}}), so we include the name of the travel request case after the task name

Add a third List widget to the far right of the same row as the two other lists. If we want the three list widgets to be equally spaced, use the handle on the right or left-hand side of the widget to drag it to the left or right until it spans as many cells as you want (four, in our case, to have three equally spaced lists).

Set the properties of the third list widget to the following values:

  • set the Label property to an empty string to hide it (again. we’ll use the Title property instead)

  • set the Query property to type:TSK state:open for:me sort:creation:asc

  • set the Title property to All my open tasks

  • set the Format property to {{item.name}} ({{item.root.name}}), so we include the name of the travel request case after the task name

Suppose we want to add an instant-filter field to the first list, to allow the user to filter the list to find a particular travel request. Drag & drop a new Text widget between the Output textarea and the List widget on the left. Then drag its right-hand side handle to the left in order to let it span the same number of columns as the list widget and name it Search. Set its value binding to {{caseSearch}}. We can now use that variable within the Query property of our first List widget to dynamically update the saved search terms for the resulting case list.

Select the first List widget (containing the open travel request cases) and add {{caseSearch}} at the end of Query, so it now is configured as type:CAS state:open model:'Travel Request' sort:creation:asc {{caseSearch}}.

The dashboard view should now look like this:

dashboard 03

Now let’s save the form and return back to our Tutorial App.

11.3. Creating the case model for the dashboard

As we said above, we’re going to model a case to represent our dashboard. Hit C or click the Create button and select Create Case Model then use Travel Management Dashboard as the name and set the Dashboard View for the Init Form and Work Form properties. Remove all selections from the Allowed Actions section, except the Create Variables action, as although we don’t want to work with that special case, we do want to display it. If you want to share the dashboard with others, you can select the appropriate groups within the Candidate Groups property.

Now click the Create button and redeploy the Tutorial App, then go to the user dashboard.

11.4. Creating an instance of our dashboard

Before we can set the dashboard as our default one, we need to create a case instance based on that case model, so hit C or click the Create button within the user dashboard, select our Travel Management Dashboard template and click Create.

If you want to avoid having a case with an empty name, use the Edit view (only available as an admin or modeler) and set the Name field to something like Travel Management Dashboard and click the Save button.

Your dashboard should now look similar to this one:

dashboard 04

11.4.1. Hiding the Save and Cancel buttons in the dashboard

Because our dashboard is a simple case, the Save and the Cancel buttons are still shown in our dashboard view, but we don’t want them there. Here’s a technique to hide those buttons by adding a hidden widget to the Dashboard View form that will cause the form engine to hide the buttons.

  • Go to the Dashboard View form and add a Checkbox widget at the end of the form.

  • Set the Value to {{_hideSavePane}}.

  • Set the Default value to true (enabled).

  • Set Style class to hidden.

  • Make sure the Visible attribute is enabled (true).

  • Label it (Hide Buttons Widget) to indicate what it’s used for.

Redeploy the Tutorial App and migrate the current dashboard case.

Your dashboard should now look similar to this one:

dashboard 05
The Manage Travel Request task will be assigned to you if it went through an approval loop.

11.5. Adding count widgets to the dashboard view

Assume we have a lot of open tasks or cases and we can’t see all of them in the list widget, but would like to know how many there are. There are special Count widgets that allow us to display a link with a count of work items based on its associated query.
Go back to the Dashboard View form designer and add new Search count link widgets just below each of our list widgets, making their width span equally with the list widget they belong to.
Remove the label, as we only want to display the link text that includes the count of work items in the list.

For the first count widget, use the following properties:

  • set the Link text property to $count open travel request [case|cases] found

  • set the Query property to type:CAS state:open model:'Travel Request' (for the count query we obviously don’t need the sort term and we always want to show all open travel request cases, so we remove the caseSearch term)

  • set the Target property to _self to set the navigation to the same window

For the second count widget, use the following properties:

  • set the Link text property to $count open travel management [task|tasks] found, assigned to me

  • set the Query property to type:TSK state:open for:me name:'Manage Travel Request' (again, we don’t need the sort term)

  • set the Target property to _self to set the navigation to the same window

For the third count widget, use the following properties:

  • set the Link text property to $count open [task|tasks] found assigned to me

  • set the Query property to type:TSK state:open for:me

  • set the Target property to _self to set the navigation to the same window

The $count term is a special term which will be set to the count result returned by executing the query.
In the [x|y] term, the x gives the text to be used if the count is exactly 1 and y will be used if the count is more than 1.

Your dashboard view should now look similar to this one:

dashboard 06

Go to the Tutorial App, redeploy it, go to the Travel Management Dashboard case and click the Migrate action in order to update our dashboard case to the latest version.

Your dashboard view now should look like this:

dashboard 07

11.6. Adding create buttons to the dashboard view

As a next step, we would like to add a new Create button to the dashboard view so a user can create a new Travel Request without using the general Create button.
Go back to the Dashboard View form and add a new Create button below the first count widget and resize it to only span four columns.
Use Create new travel request as the Button text property, choose Case as the Work item type property and select Travel Request as the Work item model property.
This will create a button that navigates directly to the init-form for a new travel request (the same URL, actually, as if you had clicked the create button and selected the travel request template).

Your dashboard view now should look like this:

dashboard 08

Go to the Tutorial App, redeploy it, go to the Travel Management Dashboard case and click the Migrate action in order to update our dashboard case to the latest version.

Your dashboard view now should look like this:

dashboard 09

If you click the Create new travel request button, you will go directly to the init form and be able to create a new Travel Request.

11.7. Passing local context variables to the init form with a create button

Let’s say we want to add some information we already have on the dashboard form and pass it to the init form being invoked by clicking a create button. We can do so by using context parameters.

To visually separate the create button from the list widgets, let’s add a horizontal line between them by dragging & dropping a new Horizontal line between the count widgets and the create button.
Then move the create button to the same four columns as the second list widget, giving us space to add a new text field to the first four columns.
Now drag a new Text widget and drop it on the left-hand side of our create button, name it Request name and bind it to {{travelRequestName}}. Optionally, you can specify a description by setting the Description property to Set the new travel request name used for creating a new travel request.

Next, select the create button and click the Context variables property and enter the following in the property dialog:

dashboard 10

We’ll use the value from our newly added text field, ({{travelRequestName}}), and pass it along to the init-form as the name property, so our name field in the init-form will become prepopulated with that value.

Your view should now look like this:

dashboard 11

Go to the Tutorial App, redeploy it, go to the Travel Management Dashboard case and click the Migrate action in order to update our dashboard case to the latest version.
If you now enter some text in the request name field and click the create button, that text is passed along and directly added to the init-form.

If you want, you can add even more fields and functionality to your dashboard view.

11.8. Setting our dashboard as the default one

Now we’ve created our dashboard case, we would like to use it as the default one for the user dashboard.
First, make sure our new custom dashboard is currently shown and copy the URL-part starting with the CAS part (something like CAS/GEAR-xxxx/browse).
We can then set it as the default dashboard by going to our user profile (select the User profile menu action in the top right menu bar) and pasting the copied URL to the Home URL field, finally saving the user profile.

dashboard 12

To make the changes visible, you will probably need to refresh the current view, and then you should find yourself looking directly at your new, custom dashboard!
You can always navigate to it by clicking the logo in the top menu bar. If you want to go back to the standard user dashboard, you can do so by selecting it from the dashboard menu or with the Home icon in the menu bar.