New Mobile Features & Pricing for Tempo

2008-04-07 20:00:00 -0400


Since we launched Tempo a few weeks ago we’ve been hard at work adding new features to provide some of the mobile access we were looking for here at Zetetic.

The easiest to tackle was a mobile web interface for phones with data plans and iphones and such to have a quick and easy way to enter time. The screenshots in the tour give you a quick idea — it’s a miniature interface for logging your time on the go.

We also added a capability that allows you to record your hours by sending a simple e-mail. On every Tempo user’s account there is now an additional field called ‘alias’ that we set to something fairly random, but which you can change. Here’s how it works:

Let’s pretend my alias is super20x6. I could send the following e-mail to super20x6@keeptempo.com and it would get added to my time entries:


1.5 updated pl/sql stored procedure @bigco @oracle @plsql @development

This will create a new entry for one and a half hours, description ‘updated pl/sql stored procedure’, it will associate with my project BigCo, and it will be tagged with oracle, plsql, and development.

To find out more about how this capability works, skip on over to the new Mobile section in our FAQ.

Finally, we’ve made some adjustments to our pricing structure for premium plans. The big change is that all premium plans now provide unlimited projects (they still start at only $5 / month).

We’re definitely interested in hearing your thoughts on the new features and pricing. Leave comments here or email us at support@zetetic.net.


Respect Is Due

2008-03-19 20:00:00 -0400


Throughout the course of building Tempo, we’ve relied heavily on software written by other people and made freely available. It’s worth doing a quick run-down to give credit where credit is due.


Ruby On Rails
web application framework

No surprise there, right?


PostgreSQL
relational database

Our favorite relational database system, Postgres is the most mature of the free systems out there, has the best feature set, and has quite a bit in common with Oracle. Highly recommended.


FamFamFam icons

Everybody needs icons, we’re big fans of the Silk set.


Acts As State Machine Rails plugin

This plugin by Scott Barron allows an ActiveRecord model to act as a finite state machine rather elegantly.


HAML & SASS HTML & CSS templating

Gone are the days when we painfully labor over HTML templates thanks to this great Rails plugin by Hampton Catlin. We can’t live without it now.


gchartrb Google Charts for Ruby

Those charts in Tempo look really good, but they’re largely the work of Google’s Chart API and this wrapper library for Ruby written by deepak.jois and aseemtandon. All we had to do was write some clever SQL and voila!


Active Merchant Rails plugin

Definitely the easiest way to integrate with a payment gateway in Rails. Also provides an awesome layer of abstraction in the event that we decide to switch gateways – we won’t have to do a major rewrite of the code in our site that handles payment processing.


Ruport Ruby Reports

Ruport made it incredibly easy for us to provide Excel/CSV and PDF exports from within Tempo’s WYSIWYG reporting interface.


RESTful Authentication Rails plugin

Very handy plugin by Rick Olson for quickly setting up an authentication system for your users that includes an activation step.

Thanks everyone for making these valuable open source contributions to make software like Tempo possible.


Tempo: Launch!

2008-03-17 20:00:00 -0400


Today marks the launch of our newest app, Tempo, a time tracking app for stats addicts, consultants, and anybody involved in professional services and billing time. The “beta” tag is gone, the gloves are off, the doors are open. Check out the tour to find out what it’s all about, sign up for a free account, let us know what you think (e-mail us: support AT zetetic DOT net). As our regulars know, we love hearing your suggestions.


Tempo: That's the Way We Get By - Part 1

2008-03-12 20:00:00 -0400


We built our newest product, Tempo, based on some of our own needs as a business here at Zetetic. Over the next couple of weeks (if we have the time!) we’re going to start talking about some of those reasons to give you a feel for how Tempo works and what it can do for your business.

Now, I’m basically a worker bee, in the sense that I’m not management here at Zetetic. I work on a number of projects that are disparate in terms of technology and clientele, and my day is often split up working on sub tasks within those projects and contracts. I generally use Tempo as the day goes on, whenever I complete a project or switch tracks.

The bookmarklet makes this particularly easy in that I don’t have to go to the site, bring up the new entry form, etc. I just click a button in my browser, I’m still logged in from who knows how long ago, I tap in the hours, and some tags describing what I did.

Usually around the end of the week I’ll log into the site and take a look at a couple of the charts. I generally like to review what projects I’ve spent my time on:




click to embiggen

The chart makes it very easy to see where I’ve been spending the most of my time, and where I might want to put a little more in.

Also instructive is taking a look at a break down of hours by tag:




click to embiggen

Here I can see that the lion’s share of my time so far this week has been spent on rails development, and that ‘recruitment’ could use a little love, because it’s on our minds.

Finally, I find myself looking at my total time trend for the week, or the month, to get a feel for, well, how productive (or not) I’ve been:




click to embiggen

I always like to see that my time trend for the month so far has gone up and not down! But basically I should see a fairly steady trend, or I can expect some abnormal billing at the end of the month.


Setting Rails Date Helpers Via Javascript

2008-03-10 20:00:00 -0400


This took enough of my time that I think it’s worth a blog post. In Tempo you’ll see a familiar paradigm in the time reporting interface (the main screen): a list of editable items in a row, each with the same set of controls. They are editable via AJAX calls, so you can open a number of them for editing at once.

Now, when you’re looking to add javascript observers to these elements (to do automated things like type ahead, etc), you have to assign them unique id attributes, usually based on the object id. While it’s easy to add an :id attribute to any of the usual tag helpers in Rails, it doesn’t work like this with date_select:


%table
%tr.s1
%td{:colspan => '2'}= project_select(f, @current_user.projects, entry)
%td{}
= f.date_select :occurred_on, :order => [:month, :day, :year], :start_year => 2007, :use_short_month => true, :use_short_year => true, :id => "#{entry.id}"
= popup_calendar("entry_#{entry.id}_occurred_on", entry.occurred_on)

Our javascript calendar is expecting a unique ID on the date select drop downs so that it can set their values. But, that’s not the case, the id of each drop down is generated automatically from the name attribute, thus:


<select id="entry_occurred_on_2i" name="entry[occurred_on(2i)]">
<option value="1">Jan</option>
<option value="2">Feb</option>
<option value="3" selected="selected">Mar</option>
...
</select>

Makes sense, really, since the separate drop downs are being generated to be re-assembled when posted, and what else to id them?

The trick to getting unique id’s into these elements was a monkey patch I put in config/initializers/date_helper.rb:


module ActionView
module Helpers
module DateHelper
def name_and_id_from_options(options, type)
options[:name] = (options[:prefix] || DEFAULT_PREFIX) + (options[:discard_type] ? '' : "[#{type}]")
name = options[:name].gsub(/([\[\(])|(\]\[)/, '_').gsub(/[\]\)]/, '')
unless options[:id].nil?
options[:id] = name.sub(/_/, "_#{options[:id]}_")
else
options[:id] = name
end
end
end
end
end

Pretty close to the original, it preserves the original behavior, but respects your inclusion of the :id attribute in the options you pass to date_select. Now our id’s look like:


<select id="entry_2013_occurred_on_3i" name="entry[occurred_on(3i)]">

We found a similar problem with the auto_complete plugin – doesn’t work when there are more than one active on the screen at once, due to non-unique id’s. That required a bit more work. First a monkey-patch in config/initializers/auto_complete_macros_helper.rb:


module AutoCompleteMacrosHelper
def text_field_with_auto_complete(object, method, tag_options = {}, completion_options = {}, object_id = nil)
if object_id.nil?
field_id = "#{object}_#{method}"
else
field_id = "#{object}_#{object_id}_#{method}"
tag_options[:id] = field_id
end

(completion_options[:skip_style] ? "" : auto_complete_stylesheet) +
text_field(object, method, tag_options) +
content_tag("div", "", :id => "#{field_id}_auto_complete", :class => "auto_complete") +
auto_complete_field(field_id, { :url => { :action => "auto_complete_for_#{object}_#{method}" } }.update(completion_options))
end
end

Adding an optional parameter on there seemed like the easiest thing to do for the moment, creates for only a slight change in our form:


= text_field_with_auto_complete :entry, :tag_s, {:size => 40}, { :indicator => "entry_#{entry.id}_tag_s_form_loader", :frequency => 0.4, :tokens => ' ' }, entry.id

I’m tempted to make it work off of whatever shows up in tag_options[:id] but this will do for now.