caboose-cms 0.4.42 → 0.4.43

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.
Files changed (34) hide show
  1. checksums.yaml +8 -8
  2. data/app/assets/javascripts/caboose/jquery.fileupload.js +1441 -0
  3. data/app/assets/javascripts/caboose/lodash.min.js +56 -0
  4. data/app/assets/javascripts/caboose/s3upload.js +124 -0
  5. data/app/controllers/caboose/ab_variants_controller.rb +1 -1
  6. data/app/controllers/caboose/application_controller.rb +1 -1
  7. data/app/controllers/caboose/images_controller.rb +269 -0
  8. data/app/controllers/caboose/pages_controller.rb +21 -12
  9. data/app/controllers/caboose/permissions_controller.rb +1 -1
  10. data/app/controllers/caboose/roles_controller.rb +1 -1
  11. data/app/controllers/caboose/settings_controller.rb +1 -1
  12. data/app/controllers/caboose/sites_controller.rb +156 -0
  13. data/app/controllers/caboose/users_controller.rb +1 -1
  14. data/app/models/caboose/asset.rb +2 -2
  15. data/app/models/caboose/core_plugin.rb +7 -6
  16. data/app/models/caboose/domain.rb +8 -0
  17. data/app/models/caboose/media_category.rb +18 -0
  18. data/app/models/caboose/media_file.rb +9 -0
  19. data/app/models/caboose/media_image.rb +16 -0
  20. data/app/models/caboose/page.rb +16 -9
  21. data/app/models/caboose/schema.rb +191 -158
  22. data/app/models/caboose/site.rb +9 -0
  23. data/app/models/caboose/site_membership.rb +12 -0
  24. data/app/views/caboose/blocks/admin_edit.html.erb +2 -1
  25. data/app/views/caboose/blocks/admin_new.html.erb +5 -1
  26. data/app/views/caboose/images/admin_index.html.erb +24 -0
  27. data/app/views/caboose/images/admin_new.html.erb +63 -0
  28. data/app/views/caboose/pages/admin_index.html.erb +6 -3
  29. data/app/views/caboose/sites/admin_edit.html.erb +199 -0
  30. data/app/views/caboose/sites/admin_index.html.erb +31 -0
  31. data/app/views/caboose/sites/admin_new.html.erb +33 -0
  32. data/config/routes.rb +25 -0
  33. data/lib/caboose/version.rb +1 -1
  34. metadata +18 -2
@@ -0,0 +1,9 @@
1
+
2
+ class Caboose::Site < ActiveRecord::Base
3
+ self.table_name = "sites"
4
+
5
+ has_many :site_memberships, :class_name => 'Caboose::SiteMembership', :dependent => :delete_all
6
+ has_many :domains, :class_name => 'Caboose::Domain', :dependent => :delete_all
7
+ attr_accessible :id, :name, :description
8
+
9
+ end
@@ -0,0 +1,12 @@
1
+
2
+ class Caboose::SiteMembership < ActiveRecord::Base
3
+ self.table_name = "site_membership"
4
+
5
+ belongs_to :site, :class_name => 'Caboose::Site'
6
+ belongs_to :user, :class_name => 'Caboose::User'
7
+ attr_accessible :id, :site_id, :user_id, :role
8
+
9
+ ROLE_ADMIN = 'Admin'
10
+ ROLE_USER = 'User'
11
+
12
+ end
@@ -18,7 +18,7 @@ end
18
18
  <!--<h2 style='margin-top: 0; padding-top: 0;'>Edit <%= @block.name ? @block.name : @block.block_type.description %></h2>-->
19
19
  <h2 style='margin-top: 0; padding-top: 0;'><%= raw crumbs.reverse.join(' > ') %></h2>
20
20
  <p id='block_type_container'><div id='block_<%= @block.id %>_block_type_id'></div></p>
21
-
21
+
22
22
  <% if @block.block_type.use_render_function_for_layout %>
23
23
  <!-- Start -->
24
24
  <%= raw @block.render(@block, {
@@ -88,6 +88,7 @@ $(window).load(function() {
88
88
 
89
89
  var controller = false;
90
90
  $(document).ready(function() {
91
+ modal = new CabooseModal(800);
91
92
  controller = new BlockController({
92
93
  block: <%= raw Caboose.json(@block.js_hash) %>,
93
94
  authenticity_token: '<%= form_authenticity_token %>',
@@ -35,7 +35,11 @@ b = @block
35
35
 
36
36
  var modal = false;
37
37
  $(window).load(function() {
38
- modal = new CabooseModal(800);
38
+ modal = new CabooseModal(800);
39
+ });
40
+
41
+ $(document).ready(function() {
42
+ modal = new CabooseModal(800);
39
43
  });
40
44
 
41
45
  function add_child_block()
@@ -0,0 +1,24 @@
1
+ <h1>Images</h1>
2
+
3
+ <% if @domain && @media_category %>
4
+ <p>
5
+ <a href='/admin/images/new'>Upload Images</a> |
6
+ <a href='/admin/images/new-category?parent_id=<%= @media_category.id %>'>New Category</a>
7
+ </p>
8
+ <% if @media_category.children.count > 0 || @media_category.media_images.count > 0 %>
9
+ <ul class='media'>
10
+ <% @media_category.children.each do |cat| %>
11
+ <li class='category' id='cat<%= cat.id %>'><a href='/admin/images?media_category_id=<%= cat.id %>'><%= cat.name %></a></li>
12
+ <% end %>
13
+ <% @media_category.media_images.each do |mi| %>
14
+ <li class='image' id='image<%= mi.id %>'><a href='/admin/images/<%= mi.id %>'><img src='<%= mi.image.url(:thumb) %>' /><span><%= img.name %></span></a></li>
15
+ <% end %>
16
+ </ul>
17
+ <% else %>
18
+ <p>This category is empty.</p>
19
+ <% end %>
20
+ <% elsif @domain && @media_category.nil? %>
21
+ <p>Invalid media category.</p>
22
+ <% else %>
23
+ <p>It doesn't look like this site is configured for the current domain. Please <a href='/admin/sites'>configure your sites</a>.</p>
24
+ <% end %>
@@ -0,0 +1,63 @@
1
+
2
+ <h1>Upload Images</h1>
3
+
4
+ <input type="file" id="file" onchange="s3_upload();"/>
5
+ <p id="status">Please select a file</p>
6
+ <div id="preview"><img src="/static/default.png" /></div>
7
+
8
+ <% content_for :caboose_css do %>
9
+ <style type='text/css'>
10
+ .progress { max-width: 600px; margin: 0.2em 0 0.2em 0; }
11
+ .progress .bar { height: 1.2em; padding: 0.2em; color: white; display: none; }
12
+ </style>
13
+ <% end %>
14
+
15
+ <% content_for :caboose_js do %>
16
+ <%= javascript_include_tag 'jquery.ui.all' %>
17
+ <%= javascript_include_tag 'caboose/jquery.fileupload.js' %>
18
+ <script type='text/javascript'>
19
+
20
+ $(function() {
21
+ $('.directUpload').find("input:file").each(function(i, elem) {
22
+
23
+ var fileInput = $(elem);
24
+ var form = $(fileInput.parents('form:first'));
25
+ var submitButton = form.find('input[type="submit"]');
26
+ var progressBar = $("<div class='bar'></div>");
27
+ var barContainer = $("<div class='progress'></div>").append(progressBar);
28
+
29
+ fileInput.after(barContainer);
30
+ fileInput.fileupload({
31
+ fileInput: fileInput,
32
+ url: '', // @s3_direct_post.url
33
+ type: 'POST',
34
+ autoUpload: true,
35
+ formData: '', // @s3_direct_post.fields.to_json.html_safe
36
+ paramName: 'file', // S3 does not like nested name fields i.e. name="user[avatar_url]"
37
+ dataType: 'XML', // S3 returns XML if success_action_status is set to 201
38
+ replaceFileInput: false,
39
+ fileuploadsubmit: function() {
40
+ alert('Testing');
41
+ },
42
+ progressall: function (e, data) {
43
+ var progress = parseInt(data.loaded / data.total * 100, 10);
44
+ progressBar.css('width', progress + '%')
45
+ },
46
+ start: function (e) {
47
+ submitButton.prop('disabled', true);
48
+ progressBar.css('background', 'green').css('display', 'block').css('width', '0%').text("Loading...");
49
+ },
50
+ done: function(e, data) {
51
+ submitButton.prop('disabled', false);
52
+ progressBar.text("Uploading done");
53
+ },
54
+ fail: function(e, data) {
55
+ submitButton.prop('disabled', false);
56
+ progressBar.css("background", "red").text("Failed");
57
+ }
58
+ });
59
+ });
60
+ });
61
+
62
+ </script>
63
+ <% end %>
@@ -1,5 +1,8 @@
1
1
  <h1>Pages</h1>
2
2
 
3
- <p><a href='/admin/pages/new'>New Page</a></p>
4
-
5
- <%= raw pages_list(@home_page) %>
3
+ <% if @domain %>
4
+ <p><a href='/admin/pages/new'>New Page</a></p>
5
+ <%= raw pages_list(@home_page) %>
6
+ <% else %>
7
+ <p>It doesn't look like this site is configured for the current domain. Please <a href='/admin/sites'>configure your sites</a>.</p>
8
+ <% end %>
@@ -0,0 +1,199 @@
1
+ <%
2
+ s = @site
3
+ admin_ids = Caboose::SiteMembership.where(:site_id => s.id, :role => Caboose::SiteMembership::ROLE_ADMIN).pluck(:user_id)
4
+ user_ids = Caboose::SiteMembership.where(:site_id => s.id, :role => Caboose::SiteMembership::ROLE_USER ).pluck(:user_id)
5
+ admin_ids = [] if admin_ids.nil?
6
+ user_ids = [] if user_ids.nil?
7
+ %>
8
+ <h1>Edit Site</h1>
9
+
10
+ <p><div id='site_<%= @site.id %>_name' ></div></p>
11
+ <p><div id='site_<%= @site.id %>_description' ></div></p>
12
+
13
+ <h2>Domains</h2>
14
+ <p><a href='#' onclick="add_domain(<%= @site.id %>);">New Domain</a></p>
15
+ <div id='new_domain_container'></div>
16
+ <% if @site.domains && @site.domains.count > 0 %>
17
+ <table class='data'>
18
+ <tr>
19
+ <th>Domain</th>
20
+ <th>Primary</th>
21
+ <th>Delete</th>
22
+ </tr>
23
+ <% @site.domains.all.each do |d| %>
24
+ <tr>
25
+ <td><%= d.domain %></td>
26
+ <td align='center'><input type='radio' name='primary_domain' <%= d.primary? ? "checked='true'" : '' %> onclick="set_primary_domain(<%= s.id %>, <%= d.id %>);" /></td>
27
+ <td align='center'><input type='button' value='Delete' onclick="delete_domain(<%= @site.id %>, <%= d.id %>);" /></td>
28
+ </tr>
29
+ <% end %>
30
+ </table>
31
+ <% else %>
32
+ <p>This site doesn't have any domains yet.</p>
33
+ <% end %>
34
+ <div id='domain_message'></div>
35
+
36
+ <h2>Members</h2>
37
+ <div id='members'>
38
+ <table class='data'>
39
+ <tr><th>User</th><th>None</th><th>User</th><th>Admin</th></tr>
40
+ <% Caboose::User.reorder('last_name, first_name').all.each do |u| %>
41
+ <tr>
42
+ <td><%= u.first_name %> <%= u.last_name %> (<%= u.email %>)</td>
43
+ <td align='center'><input type='radio' name='user<%= u.id %>' <%= !admin_ids.include?(u.id) && !user_ids.include?(u.id) ? "checked='true'" : '' %> onclick="remove_site_membership(<%= s.id %>, <%= u.id %>);" /></td>
44
+ <td align='center'><input type='radio' name='user<%= u.id %>' <%= user_ids.include?(u.id) ? "checked='true'" : '' %> onclick="add_site_membership(<%= s.id %>, <%= u.id %>, 'User');" /></td>
45
+ <td align='center'><input type='radio' name='user<%= u.id %>' <%= admin_ids.include?(u.id) ? "checked='true'" : '' %> onclick="add_site_membership(<%= s.id %>, <%= u.id %>, 'Admin');" /></td>
46
+ </tr>
47
+ <% end %>
48
+ </table>
49
+ </div>
50
+
51
+ <div id='message'></div>
52
+ <div id='controls'>
53
+ <input type='button' value='Back' onclick="window.location='/admin/sites';" />
54
+ <input type='button' value='Delete Site' onclick="delete_site(<%= @site.id %>);" />
55
+ </div>
56
+
57
+ <% content_for :caboose_css do %>
58
+ <style type='text/css'>
59
+ #content input[type=checkbox] { position: relative; }
60
+ #members { height: 200px; overflow-y: scroll; margin-bottom: 20px; }
61
+ </style>
62
+ <% end %>
63
+ <% content_for :caboose_js do %>
64
+ <%= javascript_include_tag "caboose/model/all" %>
65
+ <script type="text/javascript">
66
+
67
+ $(document).ready(function() {
68
+ new ModelBinder({
69
+ name: 'Site',
70
+ id: <%= @site.id %>,
71
+ update_url: '/admin/sites/<%= @site.id %>',
72
+ authenticity_token: '<%= form_authenticity_token %>',
73
+ attributes: [
74
+ { name: 'name' , nice_name: 'Name' , type: 'text' , value: <%= raw Caboose.json(@site.name) %>, width: 400 },
75
+ { name: 'description' , nice_name: 'Description' , type: 'textarea' , value: <%= raw Caboose.json(@site.description) %>, width: 600, height: 75 }
76
+ ]
77
+ });
78
+ });
79
+
80
+ function delete_site(site_id, confirm)
81
+ {
82
+ if (!confirm)
83
+ {
84
+ var p = $('<p/>').addClass('note confirm')
85
+ .append('Are you sure you want to delete the site? ')
86
+ .append($('<input/>').attr('type','button').val('Yes').click(function() { delete_site(site_id, true); })).append(' ')
87
+ .append($('<input/>').attr('type','button').val('No').click(function() { $('#message').empty(); }));
88
+ $('#message').empty().append(p);
89
+ return;
90
+ }
91
+ $('#message').html("<p class='loading'>Deleting site...</p>");
92
+ $.ajax({
93
+ url: '/admin/sites/' + site_id,
94
+ type: 'delete',
95
+ success: function(resp) {
96
+ if (resp.error) $('#message').html("<p class='note error'>" + resp.error + "</p>");
97
+ if (resp.redirect) window.location = resp.redirect;
98
+ }
99
+ });
100
+ }
101
+
102
+ function add_site_membership(site_id, user_id, role)
103
+ {
104
+ $.ajax({
105
+ url: '/admin/sites/' + site_id +'/members',
106
+ type: 'post',
107
+ data: {
108
+ user_id: user_id,
109
+ role: role
110
+ },
111
+ succes: function(resp) {}
112
+ });
113
+ }
114
+
115
+ function remove_site_membership(site_id, user_id)
116
+ {
117
+ $.ajax({
118
+ url: '/admin/sites/' + site_id +'/members/' + user_id,
119
+ type: 'delete',
120
+ succes: function(resp) {}
121
+ });
122
+ }
123
+
124
+ function add_domain(site_id, domain)
125
+ {
126
+ if (!domain)
127
+ {
128
+ var div = $('<div/>')
129
+ .append($('<p/>')
130
+ .addClass('note warning')
131
+ .append("What domain would you like to add?<br />")
132
+ .append($('<input/>').attr('type','text').attr('id','new_domain').css('width', '200px')).append(' ')
133
+ .append($('<input/>').attr('type','button').val('Add').click(function() { add_domain(site_id, $('#new_domain').val()); })).append(' ')
134
+ .append($('<input/>').attr('type','button').val('Cancel').click(function() { $('#new_domain_container').empty(); }))
135
+ )
136
+ .append($('<div/>').attr('id', 'new_domain_message'));
137
+ $('#new_domain_container').empty().append(div);
138
+ return;
139
+ }
140
+ $('#new_domain_message').empty().html("<p class='loading'>Adding domain...</p>");
141
+ $.ajax({
142
+ url: '/admin/sites/' + site_id + '/domains',
143
+ type: 'post',
144
+ data: { domain: domain },
145
+ success: function(resp) {
146
+ if (resp.error) $('#new_domain_message').html("<p class='note error'>" + resp.error + "<br /></p>");
147
+ if (resp.refresh) window.location.reload(true);
148
+ }
149
+ });
150
+ }
151
+
152
+ function delete_domain(site_id, domain_id, confirm)
153
+ {
154
+ if (!confirm)
155
+ {
156
+ var p = $('<p/>').addClass('note confirm')
157
+ .append('Are you sure you want to delete the domain? ')
158
+ .append($('<input/>').attr('type','button').val('Yes').click(function() { delete_domain(site_id, domain_id, true); })).append(' ')
159
+ .append($('<input/>').attr('type','button').val('No').click(function() { $('#domain_message').empty(); }));
160
+ $('#domain_message').empty().append(p);
161
+ return;
162
+ }
163
+ $('#domain_message').html("<p class='loading'>Deleting domain...</p>");
164
+ $.ajax({
165
+ url: '/admin/sites/' + site_id + '/domains/' + domain_id,
166
+ type: 'delete',
167
+ success: function(resp) {
168
+ if (resp.error) $('#message').html("<p class='note error'>" + resp.error + "</p>");
169
+ if (resp.refresh) window.location.reload(true);
170
+ }
171
+ });
172
+ }
173
+
174
+ function set_primary_domain(site_id, domain_id)
175
+ {
176
+ $.ajax({
177
+ url: '/admin/sites/' + site_id + '/domains/' + domain_id + '/set-primary',
178
+ type: 'put',
179
+ success: function(resp) {}
180
+ });
181
+ }
182
+
183
+ </script>
184
+ <% end %>
185
+
186
+ <% content_for :caboose_css do %>
187
+ <style type='text/css'>
188
+ #gravatar {
189
+ float: right;
190
+ width: 150px;
191
+ text-align: right;
192
+ margin: 0 4px 0 0;
193
+ padding: 0;
194
+ }
195
+ #gravatar img {
196
+ border: #fff 2px solid;
197
+ }
198
+ </style>
199
+ <% end %>
@@ -0,0 +1,31 @@
1
+ <h1>Sites</h1>
2
+
3
+ <form action='/admin/sites' method='get' class='search_form'>
4
+ <input type='text' name='name_like' placeholder='Name' />
5
+ <input type='submit' value='Search' />
6
+ </form>
7
+
8
+ <p><a href='/admin/sites/new'>New Site</a></p>
9
+
10
+ <% if @sites && @sites.count > 0 %>
11
+ <table class='data' id='users_table'>
12
+ <tr>
13
+ <%= raw @pager.sortable_table_headings({
14
+ 'name' => 'Name',
15
+ 'description' => 'Description',
16
+ 'name, description' => 'Domains'
17
+ })
18
+ %>
19
+ </tr>
20
+ <% @sites.each do |site| %>
21
+ <tr onclick="window.location='/admin/sites/<%= site.id %>';">
22
+ <td><%= site.name %></td>
23
+ <td><%= site.description %></td>
24
+ <td><%= raw site.domains ? site.domains.collect{ |d| d.domain }.join('<br />') : '' %></td>
25
+ </tr>
26
+ <% end %>
27
+ </table>
28
+ <p><%= raw @pager.generate %></p>
29
+ <% else %>
30
+ <p>There are no sites right now.</p>
31
+ <% end %>
@@ -0,0 +1,33 @@
1
+
2
+ <h1>New Site</h1>
3
+
4
+ <form action='/admin/sites' method='post' id='new_site_form'>
5
+ <input type='hidden' name='authenticity_token' value='<%= form_authenticity_token %>' />
6
+ <p><input type='text' name='name' id='name' placeholder='Name' value='' style='width: 400px;' /></p>
7
+ <div id='message'></div>
8
+ <p><input type='submit' value='Add Site' /></p>
9
+ </form>
10
+
11
+ <% content_for :caboose_js do %>
12
+ <script type='text/javascript'>
13
+
14
+ $(document).ready(function() {
15
+ $('#new_site_form').submit(function() { add_site(); return false; });
16
+ });
17
+
18
+ function add_site()
19
+ {
20
+ $('#message').html("<p class='loading'>Adding site...</p>");
21
+ $.ajax({
22
+ url: '/admin/sites',
23
+ type: 'post',
24
+ data: $('#new_site_form').serialize(),
25
+ success: function(resp) {
26
+ if (resp.error) $('#message').html("<p class='note error'>" + resp.error + "</p>");
27
+ if (resp.redirect) window.location = resp.redirect;
28
+ }
29
+ });
30
+ }
31
+
32
+ </script>
33
+ <% end %>
@@ -21,6 +21,21 @@ Caboose::Engine.routes.draw do
21
21
  get "my-account" => "users#my_account"
22
22
  put "my-account" => "users#update_my_account"
23
23
 
24
+ post "admin/sites/:id/members" => "sites#admin_add_member"
25
+ delete "admin/sites/:id/members/:user_id" => "sites#admin_remove_member"
26
+
27
+ post "admin/sites/:id/domains" => "sites#admin_add_domain"
28
+ put "admin/sites/:id/domains/:domain_id/set-primary" => "sites#admin_set_primary_domain"
29
+ delete "admin/sites/:id/domains/:domain_id" => "sites#admin_remove_domain"
30
+
31
+ get "admin/sites/options" => "sites#options"
32
+ get "admin/sites" => "sites#admin_index"
33
+ get "admin/sites/new" => "sites#admin_new"
34
+ get "admin/sites/:id" => "sites#admin_edit"
35
+ put "admin/sites/:id" => "sites#admin_update"
36
+ post "admin/sites" => "sites#admin_add"
37
+ delete "admin/sites/:id" => "sites#admin_delete"
38
+
24
39
  get "admin/users" => "users#index"
25
40
  get "admin/users/options" => "users#options"
26
41
  get "admin/users/new" => "users#new"
@@ -47,6 +62,16 @@ Caboose::Engine.routes.draw do
47
62
  post "admin/roles/:id/permissions/:permission_id" => "roles#add_permission"
48
63
  delete "admin/roles/:id/permissions/:permission_id" => "roles#remove_permission"
49
64
 
65
+ get "admin/images" => "images#admin_index"
66
+ get "admin/images/sign-s3" => "images#admin_sign_s3"
67
+ get "admin/images/new" => "images#admin_new"
68
+ get "admin/images/:id" => "images#admin_edit"
69
+ put "admin/images/:id" => "images#admin_update"
70
+ post "admin/images/:id/image" => "images#admin_update_image"
71
+ post "admin/images" => "images#admin_add"
72
+ delete "admin/images/:id" => "images#admin_delete"
73
+
74
+
50
75
  get "admin/permissions" => "permissions#index"
51
76
  get "admin/permissions/options" => "permissions#options"
52
77
  get "admin/permissions/new" => "permissions#new"