user_announcements 0.0.1 → 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +69 -3
- data/app/controllers/admin/announcements_controller.rb +1 -1
- data/app/helpers/user_announcements_helper.rb +40 -16
- data/app/models/announcement.rb +9 -5
- data/app/models/announcement_finder.rb +11 -6
- data/app/views/admin/announcements/_announcement.html.erb +3 -3
- data/app/views/admin/announcements/_form.html.erb +2 -2
- data/app/views/admin/announcements/index.html.erb +3 -3
- data/app/views/user_announcements/_announcement.html.erb +3 -9
- data/app/views/user_announcements/index.html.erb +3 -2
- data/lib/generators/user_announcements/install_generator.rb +27 -0
- data/lib/generators/user_announcements/templates/css.scss +29 -0
- data/lib/generators/user_announcements/templates/initializer.rb +6 -0
- data/lib/generators/{templates/create_user_announcement_tables.rb → user_announcements/templates/migration.rb} +6 -1
- data/lib/user_announcements/engine.rb +7 -0
- data/lib/user_announcements/version.rb +1 -1
- metadata +5 -10
- data/db/migrate/20130521175710_create_announcements.rb +0 -9
- data/lib/generators/user_announcements_generator.rb +0 -32
data/README.md
CHANGED
@@ -1,5 +1,71 @@
|
|
1
|
-
#
|
1
|
+
# user_announcements
|
2
2
|
|
3
|
-
|
3
|
+
[![Gem Version](https://badge.fury.io/rb/user_announcements.png)](http://badge.fury.io/rb/user_announcements)
|
4
|
+
[![Code Climate](https://codeclimate.com/github/stevedowney/user_announcements.png)](https://codeclimate.com/github/stevedowney/user_announcements)
|
4
5
|
|
5
|
-
|
6
|
+
Manage and display site-wide announcements on a per-user basis.
|
7
|
+
|
8
|
+
Coming soon, scope by user role and announcement type.
|
9
|
+
|
10
|
+
### Acknowledgements
|
11
|
+
|
12
|
+
This gem was inspired by the [Site-Wide Announcements (revised)](http://railscasts.com/episodes/103-site-wide-announcements-revised)
|
13
|
+
episode of [RailsCasts](http://railscasts.com/). If you don't have a premium account you can see the
|
14
|
+
[original episode](http://railscasts.com/episodes/103-site-wide-announcements).
|
15
|
+
|
16
|
+
## Installation
|
17
|
+
|
18
|
+
Add it to your Gemfile:
|
19
|
+
|
20
|
+
```ruby
|
21
|
+
gem "user_announcements"
|
22
|
+
```
|
23
|
+
|
24
|
+
Run bundler:
|
25
|
+
|
26
|
+
```sh
|
27
|
+
bundle install
|
28
|
+
```
|
29
|
+
|
30
|
+
Install files:
|
31
|
+
|
32
|
+
```sh
|
33
|
+
rails generate user_announcements:install
|
34
|
+
```
|
35
|
+
|
36
|
+
By default, Bootstrap styling is applied. This can be turned on/off:
|
37
|
+
|
38
|
+
```ruby
|
39
|
+
# ../config/initializers/user_announcements.rb
|
40
|
+
|
41
|
+
# control Bootstrap styling
|
42
|
+
# c.bootstrap = false
|
43
|
+
c.bootstrap = true
|
44
|
+
|
45
|
+
```
|
46
|
+
|
47
|
+
Don't forget to restart your Rails server.
|
48
|
+
|
49
|
+
## Getting Going
|
50
|
+
|
51
|
+
To create an announcement go to:
|
52
|
+
|
53
|
+
```
|
54
|
+
http://<your app>/admin/announcements
|
55
|
+
```
|
56
|
+
|
57
|
+
To see the announcment add the helper method to your views, e.g.:
|
58
|
+
|
59
|
+
```erb
|
60
|
+
#../layouts/application.html.erb
|
61
|
+
|
62
|
+
<body>
|
63
|
+
<%= user_announcements %>
|
64
|
+
...
|
65
|
+
```
|
66
|
+
|
67
|
+
Non-admin users can see (and unhide) announcements they have hidden:
|
68
|
+
|
69
|
+
```
|
70
|
+
http://<your app>/announcements
|
71
|
+
```
|
@@ -2,7 +2,7 @@ class Admin::AnnouncementsController < Admin::BaseController
|
|
2
2
|
before_filter :find_announcement, :only => [:edit, :update, :destroy]
|
3
3
|
|
4
4
|
def index
|
5
|
-
@announcements =
|
5
|
+
@announcements = AnnouncementFinder.ordered
|
6
6
|
end
|
7
7
|
|
8
8
|
def new
|
@@ -1,10 +1,7 @@
|
|
1
1
|
module UserAnnouncementsHelper
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
# type: "blog"
|
6
|
-
# role: "admin super-admin"
|
7
|
-
def announcements(options={})
|
3
|
+
# Helper method for displaying messages for +current_user+.
|
4
|
+
def user_announcements(options={})
|
8
5
|
return if controller.controller_name == 'user_announcements'
|
9
6
|
|
10
7
|
announcements_rows = AnnouncementFinder.current_for_user(current_user)
|
@@ -16,21 +13,27 @@ module UserAnnouncementsHelper
|
|
16
13
|
end
|
17
14
|
|
18
15
|
def announcement_div(announcement)
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
16
|
+
if bootstrap?
|
17
|
+
announcement_div_bootstrap(announcement)
|
18
|
+
else
|
19
|
+
announcement_div_non_bootstrap(announcement)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def announcement_div_bootstrap(announcement)
|
24
24
|
div_for announcement, class: 'alert', style: 'width:40em' do
|
25
25
|
link_to(hide_user_announcement_path(announcement), remote: true) do
|
26
|
-
content_tag(:button, raw('×'), type: 'button', class: 'close'
|
26
|
+
content_tag(:button, raw('×'), type: 'button', class: 'close')
|
27
27
|
end +
|
28
|
-
announcement.
|
28
|
+
announcement.message.html_safe
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def announcement_div_non_bootstrap(announcement)
|
33
|
+
div_for(announcement, class: 'non-bootstrap') do
|
34
|
+
announcement.message.html_safe +
|
35
|
+
link_to("hide announcement", hide_user_announcement_path(announcement), remote: true)
|
29
36
|
end
|
30
|
-
# div_for(announcement) do
|
31
|
-
# announcement.body.html_safe +
|
32
|
-
# link_to("hide announcement", 'hide_announcement_path(announcement)', remote: true)
|
33
|
-
# end
|
34
37
|
end
|
35
38
|
|
36
39
|
def unhide_announcement_link(announcement)
|
@@ -41,6 +44,20 @@ module UserAnnouncementsHelper
|
|
41
44
|
end
|
42
45
|
end
|
43
46
|
|
47
|
+
def ua_table_attrs
|
48
|
+
if bootstrap?
|
49
|
+
{class: "table table-striped table-bordered table-condensed table-hover"}
|
50
|
+
else
|
51
|
+
{class: 'ua-table'}
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def ua_table_tag(options={})
|
56
|
+
content_tag(:table, options.merge(ua_table_attrs)) do
|
57
|
+
yield
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
44
61
|
def boolean_display(boolean)
|
45
62
|
( boolean ? '✔' : ' ' ).html_safe
|
46
63
|
end
|
@@ -63,4 +80,11 @@ module UserAnnouncementsHelper
|
|
63
80
|
end
|
64
81
|
end
|
65
82
|
|
83
|
+
def bootstrap?
|
84
|
+
if params.has_key?(:bootstrap)
|
85
|
+
params[:bootstrap] == 'true'
|
86
|
+
else
|
87
|
+
UserAnnouncements.config.bootstrap
|
88
|
+
end
|
89
|
+
end
|
66
90
|
end
|
data/app/models/announcement.rb
CHANGED
@@ -1,17 +1,18 @@
|
|
1
1
|
class Announcement < ActiveRecord::Base
|
2
|
-
attr_accessible :
|
2
|
+
attr_accessible :message, :starts_at, :ends_at, :active
|
3
3
|
|
4
4
|
has_many :user_announcements, :dependent => :destroy
|
5
5
|
|
6
|
-
validates_presence_of :
|
6
|
+
validates_presence_of :message, :starts_at, :ends_at
|
7
7
|
|
8
|
-
|
8
|
+
INACTIVE = 'inactive'
|
9
9
|
PAST = 'past'
|
10
10
|
CURRENT = 'current'
|
11
11
|
FUTURE = 'future'
|
12
12
|
|
13
13
|
def status
|
14
14
|
case
|
15
|
+
when active.presence.nil? then INACTIVE
|
15
16
|
when ends_at.try(:past?) then PAST
|
16
17
|
when starts_at.try(:future?) then FUTURE
|
17
18
|
else CURRENT
|
@@ -23,18 +24,21 @@ class Announcement < ActiveRecord::Base
|
|
23
24
|
end
|
24
25
|
|
25
26
|
def status_order
|
26
|
-
{ FUTURE => 1, CURRENT => 2, PAST => 3 }[status]
|
27
|
+
{ FUTURE => 1, CURRENT => 2, PAST => 3, INACTIVE => 4 }[status]
|
27
28
|
end
|
28
29
|
|
29
30
|
class << self
|
30
31
|
|
32
|
+
def active
|
33
|
+
where(active: true)
|
34
|
+
end
|
35
|
+
|
31
36
|
def new_with_defaults
|
32
37
|
new do |ann|
|
33
38
|
ann.active = true
|
34
39
|
ann.starts_at = Time.now.at_beginning_of_day
|
35
40
|
ann.ends_at = 1.week.from_now.at_midnight
|
36
41
|
end
|
37
|
-
|
38
42
|
end
|
39
43
|
|
40
44
|
end
|
@@ -2,17 +2,22 @@ class AnnouncementFinder
|
|
2
2
|
|
3
3
|
class << self
|
4
4
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
# end
|
5
|
+
def ordered
|
6
|
+
Announcement.all.sort_by(&:status_order)
|
7
|
+
end
|
9
8
|
|
10
9
|
def current
|
11
|
-
Announcement
|
10
|
+
Announcement
|
11
|
+
.active
|
12
|
+
.where("starts_at is null or starts_at < :now", now: DateTime.now)
|
13
|
+
.where("ends_at is null or ends_at > :now", now: DateTime.now)
|
12
14
|
end
|
13
15
|
|
14
16
|
def past_or_current
|
15
|
-
Announcement
|
17
|
+
Announcement
|
18
|
+
.active
|
19
|
+
.where("(starts_at is null or starts_at < :now)", :now => DateTime.now)
|
20
|
+
.order('created_at desc')
|
16
21
|
end
|
17
22
|
|
18
23
|
def current_for_user(user)
|
@@ -1,7 +1,7 @@
|
|
1
1
|
<tr id="<%= dom_id(announcement) %>" class='<%= announcement.status %>'>
|
2
|
-
<td><%=raw announcement.
|
3
|
-
<td><%= announcement.starts_at.try(:to_s, :db) %></td>
|
4
|
-
<td><%= announcement.ends_at.try(:to_s, :db) %></td>
|
2
|
+
<td><%=raw announcement.message %></td>
|
3
|
+
<td class='date'><%= announcement.starts_at.try(:to_s, :db) %></td>
|
4
|
+
<td class='date'><%= announcement.ends_at.try(:to_s, :db) %></td>
|
5
5
|
<td><%= announcement.status %></td>
|
6
6
|
<td><%= boolean_display(announcement.active)%></td>
|
7
7
|
<td><%= link_to('edit', edit_admin_announcement_path(announcement), :class => 'btn btn-mini') %></td>
|
@@ -4,8 +4,8 @@
|
|
4
4
|
<%#= f.input(:starts_at, :as => :string, :input_html => {class: 'datepicker'}) %>
|
5
5
|
<%#= f.input(:ends_at, :as => :string, :input_html => {class: 'datepicker'}) %>
|
6
6
|
<p>
|
7
|
-
<%= f.label(:
|
8
|
-
<%= f.text_area :
|
7
|
+
<%= f.label(:message) %>
|
8
|
+
<%= f.text_area :message, size: "60x10", class: 'span6' %>
|
9
9
|
</p>
|
10
10
|
|
11
11
|
<%= ua_datetime_p(f, :starts_at) %>
|
@@ -1,10 +1,10 @@
|
|
1
|
-
<h1>Announcements</h1>
|
1
|
+
<h1>Administer Announcements</h1>
|
2
2
|
|
3
3
|
<p>
|
4
4
|
<%= link_to('New Announcement', new_admin_announcement_path(), :class => 'btn btn-primary') %>
|
5
5
|
</p>
|
6
6
|
|
7
|
-
|
7
|
+
<%= ua_table_tag(id: 'admin-announcements') do %>
|
8
8
|
<thead>
|
9
9
|
<tr>
|
10
10
|
<th>Announcement</th>
|
@@ -19,4 +19,4 @@
|
|
19
19
|
<tbody>
|
20
20
|
<%= render @announcements %>
|
21
21
|
</tbody>
|
22
|
-
|
22
|
+
<% end %>
|
@@ -1,14 +1,8 @@
|
|
1
|
+
|
1
2
|
<tr id="<%= dom_id(announcement) %>">
|
2
3
|
<td class='date'><%= announcement.created_at.try(:to_s, :db) %></td>
|
3
4
|
<td>
|
4
|
-
<%= announcement.
|
5
|
+
<%= announcement.message.html_safe %>
|
5
6
|
<%= unhide_announcement_link(announcement) %>
|
6
7
|
</td>
|
7
|
-
</tr>
|
8
|
-
|
9
|
-
<style>
|
10
|
-
td.date {
|
11
|
-
white-space: nowrap;
|
12
|
-
vertical-align: top;
|
13
|
-
}
|
14
|
-
</style>
|
8
|
+
</tr>
|
@@ -1,6 +1,6 @@
|
|
1
1
|
<h1>Announcements</h1>
|
2
2
|
|
3
|
-
|
3
|
+
<%= ua_table_tag(id: 'user-announcements') do %>
|
4
4
|
<thead>
|
5
5
|
<tr>
|
6
6
|
<th>Date</th>
|
@@ -10,4 +10,5 @@
|
|
10
10
|
<tbody>
|
11
11
|
<%= render partial: 'user_announcements/announcement', collection: @announcements %>
|
12
12
|
</tbody>
|
13
|
-
|
13
|
+
<% end %>
|
14
|
+
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'rails/generators/active_record/migration'
|
2
|
+
|
3
|
+
module UserAnnouncements
|
4
|
+
module Generators
|
5
|
+
class InstallGenerator < Rails::Generators::Base
|
6
|
+
include Rails::Generators::Migration
|
7
|
+
extend ActiveRecord::Generators::Migration
|
8
|
+
source_root File.join(File.dirname(__FILE__), "templates")
|
9
|
+
|
10
|
+
desc <<DESC
|
11
|
+
Description:
|
12
|
+
Copies stylesheet to 'app/assets/stylesheets/user_announcements.css.scss'
|
13
|
+
Copies configuration to 'config/initializers/user_announcements.rb'
|
14
|
+
Copies db migration to 'db/migrate/<timestamp>/create_user_announcement_tables.rb'
|
15
|
+
|
16
|
+
DESC
|
17
|
+
|
18
|
+
def install
|
19
|
+
copy_file "css.scss", 'app/assets/stylesheets/user_announcements.css.scss'
|
20
|
+
copy_file "initializer.rb", 'config/initializers/user_announcements.rb'
|
21
|
+
migration_template "migration.rb", "db/migrate/create_user_announcement_tables.rb"
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
@@ -0,0 +1,29 @@
|
|
1
|
+
table.ua-table {
|
2
|
+
border: 1px solid black;
|
3
|
+
|
4
|
+
th, td {
|
5
|
+
border: 1px solid black;
|
6
|
+
padding: 0.5em;
|
7
|
+
}
|
8
|
+
|
9
|
+
td {
|
10
|
+
vertical-align: top;
|
11
|
+
|
12
|
+
&.date {
|
13
|
+
white-space: nowrap;
|
14
|
+
}
|
15
|
+
}
|
16
|
+
}
|
17
|
+
|
18
|
+
.announcement.non-bootstrap {
|
19
|
+
width: 100%;
|
20
|
+
background-color: #F1F094;
|
21
|
+
border-bottom: solid 1px black;
|
22
|
+
padding: 10px;
|
23
|
+
text-align: center;
|
24
|
+
a {
|
25
|
+
font-size: 12px;
|
26
|
+
margin-left: 5px;
|
27
|
+
color: #6E5910;
|
28
|
+
}
|
29
|
+
}
|
@@ -1,10 +1,12 @@
|
|
1
1
|
class CreateUserAnnouncementTables < ActiveRecord::Migration
|
2
2
|
def change
|
3
3
|
create_table :announcements do |t|
|
4
|
-
t.text :
|
4
|
+
t.text :message
|
5
5
|
t.datetime :starts_at
|
6
6
|
t.datetime :ends_at
|
7
7
|
t.boolean :active
|
8
|
+
t.text :roles
|
9
|
+
t.text :types
|
8
10
|
t.timestamps
|
9
11
|
end
|
10
12
|
|
@@ -13,5 +15,8 @@ class CreateUserAnnouncementTables < ActiveRecord::Migration
|
|
13
15
|
t.integer :announcement_id
|
14
16
|
t.timestamps
|
15
17
|
end
|
18
|
+
|
19
|
+
add_index :user_announcements, :user_id
|
20
|
+
add_index :user_announcements, :announcement_id
|
16
21
|
end
|
17
22
|
end
|
@@ -2,5 +2,12 @@ module UserAnnouncements
|
|
2
2
|
class Engine < ::Rails::Engine
|
3
3
|
config.generators.integration_tool :rspec
|
4
4
|
config.generators.test_framework :rspec
|
5
|
+
|
6
|
+
config.bootstrap = false
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.config(&block)
|
10
|
+
yield Engine.config if block
|
11
|
+
Engine.config
|
5
12
|
end
|
6
13
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: user_announcements
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.2
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -290,9 +290,10 @@ files:
|
|
290
290
|
- app/views/user_announcements/hide.js.erb
|
291
291
|
- app/views/user_announcements/index.html.erb
|
292
292
|
- config/routes.rb
|
293
|
-
-
|
294
|
-
- lib/generators/templates/
|
295
|
-
- lib/generators/
|
293
|
+
- lib/generators/user_announcements/install_generator.rb
|
294
|
+
- lib/generators/user_announcements/templates/css.scss
|
295
|
+
- lib/generators/user_announcements/templates/initializer.rb
|
296
|
+
- lib/generators/user_announcements/templates/migration.rb
|
296
297
|
- lib/tasks/user_announcements_tasks.rake
|
297
298
|
- lib/user_announcements/engine.rb
|
298
299
|
- lib/user_announcements/version.rb
|
@@ -313,18 +314,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
313
314
|
- - ! '>='
|
314
315
|
- !ruby/object:Gem::Version
|
315
316
|
version: '0'
|
316
|
-
segments:
|
317
|
-
- 0
|
318
|
-
hash: -1264060976197441369
|
319
317
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
320
318
|
none: false
|
321
319
|
requirements:
|
322
320
|
- - ! '>='
|
323
321
|
- !ruby/object:Gem::Version
|
324
322
|
version: '0'
|
325
|
-
segments:
|
326
|
-
- 0
|
327
|
-
hash: -1264060976197441369
|
328
323
|
requirements: []
|
329
324
|
rubyforge_project:
|
330
325
|
rubygems_version: 1.8.25
|
@@ -1,32 +0,0 @@
|
|
1
|
-
require 'rails/generators/active_record/migration'
|
2
|
-
|
3
|
-
class UserAnnouncementsGenerator < Rails::Generators::Base
|
4
|
-
include Rails::Generators::Migration
|
5
|
-
extend ActiveRecord::Generators::Migration
|
6
|
-
|
7
|
-
desc "Put the code"
|
8
|
-
source_root File.join(File.dirname(__FILE__), "templates")
|
9
|
-
|
10
|
-
def install
|
11
|
-
# copy_javascript if needs_js_copied?
|
12
|
-
migration_template "create_user_announcement_tables.rb", "db/migrate/create_user_announcement_tables.rb"
|
13
|
-
end
|
14
|
-
|
15
|
-
private
|
16
|
-
|
17
|
-
def copy_javascript
|
18
|
-
copy_file File.join(javascript_path, 'announcements.js'), js_destination
|
19
|
-
end
|
20
|
-
|
21
|
-
def javascript_path
|
22
|
-
File.join(%w(.. .. .. .. app assets javascripts))
|
23
|
-
end
|
24
|
-
|
25
|
-
def needs_js_copied?
|
26
|
-
::Rails.version < '3.1' || !::Rails.application.config.assets.enabled
|
27
|
-
end
|
28
|
-
|
29
|
-
def js_destination
|
30
|
-
'public/javascripts/announcements.js'
|
31
|
-
end
|
32
|
-
end
|