punchcard 0.2.1 → 0.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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