New Project: Harvest4Chrome

Post date: 16-Apr-2012 02:10:46

The time has come, the Walrus said...

At Red Ant the main thing we sell is time - project manager time, designer time, developer time - so keeping track of time accurately is paramount. For this we use Harvest, and while we've seen other web apps come and go Harvest seems to have stuck around. (This might be the highest endorsement we can offer - it's one of the few tools we haven't replaced.)

Part of the appeal is the wide range of ways we can access it, and we use them all - a nice web interface, desktop widgets, mobile apps, a robust API. In some respects the API is the nicest part, though, because that means that any feature it doesn't have, we can build.

The Itch

As they say, these things usually start with an itch. For me, the itch was that when confronted with a technical problem, I tend to jump right in - and I regularly forget to start a new Harvest timer when I start working. If I'm concentrating on the problem, I'm neglecting my timers - if I'm mindful of my of my timers, I'm distracted from the task at hand.

What seemed called-for was a simple, highly visible display of my current Harvest status. Seeing as my primary browser is currently Chrome, a Chrome extension was the logical choice.

Break on through to the other site

Google maintains a series of tutorials on developing extensions for Chrome, so I was soon up and running. After a refresher course on XMLHttpRequest, my only two real challenges were securely storing the user's Harvest credentials, and defeating Javascript's 'same origin policy' security restrictions so that my extension could reach Harvest's RESTful API.

The former is a challenging problem - Chrome doesn't currently offer API access to it's 'saved passwords' system, so I had to fall back on the security Chrome uses to protect personal user data on the file system. The latter is a serious problem for normal JS development (with hacky fixes like JSONP) which prompted Google to include a 'permission' facet to their extensions API, allowing users to accept a whitelist of domains that the extension is allowed to access.

After tackling those challenges I had a 'badge' (a Chrome UI icon able to display a small image and/or a few characters of text) that turned an an eye-catching red when I was neglecting my timers.

More Itching, More Scratching

Usually a feature demands the manner in which you implement it, but equally sometimes the implementation suggests new features. To test whether a timer was active I was collecting all the timer information for the current day, so it seemed natural to display that information (if only while testing the main purpose of the extension.) An extension 'popup' (a small pane that folds out when a badge is clicked) seemed a natural place for this, so that was the next feature added. Showing timers in the popup naturally suggested that you should be able to click on them (thus switching timers) so that went in next. I stopped short of adding a full interface for creating timers because that seemed more natural to leave in Harvest's web interface, but while mulling that over I stumbled on to another use case that isn't quite natural for me while using Harvest.

I log time every day on maintenance tasks like reviewing the status of our servers, triaging my ticket queue and otherwise staying responsive to customers, project managers and other stakeholders. Harvest offers a mechanism to clone tasks from one day to another, but this isn't analogous to what I think of myself as doing (interacting with a 'default timer') and is a bit click-intensive for my likes. So, could I come up with a mechanism that was natural for users to create these default timers and and start/stop them?

Creating them was relatively easy - Chrome extension options pages are just HTML so with a little jQuery I could work up an dynamic form with all the necessary fields. (The only complication is that the options available in the defaults are sensitive to the user credentials provided - my solution for this is a little hacky and I think I might rework it in the future.) My initial efforts to manage them was a bit of a misstep though - creating timers in Harvest also starts them (a sensible default) meaning that 'creating' them new each day meant that they were running for the moment I set them up, regardless of the user's actual behaviour. So I switched tacks and implemented them as a kind of 'ghost' timer - featured in the list of daily timers, but not created until the user actually clicked on them to switch to them. (They're blue in the interface, for those playing along at home.) Works like a charm, and feels very natural.

Conclusions

As my first Chrome extension, I found the learning curve pretty gentle. I'm an experienced front- and back-end developer, though, so YMMV. Certainly my previous Javascript experience stood me in good stead - particularly my knowledge of a handy Javascript library (jQuery) and it's availability via Google's hosted option leapfrogged me through the development pretty quickly. Google's documentation for extension development is clear and accessible, and my only real frustration was the lack of access to Chrome's password safe - hopefully we'll see that added in the future.

Ultimately, while some might argue against developing browser-specific extensions (given the ebb and flow of browser popularity) I'm confident that the productivity gains from this will make it well worth the time it took.

If you use Chrome and Harvest, feel free to get Harvest4Chrome from GitHub and try it now - I'd love to hear what you think.