countdowner 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,131 @@
1
+ # Countdowner
2
+
3
+ Countdown announcer for site maintenance etc.
4
+
5
+ [![Build Status](https://secure.travis-ci.org/zubin/countdowner.png)](http://travis-ci.org/zubin/countdowner)
6
+
7
+ ![Molly with Kylie](http://images.smh.com.au/2011/12/17/2845044/art-Molly-420x0.jpg "Molly with Kylie (source: SMH)")
8
+
9
+ ## Synopsis
10
+
11
+ ### Scenario
12
+
13
+ Your site is undergoing infrastructure changes which require downtime. Wouldn't it be great to warn users of impending doom well in advance.
14
+
15
+ ### Solution
16
+
17
+ Simply create a message:
18
+
19
+ Countdowner::Message.create! message: "Site closing for maintenance {{target}}",
20
+ start_at: Time.parse("9pm").utc,
21
+ target: Time.parse("10pm").utc,
22
+ end_at: Time.parse("10:01pm").utc
23
+
24
+ From 9pm users will see something like:
25
+
26
+ Site closing for maintenance 1 hour from now
27
+
28
+ ## Features
29
+
30
+ * human readable time remaining
31
+ * updated via Javascript, so it's always up-to-date
32
+ * when Javascript is disabled, users will see UTC time
33
+ * timezone agnostic
34
+ * unaffected by caching
35
+
36
+ ## Installation
37
+
38
+ Add this line to your application's Gemfile:
39
+
40
+ gem 'countdowner'
41
+
42
+ And then execute:
43
+
44
+ $ bundle
45
+
46
+ ### Rails 3.1 and above
47
+
48
+ # application.js
49
+ //= require jquery.timeago
50
+ //= require jquery.countdowner
51
+
52
+ # Install migrations and migrate
53
+ $ rake countdowner_engine:install:migrations db:migrate
54
+
55
+ ### Rails 3.0 and below
56
+
57
+ **TODO: generators**
58
+
59
+ For now, copy these files into your app (paths are relative to gem).
60
+
61
+ * vendor/assets/javascripts/jquery.timeago.js
62
+ * lib/assets/javascripts/jquery.countdowner.js
63
+ * db/migrations/20121018090014_create_countdowners.rb
64
+
65
+ Then, include the Javascript files and migrate the database.
66
+
67
+ ### All versions
68
+
69
+ Add this to your layout:
70
+
71
+ # application.html.erb (after opening body tag)
72
+ <%= countdowner %>
73
+
74
+ Style it, eg:
75
+
76
+ # countdowner.css
77
+ #countdowner { background:#900; color:white; font-size:1.25em; padding:1em 2em; text-align:center; }
78
+
79
+ ## Optional configuration
80
+
81
+ If you're not fussed about non-Javascript users, you can prevent the UTC time appearing before the DOM loads.
82
+
83
+ # application.html.erb
84
+ <%= countdowner(hidden_initially: true) %>
85
+
86
+ If you're site cops a lot of traffic, cache it!
87
+
88
+ # application.html.erb (note that `expires_in` only works with memcache)
89
+ <% cache('countdowner', expires_in: 5.minutes) do %>
90
+ <%= countdowner %>
91
+ <% end %>
92
+
93
+ ## Requirements
94
+
95
+ * rails (>= 2.3)
96
+ * jQuery
97
+
98
+ ## Acknowledgments
99
+
100
+ This gem uses the excellent [timeago](http://timeago.yarp.com/) jQuery plugin.
101
+
102
+ ## Contributing
103
+
104
+ 1. Fork it
105
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
106
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
107
+ 4. Push to the branch (`git push origin my-new-feature`)
108
+ 5. Create new Pull Request
109
+
110
+ ## MIT License
111
+
112
+ Copyright 2012 Zubin Henner
113
+
114
+ Permission is hereby granted, free of charge, to any person obtaining
115
+ a copy of this software and associated documentation files (the
116
+ "Software"), to deal in the Software without restriction, including
117
+ without limitation the rights to use, copy, modify, merge, publish,
118
+ distribute, sublicense, and/or sell copies of the Software, and to
119
+ permit persons to whom the Software is furnished to do so, subject to
120
+ the following conditions:
121
+
122
+ The above copyright notice and this permission notice shall be
123
+ included in all copies or substantial portions of the Software.
124
+
125
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
126
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
127
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
128
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
129
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
130
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
131
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,15 @@
1
+ #!/usr/bin/env rake
2
+ begin
3
+ require 'bundler/setup'
4
+ rescue LoadError
5
+ puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
6
+ end
7
+
8
+ Bundler::GemHelper.install_tasks
9
+
10
+ task :build_js do
11
+ require 'coffee-script'
12
+ js_path = File.expand_path('../lib/assets/javascripts', __FILE__)
13
+ js = CoffeeScript.compile(File.read(File.join(js_path, 'src', 'jquery.countdowner.js.coffee')))
14
+ File.open(File.join(js_path, 'jquery.countdowner.js'), 'w') { |f| f << js }
15
+ end
@@ -0,0 +1,9 @@
1
+ class CreateCountdowners < ActiveRecord::Migration
2
+ def change
3
+ create_table :countdowners do |t|
4
+ t.datetime :target, :start_at, :end_at
5
+ t.string :message
6
+ end
7
+ add_index :countdowners, [:target, :start_at, :end_at]
8
+ end
9
+ end
@@ -0,0 +1,29 @@
1
+ (function() {
2
+
3
+ $(function() {
4
+ var $countdowner, allowFuture, removeAfterEnd,
5
+ _this = this;
6
+ $countdowner = $('#countdowner');
7
+ if ($countdowner.length) {
8
+ removeAfterEnd = function() {
9
+ console.log("checking...");
10
+ if ($countdowner.data('end_at') < new Date().toISOString()) {
11
+ $countdowner.remove();
12
+ if (_this.checkEnd != null) {
13
+ clearInterval(_this.checkEnd);
14
+ }
15
+ return true;
16
+ }
17
+ };
18
+ if (!removeAfterEnd()) {
19
+ allowFuture = $.timeago.settings.allowFuture;
20
+ $.timeago.settings.allowFuture = true;
21
+ $countdowner.find('time').timeago();
22
+ $countdowner.show();
23
+ $.timeago.settings.allowFuture = allowFuture;
24
+ return this.checkEnd = setInterval(removeAfterEnd, 60000);
25
+ }
26
+ }
27
+ });
28
+
29
+ }).call(this);
@@ -0,0 +1,16 @@
1
+ $ ->
2
+ $countdowner = $('#countdowner')
3
+ if $countdowner.length
4
+ removeAfterEnd = =>
5
+ console.log "checking..."
6
+ if $countdowner.data('end_at') < new Date().toISOString()
7
+ $countdowner.remove()
8
+ clearInterval(@checkEnd) if @checkEnd?
9
+ true
10
+ unless removeAfterEnd()
11
+ allowFuture = $.timeago.settings.allowFuture
12
+ $.timeago.settings.allowFuture = true
13
+ $countdowner.find('time').timeago()
14
+ $countdowner.show()
15
+ $.timeago.settings.allowFuture = allowFuture
16
+ @checkEnd = setInterval(removeAfterEnd, 60000)
@@ -0,0 +1,4 @@
1
+ require 'countdowner/action_view'
2
+ require 'countdowner/datetime'
3
+ require 'countdowner/message'
4
+ require 'countdowner/rails'
@@ -0,0 +1,16 @@
1
+ module Countdowner
2
+ module ActionView
3
+ def countdowner(options = {})
4
+ message = Countdowner::Message.current or return
5
+ options[:id] = 'countdowner'
6
+ options[:'data-end_at'] = Countdowner::Datetime.new(message.end_at).iso
7
+ options[:style] = 'display:none' if options.delete(:hidden_initially)
8
+ content_tag(:div, options) do
9
+ time = Countdowner::Datetime.new(message.target)
10
+ message.message.sub('{{target}}', content_tag(:time, time.to_s, :datetime => time.iso)).html_safe
11
+ end
12
+ end
13
+ end
14
+ end
15
+
16
+ ActionView::Base.send :include, Countdowner::ActionView
@@ -0,0 +1,15 @@
1
+ module Countdowner
2
+ class Datetime
3
+ def initialize(time)
4
+ @utc = time.getutc
5
+ end
6
+
7
+ def iso
8
+ @utc.iso8601
9
+ end
10
+
11
+ def to_s
12
+ @utc.to_s
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,26 @@
1
+ module Countdowner
2
+ class Message < ActiveRecord::Base
3
+ attr_accessible :message, :start_at, :target, :end_at
4
+ validates_presence_of :message, :start_at, :target, :end_at
5
+ validates_format_of :message, :with => /\{\{target\}\}/
6
+ validate :ensure_valid_periods
7
+
8
+ def self.current
9
+ find(:first, :order => "target",
10
+ :conditions => ["target > :now and end_at > :now and start_at < :now", {:now => Time.now.utc}])
11
+ end
12
+
13
+ private
14
+
15
+ def self.table_name
16
+ 'countdowners'
17
+ end
18
+
19
+ def ensure_valid_periods
20
+ if target.present?
21
+ errors.add(:start_at, "must be before target") if start_at.present? && start_at > target
22
+ errors.add(:end_at, "must be after target") if end_at.present? && end_at < target
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,3 @@
1
+ if ::Rails.version >= '3.1'
2
+ Countdowner::Engine = Class.new(::Rails::Engine)
3
+ end
@@ -0,0 +1,3 @@
1
+ module Countdowner
2
+ VERSION = "0.2.0"
3
+ end
@@ -0,0 +1,4 @@
1
+ # desc "Explaining what the task does"
2
+ # task :countdowner do
3
+ # # Task goes here
4
+ # end
metadata ADDED
@@ -0,0 +1,175 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: countdowner
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.2.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Zubin Henner
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-10-18 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rails
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
30
+ - !ruby/object:Gem::Dependency
31
+ name: rails
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - '='
36
+ - !ruby/object:Gem::Version
37
+ version: 3.2.8
38
+ type: :development
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - '='
44
+ - !ruby/object:Gem::Version
45
+ version: 3.2.8
46
+ - !ruby/object:Gem::Dependency
47
+ name: rspec-rails
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ type: :development
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ - !ruby/object:Gem::Dependency
63
+ name: capybara
64
+ requirement: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ! '>='
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
70
+ type: :development
71
+ prerelease: false
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ! '>='
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
78
+ - !ruby/object:Gem::Dependency
79
+ name: shoulda-matchers
80
+ requirement: !ruby/object:Gem::Requirement
81
+ none: false
82
+ requirements:
83
+ - - ! '>='
84
+ - !ruby/object:Gem::Version
85
+ version: '0'
86
+ type: :development
87
+ prerelease: false
88
+ version_requirements: !ruby/object:Gem::Requirement
89
+ none: false
90
+ requirements:
91
+ - - ! '>='
92
+ - !ruby/object:Gem::Version
93
+ version: '0'
94
+ - !ruby/object:Gem::Dependency
95
+ name: sqlite3
96
+ requirement: !ruby/object:Gem::Requirement
97
+ none: false
98
+ requirements:
99
+ - - ! '>='
100
+ - !ruby/object:Gem::Version
101
+ version: '0'
102
+ type: :development
103
+ prerelease: false
104
+ version_requirements: !ruby/object:Gem::Requirement
105
+ none: false
106
+ requirements:
107
+ - - ! '>='
108
+ - !ruby/object:Gem::Version
109
+ version: '0'
110
+ - !ruby/object:Gem::Dependency
111
+ name: coffee-script
112
+ requirement: !ruby/object:Gem::Requirement
113
+ none: false
114
+ requirements:
115
+ - - ! '>='
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ none: false
122
+ requirements:
123
+ - - ! '>='
124
+ - !ruby/object:Gem::Version
125
+ version: '0'
126
+ description: Countdown announcer for site maintenance etc.
127
+ email:
128
+ - zubin.henner@gmail.com
129
+ executables: []
130
+ extensions: []
131
+ extra_rdoc_files: []
132
+ files:
133
+ - db/migrate/20121018090014_create_countdowners.rb
134
+ - lib/assets/javascripts/jquery.countdowner.js
135
+ - lib/assets/javascripts/src/jquery.countdowner.js.coffee
136
+ - lib/countdowner/action_view.rb
137
+ - lib/countdowner/datetime.rb
138
+ - lib/countdowner/message.rb
139
+ - lib/countdowner/rails.rb
140
+ - lib/countdowner/version.rb
141
+ - lib/countdowner.rb
142
+ - lib/tasks/announce_until_tasks.rake
143
+ - Rakefile
144
+ - README.md
145
+ homepage: https://github.com/zubin/countdowner
146
+ licenses: []
147
+ post_install_message:
148
+ rdoc_options: []
149
+ require_paths:
150
+ - lib
151
+ required_ruby_version: !ruby/object:Gem::Requirement
152
+ none: false
153
+ requirements:
154
+ - - ! '>='
155
+ - !ruby/object:Gem::Version
156
+ version: '0'
157
+ segments:
158
+ - 0
159
+ hash: 3925088943962807564
160
+ required_rubygems_version: !ruby/object:Gem::Requirement
161
+ none: false
162
+ requirements:
163
+ - - ! '>='
164
+ - !ruby/object:Gem::Version
165
+ version: '0'
166
+ segments:
167
+ - 0
168
+ hash: 3925088943962807564
169
+ requirements: []
170
+ rubyforge_project:
171
+ rubygems_version: 1.8.24
172
+ signing_key:
173
+ specification_version: 3
174
+ summary: Countdown announcer for site maintenance etc.
175
+ test_files: []