TaskJuggler: a tutorial

Apps

TaskJuggler is a complete project management solution in that you can use it right from the planning stage through to project completion. It offers comprehensive reports and makes it easy to manage tasks, costs and resources. You can follow the exploits of each of the teams working on the project and determine instantly where you need to allocate more workers to make sure you stay on course. Want to learn how to use it? Then read on!

Be still for a moment and notice the people moving all around you. People going to someplace and people coming from something. All the while they're working, on a project. Whether you realise it or not, just about everything you do, every day, can be classified as a project. And while people constitute a fundamental part of any project, you'd be lost without an excellent project management tool to keep track of the people and the individual tasks that comprise a project.

Fortunately, such a project management tool is in the software repositories for most distributions, and so most of us can get it with

sudo apt-get install taskjuggler/

or

su -c yum install taskjuggler 

But there's a catch. First, TaskJuggler is a KDE app, and second, it's developed and tested primarily for OpenSUSE. Don't let this bother you, for it works flawlessly on other distros as well.

Also, version 2.4.1, on offer through the software repositories for Jaunty, has one major flaw. It doesn't play ball if you're in a .30 time zone. The flaw affects TaskJuggler as a whole and doesn't just disable a feature, so you can't use TaskJuggler 2.4.1 on a .30 time zone period. So, if you're in a +2.30 or +5.30 time zone or similar, you're better off with 2.4.2 or the latest 2.4.3 version.

TaskJuggler can be run from the CLI, but our focus is on the graphical front-end. Plus, you can't see charts and all the fancy HTML reports on the shell, which every project management tool needs, so it's GUI all the way,

TaskJuggler offers many built-in keywords (called properties) that you can use to define various elements of your project. For example, you can use the currency property to define whether the costs described in the project are in USD or EUR, etc, or the project property to define a name and ID for your project, and so on.

The main part of the TaskJuggler window, which you will use to enter all the details about the project, is called the editor. On the left pane are many entries such as Tasks, Resources and Accounts. These are handy when you wish to quickly access a particular section of the project file.

We begin this article by describing how you define a project and all its intricacies in TaskJuggler before showing you how to generate charts, reports, etc, and tracking your project's progress. Guess we now know why horizontal TOC's aren't so popular.

You can use the ID to refer to any TaskJuggler property instead of using the complete name of the property.

You can use the ID to refer to any TaskJuggler property instead of using the complete name of the property.

Project: Begin

To start a new project, click File > New after launching TaskJuggler from the Office menu. You have the option to start a blank, simple or large project. If you choose blank, you'll have to fill in all the details of your project by hand. But, choosing either simple or large will give you a template for your project.

The first step is to define your project like this:

project carpimp "Pimping Cars" "1.0" 2009-08-20 2009-09-20 {
  timeformat "%Y-%m-%d"
  currency "EUR"

This tells TaskJuggler the name of your project, its ID, a version number and its start and end date. The currency and timeformat properties are self-explanatory. You can use different values for them for different projects per your need.Another useful property is /scenario. Typically you define two scenarios, a plan, which is a step-by-step breakdown of the project, and another scenario to cover delays in the project.

scenario plan "Plan" {
    scenario delayed "Delayed"

Here, the Delayed scenario inherits all the values from the Plan scenario because of the nested structure. This helps us to track project delays if there are tasks that haven't been completed in the alloted time period. This will become clearer as we move along with our project.

As an example, throughout the rest of this article, our example project will be pimping a car. Yeah!

Defining project resources

We'll get to the actual tasks that constitute our project in a while but before we do, let's define our resources. All tasks use the resources to meet their objectives. So, all your workers are resources, because you can't really put in pimped rims for the tyres without some elbow grease.

resource elec "Electronics" {
resource elec1 "Mac Jordan Jr." 
resource elec2 "Mac Jordan" { rate 500.0 }
}
resource body "Body Work" {
resource body1 "Jeff Hoorah" { 
    vacation 2009-09-05 - 2009-09-07 
    workinghours {
        wed 11:00 - 16:00
    }
}

We've just defined two resource teams, Electronics and Body Work. When using any of the built-in properties, you must specify a name and a unique ID for that property. For each team we've then defined the workers and any specifics concerning those workers. For instance, the 'rate' property is used to defined the rate for Mac Jordan, who is a seasoned electronics expert and thus can command higher pay than the other people working on the project. Each of the resources can have their own exception to various globally defined properties. For instance, the example code above, body 1 (Jeff Hoorah) works only for five hours, from 11:00 - 16:00, regardless of the globally defined work hours.

Expenses and income

Simple maths lesson folks. Your income is the payments made to you by, hopefully, satisfied customers, balanced against your costs.

Using the resources that we've just defined costs money. Add to that the cost of all the pimped-up goodies you'll put in the car. All of these constitute your costs.

account eqp "Equipment" cost
account inc "Income" revenue

The 'account' property expects three values: ID, name, and type. The type can be cost or revenue. For cost analysis, TaskJuggler subtracts the sum of all cost accounts from the sum of all revenue accounts.

So, if you have another revenue account "Pics" which details the income generated from selling pictures of your pimped cars, the profit would be calculated by doing (Income+Pics) - (Equipment).

We've only just defined our two accounts here. The major step is to assign tasks to these accounts so that TaskJuggler will know your income from your expenses. We'll do that when describing tasks later on in the article.

Your project no doubt constitutes many tasks. The changing of tyres, body work, doing a new paint job, putting in a juiced-up music system, etc are just some of the tasks that make up our pimped cars project.

task carp "Pimping Cars" {
     task pj "Paint Job" {
          depends !bb
     }
     task wire "Electrical Wires" {
          length 1d
     }
     task music "Music System" {
          depends !wire
     }   
     task bb "Bumper & Body work" {
          task roof "Sun Roof" {
          }
     }   
}

To complete this project, we need to do a number of things, each described as a task. Some of these tasks, for example Paint Job can't be started until all the body work has been completed. This is where we use the depends property.

The length property is used to define the amount of time allocated to each task. The length, when defined in days, means working time and not calendar days. So, 1d means 1 working day and not the full 24 hours. You can define working hours for your project like so:

dailyworkinghours 8
weekstartsmonday
     workinghours mon -fri 8:00 - 12:00, 13:00 - 17:00
     workinghours sat, sun off

As you can see from the code snippet, tasks can be nested. This is important, because you can't reference a task without knowing the proper structure. In our case, we use !bb when referencing the 'Bumper and Body Work task'. The ! moves the scope to the parent task. So, !bb, when used within the 'Paint Job' task, first moves the scope to the 'Pimping Cars' task (parent), where we find the 'Bumper and Body Work task'. Without the ! character, we can't reference tasks outside the scope of the current task.

Imagine the refrigerator inside your kitchen in your house. If you're sitting in your bedroom and want a glass of juice, you can't just reach into the refrigerator. You'd have to first walk into the kitchen and then you can access the refrigerator.

The . character is similarly used to reference sub-tasks. So, to call up the 'Sun Roof' task, you'd have to use bb.roof. If you've ever used inheritance to write a C++ program, this should make good sense.

Now, you can't possibly expect the work to get done if you don't assign any workers to it. To assign workers, or resources as TaskJugger calls them, we use the allocate property.

task wire "Electrical Wires" {
          allocate elec
          length 1d
     }	

A comma-separated list of workers can be used with the allocate property to assign multiple resources to a task.

Tasks don't show on the calendar HTML report unless you've assigned resources to them using the allocate property.

Tasks don't show on the calendar HTML report unless you've assigned resources to them using the allocate property.

Using macros

Macros, in the realm of TaskJuggler, are used when you have to repeat the same text many times in the project. For instance, when you have to allocate the same workers to different tasks, instead of explicitly writing them into each tasks, you can define a global macro, and reference that macro from the tasks.

Basically, if you define a macro as macro EXPAND [expand into this text], and reference it later as ${EXPAND}, it will be expanded to expand into this text. So, when allocating the same resources to multiple tasks, you can create a macro:

macro allocate_elec [
allocate elec1 { rate 500.0 }
allocate elec2
]

and reference it in task wire as ${allocate_elec}.

Meticulous details

TaskJuggler expects you to input many details for each of the defined tasks before allowing you to compile the project.

One of the most important properties for any task is start, which is used to tell TaskJuggler the date on which the project is to be started. But despite all the best-laid plans, some tasks might get delayed. For instance, if the Music System task actually starts on 2 September instead of 1 September, you can tell that to TaskJuggler like so:

task music "Music System" {
       depends !wire
       start 2009-09-01
       delayed:start 2009-09-02
       length 2d
}

Remember how we created the plan and delayed scenarios right at the start? We use the delayed property here to specify the actual start date of the task. You can similarly use the delayed property for other tasks that are running late.

By default, TaskJuggler assumes all tasks are on schedule and completed on time. If this isn't the case, you can use the complete property to tell TaskJuggler the status of each task.

task music "Music System" {
       depends !wire
       start 2009-09-01
       delayed:start 2009-09-02
       length 2d 
       delayed:length 5d
       complete 45

The complete property here tells TaskJuggler that the Music System task is only 45% complete. Also notice that we've used two delayed properties above, to define the delays in the start as well as the length.

Apart from merely allocating resources to tasks, you can even describe the number of hours they'd spend working on each of the tasks. We use the limits property to do this:

task wire "Electrical Wires" {
       allocate elec2 { limits { dailymax 3h } }
       length 4d
}	

With this snippet, we've told TaskJuggler that our elect2 resource (Mac Jordan) will only work for three hours on the Electrical Wires task for each of the four days that it takes to complete the task.

Show me the money

The last thing to do is to assign our tasks to the proper accounts. Since we created the eqp account to tackle costs for the equipment used on each task, let's use the eqp account globally such that all tasks inherit it:

task carp "Pimping Cars" {
     account eqp
     task pj "Paint Job" {
     }
     task wire "Electrical Wires" {
     }
     task music "Music System" {
     }   
     task bb "Bumper & Body work" {
      }
}

Next, we need to show all of our earnings. More often than not, you'd accept an initial downpayment for the project and receive payments at various stages of the product development, before receiving the final payment on completion of the product.

Needless to say, you'd have to write in each of those payments. This involves describing the individual stages at which you demonstrate the product to TaskJuggler:

task demo "Demonstrations" {
account inc
    task down "Downpayment" {
#Shared the complete plan for overhauling the customer's car with detailed 
        #schedule.
        credit 2009-08-25 "Initial downpayment" 5000.0
    }
    task fd "First Demonstration {
#The first demonstration is held for the customer once the body work is done.
        depends !!carp.bb
        startcredit 15000.0
    }
    task finish "Finished" {
        #The project is finished, we've completely pimped the client's car. 
        depends carp.pj
        startcredit 20000.0
    }
}

Instead of specifying credit later in the project along with the other payments, you can do it right at the start of the project, where you first defined the different accounts:

account eqp "Equipment" cost
account inc "Income" revenue {
credit 2009-08-25 "Initial downpayment" 5000.0
}

If the figures seem exaggerated, don't blame us. There's huge money to be made in the car pimpin' business. But, if you're unsure start small. Say, modding bikes.

There are three properties you can use when specifying the amounts made to you by the customer: credit, startcredit and endcredit. The startcredit and endcredit properties, as the name suggests, are used to specify payments made to you when a task begins or ends. The credit property is used for specifying the initial payments made to you.

Report card

Thankfully, after all the effort that goes into keeping TJ abreast of your project intricacies, you don't have to do anything special to make it generate reports.

If you've chosen either of simple or large template when starting your project, you already have everything in place to view the reports on your project. Just press F9 to compile your project and then click the Reports tab on the left panel. Now click on any of the options listed in the left panel and voila, instant report.

When you press F9 to compile your project, TaskJuggler will print out all the errors at the bottom of the window.

When you press F9 to compile your project, TaskJuggler will print out all the errors at the bottom of the window.

Since no report can be complete without a Gantt Chart, you too can create one using this code:

taskreport "Gantt Chart" {
  headline "Project Gantt Chart"
  columns hierarchindex, name, start, end, effort, duration, chart
  # For this report we like to have the abbreviated weekday in front
  # of the date. %a is the tag for this.
  timeformat "%a %Y-%m-%d"
  loadunit days
  hideresource 1
}

When you now compile your project, you'll notice a Gantt Chart link under Interactive Reports in the Reports menu. Clicking on it will bring up a report, showing all the fields we specified. The Gantt Chart appears on the extreme right pane of the TaskJuggler window.

Apart from a taskreport, you can also get TaskJuggler to generate resource reports using the resourcereport property. You can similarly use the htmlaccountreport property to monitor your accounts:

htmlaccountreport "Accounts.html" {
  columns no, name, scenario, total, monthly
  headline "Income and Expenses"
  caption "Income and Expenses at a glance. But, also in detail at the same time. You'll see from the screenshot."
  scenarios plan, delayed
}

The scenarios plan, delayedstatement, helps you to quickly notice the difference in expenses in case of delays.

The tracking Gantt chart shows the percentage of work done on each project, along with delays and the scheduled end date.

The tracking Gantt chart shows the percentage of work done on each project, along with delays and the scheduled end date.

First published in Linux Format

First published in Linux Format magazine

You should follow us on Identi.ca or Twitter


Your comments

thanks

your tutorial gave me a good starting point, thank you

i cant get the UI for

i cant get the UI for taskjuggler in ubuntu 11.10

where is the gui for TaskJuggler on Ubuntu 11.10 ?

hi even i am not able to find how to start the gui for tj on Ubuntu 11.10?

Great tutorial! how to get the gui on mint cinnamon,any idea?

I'm running linux mint 14 with cinnamon and I can't get taskjuggler installed using 'apt-get install taskjuggler'. I installed gem and got the gem for taskjuggler3.4.0 and now I can run it through the terminal using the 'tj3' command. All that aside, I like the way you've explained every property. It helps to have a little extra explanation. Thank you. And please tell me if you know a way to get the gui working for taskjuggler on mint cinammon. Right now I'm using the terminal only.

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.

Post new comment

CAPTCHA
We can't accept links (unless you obfuscate them). You also need to negotiate the following CAPTCHA...

Username:   Password:
Create Account | About TuxRadar