Thursday, October 24, 2013

Bookmarklet Reporting with dotProject

I’ve been using dotProject for keeping track of my hours on certain projects. It’s a bit of overkill for my needs, but it was easy to get started without worrying about trying to find the perfect tool. Over time I’ve found that going my own route has given me some perspective of what I want.

dotProject's interface is rather ancient by web standards, and it’s feature-set is a bit daunting. Some features seem overly complicated and others seem rather sparse. However, the simple html design lends itself to being very flexible to get what I need out of the system.

One particular report that is my bread and butter is the “Task Log”. All my projects have tasks, and I log hours to those tasks. At the end of the month I just want a list of all the logged hours for the month in a nice list.

However, the big issue I have is the default begin/end dates are useless to me. They load on a 2 week cycle, so the default end-date will be the current date, with the begin date set to 2 weeks ago. Changing them should be simple, but the date textboxes are read-only, and the only way to change them is with a popup widget that is cumbersome to deal with.

One day I had some inspiration and thought, if the dates are being sent as query parameters, why not just formulate those parameters myself? After a little bit of experimentation I ended up building 2 JavaScript bookmarklets: One runs the report for the current month, and the other opens a dialog asking for the month before running the report.

A bookmarklet is just a bookmark, but instead of a URL to a webpage, it contains JavaScript that instructs the browser to do something. In this case I'm instructing it to open the URL of the report using the dates that I want.


I’m going to show the main logic I used, followed by compacted versions. I'm not a huge fan of compacted code, but I was afraid that there might be a size limit for bookmark's URL. At the end I’ll show some examples in screenshots.


Full disclosure: this is my test code, some or all of it may not work correctly, you may need to make some tweaks.


Main code logic
Don’t forget to use your URL instead of the fake one used in this example 

//This is the URL before you add the date parameters
var BASE_URL = "http://dotproject.example.com/index.php?m=projects&a=reports&project_id=0&report_type=tasklogs&log_userfilter=0&do_report=submit";

//first day of current month
var begin_date = new Date();
begin_date.setDate(1);    

//last day of current month
var end_date = new Date(begin_date.getFullYear(), begin_date.getMonth() + 1, 0);

//open the URL, with the formatted dates
open( buildURL( formatDate(begin_date), formatDate(end_date)));

//format YYYYMMDD
function formatDate(dtDate) 
{
    var sDate = "";
    sDate += dtDate.getFullYear();
    sDate += pad2(dtDate.getMonth()+1);
    sDate += pad2(dtDate.getDate());    
    return sDate;
}

//pad 0 (zero) to single-digit date parts (i.e. 3/9/2013 = 03/09/2013)
function pad2(n) 
{
 var str = String(n);
 if(str.length < 2) { 
  str = "0" + str; 
 }
 return str;
}

//return the full URL (BASE_URL + THE date parameters)
function buildURL(sBegin, sEnd) {
    var str = "";
    str = BASE_URL+"&log_start_date="+sBegin+"&log_end_date="+sEnd;
    return str;
}



Task Log: Current Month (compacted)
Don’t forget to use your URL instead of the fake one used in this example
//open report for the current month:
javascript:(function(){
 var BASE_URL = "http://dotproject.example.com/index.php?m=projects&a=reports&project_id=0&report_type=tasklogs&log_userfilter=0&do_report=submit";
 function fd(d) {var s="";s=d.getFullYear();s+=pd(d.getMonth()+1);s+=pd(d.getDate());return s;}
 function pd(a){a=String(a);a.length<2 a="" amp="" br="" return=""> var m1 = new Date();m1.setDate(1);
 var m2 = new Date(m1.getFullYear(),m1.getMonth()+1,0);
 location.href=BASE_URL+"&log_start_date="+fd(m1)+"&log_end_date="+fd(m2);
 })(); 

Task Log: Ask for Month
Don’t forget to use your URL instead of the fake one used in this example
//ask for month (number), then open the report:
javascript:(function(){
 var BASE_URL = "http://dotproject.example.com/index.php?m=projects&a=reports&project_id=0&report_type=tasklogs&log_userfilter=0&do_report=submit";
 function fd(d) {var s="";s=d.getFullYear();s+=pd(d.getMonth()+1);s+=pd(d.getDate());return s;}
 function pd(a){a=String(a);a.length<2 a="" amp="" br="" return=""> var m1 = new Date();m1.setDate(1);
 var m = prompt("Enter Month: ", m1.getMonth()+1);
 m1.setMonth(m-1);
 var m2 = new Date(m1.getFullYear(),m1.getMonth()+1,0);
 location.href=BASE_URL+"&log_start_date="+fd(m1)+"&log_end_date="+fd(m2); 
 })();


Adding bookmarklets in pictures

Default report parameters, those dates won't help me
Start with a new bookmark, and paste the JavaScript into the Location field
Here's the result, the dates load correctly!
Creating a separate bookmark to ask for the month
Here is the bookmarklet asking for the month
The report showing the correct dates!


No comments:

Post a Comment