Skip to content

Instantly share code, notes, and snippets.

@gregschwartz
Last active July 28, 2016 17:17
Show Gist options
  • Star 5 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save gregschwartz/25b9f0d5260498e0d69a to your computer and use it in GitHub Desktop.
Save gregschwartz/25b9f0d5260498e0d69a to your computer and use it in GitHub Desktop.
RescueTime widget for Dashing.io

Preview

Description

A widget for Dashing which displays the number of hours you've logged on RescueTime, in one productivity grade. If you want time in multiple grade displayed, use multiple widgets (see example).

RescueTime is a "personal analytics service that shows you how you spend your time" on the computer.

Dependencies

None.

##Installation

  1. Copy rescuetime.html, rescuetime.coffee, and rescuetime.scss into the /widgets/rescuetime directory.
  2. Copy rescuetime.rb into your /jobs folder.
  3. Go register for an API key.
  4. Edit /jobs/rescuetime.rb and replace YOUR_RESCUETIME_KEY_HERE with your API key.

##How it works Each widget can display the current day's time within in a single productivity grade:

  • very_productive
  • productive
  • neutral
  • unproductive
  • very_unproductive
  • total_productive (special grade: very_productive + productive)
  • total_unproductive (special grade: very_unproductive + unproductive)

I recommend using total_productive and/or total_unproductive, for the simplest view of your day.

##Add widget(s) to a dashboard Edit the dashboard by adding:

<li data-row="1" data-col="1" data-sizex="1" data-sizey="1">
	<div data-id="rescuetime_total_productive" data-view="Rescuetime" data-title="Productive" data-min="0" data-max="240"></div>
</li>
  • Notice that data-id is rescuetime_total_productive. Each productivity grade must be prepended by rescuetime_.
  • data-view must be set to "Rescuetime".
  • data-title can be whatever you want.

If you wanted to add a widget for total_unproductive as well, you would then add:

<li data-row="1" data-col="1" data-sizex="1" data-sizey="1">
	<div data-id="rescuetime_total_unproductive" data-view="Rescuetime" data-title="Unproductive" data-min="0" data-max="240"></div>
</li>

##Settings /jobs/rescuetime.rb has two optional settings: Goals and an Hour Filter.

###Goals If a goals is set for a productivity grade, the graph will use that as the maximum. It will also set the color of the graph based upon the goal. If no goal is set, widgets default to a maximum of 8 hours.

For example, setting a goal of total_productive: 5*60 would cause all widgets displaying total_productive to be based out of 5 hours (5*60 minutes). Time greater than the goal will be indicated by the numbers, but the graph will no longer increase in size.

As stated, the goal will also change the color of the graph. Productive categories are colored like so:

  • = 100%: bright green

  • = 75%: light green

  • = 50%: yellow

  • < 50%: gray

Neutral and Unproductive categories are colored like so:

  • = 80%: bright red

  • < 80%: light red

###Hour Filter The hour filter allows you to force the widgets to only analyze a range of hours. This way you can ignore time spent on your computer outside of "working hours", whatever those are for you. They're optional; if you want to turn them off, set hours_to_analyze = nil.

class Dashing.Rescuetime extends Dashing.Widget
@accessor 'value', Dashing.AnimatedValue
constructor: ->
super
@observe 'value', (value) ->
#console.log("CONSTRUCTOR+OBSERVE: max="+ @get("max")) if this.id=="rescuetime_total_productive"
meter = $(@node).find(".meter")
#meter.attr("max", @get("max"))
meter.trigger('configure', {"fgColor": @get("color") })#, "max": @get("max")})
meter.val(value).trigger('change')
ready: ->
meter = $(@node).find(".meter")
meter.attr("data-bgcolor", meter.css("background-color"))
meter.attr("data-fgcolor", meter.css("color"))
meter.knob()
<h1 class="title" data-bind="title"></h1>
<input class="meter" data-angleOffset=-125 data-angleArc=250 data-width=200 data-readOnly=true data-bind-value="value" data-bind-data-min="min" data-bind-data-max="max">
<p class="prettyValue" data-bind="prettyValue">time</p>
<p class="more-info" data-bind="moreinfo"></p>
<p class="updated-at" data-bind="updatedAtMessage"></p>
require 'net/https'
require 'json'
######################### CONFIGURATION START #########################
# RescueTime API Key from https://www.rescuetime.com/anapi/setup_submit
rescuetime_api_key = "YOUR_RESCUETIME_KEY_HERE"
goals = {
total_productive: 5*60, #minutes, equal or greater to
total_unproductive: 3*60, #minutes, less than
}
hours_to_analyze = 9..18 #set to nil if you don't want hour based filtering
######################### CONFIGURATION END ###########################
def pretty_time(seconds)
return "" if !seconds
mins = seconds/60
"#{(mins/60).floor}h#{(mins%60).floor}m"
end
#debugging
SCHEDULER.every '1m', :first_in => 0 do |job|
http = Net::HTTP.new("www.rescuetime.com", 443)
http.use_ssl = true
http.verify_mode = OpenSSL::SSL::VERIFY_PEER
#gets the data for today broken by productivity (very distracting, distracting, neutral, etc)
#see https://www.rescuetime.com/anapi/setup/documentation for other options
response = http.request(Net::HTTP::Get.new("/anapi/data?key=#{rescuetime_api_key}&format=json&perspective=interval&restrict_kind=productivity"))
usage = JSON.parse(response.body)
data = {
very_productive: 0,
productive: 0,
neutral: 0,
unproductive: 0,
very_unproductive: 0
}
usage["rows"].each do |row|
if hours_to_analyze
date = DateTime.parse row[0]
next unless hours_to_analyze.include? date.hour
end
data[:very_productive] += row[1] if row[3]==2
data[:productive] += row[1] if row[3]==1
data[:neutral] += row[1] if row[3]==0
data[:unproductive] += row[1] if row[3]==-1
data[:very_unproductive] += row[1] if row[3]==-2
end
data[:total_productive] = data[:very_productive] + data[:productive]
data[:total_unproductive] = data[:unproductive] + data[:very_unproductive]
data.each do |key,seconds|
minutes = seconds/60
my_data = { value: minutes, prettyValue: pretty_time(seconds), color: "#00ff00" }
if goals[key]
goal = goals[key].to_f
if key.to_s.include?("unproductive")
if minutes>goal
my_data["color"] = "#ff0000"
elsif minutes/goal >= 0.75
my_data["color"] = "#E38217"
elsif minutes/goal >= 0.5
my_data["color"] = "#ffff00"
else
my_data["color"] = "#EEE8AA"
end
else
if minutes/goal >= 0.8
my_data["color"] = "#00ff00"
else
my_data["color"] = "#BCED91"
end
end
if minutes>goal
my_data["max"] = minutes
else
my_data["max"] = goal
end
else
my_data["max"] = 8*60
end
if key==:total_productive
my_data["moreinfo"] = "Very productive: #{pretty_time(data[:very_productive])} Productive: #{pretty_time(data[:productive])}"
elsif key==:total_unproductive
my_data["moreinfo"] = "Very unproductive: #{pretty_time(data[:very_unproductive])} Unproductive: #{pretty_time(data[:unproductive])}"
end
send_event("rescuetime_#{key}", my_data)
end
end
// ----------------------------------------------------------------------------
// Sass declarations
// ----------------------------------------------------------------------------
$background-color: #9c4274;
$title-color: rgba(255, 255, 255, 0.7);
$moreinfo-color: rgba(255, 255, 255, 0.3);
$rescuetime-background: darken($background-color, 15%);
// ----------------------------------------------------------------------------
// Widget-rescuetime styles
// ----------------------------------------------------------------------------
.widget-rescuetime {
background-color: $background-color;
input.rescuetime {
background-color: $rescuetime-background;
color: #fff;
}
.title {
color: $title-color;
}
.prettyValue {
background: inherit;
position: absolute;
top: 180px;
left: 90px;
width: 120px;
font-size: 32px;
}
.more-info {
color: $moreinfo-color;
}
.updated-at {
color: rgba(0, 0, 0, 0.3);
}
}
@csu
Copy link

csu commented Mar 4, 2015

Thanks! It worked perfectly!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment