diff --git a/README.md b/README.md new file mode 100644 index 0000000..69414a3 --- /dev/null +++ b/README.md @@ -0,0 +1,35 @@ +This script set is for adding local time tracking feature to [Hiveminder](http://hiveminder.com/). + +Yeah, I know Hiveminder supports time tracking. But it doesn't work at offline. +I sometimes place myself at offline, because working at online has a number of temptations, twitter/irc/im and so on.. + + +## Features + +* Simple time tracking +* Fluid app support (also include my userstyle for this) +* Enable growl notification instead of jGrowl (Fluid only) +* Notify current tasks every 10 minutes (it probably get you back to work ;) + + +## Current issues + +* Currently it doesn't save elapsed time, so you lost it when reload page. + + +## How to use + +### For fluid app users + +* Setup hiveminder fluid app +* Open the app and go preferences panel -> Userstyles, and copy 'hiveminder-fluid.css' and paste it there. +* Copy `jgrowll.user.js` and `hiveminder-local-time-track.user.js` into `~/Library/Application Support/Fluid/SSB/{Your App Name/Userscripts/` and enable these. + +### For firefox users + +* install `hiveminder-local-time-track.user.js` as Greasemonkey script and enable it. + + +## Author + +Daisuke Murase diff --git a/hiveminder-fluid.css b/hiveminder-fluid.css new file mode 100644 index 0000000..e2fe80e --- /dev/null +++ b/hiveminder-fluid.css @@ -0,0 +1,27 @@ +div#info-wrapper { + display: none !important; +} + +div#content-wrapper2 { + margin-left: 0px !important; +} + +div#headers { + display: none !important; +} + +.tasklist-fragment > .feed-list { + display: none !important; +} + +div#footer { + display: none !important; +} + +div#actions_container { + display: none !important; +} + +h1.title { + display: none !important; +} diff --git a/hiveminder-local-time-track.user.js b/hiveminder-local-time-track.user.js new file mode 100644 index 0000000..1099446 --- /dev/null +++ b/hiveminder-local-time-track.user.js @@ -0,0 +1,143 @@ +// ==UserScript== +// @name hiveminder local time tracking +// @namespace unknownplace.org +// @description add time tracking feature on hiveminder +// @include http://hiveminder.com/* +// @include https://hiveminder.com/* +// ==/UserScript== + +(function (d, w) { + var debug = false; + function log() { debug && w.console.log.apply(null, arguments) }; + + var $ = w.jQuery; + var tasks = []; + + var start_button = $("") + .text("Start!") + .addClass("track_start").css({ + "display": "block", + "width": "50px", + "padding": "4px", + "-moz-border-radius-topleft": "5px", + "-moz-border-radius-bottomleft": "5px", + "-webkit-border-top-left-radius": "5px", + "-webkit-border-bottom-left-radius": "5px", + "background-color": "#00bb00", + "color": "#ffffff", + "text-align": "center", + "float": "left" + }); + + var stop_button = $("") + .text("Stop!") + .addClass("track_stop").css({ + "display": "block", + "width": "50px", + "padding": "4px", + "-moz-border-radius-topleft": "5px", + "-moz-border-radius-bottomleft": "5px", + "-webkit-border-top-left-radius": "5px", + "-webkit-border-bottom-left-radius": "5px", + "background-color": "#ff3344", + "color": "#ffffff", + "text-align": "center", + "float": "left" + }).hide(); + + var indicator = $("
") + .text("00:00:00") + .addClass("track_indicator").css({ + "display": "block", + "width": "80px", + "padding": "4px", + "-moz-border-radius-topright": "5px", + "-moz-border-radius-bottomright": "5px", + "-webkit-border-top-right-radius": "5px", + "-webkit-border-bottom-right-radius": "5px", + "background-color": "#eee", + "color": "#333", + "text-align": "center", + "font-weight": "bold", + "float": "left" + }); + + var time_format = function (sec) { + var h = parseInt(sec / 60 / 60); + var m = parseInt((sec - h*60*60) / 60); + var s = parseInt(sec - h*60*60 - m*60); + if (h < 10) h = "0" + h; + if (m < 10) m = "0" + m; + if (s < 10) s = "0" + s; + return h + ":" + m + ":" + s; + } + + var start = function (task) { + stop(); + + task.running = (new Date()).getTime() - task.time * 1000; + $(".track_start", task.obj).hide(); + $(".track_stop", task.obj).show(); + + setTimeout(timer, 200, task); + + $.jGrowl("Start \"" + task.name + "\""); + }; + + var stop = function () { + for (var i in tasks) { + var task = tasks[i]; + if (task.running) { + task.running = false; + $(".track_stop", task.obj).hide(); + $(".track_start", task.obj).show(); + + $.jGrowl("Stopped \"" + task.name + "\""); + } + } + }; + + var timer = function (task) { + if (task.running) { + var elapsed = ((new Date()).getTime() - task.running) / 1000; + + if (parseInt(elapsed / 60) > parseInt(task.time / 60)) { + if ( (parseInt(elapsed / 60) % 10) == 0 ) { + $.jGrowl(task.name + " [" + time_format(elapsed) + "]", { + header: "You're doing now:" + }); + } + } + + task.time = elapsed; + task.indicator.text( time_format(task.time) ); + + setTimeout(arguments.callee, 200, task); + } + }; + + $(".todo .task").each(function (i) { + var task = { + obj : this, + id : $(".record_locator", this).text(), + name: $(".task_summary", this).text(), + time: 0, + running: false, + indicator: indicator.clone() + } + tasks.push(task); + + var div = $("
").css({ + "display": "block", + "overflow": "auto" + }); + + $(".edit_context_menu", this).after(div); + div + .append( start_button.clone().click(function () { start(task) }) ) + .append( stop_button.clone().click(stop) ) + .append( task.indicator ); + }); + +})(document, (typeof(unsafeWindow) != "undefined") ? unsafeWindow : window); + diff --git a/jgrowl.user.js b/jgrowl.user.js new file mode 100644 index 0000000..3378568 --- /dev/null +++ b/jgrowl.user.js @@ -0,0 +1,35 @@ +// ==UserScript== +// @name jgrowl +// @namespace http://fluidapp.com +// @description do growl notification instead of jgrowl +// @include * +// @author Daisuke Murase +// ==/UserScript== + +(function (app) { + if (!app) return; + + function strip_tags (str) { + str = str.replace(/<.*?>/g, ""); + return str; + } + + var jGrowl = jQuery.jGrowl; + jQuery.jGrowl = function (message, option) { + if (typeof(option) != "object") option = {}; + + // strip html tags + var header = strip_tags(option["header"] || ""); + var description = strip_tags(message || ""); + + app.showGrowlNotification({ + title: header, + description: description, + sticky: !!option["sticky"], + onclick: function () { app.activate() } + }); + + return true; + } + +})(window.fluid);