punchcard 0.2.1 → 0.2.2

Sign up to get free protection for your applications and to get access to all the features.
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.2.1
1
+ 0.2.2
data/lib/public/js/app.js CHANGED
@@ -1,9 +1,19 @@
1
1
  // Update status for all people
2
2
  function update_status() {
3
+ var in_office = [];
3
4
  $.getJSON('/status.json', function(json) {
4
5
  $.each(json, function(index, person) {
5
6
  update_person(person);
6
7
  });
8
+ $('abbr.timeago').timeago();
9
+
10
+ title = 'Punchcard.'
11
+ if ($('.gravatar.pending').size() > 0) {
12
+ title = 'In office: ' + $('.gravatar.pending').map(function() {
13
+ return $(this).attr('title');
14
+ }).get().join(', ');
15
+ }
16
+ $('head title').html(title);
7
17
  });
8
18
  };
9
19
 
@@ -0,0 +1,141 @@
1
+ /*
2
+ * timeago: a jQuery plugin, version: 0.9.2 (2010-09-14)
3
+ * @requires jQuery v1.2.3 or later
4
+ *
5
+ * Timeago is a jQuery plugin that makes it easy to support automatically
6
+ * updating fuzzy timestamps (e.g. "4 minutes ago" or "about 1 day ago").
7
+ *
8
+ * For usage and examples, visit:
9
+ * http://timeago.yarp.com/
10
+ *
11
+ * Licensed under the MIT:
12
+ * http://www.opensource.org/licenses/mit-license.php
13
+ *
14
+ * Copyright (c) 2008-2010, Ryan McGeary (ryanonjavascript -[at]- mcgeary [*dot*] org)
15
+ */
16
+ (function($) {
17
+ $.timeago = function(timestamp) {
18
+ if (timestamp instanceof Date) return inWords(timestamp);
19
+ else if (typeof timestamp == "string") return inWords($.timeago.parse(timestamp));
20
+ else return inWords($.timeago.datetime(timestamp));
21
+ };
22
+ var $t = $.timeago;
23
+
24
+ $.extend($.timeago, {
25
+ settings: {
26
+ refreshMillis: 60000,
27
+ allowFuture: false,
28
+ strings: {
29
+ prefixAgo: null,
30
+ prefixFromNow: null,
31
+ suffixAgo: "ago",
32
+ suffixFromNow: "from now",
33
+ seconds: "less than a minute",
34
+ minute: "about a minute",
35
+ minutes: "%d minutes",
36
+ hour: "about an hour",
37
+ hours: "about %d hours",
38
+ day: "a day",
39
+ days: "%d days",
40
+ month: "about a month",
41
+ months: "%d months",
42
+ year: "about a year",
43
+ years: "%d years",
44
+ numbers: []
45
+ }
46
+ },
47
+ inWords: function(distanceMillis) {
48
+ var $l = this.settings.strings;
49
+ var prefix = $l.prefixAgo;
50
+ var suffix = $l.suffixAgo;
51
+ if (this.settings.allowFuture) {
52
+ if (distanceMillis < 0) {
53
+ prefix = $l.prefixFromNow;
54
+ suffix = $l.suffixFromNow;
55
+ }
56
+ distanceMillis = Math.abs(distanceMillis);
57
+ }
58
+
59
+ var seconds = distanceMillis / 1000;
60
+ var minutes = seconds / 60;
61
+ var hours = minutes / 60;
62
+ var days = hours / 24;
63
+ var years = days / 365;
64
+
65
+ function substitute(stringOrFunction, number) {
66
+ var string = $.isFunction(stringOrFunction) ? stringOrFunction(number, distanceMillis) : stringOrFunction;
67
+ var value = ($l.numbers && $l.numbers[number]) || number;
68
+ return string.replace(/%d/i, value);
69
+ }
70
+
71
+ var words = seconds < 45 && substitute($l.seconds, Math.round(seconds)) ||
72
+ seconds < 90 && substitute($l.minute, 1) ||
73
+ minutes < 45 && substitute($l.minutes, Math.round(minutes)) ||
74
+ minutes < 90 && substitute($l.hour, 1) ||
75
+ hours < 24 && substitute($l.hours, Math.round(hours)) ||
76
+ hours < 48 && substitute($l.day, 1) ||
77
+ days < 30 && substitute($l.days, Math.floor(days)) ||
78
+ days < 60 && substitute($l.month, 1) ||
79
+ days < 365 && substitute($l.months, Math.floor(days / 30)) ||
80
+ years < 2 && substitute($l.year, 1) ||
81
+ substitute($l.years, Math.floor(years));
82
+
83
+ return $.trim([prefix, words, suffix].join(" "));
84
+ },
85
+ parse: function(iso8601) {
86
+ var s = $.trim(iso8601);
87
+ s = s.replace(/\.\d\d\d+/,""); // remove milliseconds
88
+ s = s.replace(/-/,"/").replace(/-/,"/");
89
+ s = s.replace(/T/," ").replace(/Z/," UTC");
90
+ s = s.replace(/([\+-]\d\d)\:?(\d\d)/," $1$2"); // -04:00 -> -0400
91
+ return new Date(s);
92
+ },
93
+ datetime: function(elem) {
94
+ // jQuery's `is()` doesn't play well with HTML5 in IE
95
+ var isTime = $(elem).get(0).tagName.toLowerCase() == "time"; // $(elem).is("time");
96
+ var iso8601 = isTime ? $(elem).attr("datetime") : $(elem).attr("title");
97
+ return $t.parse(iso8601);
98
+ }
99
+ });
100
+
101
+ $.fn.timeago = function() {
102
+ var self = this;
103
+ self.each(refresh);
104
+
105
+ var $s = $t.settings;
106
+ if ($s.refreshMillis > 0) {
107
+ setInterval(function() { self.each(refresh); }, $s.refreshMillis);
108
+ }
109
+ return self;
110
+ };
111
+
112
+ function refresh() {
113
+ var data = prepareData(this);
114
+ if (!isNaN(data.datetime)) {
115
+ $(this).text(inWords(data.datetime));
116
+ }
117
+ return this;
118
+ }
119
+
120
+ function prepareData(element) {
121
+ element = $(element);
122
+ if (!element.data("timeago")) {
123
+ element.data("timeago", { datetime: $t.datetime(element) });
124
+ var text = $.trim(element.text());
125
+ if (text.length > 0) element.attr("title", text);
126
+ }
127
+ return element.data("timeago");
128
+ }
129
+
130
+ function inWords(date) {
131
+ return $t.inWords(distance(date));
132
+ }
133
+
134
+ function distance(date) {
135
+ return (new Date().getTime() - date.getTime());
136
+ }
137
+
138
+ // fix for IE6 suckage
139
+ document.createElement("abbr");
140
+ document.createElement("time");
141
+ })(jQuery);
@@ -33,7 +33,7 @@ class Person < ActiveRecord::Base
33
33
  :email => email,
34
34
  :gravatar_url => gravatar_url(:size => 80),
35
35
  :pending => !!pending?,
36
- :checked_in_at => pending?.try(:checked_in_at)
36
+ :checked_in_at => pending? ? pending?.checked_in_at.getutc.iso8601 : nil
37
37
  }
38
38
  end
39
39
 
data/lib/punchcard.rb CHANGED
@@ -10,7 +10,8 @@ ActiveRecord::Base.logger = Logger.new(STDOUT)
10
10
  ActiveRecord::Base.logger.level = Logger::WARN
11
11
  ActiveRecord::Migration.verbose = false
12
12
 
13
- if ENV['DATABASE_URL']
13
+ # Heroku-deployed apps will have this
14
+ if File.exist?('config/database.yml')
14
15
  dbconfig = YAML.load(File.read('config/database.yml'))
15
16
  ActiveRecord::Base.establish_connection dbconfig[ENV['RACK_ENV']]
16
17
  else
@@ -4,6 +4,7 @@
4
4
  %title Punchcard
5
5
  %script{:src => "http://ajax.googleapis.com/ajax/libs/jquery/1.4.3/jquery.min.js"}
6
6
  %script{:src => 'http://ajax.microsoft.com/ajax/jquery.templates/beta1/jquery.tmpl.min.js'}
7
+ %script{:src => "/js/jquery.timeago.js"}
7
8
  %script{:src => "/js/app.js"}
8
9
  :plain
9
10
  <link rel="stylesheet" href="/css/blueprint.css" type="text/css" media="screen" />
@@ -14,7 +15,9 @@
14
15
  <li id="${_id}">
15
16
  <img src="${gravatar_url}" title="${name}" class="gravatar {{if pending == true}}pending{{/if}} ${pending}"/>
16
17
  <div class="person">${name}</div>
17
- <div class="checked_in_at">{{if checked_in_at}}Checked in at ${checked_in_at}{{/if}}&nbsp;</div>
18
+ {{if checked_in_at}}
19
+ <abbr class="timeago" title="${checked_in_at}"></abbr>
20
+ {{/if}}
18
21
  </li>
19
22
  </script>
20
23
 
@@ -8,11 +8,12 @@ $yellow: #fc0
8
8
  #main
9
9
  width: 800px
10
10
  margin-top: 30px
11
- padding: 30px 20px
11
+ padding: 20px 20px 10px 20px
12
12
  margin-left: auto
13
13
  margin-right: auto
14
- background: #eadab6 url('/cardbg.png') repeat-x
15
- -moz-box-shadow: 3px 3px 4px #d2bd8e
14
+ background: #eadab6
15
+ border-top: 10px solid #f8bba6
16
+ -moz-box-shadow: 3px 3px 0px #d2bd8e
16
17
 
17
18
  .clear
18
19
  clear: both
@@ -34,9 +35,12 @@ $yellow: #fc0
34
35
  .gravatar
35
36
  margin-bottom: 0
36
37
 
37
- .checked_in_at
38
+ .timeago
38
39
  color: #888
39
40
  font-size: 16px
41
+ text-decoraion: none
42
+ border: none
43
+ display: block
40
44
  position: relative
41
45
  top: -10px
42
46
 
data/punchcard.gemspec CHANGED
@@ -5,7 +5,7 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{punchcard}
8
- s.version = "0.2.1"
8
+ s.version = "0.2.2"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Christoph Olszowka"]
@@ -31,6 +31,7 @@ Gem::Specification.new do |s|
31
31
  "lib/public/cardbg.png",
32
32
  "lib/public/css/blueprint.css",
33
33
  "lib/public/js/app.js",
34
+ "lib/public/js/jquery.timeago.js",
34
35
  "lib/punchcard.rb",
35
36
  "lib/punchcard/person.rb",
36
37
  "lib/punchcard/punch.rb",
metadata CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
5
5
  segments:
6
6
  - 0
7
7
  - 2
8
- - 1
9
- version: 0.2.1
8
+ - 2
9
+ version: 0.2.2
10
10
  platform: ruby
11
11
  authors:
12
12
  - Christoph Olszowka
@@ -170,6 +170,7 @@ files:
170
170
  - lib/public/cardbg.png
171
171
  - lib/public/css/blueprint.css
172
172
  - lib/public/js/app.js
173
+ - lib/public/js/jquery.timeago.js
173
174
  - lib/punchcard.rb
174
175
  - lib/punchcard/person.rb
175
176
  - lib/punchcard/punch.rb