caboose-cms 0.2.70 → 0.2.71

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
- MWE2N2IxNDliN2ZmNjM3MDk5NzNkYjgxMWY0NGQ0NzhjZTFjMjkwMA==
4
+ YjZiMGI3ZWI5NTY4YTBkNDA2NjlhMjVlM2E5YjUzODVkYWNhY2NhNg==
5
5
  data.tar.gz: !binary |-
6
- YjI3MDM4NmU3MWI5YmEyMjM3N2MzZjdhMzFiOGEwNzBiNzNmM2I3Mg==
6
+ YjZlZmM5YWY2NWMxNjNlNDlhNGZiNzYwNDQ2ZWQ1OTg5ZmE4OTQyMA==
7
7
  !binary "U0hBNTEy":
8
8
  metadata.gz: !binary |-
9
- NGJkMmY5NWQxZjFjNDdmMDUwNDYwZGU3MTU3MmQ4Y2FkNDZmOGE1Y2VkYWQ3
10
- NjViZWE0NmRkZjEyMGNlZDJhODQzYWQ2NzdjNjY0YWY0YWNmZmUwMTEwODQ5
11
- ODZjYTc3MTMyODQ2YzUzNTk5Mjk0NWQ0MWZkOThmMTFmYjUzMzk=
9
+ ZmRiN2VkMDRhMWNhNWU3Mzg4YTY5YzZlZGE2ZmMyNTU2MGU2NTg2NDMxOTEw
10
+ NjliYTU2ZTBmNzlhOTA0MDc0MzQ1MGQyZDg3MDFhYzRhYjUxY2MxZWRjYTFj
11
+ ZmM2ZDczZDJiNmUxOGRiMzJjNDUzMzNkN2U3NjZmZTJkZDYwMzU=
12
12
  data.tar.gz: !binary |-
13
- OTkwYjM4NmU4ZTMyNDEzODkzNmU2YTEyOGZiMTczOGYyOTYxZDk5MmEzNjYy
14
- OTk3YTY5NmNlNmJhNTM1MWU2NDMzODFmYWQ4MTVhNDE4YzRiZDhkMTAxODRl
15
- NThlNzYwZmI1MzI3ZjhmMmIxNDQ5MjYwMmE0NmY4NzQ1NmQzYjI=
13
+ NjJkYzUxYmNhZGFmMjMxYjA3MmE5YTBkMzliNWNmYmY3MGVlZDY0YzdlYmJl
14
+ MzBlNjc0NTJkN2VkOWRkM2FhYWFjYjBlMGUzZDgyMDg4M2NiNzU5NGYwZmNh
15
+ ZTU4NDI4NTQ0ZmM1YmEwNGQ2ODZhOGM3ZDU0MWI4MTliYmVlOWY=
@@ -0,0 +1,169 @@
1
+ module Caboose
2
+ class PostsController < ApplicationController
3
+
4
+ # GET /posts
5
+ def index
6
+ @posts = Post.where(:published => true).limit(5).order('created_at DESC')
7
+ end
8
+
9
+ # GET /posts/:id
10
+ def detail
11
+ @post = Post.find_by_id(params[:id])
12
+ unless @post.present?
13
+ flash[:notice] = 'The posts post you tried to access does not exist.'
14
+ redirect_to action: :index
15
+ end
16
+ end
17
+
18
+ #=============================================================================
19
+ # Admin actions
20
+ #=============================================================================
21
+
22
+ # GET /admin/posts
23
+ def admin_index
24
+ return if !user_is_allowed('posts', 'view')
25
+
26
+ @gen = Caboose::PageBarGenerator.new(params, {
27
+ 'name' => ''
28
+ },{
29
+ 'model' => 'Caboose::Post',
30
+ 'sort' => 'created_at DESC',
31
+ 'desc' => false,
32
+ 'base_url' => '/admin/posts'
33
+ })
34
+ @posts = @gen.items
35
+ render :layout => 'caboose/admin'
36
+ end
37
+
38
+ # GET /admin/posts/:id/edit
39
+ def admin_edit_general
40
+ return if !user_is_allowed('posts', 'edit')
41
+ @post = Post.find(params[:id])
42
+ render :layout => 'caboose/admin'
43
+ end
44
+
45
+ # GET /admin/posts/:id/content
46
+ def admin_edit_content
47
+ return if !user_is_allowed('posts', 'edit')
48
+ @post = Post.find(params[:id])
49
+ render :layout => 'caboose/admin'
50
+ end
51
+
52
+ # GET /admin/posts/:id/categories
53
+ def admin_edit_categories
54
+ return if !user_is_allowed('posts', 'edit')
55
+ @post = Post.find(params[:id])
56
+ @categories = PostCategory.reorder(:name).all
57
+ render :layout => 'caboose/admin'
58
+ end
59
+
60
+ # POST /admin/posts/:id
61
+ def admin_update
62
+ Caboose.log(params)
63
+ return if !user_is_allowed('posts', 'edit')
64
+
65
+ resp = Caboose::StdClass.new({'attributes' => {}})
66
+ post = Post.find(params[:id])
67
+
68
+ save = true
69
+ params.each do |name, value|
70
+ case name
71
+ when 'category_id'
72
+ post.category_id = value
73
+ when 'title'
74
+ post.title = value
75
+ when 'body'
76
+ post.body = value
77
+ when 'image'
78
+ post.image = value
79
+ when 'published'
80
+ post.published = value.to_i == 1
81
+ when 'created_at'
82
+ post.created_at = DateTime.parse(value)
83
+ end
84
+ end
85
+ resp.success = save && post.save
86
+ if params[:image]
87
+ resp.attributes['image'] = { 'value' => post.image.url(:thumb) }
88
+ end
89
+ render :json => resp
90
+ end
91
+
92
+ # GET /admin/posts/new
93
+ def admin_new
94
+ return if !user_is_allowed('posts', 'new')
95
+ @new_post = Post.new
96
+ render :layout => 'caboose/admin'
97
+ end
98
+
99
+ # POST /admin/posts
100
+ def admin_add
101
+ return if !user_is_allowed('posts', 'add')
102
+
103
+ resp = Caboose::StdClass.new({
104
+ 'error' => nil,
105
+ 'redirect' => nil
106
+ })
107
+
108
+ post = Post.new
109
+ post.title = params[:title]
110
+ post.published = false
111
+
112
+ if post.title == nil || post.title.length == 0
113
+ resp.error = 'A title is required.'
114
+ else
115
+ post.save
116
+ resp.redirect = "/admin/posts/#{post.id}/edit"
117
+ end
118
+
119
+ render :json => resp
120
+ end
121
+
122
+ # PUT /admin/posts/:id/add-to-category
123
+ def admin_add_to_category
124
+ return if !user_is_allowed('posts', 'edit')
125
+
126
+ post_id = params[:id]
127
+ cat_id = params[:post_category_id]
128
+
129
+ if !PostCategoryMembership.exists?(:post_id => post_id, :post_category_id => cat_id)
130
+ PostCategoryMembership.create(:post_id => post_id, :post_category_id => cat_id)
131
+ end
132
+
133
+ render :json => true
134
+ end
135
+
136
+ # PUT /admin/posts/:id/remove-from-category
137
+ def admin_remove_from_category
138
+ return if !user_is_allowed('posts', 'edit')
139
+
140
+ post_id = params[:id]
141
+ cat_id = params[:post_category_id]
142
+
143
+ if PostCategoryMembership.exists?(:post_id => post_id, :post_category_id => cat_id)
144
+ PostCategoryMembership.where(:post_id => post_id, :post_category_id => cat_id).destroy_all
145
+ end
146
+
147
+ render :json => true
148
+ end
149
+
150
+ # GET /admin/posts/:id/delete
151
+ def admin_delete_form
152
+ return if !user_is_allowed('posts', 'delete')
153
+ @post = Post.find(params[:id])
154
+ render :layout => 'caboose/admin'
155
+ end
156
+
157
+ # DELETE /admin/posts/:id
158
+ def admin_delete
159
+ return if !user_is_allowed('posts', 'edit')
160
+
161
+ post_id = params[:id]
162
+ PostCategoryMembership.where(:post_id => post_id).destroy_all
163
+ Post.where(:id => post_id).destroy_all
164
+
165
+ render :json => { 'redirect' => '/admin/posts' }
166
+ end
167
+
168
+ end
169
+ end
@@ -1,8 +1,16 @@
1
1
 
2
2
  class Caboose::Post < ActiveRecord::Base
3
3
  self.table_name = "posts"
4
- belongs_to :category
5
- attr_accessible :id, :category_id, :title, :body, :published
4
+
5
+ has_many :post_category_memberships
6
+ has_many :post_categories, :through => :post_category_memberships
7
+
8
+ attr_accessible :id,
9
+ :category_id,
10
+ :title,
11
+ :body,
12
+ :published,
13
+ :created_at
6
14
  has_attached_file :image,
7
15
  :path => 'posts/:id_:style.:extension',
8
16
  :styles => {
@@ -0,0 +1,10 @@
1
+
2
+ class Caboose::PostCategory < ActiveRecord::Base
3
+ self.table_name = "post_categories"
4
+
5
+ has_many :post_category_memberships
6
+ has_many :posts, :through => :post_category_memberships
7
+
8
+ attr_accessible :id, :name
9
+
10
+ end
@@ -0,0 +1,9 @@
1
+
2
+ class Caboose::PostCategoryMembership < ActiveRecord::Base
3
+ self.table_name = "post_category_memberships"
4
+
5
+ belongs_to :post_category
6
+ belongs_to :post
7
+ attr_accessible :post_id, :post_category_id
8
+
9
+ end
@@ -0,0 +1,2 @@
1
+ <br style='clear: left; line-height: 0;' />
2
+ </div><!-- modal_content2 -->
@@ -0,0 +1,23 @@
1
+ <% content_for :caboose_css do %>
2
+ <% end %>
3
+ <% content_for :caboose_js do %>
4
+ <%= javascript_include_tag "caboose/model/all" %>
5
+ <% end %>
6
+
7
+ <h1>Edit Post</h1>
8
+ <ul id='tabs'>
9
+ <%
10
+ tabs = {
11
+ "/admin/posts/#{@post.id}/edit" => 'General',
12
+ "/admin/posts/#{@post.id}/content" => 'Content',
13
+ "/admin/posts/#{@post.id}/categories" => 'Categories',
14
+ "/admin/posts/#{@post.id}/delete" => 'Delete Post'
15
+ }
16
+
17
+ %>
18
+ <% tabs.each do |href,text| %>
19
+ <li<%= raw request.fullpath == href ? " class='selected'" : '' %>><a href='<%= href %>'><%= raw text %></a></li>
20
+ <% end %>
21
+ <li class='back'><input type='button' value='< Back' onclick="window.location='/admin/posts';" /></li>
22
+ </ul>
23
+ <div id='content2'>
@@ -0,0 +1,30 @@
1
+
2
+ <%= render :partial => 'caboose/posts/admin_header' %>
3
+
4
+ <div id='message'>
5
+ <p class='note error'>Are you sure you want to delete the post? This can't be undone.<br /><br />
6
+ <input type='button' value='Yes' onclick='delete_post(<%= @post.id %>, true);' />
7
+ <input type='button' value='No' onclick="window.location='/admin/posts/<%= @post.id %>/edit';" />
8
+ </p>
9
+ </div>
10
+
11
+ <%= render :partial => 'caboose/posts/admin_footer' %>
12
+ <% content_for :caboose_js do %>
13
+ <%= javascript_include_tag "caboose/model/all" %>
14
+ <script type="text/javascript">
15
+
16
+ function delete_post(post_id, confirm)
17
+ {
18
+ $('#message').html("<p class='loading'>Deleting post...</p>");
19
+ $.ajax({
20
+ url: '/admin/posts/' + post_id,
21
+ type: 'delete',
22
+ success: function(resp) {
23
+ if (resp.error) $('#message').html("<p class='note error'>" + resp.error + "</p>");
24
+ if (resp.redirect) window.location = resp.redirect
25
+ }
26
+ });
27
+ }
28
+
29
+ </script>
30
+ <% end %>
@@ -0,0 +1,42 @@
1
+
2
+ <%= render :partial => 'caboose/posts/admin_header' %>
3
+
4
+ <style type='text/css'>
5
+ #content input[type=checkbox] { position: relative; }
6
+ </style>
7
+
8
+ <% cat_ids = @post.post_categories.collect { |cat| cat.id } %>
9
+ <% @categories.each do |cat| %>
10
+ <% checked = cat_ids.include?(cat.id) %>
11
+ <p>
12
+ <input type='checkbox' id='cat_<%= cat.id %>' value='<%= cat.id %>' <%= checked ? "checked='true'" : '' %> onchange="check_category(<%= @post.id %>, this.value);" />
13
+ <label for="cat_<%= cat.id %>"><%= cat.name %></label>
14
+ </p>
15
+ <% end %>
16
+
17
+ <%= render :partial => 'caboose/posts/admin_footer' %>
18
+
19
+ <% content_for :caboose_js do %>
20
+ <%= javascript_include_tag "caboose/model/all" %>
21
+ <script type='text/javascript'>
22
+
23
+ function check_category(post_id, cat_id)
24
+ {
25
+ var checked = $('#cat_' + cat_id).is(':checked');
26
+
27
+ $.ajax({
28
+ url: '/admin/posts/' + post_id + '/' + (checked ? 'add-to-category' : 'remove-from-category'),
29
+ data: { post_category_id: cat_id },
30
+ success: function(resp) {}
31
+ });
32
+ }
33
+
34
+ var modal = false;
35
+ $(window).load(function() {
36
+ modal = new CabooseModal(800);
37
+ });
38
+
39
+ </script>
40
+ <%= tinymce_assets %>
41
+ <%= tinymce :caboose, 'width' => '575px', 'height' => '240px' %>
42
+ <% end %>
@@ -0,0 +1,32 @@
1
+
2
+ <%= render :partial => 'caboose/posts/admin_header' %>
3
+
4
+ <p><div id='post_<%= @post.id %>_body' ></div></p>
5
+
6
+ <%= render :partial => 'caboose/posts/admin_footer' %>
7
+
8
+ <% content_for :caboose_js do %>
9
+ <%= javascript_include_tag "caboose/model/all" %>
10
+ <script type='text/javascript'>
11
+
12
+ $(document).ready(function() {
13
+ m = new ModelBinder({
14
+ name: 'Post',
15
+ id: <%= @post.id %>,
16
+ update_url: '/admin/posts/<%= @post.id %>',
17
+ authenticity_token: '<%= form_authenticity_token %>',
18
+ attributes: [
19
+ { name: 'body', nice_name: 'Body', type: 'richtext', value: <%= raw Caboose.json(@post.body) %>, width: 600, height: 400 }
20
+ ]
21
+ });
22
+ });
23
+
24
+ var modal = false;
25
+ $(window).load(function() {
26
+ modal = new CabooseModal(800);
27
+ });
28
+
29
+ </script>
30
+ <%= tinymce_assets %>
31
+ <%= tinymce :caboose, 'width' => '575px', 'height' => '240px' %>
32
+ <% end %>
@@ -0,0 +1,36 @@
1
+
2
+ <%= render :partial => 'caboose/posts/admin_header' %>
3
+
4
+ <p><div id='post_<%= @post.id %>_published' ></div></p>
5
+ <p><div id='post_<%= @post.id %>_title' ></div></p>
6
+ <p><div id='post_<%= @post.id %>_image' ></div></p>
7
+
8
+ <%= render :partial => 'caboose/posts/admin_footer' %>
9
+
10
+ <% content_for :caboose_js do %>
11
+ <%= javascript_include_tag "caboose/model/all" %>
12
+ <script type='text/javascript'>
13
+
14
+ $(document).ready(function() {
15
+ m = new ModelBinder({
16
+ name: 'Post',
17
+ id: <%= @post.id %>,
18
+ update_url: '/admin/posts/<%= @post.id %>',
19
+ authenticity_token: '<%= form_authenticity_token %>',
20
+ attributes: [
21
+ { name: 'published' , nice_name: 'Published' , type: 'checkbox' , value: <%= raw @post.published ? true : false %>, width: 600 },
22
+ { name: 'title' , nice_name: 'Title' , type: 'text' , value: <%= raw Caboose.json(@post.title) %>, width: 600 },
23
+ { name: 'image' , nice_name: 'Image' , type: 'image' , value: <%= raw Caboose.json(@post.image.url(:thumb)) %>, width: 600 }
24
+ ]
25
+ });
26
+ });
27
+
28
+ var modal = false;
29
+ $(window).load(function() {
30
+ modal = new CabooseModal(800);
31
+ });
32
+
33
+ </script>
34
+ <%= tinymce_assets %>
35
+ <%= tinymce :caboose, 'width' => '575px', 'height' => '240px' %>
36
+ <% end %>
@@ -0,0 +1,37 @@
1
+ <h1>Posts</h1>
2
+ <p><input type='button' value='New Post' onclick="window.location='/admin/posts/new';" /></p>
3
+
4
+ <% if @posts && @posts.count > 0 %>
5
+ <table class='data'>
6
+ <tr>
7
+ <%= raw @gen.sortable_table_headings({
8
+ 'id' => 'ID #',
9
+ 'published' => 'Published',
10
+ 'title' => 'Title',
11
+ 'body' => 'Body',
12
+ 'created_at' => 'Date Created'
13
+ })
14
+ %>
15
+ </tr>
16
+ <% @posts.each do |p| %>
17
+ <tr onclick="window.location='/admin/posts/<%= p.id %>/edit';">
18
+ <td><%= raw p.id %></td>
19
+ <td><%= p.published ? "Yes" : "No" %></td>
20
+ <td><%= raw p.title %></td>
21
+ <td><%= raw truncate(p.body, :length => 80) %></td>
22
+ <td><%= p.created_at.strftime("%m/%d/%Y") %></td>
23
+ </tr>
24
+ <% end %>
25
+ </table>
26
+ <p><%= raw @gen.generate %></p>
27
+ <% else %>
28
+ <p>There are no posts right now.</p>
29
+ <% end %>
30
+
31
+ <% content_for :caboose_js do %>
32
+ <script type='text/javascript'>
33
+ $(document).ready(function() {
34
+ var modal = new CabooseModal(800);
35
+ });
36
+ </script>
37
+ <% end %>
@@ -0,0 +1,37 @@
1
+
2
+ <h1>New Post</h1>
3
+
4
+ <p><input type='text' id='title' name='title' placeholder='Title' style="width: 400px;" /></p>
5
+ <div id='message'></div>
6
+ <p><input type='submit' value='Add Post' onclick='add_post();' /></p>
7
+
8
+ <% content_for :caboose_js do %>
9
+ <%= javascript_include_tag "caboose/model/all" %>
10
+ <script type='text/javascript'>
11
+
12
+ var modal = false;
13
+ $(document).ready(function() {
14
+ modal = new CabooseModal(420);
15
+ });
16
+
17
+ function add_post()
18
+ {
19
+ modal.autosize("<p class='loading'>Adding post...</p>");
20
+ $.ajax({
21
+ url: '/admin/posts',
22
+ type: 'post',
23
+ data: {
24
+ authenticity_token: "<%= form_authenticity_token %>",
25
+ title: $('#title').val(),
26
+ },
27
+ success: function(resp) {
28
+ if (resp.error)
29
+ modal.autosize("<p class='note error'>" + resp.error + "</p>");
30
+ if (resp.redirect)
31
+ window.location = resp.redirect
32
+ }
33
+ });
34
+ }
35
+
36
+ </script>
37
+ <% end %>
@@ -0,0 +1,6 @@
1
+
2
+ <div class='post'>
3
+ <h1><%= raw @post[:title] %></h1>
4
+ <figure><img src="<%= @post.image.url(:medium) %>" /></figure>
5
+ <article><%= raw @article[:body] %></article>
6
+ </div>
@@ -0,0 +1,18 @@
1
+
2
+ <div class="posts">
3
+ <% if @posts && @posts.count > 0 %>
4
+ <ul>
5
+ <% @posts.each do |p| %>
6
+ <li>
7
+ <figure><a href="/posts/<%= p.id %>"><img src="<%= p.image.url(:thumb) %>" /></a></figure>
8
+ <h5><strong><%= raw a[:title] %></strong></h5>
9
+ <p class="h-space-mvt"><%= a[:created_at].strftime("%m/%d/%Y") %></p>
10
+ <p class="h-space-mbt"><%= truncate(strip_tags(a[:body]), :length => 175) %></p>
11
+ <a class="m-btn-red h-space-mts" href="/news/<%= a.id %>">Read More</a>
12
+ </li>
13
+ <% end %>
14
+ </ul>
15
+ <% else %>
16
+ <p>There are no posts right now.</p>
17
+ <% end %>
18
+ </div>
@@ -64,6 +64,23 @@ Caboose::Engine.routes.draw do
64
64
  post "admin/pages" => "pages#admin_create"
65
65
  delete "admin/pages/:id" => "pages#admin_delete"
66
66
 
67
+ get "posts" => "posts#index"
68
+ get "posts/:id" => "posts#detail"
69
+ get "admin/posts/category-options" => "posts#admin_category_options"
70
+ get "admin/posts/new" => "posts#admin_new"
71
+ get "admin/posts/:id/delete" => "posts#admin_delete_form"
72
+ get "admin/posts/:id/edit" => "posts#admin_edit_general"
73
+ get "admin/posts/:id/content" => "posts#admin_edit_content"
74
+ get "admin/posts/:id/categories" => "posts#admin_edit_categories"
75
+ get "admin/posts/:id/add-to-category" => "posts#admin_add_to_category"
76
+ get "admin/posts/:id/remove-from-category" => "posts#admin_remove_from_category"
77
+ get "admin/posts/:id/delete" => "posts#admin_delete_form"
78
+ put "admin/posts/:id" => "posts#admin_update"
79
+ post "admin/posts/:id" => "posts#admin_update"
80
+ get "admin/posts" => "posts#admin_index"
81
+ post "admin/posts" => "posts#admin_add"
82
+ delete "admin/posts/:id" => "posts#admin_delete"
83
+
67
84
  match '*path' => 'pages#show'
68
85
  root :to => 'pages#show'
69
86
 
@@ -1,3 +1,3 @@
1
1
  module Caboose
2
- VERSION = '0.2.70'
2
+ VERSION = '0.2.71'
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.2.70
4
+ version: 0.2.71
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-10-15 00:00:00.000000000 Z
11
+ date: 2013-10-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -181,6 +181,7 @@ files:
181
181
  - app/controllers/caboose/logout_controller.rb
182
182
  - app/controllers/caboose/pages_controller.rb
183
183
  - app/controllers/caboose/permissions_controller.rb
184
+ - app/controllers/caboose/posts_controller.rb
184
185
  - app/controllers/caboose/register_controller.rb
185
186
  - app/controllers/caboose/roles_controller.rb
186
187
  - app/controllers/caboose/settings_controller.rb
@@ -202,6 +203,8 @@ files:
202
203
  - app/models/caboose/pager.rb
203
204
  - app/models/caboose/permission.rb
204
205
  - app/models/caboose/post.rb
206
+ - app/models/caboose/post_category.rb
207
+ - app/models/caboose/post_category_membership.rb
205
208
  - app/models/caboose/role.rb
206
209
  - app/models/caboose/setting.rb
207
210
  - app/models/caboose/std_class.rb
@@ -229,6 +232,16 @@ files:
229
232
  - app/views/caboose/permissions/edit.html.erb
230
233
  - app/views/caboose/permissions/index.html.erb
231
234
  - app/views/caboose/permissions/new.html.erb
235
+ - app/views/caboose/posts/_admin_footer.html.erb
236
+ - app/views/caboose/posts/_admin_header.html.erb
237
+ - app/views/caboose/posts/admin_delete_form.html.erb
238
+ - app/views/caboose/posts/admin_edit_categories.html.erb
239
+ - app/views/caboose/posts/admin_edit_content.html.erb
240
+ - app/views/caboose/posts/admin_edit_general.html.erb
241
+ - app/views/caboose/posts/admin_index.html.erb
242
+ - app/views/caboose/posts/admin_new.html.erb
243
+ - app/views/caboose/posts/detail.html.erb
244
+ - app/views/caboose/posts/index.html.erb
232
245
  - app/views/caboose/register/index.html.erb
233
246
  - app/views/caboose/roles/edit.html.erb
234
247
  - app/views/caboose/roles/index.html.erb