user_announcements 0.0.3 → 0.0.4

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/README.md CHANGED
@@ -5,9 +5,15 @@
5
5
  [![Coverage Status](https://coveralls.io/repos/stevedowney/user_announcements/badge.png?branch=master)](https://coveralls.io/r/stevedowney/user_announcements?branch=master)
6
6
  [![Code Climate](https://codeclimate.com/github/stevedowney/user_announcements.png)](https://codeclimate.com/github/stevedowney/user_announcements)
7
7
 
8
- Manage and display site-wide announcements on a per-user basis.
8
+ ## Features:
9
9
 
10
- Coming soon, scope by user role and announcement type.
10
+ * admins
11
+ * page for maintaining announcements
12
+ * announcements can be scoped by user role
13
+ * users
14
+ * hide announcements
15
+ * view past and hidden announcements
16
+ * unhide hidden announcements
11
17
 
12
18
  ### Acknowledgements
13
19
 
@@ -15,6 +21,13 @@ This gem was inspired by the [Site-Wide Announcements (revised)](http://railscas
15
21
  episode of [RailsCasts](http://railscasts.com/). If you don't have a premium account you can see the
16
22
  [original episode](http://railscasts.com/episodes/103-site-wide-announcements).
17
23
 
24
+ ## Assumptions
25
+
26
+ * your controllers respond to `ensure_admin_user` which ensures only admin users can create/edit/delete
27
+ announcemets
28
+ * your controllers respond to `current_user`, which is also a `helper_method`
29
+ * if you implement roles, `current_user` responds to `#has_role?(<role>)`
30
+
18
31
  ## Installation
19
32
 
20
33
  Add it to your Gemfile:
@@ -35,28 +48,53 @@ Install files:
35
48
  rails generate user_announcements:install
36
49
  ```
37
50
 
38
- By default, Bootstrap styling is applied. This can be turned on/off:
39
-
40
- ```ruby
41
- # ../config/initializers/user_announcements.rb
51
+ ## Getting Started
42
52
 
43
- # control Bootstrap styling
44
- # c.bootstrap = false
45
- c.bootstrap = true
53
+ ### Controller Methods Example
46
54
 
55
+ ```ruby
56
+ class ApplicationController < ActionController::Base
57
+ protect_from_forgery
58
+
59
+ private
60
+
61
+ def ensure_admin_user
62
+ current_user.has_role?('admin')
63
+ end
64
+
65
+ def current_user
66
+ @user ||= User.find(session[:user_id])
67
+ end
68
+ helper_method :current_user
69
+
70
+ end
47
71
  ```
48
72
 
49
- Don't forget to restart your Rails server.
73
+ ### User Model Methods
74
+
50
75
 
51
- ## Getting Going
76
+ ```ruby
77
+ class User < ActiveRecord::Base
78
+
79
+ def has_role?(role)
80
+ return true if role.blank?
81
+ return true if role == admin && self.admin?
82
+ # ... more elaborate role checking code here?
83
+ false
84
+ end
85
+
86
+ end
87
+ ```
52
88
 
53
- To create an announcement go to:
89
+ ### Create an Announcement
54
90
 
55
91
  ```
56
92
  http://<your app>/admin/announcements
57
93
  ```
58
94
 
59
- To see the announcment add the helper method to your views, e.g.:
95
+ ### View the Announcement
96
+
97
+ Add the helper method to your layout:
60
98
 
61
99
  ```erb
62
100
  #../layouts/application.html.erb
@@ -66,8 +104,59 @@ To see the announcment add the helper method to your views, e.g.:
66
104
  ...
67
105
  ```
68
106
 
69
- Non-admin users can see (and unhide) announcements they have hidden:
107
+ Now visit some page that uses that layout to see the announcement.
108
+
109
+ Non-admin users can see current and past announcements, including ones they have hidden,
110
+ by visiting:
70
111
 
71
112
  ```
72
113
  http://<your app>/announcements
73
114
  ```
115
+
116
+ ### URL Helpers
117
+
118
+ The following url helpers are available:
119
+
120
+ ```ruby
121
+ # admin manages announcements
122
+ admin_announcements_path
123
+
124
+ # user manages own announcements
125
+ hidden_announcements_path
126
+ ```
127
+
128
+ ## Configuration
129
+
130
+ There are several configuration settings found in `../config/initializers/user_announcements.rb`.
131
+
132
+ ```ruby
133
+ # note: all options accept lambdas
134
+
135
+ UserAnnouncements.config do |config|
136
+
137
+ # Bootstrap
138
+ config.bootstrap = true
139
+ config.styles = [['Yellow', ''], ['Red', 'alert-error'], ['Green', 'alert-success'], ['Blue', 'alert-info']]
140
+
141
+ # non-Bootstrap
142
+ # config.bootstrap = false
143
+ # config.styles = [['Yellow', 'yellow'], ['Red', 'red'], ['Green', 'green'], ['Blue', 'blue']]
144
+
145
+ # Announcement defaults
146
+ config.default_active = true
147
+ config.default_starts_at = lambda { Time.now.in_time_zone }
148
+ config.default_ends_at = lambda { 1.week.from_now.in_time_zone.end_of_day }
149
+ config.default_style = ''
150
+ # config.default_roles = ['admin']
151
+
152
+ # Roles
153
+ # config.roles = []
154
+ # config.roles = ['', 'admin']
155
+ # config.roles = [ ['Public', ''], ['Administrator', 'admin'] ]
156
+ # config.roles = lambda { MyRoleClass.map { |role| [role.name, role.id] } }
157
+
158
+ end
159
+ ```
160
+
161
+ Don't forget to restart your Rails server after changes to the config file.
162
+
@@ -1,8 +1,9 @@
1
- class Admin::AnnouncementsController < Admin::BaseController
1
+ class Admin::AnnouncementsController < ApplicationController
2
+ before_filter :ensure_admin_user
2
3
  before_filter :find_announcement, :only => [:edit, :update, :destroy]
3
4
 
4
5
  def index
5
- @announcements = AnnouncementFinder.ordered
6
+ @announcements = AnnouncementFinder.for_admin
6
7
  end
7
8
 
8
9
  def new
@@ -22,7 +23,10 @@ class Admin::AnnouncementsController < Admin::BaseController
22
23
  end
23
24
 
24
25
  def update
25
- if @announcement.update_attributes(params.fetch(:announcement))
26
+ attributes = params.fetch(:announcement)
27
+ .reverse_merge(roles: [])
28
+
29
+ if @announcement.update_attributes(attributes)
26
30
  redirect_to admin_announcements_path, :flash => { success: 'Announcement updated' }
27
31
  else
28
32
  render "edit"
@@ -1,8 +1,7 @@
1
1
  class HiddenAnnouncementsController < ApplicationController
2
- before_filter :ensure_current_user
3
-
2
+
4
3
  def index
5
- @announcements = AnnouncementFinder.past_or_current
4
+ @announcements = AnnouncementFinder.for_edit(current_user)
6
5
  @hidden_announcement_ids = HiddenAnnouncement.hidden_announcement_ids_for(current_user.id)
7
6
  end
8
7
 
@@ -19,5 +18,5 @@ class HiddenAnnouncementsController < ApplicationController
19
18
  HiddenAnnouncement.delete_all(user_id: current_user.id, announcement_id: params.fetch(:announcement_id))
20
19
  redirect_to action: 'index'
21
20
  end
22
-
21
+
23
22
  end
@@ -0,0 +1,43 @@
1
+ module UserAnnouncements::AdminHelper
2
+
3
+ def _ua_active_model_errors(model)
4
+ return unless model.errors.present?
5
+
6
+ content_tag(:div, class: ['alert', 'alert-error']) do
7
+ content_tag(:h4, "Correct the following errors:") +
8
+ content_tag(:ul) do
9
+ safe_join(model.errors.full_messages.map { |msg| content_tag(:li, msg) }, "\n")
10
+ end
11
+ end
12
+ end
13
+
14
+ def ua_table_tag(options={})
15
+ content_tag(:table, options.merge(ua_table_attrs)) do
16
+ yield
17
+ end
18
+ end
19
+
20
+ def boolean_display(boolean)
21
+ ( boolean ? '&#10004;' : '&nbsp;' ).html_safe
22
+ end
23
+
24
+ def ua_datetime_p(f, method)
25
+ content_tag(:p, class: 'datetime-select') do
26
+ f.label(method) +
27
+ ua_br +
28
+ f.datetime_select(method)
29
+ end
30
+ end
31
+
32
+ private
33
+
34
+ def ua_table_attrs
35
+ if ua_bootstrap?
36
+ {class: "ua-table bootstrap table table-striped table-bordered table-hover"}
37
+ else
38
+ {class: 'ua-table non-bootstrap'}
39
+ end
40
+ end
41
+
42
+
43
+ end
@@ -0,0 +1,39 @@
1
+ module UserAnnouncements::MiscHelper
2
+
3
+ def ua_datetime_display(datetime)
4
+ if datetime.present?
5
+ datetime.to_s(:short)
6
+ else
7
+ nil
8
+ end
9
+ end
10
+
11
+ # Return a <br> tag if not bootstrap
12
+ def ua_br
13
+ "<br />".html_safe unless ua_bootstrap?
14
+ end
15
+
16
+ def flash_messages
17
+ return nil if flash.empty?
18
+ result = []
19
+ flash.each do |name, msg|
20
+ result << build_message(name, msg)
21
+ end
22
+ result.join("").html_safe
23
+ end
24
+
25
+ def build_message(msg_type, msg)
26
+ content_tag(:div, :class => "alert alert-#{msg_type.to_s}") do
27
+ content_tag(:a, 'x', :class => "close", "data-dismiss" => "alert") + msg.html_safe
28
+ end
29
+ end
30
+
31
+ def ua_bootstrap?
32
+ if params.has_key?(:bootstrap)
33
+ params[:bootstrap] == 'true'
34
+ else
35
+ UserAnnouncements.config.bootstrap
36
+ end
37
+ end
38
+
39
+ end
@@ -0,0 +1,44 @@
1
+ module UserAnnouncements::RolesHelper
2
+ Role = Struct.new(:name, :id)
3
+
4
+ # Roles checkboxes for admin detail form
5
+ def ua_roles_html(f)
6
+ return unless _ua_roles.present?
7
+
8
+ f.label(:roles) +
9
+ ua_br +
10
+ _ua_roles_checkboxes(_ua_roles)
11
+ end
12
+
13
+ # Roles display on index page
14
+ def ua_roles_display(announcement)
15
+ role_names = announcement.roles.map { |role_id| _ua_role_id_to_name(role_id) }
16
+
17
+ safe_join(role_names, '<br />'.html_safe)
18
+ end
19
+
20
+ private
21
+
22
+ def _ua_roles_checkboxes(roles)
23
+ safe_join( roles.map { |role| _ua_role_checkbox(role) } )
24
+ end
25
+
26
+ def _ua_role_checkbox(role)
27
+ id = "role_#{role.id}"
28
+ checked = @announcement.roles.include?(role.id)
29
+
30
+ check_box_tag('announcement[roles][]', role.id, checked, id: id) + ' ' +
31
+ label_tag(id, role.name, style: "display: inline; margin-right: 1em")
32
+ end
33
+
34
+ def _ua_role_id_to_name(role_id)
35
+ _ua_roles.detect { |role| role.id == role_id }.try(:name)
36
+ end
37
+
38
+ def _ua_roles
39
+ @_ua_roles ||= Array(UserAnnouncements[:roles]).map do |role|
40
+ name_id = (role.is_a?(Array) ? role : [role, role]).map(&:to_s)
41
+ Role.new(name_id.first, name_id.last)
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,66 @@
1
+ module UserAnnouncements::ShowAnnouncements
2
+
3
+ # Helper method for displaying messages for +current_user+.
4
+ def user_announcements(options={})
5
+ return if controller.controller_name == 'hidden_announcements'
6
+
7
+ announcements_rows = AnnouncementFinder.for_display(current_user)
8
+ divs = announcements_rows.map do |announcement|
9
+ _ua_announcement_div(announcement)
10
+ end
11
+
12
+ safe_join(divs, "\n")
13
+ end
14
+
15
+ private
16
+
17
+ def _ua_announcement_div(ann)
18
+ if ua_bootstrap?
19
+ _ua_announcement_div_bootstrap(ann)
20
+ else
21
+ _ua_announcement_div_non_bootstrap(ann)
22
+ end
23
+ end
24
+
25
+ def _ua_announcement_div_bootstrap(ann)
26
+ div_for ann, class: _ua_announcement_classes(ann.style), style: 'width:40em' do
27
+ link_to(*_ua_hide_announcement_link_args(ann)) do
28
+ content_tag(:button, raw('&times;'), type: 'button', class: 'close')
29
+ end +
30
+ ann.message.html_safe
31
+ end
32
+ end
33
+
34
+ def _ua_announcement_div_non_bootstrap(ann)
35
+ div_for(ann, class: _ua_announcement_classes(ann.style)) do
36
+ ann.message.html_safe +
37
+ link_to("hide announcement", *_ua_hide_announcement_link_args(ann))
38
+ end
39
+ end
40
+
41
+ def _ua_hide_announcement_link_args(announcement)
42
+ url = hidden_announcements_path(announcement_id: announcement)
43
+ options = {
44
+ method: :post,
45
+ remote: true,
46
+ id: "hide_#{dom_id(announcement)}"
47
+ }
48
+
49
+ [url, options]
50
+ end
51
+
52
+ def _ua_unhide_announcement_link(announcement)
53
+ if @hidden_announcement_ids.include?(announcement.id)
54
+ content_tag(:div) do
55
+ link_to('Unhide', hidden_announcement_path(announcement, announcement_id: announcement), method: :delete)
56
+ end
57
+ end
58
+ end
59
+
60
+
61
+ def _ua_announcement_classes(style)
62
+ bootstrap_or_non = ua_bootstrap? ? 'bootstrap alert' : 'non-bootstrap'
63
+ [bootstrap_or_non, style.presence].compact.join(' ')
64
+ end
65
+
66
+ end
@@ -0,0 +1,20 @@
1
+ module UserAnnouncements::StyleHelper
2
+
3
+ # Style dropdown for admin detail form
4
+ def ua_style_html(f)
5
+ return unless _ua_styles.present?
6
+
7
+ f.label(:style) +
8
+ ua_br +
9
+ f.select(:style, _ua_styles)
10
+ end
11
+
12
+ private
13
+
14
+ def _ua_styles
15
+ @_ua_styles ||= UserAnnouncements[:styles].map do |style|
16
+ (style.is_a?(Array) ? style : [style, style]).map(&:to_s)
17
+ end
18
+ end
19
+
20
+ end
@@ -1,101 +1,7 @@
1
1
  module UserAnnouncementsHelper
2
-
3
- # Helper method for displaying messages for +current_user+.
4
- def user_announcements(options={})
5
- return if controller.controller_name == 'hidden_announcements'
6
-
7
- announcements_rows = AnnouncementFinder.current_for_user(current_user)
8
- divs = announcements_rows.map do |announcement|
9
- announcement_div(announcement)
10
- end
11
-
12
- safe_join(divs, "\n")
13
- end
14
-
15
- def announcement_div(announcement)
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
- div_for announcement, class: 'alert', style: 'width:40em' do
25
- link_to(*hide_announcement_link_args(announcement)) do
26
- content_tag(:button, raw('&times;'), type: 'button', class: 'close')
27
- end +
28
- announcement.message.html_safe
29
- end
30
- end
31
-
32
- def hide_announcement_link_args(announcement)
33
- url = hidden_announcements_path(announcement_id: announcement)
34
- options = {
35
- method: :post,
36
- remote: true,
37
- id: "hide_#{dom_id(announcement)}"
38
- }
39
-
40
- [url, options]
41
- end
42
-
43
- def announcement_div_non_bootstrap(announcement)
44
- div_for(announcement, class: 'non-bootstrap') do
45
- announcement.message.html_safe +
46
- link_to("hide announcement", *hide_announcement_link_args(announcement))
47
- end
48
- end
49
-
50
- def unhide_announcement_link(announcement)
51
- if @hidden_announcement_ids.include?(announcement.id)
52
- content_tag(:div) do
53
- link_to('Unhide', hidden_announcement_path(announcement, announcement_id: announcement), method: :delete)
54
- end
55
- end
56
- end
57
-
58
- def ua_table_attrs
59
- if bootstrap?
60
- {class: "ua-table bootstrap table table-striped table-bordered table-condensed table-hover"}
61
- else
62
- {class: 'ua-table non-bootstrap'}
63
- end
64
- end
65
-
66
- def ua_table_tag(options={})
67
- content_tag(:table, options.merge(ua_table_attrs)) do
68
- yield
69
- end
70
- end
71
-
72
- def boolean_display(boolean)
73
- ( boolean ? '&#10004;' : '&nbsp;' ).html_safe
74
- end
75
-
76
- def active_model_errors(model)
77
- return unless model.errors.present?
78
-
79
- content_tag(:div, class: ['alert', 'alert-error']) do
80
- content_tag(:h4, "Correct the following errors:") +
81
- content_tag(:ul) do
82
- safe_join(model.errors.full_messages.map { |msg| content_tag(:li, msg) }, "\n")
83
- end
84
- end
85
- end
86
-
87
- def ua_datetime_p(f, method)
88
- content_tag(:p, class: 'datetime-select') do
89
- f.label(method) +
90
- f.datetime_select(method)
91
- end
92
- end
93
-
94
- def bootstrap?
95
- if params.has_key?(:bootstrap)
96
- params[:bootstrap] == 'true'
97
- else
98
- UserAnnouncements.config.bootstrap
99
- end
100
- end
2
+ include UserAnnouncements::AdminHelper
3
+ include UserAnnouncements::RolesHelper
4
+ include UserAnnouncements::MiscHelper
5
+ include UserAnnouncements::StyleHelper
6
+ include UserAnnouncements::ShowAnnouncements
101
7
  end
@@ -1,9 +1,12 @@
1
1
  class Announcement < ActiveRecord::Base
2
- attr_accessible :message, :starts_at, :ends_at, :active
2
+ serialize :roles, class_name = Array
3
+ serialize :types, class_name = Array
4
+
5
+ attr_accessible :message, :starts_at, :ends_at, :active, :roles, :style
3
6
 
4
7
  has_many :hidden_announcements, :dependent => :destroy
5
8
 
6
- validates_presence_of :message, :starts_at, :ends_at
9
+ validates_presence_of :message
7
10
 
8
11
  INACTIVE = 'inactive'
9
12
  PAST = 'past'
@@ -23,6 +26,10 @@ class Announcement < ActiveRecord::Base
23
26
  status == CURRENT
24
27
  end
25
28
 
29
+ def starts_at_for_user
30
+ starts_at || created_at
31
+ end
32
+
26
33
  def status_order
27
34
  { FUTURE => 1, CURRENT => 2, PAST => 3, INACTIVE => 4 }[status]
28
35
  end
@@ -35,24 +42,13 @@ class Announcement < ActiveRecord::Base
35
42
 
36
43
  def new_with_defaults
37
44
  new do |ann|
38
- ann.active = get_default(:active)
39
- ann.starts_at = get_default(:starts_at)
40
- ann.ends_at = get_default(:ends_at)
45
+ ann.active = UserAnnouncements[:default_active]
46
+ ann.starts_at = UserAnnouncements[:default_starts_at]
47
+ ann.ends_at = UserAnnouncements[:default_ends_at]
48
+ ann.roles = Array(UserAnnouncements[:default_roles])
49
+ ann.style = UserAnnouncements[:default_style]
41
50
  end
42
51
  end
43
52
 
44
- private
45
-
46
- def get_default(column)
47
- config_key = "default_#{column}"
48
- default = UserAnnouncements.config.send(config_key)
49
-
50
- if default.is_a?(Proc)
51
- default.call
52
- else
53
- default
54
- end
55
- end
56
-
57
53
  end
58
54
  end
@@ -1,44 +1,87 @@
1
+ # Class to handle fetching +Announcement+ rows for various use cases.
1
2
  class AnnouncementFinder
2
3
 
3
4
  class << self
4
5
 
5
- def ordered
6
- Announcement.all.sort_by(&:status_order)
6
+ # Returns all +Announcement+s for admin edit page.
7
+ #
8
+ # @return [ActiveRecord::Relation<Announcement>]
9
+ def for_admin
10
+ Announcement
11
+ .all
12
+ .sort_by(&:status_order)
7
13
  end
8
14
 
9
- def current
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)
15
+ # Returns unhidden +Announcement+s that _user_ may see.
16
+ #
17
+ # @param user [User]
18
+ # @return [Array<Announcement>]
19
+ def for_display(user)
20
+ result = current
21
+ result = remove_hidden(user, result)
22
+ result = filter_by_role(user, result)
23
+ result
14
24
  end
15
25
 
16
- def past_or_current
17
- Rails.logger.debug '***** start past_or_current'
18
- r = Announcement
26
+ # Returns +Announcement+s that _user_ may edit.
27
+ #
28
+ # @param user [User]
29
+ # @return [ActiveRecord::Relation<Announcement>]
30
+ def for_edit(user)
31
+ Announcement
19
32
  .active
20
33
  .where("(starts_at is null or starts_at < :now)", :now => DateTime.now)
21
34
  .order('created_at desc')
22
- Rails.logger.debug '***** end past_or_current'
23
- # sleep 1
24
- r
25
- end
26
-
27
- def current_for_user(user)
28
- for_user(user, current)
29
35
  end
30
36
 
31
- # def past_or_current_for_user(user)
32
- # # FIXME: apply roles
33
- # past_or_current
34
- # end
37
+ private
35
38
 
36
- def for_user(user, type)
39
+ # Returns current +Announcement+s
40
+ #
41
+ # @return [ActiveRecord::Relation<Announcement>]
42
+ def current
43
+ Announcement
44
+ .active
45
+ .where("starts_at is null or starts_at < :now", now: DateTime.now)
46
+ .where("ends_at is null or ends_at > :now", now: DateTime.now)
47
+ end
48
+
49
+ # Removes any +Announcement+s from _relation_ that _user_ has hidden.
50
+ #
51
+ # @param user [User]
52
+ # @param relation [ActiveRecord::Relation<Announcement>]
53
+ # @return [ActiveRecord::Relation<Announcement>]
54
+ def remove_hidden(user, relation)
37
55
  hidden_announcement_ids = HiddenAnnouncement.hidden_announcement_ids_for(user.id)
38
- result = type
39
- result = result.where("id not in (?)", hidden_announcement_ids) if hidden_announcement_ids.present?
40
- result.sort_by(&:status_order)
56
+
57
+ if hidden_announcement_ids.present?
58
+ relation.where("id not in (?)", hidden_announcement_ids)
59
+ else
60
+ relation
61
+ end
41
62
  end
63
+
64
+ # Removes any +Announcement+s from _relation_ that _user_ can't see.
65
+ #
66
+ # @param user [User]
67
+ # @param relation [ActiveRecord::Relation<Announcement>]
68
+ def filter_by_role(user, relation)
69
+ relation.select { |announcement| user_can_see(user, announcement.roles) }
70
+ end
71
+
72
+ # Returns +true+ if _user_ can see announcement based on _roles_.
73
+ #
74
+ # @param user [User, #has_role?]
75
+ # @param roles [Array<String>]
76
+ # @return [Boolean]
77
+ def user_can_see(user, roles)
78
+ if roles.detect(&:blank?) || roles.blank?
79
+ true
80
+ else
81
+ roles.any? { |role| user.has_role?(role) }
82
+ end
83
+ end
84
+
42
85
  end
43
86
 
44
87
  end
@@ -1,9 +1,10 @@
1
1
  <tr id="<%= dom_id(announcement) %>" class='<%= announcement.status %>'>
2
2
  <td><%=raw announcement.message %></td>
3
- <td class='date'><%= announcement.starts_at.to_s(:long) %></td>
4
- <td class='date'><%= announcement.ends_at.to_s(:long) %></td>
5
- <td><%= announcement.status %></td>
6
- <td><%= boolean_display(announcement.active)%></td>
3
+ <td class='datetime'><%= ua_datetime_display(announcement.starts_at) %></td>
4
+ <td class='datetime'><%= ua_datetime_display(announcement.ends_at) %></td>
5
+ <td class='status'><%= announcement.status %></td>
6
+ <td class='active'><%= boolean_display(announcement.active)%></td>
7
+ <td><%= ua_roles_display(announcement) %></td>
7
8
  <td><%= link_to('edit', edit_admin_announcement_path(announcement), :class => 'btn btn-mini') %></td>
8
9
  <td><%= link_to('delete', admin_announcement_path(announcement), :data => {confirm: 'Are you sure?'}, :method => :delete, :class => 'btn btn-mini btn-danger') %></td>
9
10
  </tr>
@@ -1,10 +1,14 @@
1
- <%= form_for [:admin, @announcement], :html => {:class => 'form-horizontal'} do |f| %>
2
- <%= active_model_errors(f.object) %>
3
- <%#= f.input :subject, :as => :text, :input_html => {:size => "60x3", class: 'span6'} %>
4
- <%#= f.input(:starts_at, :as => :string, :input_html => {class: 'datepicker'}) %>
5
- <%#= f.input(:ends_at, :as => :string, :input_html => {class: 'datepicker'}) %>
1
+ <%= form_for [:admin, @announcement], :html => {:class => 'form-horizontal announcement-detail'} do |f| %>
2
+ <%= _ua_active_model_errors(f.object) %>
3
+
4
+ <p>
5
+ <%= f.check_box(:active) %>
6
+ <%= f.label :active %>
7
+ </p>
8
+
6
9
  <p>
7
10
  <%= f.label(:message) %>
11
+ <%= ua_br %>
8
12
  <%= f.text_area :message, size: "60x10", class: 'span6' %>
9
13
  </p>
10
14
 
@@ -13,10 +17,13 @@
13
17
  <%= ua_datetime_p(f, :ends_at) %>
14
18
 
15
19
  <p>
16
- <%= f.check_box(:active) %>
17
- <%= f.label :active %>
20
+ <%= ua_roles_html(f) %>
18
21
  </p>
19
-
22
+
23
+ <p>
24
+ <%= ua_style_html(f) %>
25
+ </p>
26
+
20
27
  <div class="form-actions">
21
28
  <%= f.submit :class => 'btn btn-primary' %>
22
29
  <%= link_to("Cancel", admin_announcements_path, :class => 'btn') %>
@@ -11,7 +11,8 @@
11
11
  <th>Starts</th>
12
12
  <th>Ends</th>
13
13
  <th>Status</th>
14
- <th>Active</th>
14
+ <th class='active'>Active</th>
15
+ <th class='roles'>Roles</th>
15
16
  <th colspan="2" width="1%">Actions</th>
16
17
  </tr>
17
18
  </thead>
@@ -1,8 +1,8 @@
1
1
 
2
2
  <tr id="<%= dom_id(announcement) %>">
3
- <td class='date'><%= announcement.created_at.try(:to_s, :db) %></td>
3
+ <td class='datetime'><%= ua_datetime_display(announcement.starts_at_for_user) %></td>
4
4
  <td>
5
5
  <%= announcement.message.html_safe %>
6
- <%= unhide_announcement_link(announcement) %>
6
+ <%= _ua_unhide_announcement_link(announcement) %>
7
7
  </td>
8
8
  </tr>
@@ -9,14 +9,14 @@ module UserAnnouncements
9
9
 
10
10
  desc <<DESC
11
11
  Description:
12
- Copies stylesheet to 'app/assets/stylesheets/user_announcements.css.scss'
12
+ Copies stylesheet to 'app/assets/stylesheets/user_announcements.css'
13
13
  Copies configuration to 'config/initializers/user_announcements.rb'
14
14
  Copies db migration to 'db/migrate/<timestamp>/create_user_announcement_tables.rb'
15
15
 
16
16
  DESC
17
17
 
18
18
  def install
19
- copy_file "css.scss", 'app/assets/stylesheets/user_announcements.css.scss'
19
+ copy_file "template.css", 'app/assets/stylesheets/user_announcements.css'
20
20
  copy_file "initializer.rb", 'config/initializers/user_announcements.rb'
21
21
  migration_template "migration.rb", "db/migrate/create_user_announcement_tables.rb"
22
22
  end
@@ -1,9 +1,26 @@
1
- UserAnnouncements.config do |c|
2
-
3
- # config.bootstrap = true
1
+ # note: all options accept lambdas
2
+
3
+ UserAnnouncements.config do |config|
4
+
5
+ # Bootstrap
6
+ config.bootstrap = true
7
+ config.styles = [['Yellow', ''], ['Red', 'alert-error'], ['Green', 'alert-success'], ['Blue', 'alert-info']]
8
+
9
+ # non-Bootstrap
10
+ # config.bootstrap = false
11
+ # config.styles = [['Yellow', 'yellow'], ['Red', 'red'], ['Green', 'green'], ['Blue', 'blue']]
12
+
13
+ # Announcement defaults
14
+ config.default_active = true
15
+ config.default_starts_at = lambda { Time.now.in_time_zone }
16
+ config.default_ends_at = lambda { 1.week.from_now.in_time_zone.end_of_day }
17
+ config.default_style = ''
18
+ # config.default_roles = ['admin']
4
19
 
5
- # config.default_active = true
6
- # config.default_starts_at = lambda { Time.now.in_time_zone }
7
- # config.default_ends_at = lambda { 1.week.from_now.in_time_zone.end_of_day }
20
+ # Roles
21
+ # config.roles = []
22
+ # config.roles = ['', 'admin']
23
+ # config.roles = [ ['Public', ''], ['Administrator', 'admin'] ]
24
+ # config.roles = lambda { MyRoleClass.map { |role| [role.name, role.id] } }
8
25
 
9
26
  end
@@ -7,6 +7,7 @@ class CreateUserAnnouncementTables < ActiveRecord::Migration
7
7
  t.boolean :active
8
8
  t.text :roles
9
9
  t.text :types
10
+ t.text :style
10
11
  t.timestamps
11
12
  end
12
13
 
@@ -0,0 +1,78 @@
1
+ table.ua-table td.status {
2
+ width: 1%;
3
+ text-align: center;
4
+ }
5
+
6
+ table.ua-table th.active {
7
+ width: 1%;
8
+ }
9
+
10
+ table.ua-table td.active {
11
+ text-align: center;
12
+ }
13
+
14
+ table.ua-table td.datetime {
15
+ width: 6em;
16
+ white-space: nowrap;
17
+ }
18
+
19
+ table.ua-table th.roles {
20
+ width: 1%;
21
+ }
22
+
23
+ table.ua-table.non-bootstrap {
24
+ border-collapse:collapse;
25
+ }
26
+
27
+ table.ua-table.non-bootstrap th, table.ua-table.non-bootstrap td {
28
+ border: 1px solid black;
29
+ padding: 0.5em;
30
+ }
31
+
32
+ table.ua-table td {
33
+ vertical-align: top;
34
+ }
35
+
36
+ .announcement.non-bootstrap {
37
+ background-color: #fcf8e3;
38
+ color: #c09853;
39
+ border-bottom: solid 1px black;
40
+ width: 100%;
41
+ padding: 10px;
42
+ text-align: center;
43
+ }
44
+
45
+
46
+ .announcement.non-bootstrap a {
47
+ font-size: 12px;
48
+ margin-left: 5px;
49
+ color: #6E5910;
50
+ }
51
+ }
52
+
53
+ .announcement.non-bootstrap.yellow {
54
+ background-color: #fcf8e3;
55
+ color: #c09853;
56
+ }
57
+
58
+ .announcement.non-bootstrap.red {
59
+ background-color: #f2dede;
60
+ /* border-color: #eed3d7;*/
61
+ color: #b94a48;
62
+ }
63
+
64
+ .announcement.non-bootstrap.green {
65
+ background-color: #dff0d8;
66
+ /* border-color: #d6e9c6;*/
67
+ color: #468847;
68
+ }
69
+
70
+ .announcement.non-bootstrap.blue {
71
+ background-color: #d9edf7;
72
+ /* border-color: #bce8f1;*/
73
+ color: #3a87ad;
74
+ }
75
+
76
+ form.announcement-detail label{
77
+ margin-bottom: 0.4em;
78
+ }
@@ -1,23 +1,28 @@
1
1
  module UserAnnouncements
2
2
 
3
3
  class Engine < ::Rails::Engine
4
+
4
5
  config.generators.integration_tool :rspec
5
6
  config.generators.test_framework :rspec
6
7
 
7
- config.bootstrap = true
8
-
9
- config.default_active = true
10
- config.default_starts_at = lambda { Time.now.in_time_zone }
11
- config.default_ends_at = lambda { 1.week.from_now.in_time_zone.end_of_day }
12
-
13
- config.roles = []
14
- config.types = []
15
- config.styles = %w(error succes info)
16
-
17
8
  end
18
9
 
19
10
  def self.config(&block)
20
11
  yield Engine.config if block
21
12
  Engine.config
22
13
  end
14
+
15
+ def self.[](key)
16
+ setting = config.send(key)
17
+
18
+ if setting.is_a?(Proc)
19
+ setting.call
20
+ else
21
+ setting
22
+ end
23
+
24
+ rescue NameError
25
+ Rails.logger.debug "[UserAnnouncements] Tried to access unknown UserAnnouncements.config key: #{key.inspect}"
26
+ nil
27
+ end
23
28
  end
@@ -1,3 +1,3 @@
1
1
  module UserAnnouncements
2
- VERSION = "0.0.3"
2
+ VERSION = "0.0.4"
3
3
  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.3
4
+ version: 0.0.4
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-05-24 00:00:00.000000000 Z
12
+ date: 2013-05-26 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rails
@@ -339,8 +339,12 @@ extensions: []
339
339
  extra_rdoc_files: []
340
340
  files:
341
341
  - app/controllers/admin/announcements_controller.rb
342
- - app/controllers/admin/base_controller.rb
343
342
  - app/controllers/hidden_announcements_controller.rb
343
+ - app/helpers/user_announcements/admin_helper.rb
344
+ - app/helpers/user_announcements/misc_helper.rb
345
+ - app/helpers/user_announcements/roles_helper.rb
346
+ - app/helpers/user_announcements/show_announcements.rb
347
+ - app/helpers/user_announcements/style_helper.rb
344
348
  - app/helpers/user_announcements_helper.rb
345
349
  - app/models/announcement.rb
346
350
  - app/models/announcement_finder.rb
@@ -355,9 +359,9 @@ files:
355
359
  - app/views/hidden_announcements/index.html.erb
356
360
  - config/routes.rb
357
361
  - lib/generators/user_announcements/install_generator.rb
358
- - lib/generators/user_announcements/templates/css.scss
359
362
  - lib/generators/user_announcements/templates/initializer.rb
360
363
  - lib/generators/user_announcements/templates/migration.rb
364
+ - lib/generators/user_announcements/templates/template.css
361
365
  - lib/tasks/user_announcements_tasks.rake
362
366
  - lib/user_announcements/engine.rb
363
367
  - lib/user_announcements/version.rb
@@ -389,7 +393,6 @@ rubyforge_project:
389
393
  rubygems_version: 1.8.25
390
394
  signing_key:
391
395
  specification_version: 3
392
- summary: Manage and display site-wide announcements by user, role and announcement
393
- type.
396
+ summary: Manage and display site-wide announcements by user, scoped by user role.
394
397
  test_files: []
395
398
  has_rdoc:
@@ -1,12 +0,0 @@
1
- class Admin::BaseController < ApplicationController
2
- before_filter :ensure_admin_user
3
-
4
- private
5
-
6
- def ensure_admin_user
7
- # FIXME
8
- # unless current_user.has_role?(:admin)
9
- # redirect_to root_path
10
- # end
11
- end
12
- end
@@ -1,33 +0,0 @@
1
- table.ua-table {
2
-
3
- td.date {
4
- white-space: nowrap;
5
- }
6
-
7
- &.non-bootstrap {
8
- border: 1px solid black;
9
-
10
- th, td {
11
- border: 1px solid black;
12
- padding: 0.5em;
13
- }
14
-
15
- td {
16
- vertical-align: top;
17
- }
18
-
19
- }
20
- }
21
-
22
- .announcement.non-bootstrap {
23
- width: 100%;
24
- background-color: #F1F094;
25
- border-bottom: solid 1px black;
26
- padding: 10px;
27
- text-align: center;
28
- a {
29
- font-size: 12px;
30
- margin-left: 5px;
31
- color: #6E5910;
32
- }
33
- }