caboose-cms 0.3.1 → 0.3.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,15 +1,15 @@
1
1
  ---
2
2
  !binary "U0hBMQ==":
3
3
  metadata.gz: !binary |-
4
- ZDIzNzA4ZDY1OGM5YmNjOWRiMGU4NjQxYjE1OWQ1YmJlNGRlNTA5ZA==
4
+ ODM4ZDFiZWFmZDkxZDgxZWZhOWFhN2ZjNjg5Zjk5NTUyMDliNmEwNA==
5
5
  data.tar.gz: !binary |-
6
- NWYxODMxNTQ0YzE1ZWQ2MjkwY2I4NWE0ZWM3Y2M4Yzg0MTAyN2E1OQ==
6
+ ZDFiNTRmZTVlOGZmZmZkYWU3YjhlYmE0OTQyODcyYWY5ZDY5ZmY4Yw==
7
7
  !binary "U0hBNTEy":
8
8
  metadata.gz: !binary |-
9
- YmMyNjFmZDYxYjcyMWM3ZmQyZTE0NWQ0ZDljODkwMjQ2ZmUyZDNmZDE5ZTg3
10
- YThlN2VlNWNlMDc4NWM0YjlkYWNlODZjNzBmNzE5ODVjNTRiNzBkOWNjNWE4
11
- NDZiNzIyMjU5NjYwNDgyZmMyMjY5MTMzZmIyMjIzZDA2MjE2M2M=
9
+ MjZkZGZlMWRmNjZjMmJhOGIyY2NiMTFiNmI4YjY3NzFkZTk0ZDZlZmE2NjUy
10
+ ZGY2NjdiNTcwNjlkMjcxNDA1OTM4YzVhMzcyZDY4NTJjYTM2ZDZiNzdhYWZm
11
+ MjdhNmMxMjRhN2Y2YTg1ZmFhNGFjMTI0YTllZmE5OWE1OWU3YWI=
12
12
  data.tar.gz: !binary |-
13
- NTgxYjgxMDM2ZWQwZGVkNTg2NjdjMDg3ZGM3ZjliMmJlNDIyMmYyODE0ZWU2
14
- ZTU3NDY5OThhNjhhMDZiZTdlZGQ2NWM3ZjZmOWY3ODBlMTUxMDM0NWVkYzhk
15
- MjY4M2M2ZDFjOTM4NTU1YTFmNzEwNTJhZTA2NjI3OGExZTMxZmE=
13
+ ZWMyNDZmYzVjNzQ0ZWUwZDlmNTMxN2MxYjEzNTU4NGE0ODFmZGVmNjk1YTgz
14
+ MTNlZTgwY2E2ZjA5Mzc3NDBiNjJmMjZhNmY3YTc1N2U4ZjNlMWVmZTcwMzIy
15
+ Njk3NzI4MDRkYjgwNmRkZTg0ZTZiNmJkNjRmNTc1ZDYzYzM4ODA=
@@ -14,3 +14,4 @@
14
14
  //= require jquery_ujs
15
15
  //= require colorbox-rails
16
16
  //= require caboose/modal_integration
17
+ //= require caboose/placeholder
@@ -15,3 +15,4 @@
15
15
  //= require colorbox-rails
16
16
  //= require caboose/modal_integration
17
17
  //= require application
18
+ //= require caboose/placeholder
@@ -14,3 +14,5 @@
14
14
  //= require jquery_ujs
15
15
  //= require colorbox-rails
16
16
  //= require caboose/modal_integration
17
+ //= require caboose/placeholder
18
+
@@ -0,0 +1,25 @@
1
+ // Placeholder IE Fix
2
+
3
+ $(document).ready(function() {
4
+ $('[placeholder]').focus(function() {
5
+ console.log("PH");
6
+ var input = $(this);
7
+ if (input.val() == input.attr('placeholder')) {
8
+ input.val('');
9
+ input.removeClass('placeholder_js');
10
+ }
11
+ }).blur(function() {
12
+ var input = $(this);
13
+ if (input.val() == '' || input.val() == input.attr('placeholder')) {
14
+ input.addClass('placeholder_js');
15
+ input.val(input.attr('placeholder'));
16
+ }
17
+ }).blur().parents('form').submit(function() {
18
+ $(this).find('[placeholder]').each(function() {
19
+ var input = $(this);
20
+ if (input.val() == input.attr('placeholder')) {
21
+ input.val('');
22
+ }
23
+ })
24
+ });
25
+ });
@@ -2,3 +2,7 @@
2
2
  body {
3
3
  font-family: Helvetica, Tahoma, Arial;
4
4
  }
5
+
6
+ .placeholder_js {
7
+ color: #aaa;
8
+ }
@@ -6,6 +6,9 @@ module Caboose
6
6
 
7
7
  def before_before_action
8
8
 
9
+ # Modify the built-in params array with URL params if necessary
10
+ parse_url_params if Caboose.use_url_params
11
+
9
12
  # Try to find the page
10
13
  @page = Page.page_with_uri(request.fullpath)
11
14
 
@@ -24,6 +27,22 @@ module Caboose
24
27
  before_action
25
28
  end
26
29
 
30
+ # Parses any parameters in the URL and adds them to the params
31
+ def parse_url_params
32
+ return if !Caboose.use_url_params
33
+ url = "#{request.fullpath}"
34
+ url[0] = "" if url.starts_with?('/')
35
+ url = url.split('?')[0] if url.include?('?')
36
+ arr = url.split('/')
37
+ i = arr.count - 1
38
+ while i >= 1 do
39
+ k = arr[i-1]
40
+ v = arr[i]
41
+ params[k] = v if v && v.length > 0
42
+ i = i-2
43
+ end
44
+ end
45
+
27
46
  # To be overridden by the child controllers
28
47
  def before_action
29
48
  end
@@ -0,0 +1,117 @@
1
+
2
+ module Caboose
3
+ class PagesBlocksController < ApplicationController
4
+
5
+ #===========================================================================
6
+ # Admin actions
7
+ #===========================================================================
8
+
9
+ # GET /admin/pages/:page_id/blocks
10
+ def admin_index
11
+ return if !user_is_allowed('pages', 'view')
12
+ blocks = PageBlock.where(:page_id => params[:page_id]).reorder(:sort_order)
13
+ render :json => blocks
14
+ end
15
+
16
+ # GET /admin/pages/:page_id/blocks/new
17
+ def admin_new
18
+ return unless user_is_allowed('pages', 'add')
19
+ @page = Page.find(params[:page_id])
20
+ @block = PageBlock.new(:page_id => params[:page_id])
21
+ render :layout => 'caboose/admin'
22
+ end
23
+
24
+ # GET /admin/pages/:page_id/blocks/:id
25
+ def admin_show
26
+ return unless user_is_allowed('pages', 'edit')
27
+ block = PageBlock.find(params[:id])
28
+ render :json => block
29
+ end
30
+
31
+ # GET /admin/pages/:page_id/blocks/:id/edit
32
+ def admin_edit
33
+ return unless user_is_allowed('pages', 'edit')
34
+ @page = Page.find(params[:page_id])
35
+ @block = PageBlock.find(params[:id])
36
+ render :layout => 'caboose/admin'
37
+ end
38
+
39
+ # POST /admin/pages/:page_id/blocks
40
+ def admin_create
41
+ return unless user_is_allowed('pages', 'add')
42
+
43
+ resp = Caboose::StdClass.new({
44
+ 'error' => nil,
45
+ 'redirect' => nil
46
+ })
47
+
48
+ b = PageBlock.new
49
+ b.page_id = params[:page_id]
50
+ b.block_type = params[:block_type]
51
+ b.sort_order = params[:sort_order].to_i
52
+ b.name = params[:name]
53
+ b.value = params[:value]
54
+
55
+ # Set the new page block order
56
+ p = Page.find(b.page_id)
57
+ if p.blocks && p.blocks.count > b.sort_order
58
+ i = b.sort_order + 1
59
+ PageBlock.where("sort_order >= ?", b.sort_order).reorder(:sort_order).each do |b2|
60
+ b2.sort_order = i
61
+ b2.save
62
+ i = i + 1
63
+ end
64
+ end
65
+
66
+ # Save the block
67
+ b.save
68
+
69
+ # Send back the response
70
+ resp.redirect = "/admin/pages/#{page.id}/edit"
71
+ render json: resp
72
+ end
73
+
74
+ # PUT /admin/pages/:page_id/blocks/:id
75
+ def admin_update
76
+ return unless user_is_allowed('pages', 'edit')
77
+
78
+ resp = StdClass.new({'attributes' => {}})
79
+ b = PageBlock.find(params[:id])
80
+
81
+ save = true
82
+ user = logged_in_user
83
+ params.each do |name, value|
84
+ case name
85
+ when 'block_type'
86
+ b.block_type = value
87
+ when 'sort_order'
88
+ b.sort_order = value.to_i
89
+ i = b.sort_order + 1
90
+ PageBlock.where("page_id = ? and sort_order >= ?", b.page_id, b.sort_order).reorder(:sort_order).each do |b2|
91
+ b2.sort_order = i
92
+ b2.save
93
+ i = i + 1
94
+ end
95
+ when 'name'
96
+ b.name = value
97
+ when 'value'
98
+ b.value = value
99
+ end
100
+ end
101
+
102
+ resp.success = save && b.save
103
+ render :json => resp
104
+ end
105
+
106
+ # DELETE /admin/pages/:page_id/blocks/:id
107
+ def admin_delete
108
+ return unless user_is_allowed('pages', 'delete')
109
+ PageBlock.find(params[:id]).destroy
110
+ resp = StdClass.new({
111
+ 'redirect' => "/admin/pages/#{params[:page_id]}/edit"
112
+ })
113
+ render :json => resp
114
+ end
115
+
116
+ end
117
+ end
@@ -21,8 +21,9 @@ module Caboose
21
21
  # itemsPerPage: Number of items you want to show per page. Defaults to 10 if not present.
22
22
  # page: Current page number. Defaults to 0 if not present.
23
23
  #
24
- attr_accessor :params, :options
24
+ attr_accessor :params, :options, :custom_url_vars
25
25
 
26
+ #def initialize(post_get, params = nil, options = nil, &custom_url_vars = nil)
26
27
  def initialize(post_get, params = nil, options = nil)
27
28
 
28
29
  params = {} if params.nil?
@@ -38,20 +39,29 @@ module Caboose
38
39
  'base_url' => '',
39
40
  'page' => 1,
40
41
  'item_count' => 0,
41
- 'items_per_page' => 10,
42
+ 'items_per_page' => 10,
43
+ 'abbreviations' => {},
44
+ 'skip' => [], # params to skip when printing the page bar
42
45
  'includes' => nil # Hash of association includes
43
46
  # {
44
47
  # search_field_1 => [association_name, join_table, column_name],
45
48
  # search_field_2 => [association_name, join_table, column_name]
46
- # }
49
+ # }
47
50
  }
48
51
  params.each { |key, val| @params[key] = val }
49
- options.each { |key, val| @options[key] = val }
50
- @params.each { |key, val| @params[key] = post_get[key].nil? ? val : post_get[key] }
52
+ options.each { |key, val| @options[key] = val }
53
+ @params.each { |key, val|
54
+ k = @options['abbreviations'].include?(key) ? @options['abbreviations'][key] : key
55
+ @params[key] = post_get[key].nil? ? (post_get[k].nil? ? val : post_get[k]) : post_get[key]
56
+ }
51
57
  @options.each { |key, val| @options[key] = post_get[key].nil? ? val : post_get[key] }
58
+ #@custom_url_vars = custom_url_vars if !custom_url_vars.nil?
52
59
  fix_desc
53
-
54
- @options['item_count'] = model_with_includes.where(where).count
60
+ set_item_count
61
+ end
62
+
63
+ def set_item_count
64
+ @options['item_count'] = model_with_includes.where(where).count
55
65
  end
56
66
 
57
67
  def model_with_includes
@@ -124,8 +134,6 @@ module Caboose
124
134
  @options['items_per_page'] = 10 if @options["items_per_page"].nil?
125
135
  @options['page'] = 1 if @options["page"].nil?
126
136
 
127
- # Variables to make the search form work
128
- vars = get_vars()
129
137
  page = @options["page"].to_i
130
138
 
131
139
  # Max links to show (must be odd)
@@ -149,24 +157,28 @@ module Caboose
149
157
  end
150
158
  end
151
159
 
152
- base_url = @params['base_url']
160
+ base_url = url_with_vars
161
+ base_url << (Caboose.use_url_params ? "/" : (base_url.include?("?") ? "&" : "?"))
162
+ keyval_delim = Caboose.use_url_params ? "/" : "="
163
+ var_delim = Caboose.use_url_params ? "/" : "&"
164
+
153
165
  str = ''
154
166
  str << "<p>Results: showing page #{page} of #{total_pages}</p>\n"
155
167
 
156
168
  if (total_pages > 1)
157
169
  str << "<div class='page_links'>\n"
158
170
  if (page > 1)
159
- str << "<a href='#{base_url}?#{vars}&page=#{prev_page}'>Previous</a>"
171
+ str << "<a href='#{base_url}page#{keyval_delim}#{prev_page}'>Previous</a>"
160
172
  end
161
173
  for i in start..stop
162
174
  if (page != i)
163
- str << "<a href='#{base_url}?#{vars}&page=#{i}'>#{i}</a>"
175
+ str << "<a href='#{base_url}page#{keyval_delim}#{i}'>#{i}</a>"
164
176
  else
165
177
  str << "<span class='current_page'>#{i}</span>"
166
178
  end
167
179
  end
168
180
  if (page < total_pages)
169
- str << "<a href='#{base_url}?#{vars}&page=#{next_page}'>Next</a>"
181
+ str << "<a href='#{base_url}page#{keyval_delim}#{next_page}'>Next</a>"
170
182
  end
171
183
  str << "</div>\n"
172
184
  end
@@ -174,29 +186,50 @@ module Caboose
174
186
  return str
175
187
  end
176
188
 
177
- def get_vars()
189
+ def url_with_vars()
190
+ if !@custom_url_vars.nil?
191
+ return @custom_url_vars.call @options['base_url'], @params
192
+ end
178
193
  vars = []
179
194
  @params.each do |k,v|
180
- if v.kind_of?(Array)
181
- v.each do |v2|
182
- vars.push("#{k}[]=#{v2}") if !v2.nil? && v2.length > 0
195
+ next if @options['skip'].include?(k)
196
+ k = @options['abbreviations'].include?(k) ? @options['abbreviations'][k] : k
197
+ if v.kind_of?(Array)
198
+ v.each do |v2|
199
+ if Caboose.use_url_params
200
+ vars.push("#{k}/#{v2}") if !v2.nil?
201
+ else
202
+ vars.push("#{k}[]=#{v2}") if !v2.nil?
203
+ end
183
204
  end
184
205
  else
185
206
  next if v.nil? || (v.kind_of?(String) && v.length == 0)
186
- vars.push("#{k}=#{v}")
207
+ if Caboose.use_url_params
208
+ vars.push("#{k}/#{v}")
209
+ else
210
+ vars.push("#{k}=#{v}")
211
+ end
187
212
  end
188
213
  end
189
- return URI.escape(vars.join('&'))
214
+ return "#{@options['base_url']}" if vars.length == 0
215
+ if Caboose.use_url_params
216
+ vars = URI.escape(vars.join('/'))
217
+ return "#{@options['base_url']}/#{vars}"
218
+ end
219
+ vars = URI.escape(vars.join('&'))
220
+ return "#{@options['base_url']}?#{vars}"
190
221
  end
191
222
 
192
223
  def sortable_table_headings(cols)
193
- vars = get_vars()
224
+ base_url = url_with_vars
225
+ base_url << base_url.include?("?") ? "&" : "?"
194
226
  str = ''
195
227
 
196
228
  # key = sort field, value = text to display
197
229
  cols.each do |sort, text|
198
- arrow = @options['sort'] == sort ? (@options['desc'] == 1 ? ' &uarr;' : ' &darr;') : ''
199
- link = @options['base_url'] + "?#{vars}&sort=#{sort}&desc=" + (@options['desc'] == 1 ? "0" : "1")
230
+ arrow = @options['sort'] == sort ? (@options['desc'] == 1 ? ' &uarr;' : ' &darr;') : ''
231
+ #link = @options['base_url'] + "?#{vars}&sort=#{sort}&desc=" + (@options['desc'] == 1 ? "0" : "1")
232
+ link = "#{base_url}sort=#{sort}&desc=" + (@options['desc'] == 1 ? "0" : "1")
200
233
  str += "<th><a href='#{link}'>#{text}#{arrow}</a></th>\n"
201
234
  end
202
235
  return str
@@ -274,6 +307,6 @@ module Caboose
274
307
  end
275
308
  str << " desc" if @options['desc'] == 1
276
309
  return str
277
- end
310
+ end
278
311
  end
279
312
  end
@@ -18,53 +18,31 @@ class Caboose::PageBlock < ActiveRecord::Base
18
18
  def render_h5() return "<h5>#{self.value}</h5>" end
19
19
  def render_h6() return "<h6>#{self.value}</h6>" end
20
20
 
21
- def render_posts
22
- obj = Caboose::StdClass(JSON.parse(self.value))
23
- defaults = {
24
- 'limit' => 10,
25
- 'no_posts_message' => "<p>There are no posts right now.</p>",
26
- 'invalid_category_message' => "<p>Invalid post category.</p>",
27
- 'body_character_limit' => 0
28
- }
29
- defaults.each { |k,v| obj[k] = v if obj[k].nil? }
30
-
31
- return obj.invalid_category_message if !Caboose::PostCategory.exists?(obj.category_id)
32
- cat = Caboose::PostCategory.find(obj.category_id)
33
- posts = obj.limit == 0 ? cat.posts.reorder('created_at DESC') : cat.posts.reorder('created_at DESC').limit(obj.limit)
34
- return obj.no_posts_message posts.nil? || posts.count == 0
35
-
36
- str = ""
37
- posts.each do |p|
38
- str = "<div class='post'>"
39
- str << "<h2>#{raw p.title}</h2>"
40
- str << "<div class='created_at'>#{p.created_at.strftime('%F %T')}</div>"
41
- str << "<div class='post_content'>"
42
- str << obj.body_character_limit > 0 ? Caboose.teaser_text(p.body, obj.body_character_limit) : p.body
43
- str << "</div>"
44
- str << "</div>"
45
- end
46
- end
47
-
48
- assoc = cat
49
- if Caboose
50
-
51
-
52
- if Caboose::PostCategoryMembership.exists?(:post_category_id => cat.id)
53
- Caboose::PostCategoryMembership.where(:post_category_id => cat.id)
54
-
21
+ def render_posts
22
+ return ""
23
+ #obj = Caboose::StdClass(JSON.parse(self.value))
24
+ #defaults = {
25
+ # 'limit' => 10,
26
+ # 'no_posts_message' => "<p>There are no posts right now.</p>",
27
+ # 'invalid_category_message' => "<p>Invalid post category.</p>",
28
+ # 'body_character_limit' => 0
29
+ #}
30
+ #defaults.each { |k,v| obj[k] = v if obj[k].nil? }
31
+ #
32
+ #return obj.invalid_category_message if !Caboose::PostCategory.exists?(obj.category_id)
33
+ #cat = Caboose::PostCategory.find(obj.category_id)
34
+ #posts = obj.limit == 0 ? cat.posts.reorder('created_at DESC') : cat.posts.reorder('created_at DESC').limit(obj.limit)
35
+ #return obj.no_posts_message posts.nil? || posts.count == 0
36
+ #
37
+ #str = ""
38
+ #posts.each do |p|
39
+ # str = "<div class='post'>"
40
+ # str << "<h2>#{raw p.title}</h2>"
41
+ # str << "<div class='created_at'>#{p.created_at.strftime('%F %T')}</div>"
42
+ # str << "<div class='post_content'>"
43
+ # str << obj.body_character_limit > 0 ? Caboose.teaser_text(p.body, obj.body_character_limit) : p.body
44
+ # str << "</div>"
45
+ # str << "</div>"
46
+ #end
55
47
  end
56
-
57
- end
58
-
59
-
60
- @_renderer = "Caboose::PageBlock#{self.block_type.upcase}Renderer".constantize.new
61
- @_renderer.page_block = self
62
- @_renderer.page_block = self
63
-
64
- self.renderer.render
65
- end
66
-
67
- @_renderer = "Caboose::PageBlock#{self.block_type.upcase}Renderer".constantize.new
68
- @_renderer.page_block = self
69
-
70
48
  end
@@ -1,27 +1,11 @@
1
1
 
2
2
  <%= render :partial => 'caboose/pages/admin_header' %>
3
-
4
- <p><input type='button' value='Add Block' onclick="add_block_at_beginning();" /></p>
5
3
 
6
- <% @page.blocks.each do |b| %>
7
- <div class='page_block'>
8
- <div id='pageblock_<%= b.id %>_name'></div>
9
- <div id='pageblock_<%= b.id %>_value'></div>
10
- <div id='page_block_<%= b.id %>_message'></div>
11
- <p><input type='button' value='Delete Block' class='delete' onclick="delete_block(<%= b.id %>);" /></p>
12
- </div>
13
- <p><input type='button' value='Add Block' onclick="add_block_after(<%= b.id %>);" /></p>
4
+ <% @page.blocks.each do |b| %>
5
+ <div id='pageblock_<%= b.id %>_value'></div>
14
6
  <% end %>
15
7
 
16
8
  <%= render :partial => 'caboose/pages/admin_footer' %>
17
- <% content_for :caboose_css do %>
18
- <style type='text/css'>
19
-
20
- div.page_block { padding: 20px; border: #ccc 1px solid; background: #efefef; }
21
- div.page_block p { padding-bottom: 0; margin-bottom: 0; }
22
-
23
- </style>
24
- <% end %>
25
9
  <% content_for :caboose_js do %>
26
10
  <script type='text/javascript'>
27
11
 
data/config/routes.rb CHANGED
@@ -66,6 +66,14 @@ Caboose::Engine.routes.draw do
66
66
  get "admin/pages" => "pages#admin_index"
67
67
  post "admin/pages" => "pages#admin_create"
68
68
  delete "admin/pages/:id" => "pages#admin_delete"
69
+
70
+ get "admin/pages/:page_id/blocks/new" => "page_blocks#admin_new"
71
+ get "admin/pages/:page_id/blocks/:id/edit" => "page_blocks#admin_edit"
72
+ get "admin/pages/:page_id/blocks/:id" => "page_blocks#admin_show"
73
+ get "admin/pages/:page_id/blocks" => "page_blocks#admin_index"
74
+ post "admin/pages/:page_id/blocks" => "page_blocks#admin_create"
75
+ put "admin/pages/:page_id/blocks/:id" => "page_blocks#admin_update"
76
+ delete "admin/pages/:page_id/blocks/:id" => "page_blocks#admin_delete"
69
77
 
70
78
  get "posts" => "posts#index"
71
79
  get "posts/:id" => "posts#detail"
data/lib/caboose.rb CHANGED
@@ -25,5 +25,9 @@ module Caboose
25
25
  # The login authenticator
26
26
  mattr_accessor :authenticator_class
27
27
  @@authenticator_class = 'Caboose::Authenticator'
28
+
29
+ # Whether or not to use URL parameters (parameters embedded in the URL before the querystring)
30
+ mattr_accessor :use_url_params
31
+ @@use_url_params = true
28
32
 
29
33
  end
@@ -1,3 +1,3 @@
1
1
  module Caboose
2
- VERSION = '0.3.1'
2
+ VERSION = '0.3.2'
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: caboose-cms
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.1
4
+ version: 0.3.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - William Barry
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-12-13 00:00:00.000000000 Z
11
+ date: 2013-12-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -145,6 +145,7 @@ files:
145
145
  - app/assets/javascripts/caboose/model/model_binder.js
146
146
  - app/assets/javascripts/caboose/model.form.page.js
147
147
  - app/assets/javascripts/caboose/model.form.user.js
148
+ - app/assets/javascripts/caboose/placeholder.js
148
149
  - app/assets/javascripts/caboose/shortcut.js
149
150
  - app/assets/javascripts/caboose/station.js
150
151
  - app/assets/stylesheets/caboose/admin.css
@@ -165,6 +166,7 @@ files:
165
166
  - app/controllers/caboose/application_controller.rb
166
167
  - app/controllers/caboose/login_controller.rb
167
168
  - app/controllers/caboose/logout_controller.rb
169
+ - app/controllers/caboose/page_blocks_controller.rb
168
170
  - app/controllers/caboose/pages_controller.rb
169
171
  - app/controllers/caboose/permissions_controller.rb
170
172
  - app/controllers/caboose/posts_controller.rb