1. Intro

This step-by-step tutorial will help edoras one modelers to get started with modeling 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, which can be found here: http://documentation.edorasware.com

1.1. What you will learn

By executing this tutorial step by step, you will learn how to create your own App, which includes the following steps and learning content.

1.1.1. Basic modeling techniques

  • Creating case models

  • Design forms

  • Design processes

  • Creating ad-hoc task models

  • Creating email templates

1.1.2. Advanced modeling

  • …​

1.2. Tutorial App

In this tutorial you will create a new App, which will handle a travel request. A person in need of traveling will create a new travel request and a travel agent is organizing the necessary bookings for the traveling.

The request process is built step by step by 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 are able to attach any necessary information like reservation information, vouchers and the like 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.

Tip
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 will find the shape repository, the main canvas for the form design in the middle and on the right hand side you find the attributes of the currently selected widget (component) of the canvas.

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

The layout is responsive having 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 repository has several sections to choose from. Use any predefined widgets in order to not having to care about bindings and any other technical issues. The widget section on the other hand has a collection of all available widgets which can be used by 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. Those fields are always available; each work item is supporting them.

Now drag and 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 that, 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 will split up the row into two parts and now having two fields in the same row, both spanning six slots.

Tip
Instead of navigating through the shape repository, 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 repository and type the name of the widget into the search field (e.g. text).

By selecting a field and clicking the red star icon, it will make the fields mandatory. Do this for both Fields. You can do the same by clicking the Required attribute on the right side.

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 on how data is stored and managed within edoras one.

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

In order to enter or show data of work items, the 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 are telling the form engine where to save and load the data for a particular field.

Let’s save the origin in a variable called 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 / retrieved from the very work item the form is used for.

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 and drop two Date fields to 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 to the date picker.

You can do so by selecting the date field and then click 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. Here we want to ensure that the selected date is not smaller then 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

Now 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 tap 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 the init and the work form of the case

  • Everything else can be left as it is by default, we will adapt that later

Now 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 your 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.

On the right side menu you can select Deploy which opens the deploy dialog. Navigate to the end of the form and click OK to deploy the App and make it available within the user dashboard so we can now test it.

app deploy 01

2.5. Test the App

In order to test the newly deployed App, we switch back to the user dashboard. You can do so by manually 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 as we designed it. Please note the validations and within the date picker, specifically see that you will not be able to enter a date earlier than today.

create case 01

Click Create to start the new case. You will see the newly created case with the same form as we used it for both, the init and the work form. So you will be able to change any data and click Save in order to change the data for that case.

create case 02

2.6. Getting familiar with the 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

let’s you specify the owner and current assignee of the work item

Share

let’s you share the work item with one or more groups

Start Process

start 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 of 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 for 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

a JSON representation of the current work item, which can also be modified (be very careful in doing so as you could break data of the work item by modifying it’s JSON representation)

3. Basic process modeling

In this chapter you will learn how to create your first process and attach it to the previously created case model in order to start it automatically once 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 opened and click Create or hit c. Now let’s choose Create Process Model and enter Travel Request Management Process as it’s name and click Create and Design in order to create the process model and directly open it in the process modeler.

create prc model 01

3.2. Getting familiar with the process modeler

The process modeler is quite similar in it’s basic functionality as the form designer. On the left hand side you find the shape repository with several sections where you can choose process elements from, the middle area is the main process canvas where you design the process and the right hand side is showing the attributes of the currently selected element in the process canvas.

You can add elements to the process by simply drag and drop them from the shape repository onto the canvas.

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

prc modeler action 01

Activating it will allow you to simply extend (enlarge) the process model or make it smaller. Give it a try once you have some elements on the canvas and make yourself familiar with that feature. Simply turn it off by clicking it once again and deselecting it.

3.3. Add a pool and lanes to the process

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

Go to the Roles section in the shape repository, drag and 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 repository and drag it to the bottom part of the pool, which will add it as a second lane below the existing one. Name it Travel Agent. Using the spacing tool mentioned before, it’s easy to make the lanes smaller or larger according to the needs.

prc modeling 02

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

Now we created two lanes representing two different types of involved people in the process, the requestor actually creating the travel request and the travel agent, responsible to manage the travel.

Let’s add a start event to the process by dragging the Start event element from the Execution section of the shape repository onto the Requestor lane. As long as that element is selected, you should see the fast-modeling menu right next to the element. Click the user symbol in order to add a user task right after the start event. Name it Manage Travel Request, click on the user symbol again and name the next task Review Travel Bookings and then 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.

prc modeling 03

Now let’s move the tasks into the right lane by simply 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, elements, etc.

prc modeling 04

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

Now save the process model by clicking on the save action in the menu bar (ignore the warnings for now, we will add task forms later) and go back 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 now created a first, yet 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 we did.

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

Did you note 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 within 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 for the navigation back to the case or you can also use the browser-back button to go back. Navigating to the task means, selecting it as the current work item. As you probably noted, this will change the available views and actions, always reflecting the possibilities of 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 we got working with the task. There is a new view, called Preview, selecting it will show you the process with a red border around the current task.

case testing 04

Go back to the work form by clicking on the form view button, add some notes and click Complete. This will complete the task and hand over the control back to the process engine continuing with the process execution and in our case will lead 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 make sure that the children view does not show the badge again as there are no more open tasks available.

3.7. Create user task forms for process execution

As we haven’t created specific user task forms yet, you realized that there were default forms used. Of course this doesn’t make much sense and we want to improve the two user tasks by designing task forms for them, showing all necessary information needed to complete the 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 options to create / 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.

Now you can choose between selecting an existing form (of course we don’t have any suitable form yet) and creating a new one. And that’s what we are going to do, so choose New. The form designer is opened again with a new form to be designed, which is 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 on how the data is organized in the work item hierarchy. The process is started within the case, so 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, so think of a hierarchy, where the case is the root, having a process as a child and the process having a task as it’s child. You can store data on every work item and every work item has also access to the data of it’s parent up to the root. But of course when building form data bindings, you have to be aware of the hierarchy and where the form is actually used. Bindings like {{foo}} without any prefix are always bound to the work item that form is used with. Let’s say you want to store / read data in the case, use the root prefix, for example the {{root.foo}} would store / read the data from the case’s variable named foo. You can also use parent as a prefix in order to go up one hierarchy level of the current work item. In a user-task, the parent would be the process.

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 a good practice to include the data the current task needs on the task form. As a first step, we add an Output textarea to it in order to display the travel request in a read-only way. Drag and drop an Output textarea from the shape repository onto the form and don’t enter a label name, 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 the same way you did with the bindings of the 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, which is stored in the case. Make sure you use the very same variable names 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 not only to be shown, but also to be editable by the travel agent, so let’s include the notes field to the form using the predefined widget named Case description. Drag and drop the Case description field from the Predefined bindings in the shape repository below the output widget on the form and rename it’s label to Travel notes.

We can now additionally add some description to the notes field to let the travel agent now, that he should enter additional information in there. Select the travel notes field and click in 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 name Manage Travel Request Task Form. In order to re-use the output widget with the all the information in it, select the output text area widget and copy it. Now you can 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 select New again. In the new form designer, paste the output widget we previously copied from the first user task form. Note that copy / paste is supported not only within the same model, but also across models, which is quite handy sometimes.

Double click the output widget in order to adapt it’s content to reflect the current task we want to create the form for. As this is just a review task, we also include the traveling notes in there directly rather than put the 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 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, create a new travel request and step through the process.

Make sure you save the process model too as we now mapped the newly created forms in there, before you redeploy the App!

After redeploying the App again, create a new case again, 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 is reflected correctly.

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 user-friendlier and add an attachment widget to it and 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 place a comment for the attachment widget for the user to understand how to use it in our context. Drag and drop an Output textarea to the bottom of the form, don’t add a label but double-click the widget to open the rich editor and enter something like this:

form design 01

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

form design 02

Now let’s fine-tune the widget by selecting it and change some attributes. First, let’s customize the Select file message by exchanging 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 available. Set the Thumbnail maximum height to 200 to prevent big pictures from useing to 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 again creating a new case, 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 that App will be deployed to the runtime of the edoras one platform and so 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 models. By default, the deploy mechanism is using a careful strategy by don’t migrating existing instance like cases, processes and tasks. This means, they will still be mapped to exactly the version they have been created with until they are either completed or migrated to a newer version.

4.2.2. Migrate existing travel request cases to newest version

For now, we want our cases to already reflect the newest change 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 action menu of the case model and migrate all existing cases to the newest, 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 reflect the newest version. You should see the attachment widget by now:

case testing 01

Click the upload icon and attach an image for instance. 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

Now we also want to add that attachment widget to the task forms. We could do this the same way as we did before by copy / paste it. But this time we want to learn a new feature within forms, sub forms, a great way for re-using existing parts of forms, either due to technical reasons or due to design reasons, doesn’t matter.

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

First, go back to the case form designer and select the output widget AND the attachment widget and copy them into the clipboard. Switch back to the new, still empty subform and paste it there. You should now have the subform look like this:

form design 03

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

4.3.1. Understanding bindings in subforms

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

Assume a subform with two fields in it with bindings to {{foo}} and {{bar}}. The subform should be used within a case form as well as within a task form but displaying the same data. Or the subform should even be used several times on the same form, but with different meanings (e.g. an address subform used twice, once for the main address another one 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 the exact same rules as explained previously in this tutorial. For instance, if the 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:

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

  • the same subform is used twice on another form

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

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

  • this results in possible expressions (e.g. within an output widget)

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

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

Example 2:

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

  • the subform is bound to {{$this}} (a special expression representing the very same context where the subform is used)

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

Example 3:

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

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

  • the same subform is used in a task form

    • the subform should always represent the very same data of the current case

    • the subform therefore needs a binding {{root}} to map it to the root context in order to display the same data as within the case form

Example 4:

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

  • the subform binding within the task form therefore needs to be {{root.myData}} in order to reflect the same data as with the case form

4.3.2. Understanding different types of subforms

Now we learned the basics for the binding / isolation of data in subforms. There are some possibilities when it comes to which form is actually used as the subform as well as whether the subform should have one entry or is able to show multiple entries.

Single-entry or multi-entry subform?

Subform widgets can be configured to hold exactly one entry (single-entry) or can hold zero to multiple entries. The difference is how the data is mapped, single-entry subforms will store its data in a map directly within the variable they are bound to. Multi-entry subforms will store the data into a collection (list) of maps in the variable they are bound to and thus are able to hold 0 to n entries.

Single- or multi-type subform?

There are basically two types of subform widgets available; single-type or multi-type subforms. The single-type subform will render just one type of form for all entries it is showing. The multi-type subform can hold different types of forms and uses something called a discriminator variable to distinguish which form should be used for which entry in the list. Assume 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 according product information. The discriminator could then be mapped to the type of the product and hence the appropriate product form would be used in the subform to represent that product the best way.

4.3.3. Adding the subform to the case form

Now having learned the basics for how subforms are bound to data and for the different types of subforms, let’s use it in our case form to 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 we want to replace them with the subform we just created.

Drag and drop a Single-type subform from the Components section of the shape repository 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 and select Reference and then the Attachment Section Sub Form to be used as the form reference.

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

Make sure Multiple entries 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 much identical as we had before adding the subform.

Because we entered a label name for the subform (optional), we can choose 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 directly open it in the form editor.

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 into the user dashboard and navigate to one of your previously created cases and you should see pretty much the same as before, but now done with a subform:

case testing 03

4.3.5. Add the subform to the task forms as well

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

Open both task forms in the form designer. You can do that by either going back to the process model and click the + button the user task to open the corresponding form, you can go to the modeler dashboard to select the form in the My Form Models widget or you can navigate to the Tutorial App and choose the appropriate forms from there.

Once opened in the form designer, drag and drop a Single-type subform at the bottom of the form and label it Attachments. As we’ve done before within 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 entries are turned off. Now the binding will be slightly different than we used on 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 is {{root}}.

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

form design 04

For the other user task form, you can simply copy / paste the subform widget from the other 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 into the user dashboard and navigate to one of your previously created cases (already having at least one attachment).

Now let’s see how we can start the process ad-hoc. Remember than 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 action menu and select Travel Request Management Process and click Start. This will start the process in the same case again. This is how ad-hoc processes can be manually started as an alternative to automatically start them during the creation of the case.

As we had in the beginning, the children view of the case shows one task as we re-started the process again in the case. Navigate to the task and check, whether you see the attachments too there:

case testing 04

5. Ad-hoc tasks and process improvements

In this chapter we will include 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 support that by adding a feedback-loop to the process.

But first find out, how this could be done by using ad-hoc tasks.

5.1. Getting familiar with ad-hoc tasks

Assume the problem as described above. There are several options how the travel agent could solve it:

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

  • Send an email to the requestor and clarify the open questions

  • Create an ad-hoc tasks within the case, assign it to the requestor and clarify the open questions

  • Add that feedback-loop to the process for better support

The first two options all work well, but are not integrated in a way that the new information is available within the case automatically. In a big organization there might be more than one travel agent working and they would need to share that information somehow, so everyone is always up to date.

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

5.2. Create ad-hoc task init form

Ad-hoc tasks can be built with forms the same way we created forms so far. 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- and a work-form. So far we used the same form in the case for both, the init- and the work-form. Additionally we will use a subform to show the data of the case with the case form itself, a nice way to ensure all data of a case is shown directly 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, drag the Name widget from the Predefined bindings section of the shape repository onto the form and rename the label to Task subject.

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

Remember, we are 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 that ad-hoc task. There is also a predefined widget to do exactly that, so drag and 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 (one of the default fields as well), so drag the Due date widget of the Predefined bindings section and drop it onto the assignee field in the right part to split that row up 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 previously, 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 and 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 necessary between the init- 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 and click Design to open it in the form designer.

Now we only have to modify it according to our needs. It doesn’t make sense to change the subject and description, so let’s make them read-only by setting their attributes Editable to false. Next remove the assignee selection and task due date, we don’t want 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 be shown up in this task form as well, because it’s a subform. Additionally we want to be able to show and hide this case information through a checkbox.

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

Now drag and 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. Now 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 where the ad-hoc task is created within. 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 let you define any expression, which must resolve to either true or false and the visibility is dynamic depending on the expression’s value. Also note that expressions are evaluated in real-time directly within the form engine of edoras one, so whenever the data upon the expression is based is changed (in our case it’s the checkbox), the visibility flag is automatically adjusted accordingly. Make sure we have Show border set to true and Multiple entries to false as there is exactly one case instance to be shown and we want it in a border to visualize its data 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 must not even be aware, in which context which 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- and work-form in the Init Form and Work Form selections of the task model and create 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 to be used.

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 / 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 would be created and you return back to the same init-form in order to create another one.

Going to the newly created ad-hoc there are several things you should note here. First of all you should be able to show / 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 them directly while in that task. You can test that by changing some case information in there, click Save (not yet Complete) and navigate to the case and check whether the data in the case itself have been updated accordingly.

To complete the task, simply click Complete and it will be finished. By default completed tasks are not visible in the children list of a case. If you still would like to see them, go to the children list of the case and select status All within the search box and 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 we just created, we now want to incorporate that agent < - > requestor feedback loop directly into the management process.

And here is the plan on how to do it:

  • Add next step selection in the management task form in order to let the travel agent choose between different options (e.g. need more information, travel organized, etc)

  • Add gateway after that task to select the appropriate sequence flow according the selected next step

  • Add feedback-task as a new path to the process which will loop back to the management task

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

5.6.1. Add next step selection possibility to management task

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

In the process model click the + button of the Manage Travel Request user task in order 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 in between. 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 out 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 decide to store it there and not in the 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 and 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 reflects the label used for that option whereas the value is used to store the selection in the mapped variable.

If we choose the first option, we want to show a new note field where the agent can specify what kind of information is needed from the requestor. So let’s drag and drop a Rich textarea from the Components section of the shape repository 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 hence the validation will to take it into consideration. Bind the field to {{root.infoRequest}}, we want to make that information persistent, even after the process has been ended, so let’s store it within the case context and that’s why we use the root prefix instead of parent like we did with the nextStep variable.

As we are already thinking ahead 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 and drop a new Output textara 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 let’s select the Information request field and enter {{parent.nextStep=='moreInfo'}} in the Visible (RT) attribute, so it will only be visible 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, so it will only be visible, 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 within the process designer.

Still remembering the spacing tool? We can make use of it now by adding 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 repository and drop it directly onto 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 in between the two user tasks.

prc design 02

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

Select the gateway element (if not yet selected) and drag / drop the small user task icon in order 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 line 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 turn green and drop it in order to connect the two tasks with a sequence flow.

prc design 05

We now modeled the feedback loop after the gateway. Next step is to tell the engine which flow to use after the gateway by specifying conditions on all outgoing sequence flows.

Select the sequence flow between the gateway and the Answer Info Request user task and click into the Condition expression attribute and enter #{nextStep=='moreInfo'} as the expression. We will explain the difference in the 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'} in the Condition expression attribute and name it finish.

It is a good practice to add a label to the gateway element. 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 as being used within forms and backend expressions as used now in the process model. The difference is where they are being evaluated, directly within the browser (frontend / forms) or on the server (backend, everywhere else like process, email templates, document templates, etc). As the frontend expression are limited to whatever the browser and form engine know in contrast to the expressions on the server side which could even 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 difference very prominent to the modeler.

But now back to our sequence flow conditions #{nextStep=='moreInfo'}. Why didn’t we use parent.nextStep as we did in the form? It is very important to always remember in which context an expression is evaluated. In the user task form we are in the context of a task work item, which is the child element of the process work item. The expression on the sequence flow however is evaluated in the context of the process itself and thus we don’t need the parent prefix as we did 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 still remember, you can simply click the + icon, select New and it will create a new form, attach it to the user task and open 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 everywhere in 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 as we already used in the management task form). Additionally make it required by clicking the red star icon.

The form will now look like this:

form design 06

Now 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 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 also visible in the init form? If you don’t want to be able to already upload attachments while initializing the travel request, simply add {{root.id}}` within the `Visible (RT)` attribute of the subform widget holding the attachment subform in the `Travel Request Form and it will not show up as long as the case is not initialized (and hence the root.id variable is not available).

If you navigate 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 then 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 capabilities within the text editor? If selecting a text fragment a toolbox appears where you can choose different formatting’s:

prc testing 03

If you now click Complete the next task will be the answer info request task where you can provide the answer and then the process is going 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 into 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’s obviously 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 that value before we hit 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 directly onto the sequence flow between the start event and the user task and name it Reset next step selection.

Move the sequence flow end of the flow between the answer and the manage task to the new reset service task by dragging the green point at the end of the arrow and dropping it onto the reset service task. If you want to re-arrange the sequence flows, there are several handles you can do that with. There is a red point in every edge of the sequence flow to move that edge with. Adding a new edge is easy too, simply point anywhere on the sequence flow and drag / move the red point which is appearing. You can move a sequence flow in parallel by moving the red rectangle appearing in the middle of the flow.

Your process model should now look like:

prc design 07

Of course we need to tell the engine now which variables to initialize within the reset service task we just added. Select the service task and click the Init variables attribute where a dialog appears to enter the variables we want to initialize or reset as in 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. If you also want to clear the previously entered information request text, add an extra row to the dialog which should then look the following way:

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 would leave that option to false, it would only initialize variables not yet existing and would leave existing variable values untouched.

Save the process model and go back to the Tutorial App in order to redeploy it and test the slightly changed behavior.

6. Model responsibilities / assignees

6.1. Getting familiar with responsibilities and sharing

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

Owner

By default, the creator of a new work item becomes the owner of it, it’s doesn’t mean, he is responsible for working with it, but more in a sense of being in the loop and always informed about what’s happening with that work item.

Assignee

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

Candidate groups

Setting one or more candidate groups makes the work item available to all users being a member of at least one of the candidate groups. Assume you have a group named "support" and use it as the candidate group of a support case. This makes all users being a member of the support group a potential assignee for the support case. All users being at least member of one of the candidate groups 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 become candidate users. They also 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 at least one of the candidate groups or you must have been added 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 now will see an owerview of your accounts, groups and users in your tenant.

Accounts

Accounts are used to divide your tenant into organizational units, locations or whatever you want. Groups and users are then created as part of an account. As for now, the account does not have any impact on visibility of work items, as we learned in the previous chapter, only groups and users are directly responsible for the visibility of work items.
You can choose alternative main-, background- and highlight-colors as well as your own logo as part of the account settings. To do so, select your current account and give it a try by choosing 004893 as the Main Color, FFFFDF as the Background Color and F2A33D as the Highlight Color. As soon as you save the account settings and reload the current page in the browser, your edoras one now should look like this:

admin 01

Simply remove any settings in order to use the default colors back again.

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 fully up to you. It could represent a group of people within your organization (e.g. the support team, HR or sales) or it could be used to represent a role (e.g. approver, travel agent). By adding a group to a user, it becomes a member of that group or role and hence will have access to all work items this group is used as a candidate group as we learned in the previous chapter.
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 are needed in order to let people log in to edoras one and participate in the work. All the users settings are managed within his user profile. The profile can be edited by the user itself (without the group permissions of course) and 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 a good practice to use the email address as the login name, although this is not a necessity.

Good Practice

Although accounts are not directly used for work item visibility, it is a good practice to create a Group for each Account having exactly the same name and use it to share work items with all users from that account. Of course the users need to be a member of that group as well. In a future release, accounts might become more visible as they now are, so this could change.

6.3. Adding travel agent group and requestor to task responsibilities

As we already 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 use a group for the travel agent assignment, let’s 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 your primary account to which the group should be added (not the admin account) and set the groups name to Travel Agents for instance 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 in order to easily test the adapted process later (so you don’t have to logout / login in order 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 additionally select the new Travel Agents group, then hit Ok in order to make yourself a member of the new group.

admin 03

6.3.2. Modeling the initial requestor’s responsibilities

As the initial requestor of the travel request, he will be responsible to answer any open questions and eventually review the travel bookings. In order to configure that, navigate to our travel request management process and open it using the Design action (if the process modeler is not open yet).
Select the Answer Info Request user task and go to the Assignee (RT) property. RT means Runtime and allows us to use an expression for the assignee during runtime rather than a fixed user during design time. As we already know, the owner of a work item is set to the current user by default, so we simply can use an expression of the owner of our root case to set the assignee of this task to the same user. Set the expression to {root.ownerId} in order 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

Now select the Review Travel Bookings user task and do the same; set 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 that the task is not assigned to a single user directly but rather to a group of users. So 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 does not appear, you might need to reload the process diagram first (only needed, 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 starting the request and the management task is assigned to the Travel Agents group and 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 and didn’t use a direct user assignment. This way, there might be several users potentially claiming that management task and organize the travel request. If there is no direct assignee set, the task will appear in the list of tasks in all users personal task list being a member of the group. But remember, we have a feedback-loop built in to the travel request management process. Now assume the travel agent needs some more information and afterwards the process goes back to the management task, but this time, we would like to automatically assign it to the same travel agent previously in charge and not the whole travel agent group.
In order to do that, we want to store the travel agent within the process instance after completing the management task in order to later use it again for the assignee of 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 and drop a new Initialize variables service task from the shape repository and drop it onto the sequence flow after the Manage Travel Request user task and name 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 current travel agent. Now click 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. We choose travelAgent as the variable name to store the current user id. For the value, we use the #{currentUserId} expression, which will always return the id of the current user, which in our case must be the travel manager just having completed the management task.

Our process should now look like this:

assignee 04

In order to use that information, 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 happens now? Whenever the management task is completed, the current user id is saved in a case variable called travelAgent and then used again 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.

But now we still have a problem; the travelAgent variable is initialized 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 in order to initialize this 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 know the travel agent yet at this point of the process.

Now your process should look like this:

assignee 07

Now 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 in order 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 having completed the previous one.

7. Add approvers to the process

In this chapter we want to add optional approvers to the travel request. Lets assume the travel agent has some regulations to follow like if the travel exceeds a certain amount of costs or if it includes traveling by airplane there must be an approval from one or more approvers.
In order to keep things easy, we simply add a new possibility 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 just add one single approver and later, we extend it with as many as necessary. This way, we can 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 new entry by selecting its row and click the up-arrow.

If the user selects this option, we want to additionally display a text field to enter any additional approval notes and of course select the approving user.
Drag and 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 repository, 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 add a new role to the process, let’s add a new lane to represent it. Drag and 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 and 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. Furthermore, we need to tell the engine when to actually use that flow and so set the Condition expression to #{nextStep=='approval'}.

approval 04

Now 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 is a good practice to use a joining gateway before that task for better visibility of the flow, although this is not necessary by the BPMN 2 standard.
In order to do that, make some more space (using the spacing tool, still remember?) before the Reset next step selection task and drop a new Exclusive gateway onto the sequence flow. Now 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 available and then drag and drop it using those green handles to the new gateway.

Your process should now look like this:

approval 05

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

The only missing thing now is the approval task form, so lets create one. Click the + icon of the Approve Travel Request user task and choose New as the option in order to create a new task form.

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

approval 06

Please note the expressions we used in the output widget, first of all, we used 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), the {{root.approvalNotes}} is the note field we added within the management task form for the travel agent to add special notes for the approver and finally we have {{root.travelAgent}}. Remember, it will be automatically set after the management task has been completed by the travel agent using a Initialize variable task.

Now let’s add the decision widget for the approver, we basically have two options; using a checkbox (for instance if we have yes / no options) or using a selection combobox, which is a little bit more verbose and of course could have more than two options.

Drag and 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 (my 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 Rick textarea, name it Decision notes and set the data binding to {{root.approvalDecisionNotes}} in order to let the approver add any special notes about the decision.

The form should now look like this:

approval 08

Now 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 an approval for the travel request, added this approval user task and routed the process back to the travel agent which then needs to decide whether to further organize the travel or stop it, if there is no approval. How does the travel agent know about the decision made by the approver? We could add this information back to the management task, so he has everything there.

Lets go back to the process and open the Manage Travel Request user task form by clicking the + icon or switch to the task form, if it is still open.
There are several options on how we could add this information. As it is a read-only information, we add it using a new output widget 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 we already made the approval. We can do so by using the Visible (RT) property we already used in other occasions. Select the output widget and set {{root.approvalDecision}} to 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 was completed.

Now save the form and go back to the Tutorial App in order to redeploy it. Start a new travel request, use the Need approval option, select an approver (e.g. yourself in order not to have to logout and login again) and you should end up in our new approval task.

approval 10

Ok, as we see the approval task now, we have some room for improvements. First of all, do you see how the expression {{root.travelAgent}} is rendered? Yes, its kind of a cryptical user-id rather than the users name. The backend would support something like this #{root.travelAgent.name} in order to get to the name of that user, but the frontend does not support that as for now.
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? Lets add another variable containing the travel agents name there.
Open the Travel Request Management process and select the Store travel agent user task. Now click the Init variables property and add the following variable initialization:

approval 11

Now save the process and open the Manage Travel Approval Task Form (or switch to it, if it is still open). Double click the output widget at the top of the form and replace {{root.travelAgent}} with {{root.travelAgentName}} so will use the name rather than the user id.

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

Tip
In order 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 on how we saved the travel agents id and name and used it in the approval output widget, you should be able to do that on your own now, right?

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 want 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 once it has been 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 a 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 directly hit Create and specify the further template later or do it 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

In order to send the email only 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 will look similar to this:

email template 02

After having placed the new elements and rerouted 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.
So 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 extension, whenever a travel request was declined, it will end the process directly without notification.

8.3. Send email if approval was declined

Ending the travel request process just because the request was not approved might not be the best solution, so we want to integrate our email template and send out a notification email once the request was declined.
Go to the Travel Request Management Process and make some space between the gateway and the end event, so we can drop a new email task onto the no sequence flow. Now drag and 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 of the Send mail service task. This will use our email template when creating the email subject and body to be sent. We want to send the email to our initial requestor and send a CC to the travel agent. In order to do that, we use {root.ownerId} as the Mail recipient and {root.travelAgent} as the Mail CC property.
Your process should now look like the following:

email template 03
Tip
As an email recipient you can either specify a fixed defined email address like foo@bar.com or you can specify an expression resolving an email address, like {root.fooEmail} (e.g. fooEmail representing a text field where the email address was entered before) or you can specify an expression resolving to any edoras one user. In this case, the email address of that user is taken to send the email to. In our case, {root.ownerId} will resolve to our initial requestor and #{root.travelAgent} will resolve to our latest travel agent managing the travel request.

9. Create document models

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

Documents can have meta-information, designed using an init- and / or work-form, the same way as we did with a task model.

9.1. Create document meta-information form

A document might have some meta information to be stored as variables in order to classify it or to be able to search for it later. This is done using a form, the same way as forms are used for cases or tasks, they can also be used to manage the meta-information 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 and drop the Name and Description field onto the canvas. Maybe we directly want to select an assignee for the document, so let’s drag and drop the Assignee selection widget below the description. To share the document with other groups, we can optionally drag and drop the Share with groups selection widget as well.

If you want to have more meta information for your document, simply add more fields to the form, you can design the document form the very same way as for a task or case.

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 drag and drop an upload-widget to it. Drag and drop the Upload widget to the top of the form (before the name field) and name it Upload document. This is a special widget, only used for uploading the content of a work item (in our case a document). That’s why we don’t need any special data binding.

We only want the upload widget, the assignee selection and the share with group field being visible during the initialization of the document but the form should be used as both, init- and work-form. There is a way to achieve that, by using the Visible (RT) property in order to show / hide a widget if the form is used as an init-form or as a work-form.

Tip
In order to show a widget only if the form is used as an init-form, use the expression !{{root.id}} as the Visible (RT) property.
If you want to hide a widget if the form is used as an init-form, use the expression {{root.id}} as the Visible (RT) property.
What does {{root.id}} mean? Well, it maps to the id of the root work item, typically the case and if we use a form as the init-form, we don’t have a case yet, that’s why we can use this expression to show or hide the widget according to the existence of the root id.

That being said, 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 widget.

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

Based on 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 in order to 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 / upload a new document to the case by clicking the Create button and select Create document. In the Template selection, choose Travel Request Document and click the Add... button in order to select a document to upload. It should automatically set the name of your selected document to the form we created and it will let you change it, if you want.
You can also select the assignee for the document as well as share it with some groups, if you want.

Creating a new document should look similar to this:

document model 03

After having created it, you will notice the missing assignee, share with groups and upload widget, remember? We used the Visible (RT) flag in order 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

After having created our new document, lets look at the different views and actions a document provides.
The first view (eye-icon) is the preview of the document which is currently supported for images, pdfs, open-office and microsoft office documents (word, excel and powerpoint). The second view is the work form of the document, similar to the forms of any work item (like cases or tasks). Then we have the comment view where you can add and see comments of the work item and the last two views are for developers / modelers where you can see all the data of the work item as a generic form or as a JSON representation.

And here is the list of actions:

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

  • Share lets you share the work item with groups

  • Move will move the current work item to another case

  • Update Placeholders will update the content within placeholders of a document, if it was created out of a template (we will learn that later)

  • Edit Document allows you to edit the document directly within a locally installed app (like Microsoft Word for instance). This only works, if the document you trying to edit is editable in a local application (same if you would double-click it on your desktop) and if your browser supports Java applets.

  • Upload Document allows you to upload / overwrite the current content with new one.

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

  • Archive will close / archive the document

Tip
You can select the available actions with the form of the document model in the Tutorial App in the section Allowed Actions.

9.3. Document models with a file template

We already learned how we can create and use a document work item using uploadable content. In our next step, we will attach a file template, also called a skeleton, in 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 to be used as the template once we create a new document based on that model. Choose an empty Word document for instance, so we can use it later with placeholders again.
After having uploaded the document, you will see it in the preview (even if it is a Word document).

document model 05

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

Go back to the Tutorial App, redeploy it and switch back to the user dashboard and navigate into one of your previous cases again. 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 the very same document you used as the skeleton in the document model.

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

9.4. Document models with a file template containing placeholders

We now learned how document skeletons can be used as the template to be copied once a new document is created. In our next step, we will add placeholders to the document, so we can automatically fill in data from the case, the document is created within.
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 alternatively 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 maker name, we will use that later for the binding. I used the expression I’m going to map afterwards as the standard text, but this is not necessary, only a good practice to see where the 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}

Tip
It’s a good practice to use the same name for the text field as the variable name we want the field to be bound to later, although this is not really necessary.

Now save the Word document. If you used the Edit document action, the new version will automatically be uploaded as the new skeleton to the document model. If not, 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 and 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 was not properly set within the title, that’s why we used caseName as the name of the marker and this is not an available variable name in our travel request case. Furthermore, we most likely would like to change the formatting of the dates too, 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 straight-through 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. In order 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 called Placeholders and here you can add mappings by clicking the Add Placeholder button for each mapping you want to configure. For each placeholder with such a mapping, the engine will first evaluate your expression and then use the outcome of it as the value for the text field.

Add the following placeholder configurations to the document template:

  • Key caseName with expression #{root.name}

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

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

The placeholder section should now look like this:

document model 09
Tip
We used a function in our expression called formatDate(date, format) which takes a date object as the first parameter and a date formatting string as the second. Please refer to the reference documentation to see further functions and how to use the expression language.

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

document model 10

9.5. Create documents from within a process

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

Drag and 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 or similar.
In the property Document model choose our newly created Travel Request Document model and use root.travelDoc` as the `Document id variable name property.
Optionally, you can specify the name for the document using the Document name variable, so set it to #{root.name}.docx.

Your process should now look like this:

document model 11
Tip
Using a variable name for the document id will give us the possibility to later access this specific document using exactly this 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.
At the end of the process, our document will be created out of the template with the data from the case and will be stored within the case.

9.6. Send documents as an attachment of an email

As the final step, we want to send a document of our case as an attachment of 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 very same task we added as 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, use the Copy button or hit Ctrl-C to copy it and then the Paste button or Ctrl-V to paste it. Drag this copied task 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

Now select the Send decline notification email task and 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 and make sure to use the approval and decline it in order to send the email with the document created as the attachment.

10. Create convenience queries

Queries are work items too in its technical representation with the aim of saving and optionally sharing a query like a filter returning a list of work items, if executed. If you’re familiar with the search in edoras one, then you’re almost there as a query is nothing else than a saved search request which can be executed at any time later.

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

First of all you can use the search kind of like a Google-search by entering terms to search for. But you can also use structured search terms like type:CAS or for:me which 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, this would be the way to create such a query item:

  • click the search box and enter type:CAS, if you hit Enter you should now see a list of cases

  • now add state:open as a second term, if you hit Enter you should now only see open cases

  • add model:'Travel Request' as a next term, if you hit Enter you should now only 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, like the state term, the type term or even the sort term.

If you have the result in the way you want it, click the Create Query button and add a name for it, then click Create and if you go back to the user dashboard, you will see the new query item in the list of My Queries.
Optionally you can share a query item with others using the Share action. This way, other will have the opportunity to see and use that query too in their dashboards.

10.2. Execute and change an existing query item

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

10.3. Exporting the data returned by a query item

Once you execute a query item, you can export its results and data by clicking the Export Query Data button. It will then create an Excel file with all data from the returned work items in it.
Unfortunately, you can’t configure the data to be exported yet, yo the Excel might become quite big. In a future release, you will be able to configure the variables and information you want to be exported as part of the query item as well.

11. Create your own dashboard

In this chapter of the tutorial we are going to create our own dashboard and we will learn how we can set it in our user profile to be used as the default.
There is currently no prominent way to create dashboard items like having a dashboard model item or the like yet, so we will use quite a commonly used workaround to achieve the same goal.

11.1. Using a case model to represent our own dashboard

As a possibility, we are going to model and design a case acting as our dashboard. Because we can design a working form for a case, we can design it in a way to act as our dashboard and once we create an instance of such a case, we simply have to store its 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 did many times before now in this tutorial, so go to the Tutorial App and hit C or click the Create button and select Create Form Model to create our dashboard view. ` Name the form Dashboard View as it is more a view rather than a form then click Create and Design to directly create the form model and open it in edoras vis to design it.

Drag and drop an Output textarea to the top of the form where we can add some information about the dashboard then double-click it and add something like this to it:

dashboard 01

We now want to add some lists to the dashboard, so drag and drop a new List widget to the form and remove the label by removing the predefined text of it. Lists are showing work item based on a query term. Still remember the query items from our last chapter? A list widget is based on exactly the same query term and using 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 label of the items in the list will be rendered. By default, it will use just the name of the work item. We would like to include the original requestor of the travel request as well so lets set the Format property to {{item.name}} (Requestor: {{item.owner.name}}) in order to 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
If we want to limit the height of the list widget, we can set the property Maximum number of rows to 10 for instance.
Your form should now look like this:

dashboard 02

Furthermore, we would like to add two more lists, one of it only showing the Manage Travel Request user tasks and on the other one showing all open tasks, regardless the type of case or app.
First the management tasks; so drag and drop one more List widget to the right hand side of the existing list and configure the following properties:

  • set the Label property to an empty string in order to hide it, we will 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 as well after the task name

Add a third List widget to the very right of the same row we already added the two other lists and drop it there. If we want the three list widgets to be equally spaced, use the handle on the right or left hand side of the widget and drag it to the left or right until it spawns 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 in order to hide it, we will 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 as well after the task name

Maybe we want to add an instant-filter field to the first list, so we can filter the list to find a particular travel request. Drag and drop a new Text widget between the Output textarea and the List widget on the left and drag its right hand side handle to the left in order to let it spawn the same number of columns as the list widget and name it Search. Set its value binding to {{caseSearch}}.
Now we can use that variable within the Query property of our first List widget in order to dynamically use the entered search text in our filtered case list.

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

The dashboard view should now look like this:

dashboard 03

Now lets save the form and return back to our Tutorial App.

11.3. Creating the case model for the dashboard

As we already talked about, we are 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 choose the Dashboard View as the Init Form and Work Form property.
Remove all selections from the Allowed Actions section, just let the Create Variables action in there, as we don’t want to work with that special case, but only 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 and select our Travel Management Dashboard template and click Create.

If you want to avoid 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 button in the dashboard

Because technically speaking our dashboard is a simple case, the Save and the Cancel button are still showed on our dashboard view, but we don’t need them. So there is a trick to hide those buttons by adding a hidden widget to the Dashboard View form which will cause the rendering engine to hide the buttons.

Go to the Dashboard View form and add a Checkbox widget at the end of the form.
Label it (Hide Buttons Widget)' to indicate what it is used for.
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).

redeploy the Tutorial App and migrate the current dashboard case.

Your dashboard should now look similar to this one:

dashboard 05

11.5. Adding count widgets to the dashboard view

Maybe 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 see how many there are. There are special Count widgets allowing us to display a link having a count of work items based on a query in it.
Go back to the Dashboard View form designer and add a new Search count link widget just below each of our list widgets and make their spanning width equally to the list widget they will belong to.
Remove the label as we only want to display a link text including the count of the 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 don’t need the sort term obviously and we always want to show all open travel request cases, so we remove the caseSearch term)

  • set the Target property to _self in order to create the navigation link in 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' (for the count query we don’t need the sort term obviously)

  • set the Target property to _self in order to create the navigation link in 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 (for the count query we don’t need the sort term obviously)

  • set the Target property to _self in order to create the navigation link in the same window

Tip
The $count term is a special term which will be bound to the count result being returned by executing the count query.
Within the [x|y] term, the x represents the label being used, if the count is exactly 1 and y will be used if the count is bigger 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 newest 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 in order to create a new Travel Request without using the general Create button.
So go back to the Dashboard View and add a new Create button below the first count widget and resize it do only spawn 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 navigating directly to the init form for a new travel request (the same URL actually as if you would click the create button and then select 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 newest version.

Your dashboard view now should look like this:

dashboard 09

If you click the Create new travel request you will be forwarded directly to the init form in order to create a new Travel Request.

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

Lets say we want to add some information we already have on the current form 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, lets add a horizontal line between them by dragging and 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 so we can add a new text field to the first four columns.
Now drag and drop a new Text widget and drop it to 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.

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

dashboard 10

We 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 be pre-populated 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 newest 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

We now created our dashboard case, now we would like to use it as the default one for the user dashboard.
First, make sure our own dashboard is currently shown and then copy the URL-part starting with the CAS part (something like CAS/GEAR-xxxx/browse).
Then we can 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 that copied URL to the Home URL field and then saving the user profile.

dashboard 12

To make the changes active, you most likely have to reload the current view and then you should find yourself directly on your own, custom dashboard!
You can always navigate to that by clicking the logo in the top right menu bar. If you want to go back to the default user dashboard, you can do so by selecting it from the dashboard menu or with the Home icon in the menu bar.