cardboard_cms 0.1.8 → 0.2.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile.lock +4 -5
- data/README.md +14 -14
- data/app/assets/javascripts/cardboard/admin.js +3 -24
- data/app/assets/javascripts/cardboard/datepicker.js +1 -5
- data/app/assets/javascripts/cardboard/rich_text.js +1 -1
- data/app/assets/javascripts/cardboard/search_filter.js +1 -1
- data/app/assets/stylesheets/cardboard/_bootstrap-select.css.scss +1 -1
- data/app/assets/stylesheets/cardboard/_framework.css.scss +1 -1
- data/app/assets/stylesheets/cardboard/_main_topbar.css.scss +1 -1
- data/app/controllers/cardboard/pages_controller.rb +25 -1
- data/app/controllers/pages_controller.rb +12 -11
- data/app/helpers/cardboard/resource_helper.rb +1 -1
- data/app/models/cardboard/field/boolean.rb +1 -1
- data/app/models/cardboard/field.rb +21 -9
- data/app/models/cardboard/page.rb +19 -30
- data/app/models/cardboard/page_part.rb +13 -46
- data/app/models/cardboard/setting.rb +3 -0
- data/app/models/cardboard/template.rb +15 -0
- data/app/views/cardboard/fields/_base_input.html.slim +1 -1
- data/app/views/cardboard/fields/_boolean.html.slim +2 -2
- data/app/views/cardboard/fields/_date.html.slim +1 -1
- data/app/views/cardboard/fields/_external_link.html.slim +2 -2
- data/app/views/cardboard/fields/_file.html.slim +4 -4
- data/app/views/cardboard/fields/_image.html.slim +2 -2
- data/app/views/cardboard/fields/_resource_link.html.slim +2 -2
- data/app/views/cardboard/fields/_rich_text.html.slim +1 -1
- data/app/views/cardboard/fields/_string.html.slim +1 -1
- data/app/views/cardboard/pages/_error.html.slim +1 -1
- data/app/views/cardboard/pages/_part_fields.html.slim +19 -0
- data/app/views/cardboard/pages/_sidebar.html.slim +8 -4
- data/app/views/cardboard/pages/_url_field.html.slim +6 -8
- data/app/views/cardboard/pages/edit.html.slim +24 -15
- data/app/views/cardboard/pages/new.html.slim +7 -0
- data/app/views/cardboard/pages/show.html.slim +3 -3
- data/app/views/cardboard/resources/_advanced_search.html.slim +1 -1
- data/app/views/cardboard/resources/_search_helper.html.slim +3 -3
- data/app/views/cardboard/resources/_simple_search.html.slim +1 -1
- data/app/views/cardboard/settings/index.html.slim +12 -3
- data/app/views/cardboard/super_user/index.html.slim +1 -1
- data/app/views/layouts/cardboard/_main_sidebar.html.slim +1 -1
- data/app/views/layouts/cardboard/_main_topbar.html.slim +1 -1
- data/app/views/layouts/cardboard/application.html.slim +1 -1
- data/cardboard.gemspec +1 -1
- data/config/routes.rb +2 -0
- data/db/migrate/1_create_cardboard.rb +63 -0
- data/lib/cardboard/engine.rb +1 -11
- data/lib/cardboard/helpers/seed.rb +31 -30
- data/lib/cardboard/version.rb +1 -1
- data/lib/cardboard_cms.rb +6 -2
- data/lib/generators/cardboard/install/install_generator.rb +5 -13
- data/lib/tasks/cardboard_tasks.rake +5 -3
- data/test/dummy/app/views/{pages → templates}/about-us.html.slim +0 -0
- data/test/dummy/app/views/templates/home.html.slim +5 -0
- data/test/dummy/config/cardboard.yml +1 -1
- data/test/dummy/db/schema.rb +7 -39
- data/test/dummy/db/seeds.rb +1 -1
- data/test/factories.rb +40 -1
- data/test/integration/page_editing_test.rb +2 -1
- data/test/integration/seeding_test.rb +16 -31
- data/test/models/field_test.rb +42 -28
- data/test/models/page_test.rb +1 -1
- data/test/models/template_test.rb +11 -0
- data/test/test_helper.rb +5 -1
- metadata +13 -29
- data/app/views/cardboard/pages/_subpart_fields.html.slim +0 -20
- data/lib/generators/cardboard/install/templates/migrations/1_create_cardboard_fields.rb +0 -21
- data/lib/generators/cardboard/install/templates/migrations/2_create_cardboard_page_parts.rb +0 -17
- data/lib/generators/cardboard/install/templates/migrations/3_create_cardboard_pages.rb +0 -18
- data/lib/generators/cardboard/install/templates/migrations/4_create_cardboard_settings.rb +0 -14
- data/test/dummy/app/views/pages/home.html.slim +0 -3
- data/test/dummy/db/migrate/20130426021522_create_news_posts.rb +0 -10
- data/test/dummy/db/migrate/20130501195423_create_icescreams.rb +0 -10
- data/test/dummy/db/migrate/20130502165540_create_beans.rb +0 -12
- data/test/dummy/db/migrate/20130522151358_create_cardboard_fields.rb +0 -21
- data/test/dummy/db/migrate/20130522151359_create_cardboard_page_parts.rb +0 -17
- data/test/dummy/db/migrate/20130522151400_create_cardboard_pages.rb +0 -18
- data/test/dummy/db/migrate/20130522151401_create_cardboard_settings.rb +0 -14
- data/test/dummy/db/migrate/20130607132558_create_admins.rb +0 -9
- data/vendor/assets/javascripts/cardboard/jquery.pjax.js +0 -840
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 75333a699fb1dccadb5e0e997b8c7a500ba5b9dd
|
4
|
+
data.tar.gz: 055466fb6267926f0b78c134a82598d7aa5b6364
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1e4f0901db574ea6abdfc3a8c3390690741a06e0c4d4aedb3d2c29594267f3e3c031b2942b649d9103bd8ce62f3d91e09fb48040047680bc6345329214ad7bc1
|
7
|
+
data.tar.gz: 6fe7a9005e459619530949535a6bdaf23c021299e4c97b654e83192e5529198db8ba2ad61f93468019702562a730619c4cafb920ec5a141ad47bf708890b5855
|
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
cardboard_cms (0.1
|
4
|
+
cardboard_cms (0.2.1)
|
5
5
|
bootstrap-datepicker-rails
|
6
6
|
bootstrap-sass (~> 2.2)
|
7
7
|
bootstrap-wysihtml5-rails
|
@@ -18,7 +18,6 @@ PATH
|
|
18
18
|
kaminari
|
19
19
|
kaminari-bootstrap (~> 0.1.3)
|
20
20
|
rack-cache
|
21
|
-
rack-pjax
|
22
21
|
rails (~> 4.0.0)
|
23
22
|
ranked-model (>= 0.2.1)
|
24
23
|
ransack (>= 1.0.0)
|
@@ -27,6 +26,7 @@ PATH
|
|
27
26
|
simple_form (>= 3.0.0)
|
28
27
|
slim (>= 1.3.8)
|
29
28
|
stringex
|
29
|
+
turbolinks
|
30
30
|
|
31
31
|
GEM
|
32
32
|
remote: http://rubygems.org/
|
@@ -207,9 +207,6 @@ GEM
|
|
207
207
|
rack (1.5.2)
|
208
208
|
rack-cache (1.2)
|
209
209
|
rack (>= 0.4)
|
210
|
-
rack-pjax (0.7.0)
|
211
|
-
nokogiri (~> 1.5)
|
212
|
-
rack (~> 1.3)
|
213
210
|
rack-test (0.6.2)
|
214
211
|
rack (>= 1.0)
|
215
212
|
rails (4.0.0)
|
@@ -285,6 +282,8 @@ GEM
|
|
285
282
|
treetop (1.4.14)
|
286
283
|
polyglot
|
287
284
|
polyglot (>= 0.3.1)
|
285
|
+
turbolinks (2.2.1)
|
286
|
+
coffee-rails
|
288
287
|
turn (0.9.6)
|
289
288
|
ansi
|
290
289
|
tzinfo (0.3.37)
|
data/README.md
CHANGED
@@ -28,7 +28,7 @@ Add the gem to the `Gemfile`
|
|
28
28
|
gem "cardboard_cms", github: "smashingboxes/cardboard"
|
29
29
|
```
|
30
30
|
|
31
|
-
And run `bundle install`.
|
31
|
+
And run `bundle install`.
|
32
32
|
|
33
33
|
Run the generator to install cardboard and it's migrations:
|
34
34
|
```sh
|
@@ -45,7 +45,7 @@ rake cardboard:seed
|
|
45
45
|
|
46
46
|
## Usage
|
47
47
|
### Get a page
|
48
|
-
Add a file in your `app/views/
|
48
|
+
Add a file in your `app/views/templates` with filename matching the identifier of the page. Inside this file you can access the page with:
|
49
49
|
```ruby
|
50
50
|
current_page
|
51
51
|
```
|
@@ -57,7 +57,7 @@ current_page.get('slideshow')
|
|
57
57
|
### Fetch a repeatable page part
|
58
58
|
Repeatable parts returns an active record collection. This means that regular Rails methods such as `where`, `limit`, `first`, `each`, etc can be used on page parts
|
59
59
|
```slim
|
60
|
-
- current_page.get('slideshow').each do |slide|
|
60
|
+
- current_page.get('slideshow').each do |slide|
|
61
61
|
p= image_tag slide.attr('image1').thumb('600x300').url, alt: slide.attr('description') if slide.attr('image1')
|
62
62
|
```
|
63
63
|
### Fetch a single field
|
@@ -127,7 +127,7 @@ Key | Type | Default | Definition
|
|
127
127
|
---|--- | ---|---
|
128
128
|
[fields](#fields) | hash | nil | list of fields that make this part's form
|
129
129
|
position | integer | auto-increment | position of the part on the admin page
|
130
|
-
repeatable | boolean | false | can the client add multiple of these parts (example a slide in a slideshow)
|
130
|
+
repeatable | boolean | false | can the client add multiple of these parts (example a slide in a slideshow)
|
131
131
|
|
132
132
|
|
133
133
|
####fields
|
@@ -155,10 +155,10 @@ rails g cardboard:resource model_name
|
|
155
155
|
Then customize the `controllers/cardboard/model_name_controller.rb` and associated views to your heart's desire.
|
156
156
|
|
157
157
|
|
158
|
-
The default cardboard resource scaffold help you quickly get started by making the most of the following gems.
|
158
|
+
The default cardboard resource scaffold help you quickly get started by making the most of the following gems.
|
159
159
|
|
160
|
-
Gem | Description
|
161
|
-
--- | ---
|
160
|
+
Gem | Description
|
161
|
+
--- | ---
|
162
162
|
[InheritedResources](https://github.com/josevalim/inherited_resources) | Inherited Resources speeds up development by making your controllers inherit all restful actions so you just have to focus on what is important.
|
163
163
|
[Simple Form](https://github.com/plataformatec/simple_form) | Forms made easy! It's tied to a simple DSL, with no opinion on markup.
|
164
164
|
[Kaminari](https://github.com/amatsuda/kaminari) | A Scope & Engine based, clean, powerful, customizable and sophisticated paginator
|
@@ -179,7 +179,7 @@ You can also choose to remove a resource from the menu
|
|
179
179
|
```ruby
|
180
180
|
default_order "name DESC" # default: 'updated_at desc'
|
181
181
|
```
|
182
|
-
You can pass any `ransack` sort order, which includes associations. Example:
|
182
|
+
You can pass any `ransack` sort order, which includes associations. Example:
|
183
183
|
```ruby
|
184
184
|
default_order "user_name" # belongs to a user
|
185
185
|
```
|
@@ -210,13 +210,13 @@ We use kaminari, so all you need to do is add to your index view:
|
|
210
210
|
|
211
211
|
|
212
212
|
#### Column sorting helper
|
213
|
-
Cardboard's controllers inherit from a `@q` variable which gives access to the ransack gem.
|
213
|
+
Cardboard's controllers inherit from a `@q` variable which gives access to the ransack gem.
|
214
214
|
```
|
215
|
-
= sort_link @q, :name, "Product Name"
|
215
|
+
= sort_link @q, :name, "Product Name"
|
216
216
|
```
|
217
217
|
|
218
218
|
#### Custom resource helpers
|
219
|
-
To add custom helpers for your resource simply create a helper with the same name.
|
219
|
+
To add custom helpers for your resource simply create a helper with the same name.
|
220
220
|
Example:
|
221
221
|
```ruby
|
222
222
|
module Cardboard
|
@@ -232,7 +232,7 @@ The css/js for the resources is the same as the cardboard admin interface. If yo
|
|
232
232
|
Note: Make sure to remove `*= require_tree .` from your application.css, you don't want your cardboard css and js to leak into your main app!
|
233
233
|
|
234
234
|
## Create Settings
|
235
|
-
You can create new settings that will be editable from the admin panel.
|
235
|
+
You can create new settings that will be editable from the admin panel.
|
236
236
|
|
237
237
|
In your `config/cardboard.yml`
|
238
238
|
|
@@ -269,7 +269,7 @@ PagesController.class_eval do
|
|
269
269
|
@example = "cool"
|
270
270
|
end
|
271
271
|
end
|
272
|
-
```
|
272
|
+
```
|
273
273
|
### Page Path
|
274
274
|
In your controllers you may want to redirect to a specific page. You can do so with the following:
|
275
275
|
```ruby
|
@@ -315,7 +315,7 @@ Use the page identifier defined in the cardboard.yml file (or see yoda)
|
|
315
315
|
= link_to_page "page_identifier", class: "btn" do |page|
|
316
316
|
"hello #{page.title}"
|
317
317
|
end
|
318
|
-
|
318
|
+
|
319
319
|
# or, to simply use the page title
|
320
320
|
|
321
321
|
= link_to_page "page_identifier", class: "btn"
|
@@ -5,7 +5,7 @@
|
|
5
5
|
//= require jquery_ujs
|
6
6
|
//= require jquery.ui.sortable
|
7
7
|
//= require cardboard/jquery.livesearch
|
8
|
-
//= require
|
8
|
+
//= require turbolinks
|
9
9
|
//= require bootstrap-button
|
10
10
|
//= require bootstrap-dropdown
|
11
11
|
//= require bootstrap-modal
|
@@ -21,42 +21,21 @@
|
|
21
21
|
//= require cardboard/content_sidebar
|
22
22
|
//= require cardboard/search_filter
|
23
23
|
//= require select2
|
24
|
-
|
25
24
|
// require cardboard/jquery.wysihtml5imgresizer
|
26
25
|
|
27
26
|
|
28
|
-
$(document).pjax('a:not([data-remote]):not([data-behavior]):not([data-skip-pjax]):not([href="#"]):not([href=""]):not([data-method])', '[data-pjax-container]');
|
29
|
-
|
30
|
-
$(document).on('submit', 'form[data-pjax]', function(event) {
|
31
|
-
$.pjax.submit(event, '[data-pjax-container]');
|
32
|
-
});
|
33
|
-
|
34
27
|
$(document).on('click', '.nav-tabs a', function(e){
|
35
28
|
e.preventDefault();
|
36
29
|
$(this).tab('show');
|
37
30
|
});
|
38
31
|
|
39
|
-
$(document).on("
|
32
|
+
$(document).on("page:load ready cocoon:after-insert", function(e){
|
40
33
|
|
41
34
|
$('select:not([data-search-select])').selectpicker();
|
42
35
|
$('select[data-search-select]').select2({allowClear: true, width: "resolve"});
|
43
36
|
|
44
37
|
$('.nav-tabs a:first').tab('show');
|
45
|
-
});
|
46
|
-
|
47
|
-
$(function(){
|
48
|
-
$('.page_link .link_wrap a').click(function(){
|
49
|
-
$('.nav_resource_link.active').removeClass('active');
|
50
|
-
$('#nav_dashboard_link').addClass('active');
|
51
|
-
});
|
52
|
-
|
53
|
-
$('.nav_resource_link').click(function(){
|
54
|
-
$('.nav_resource_link.active, #nav_dashboard_link').removeClass('active');
|
55
|
-
$(this).addClass('active');
|
56
|
-
$("#content_sidebar").removeClass('toggle');
|
57
|
-
$('#content').removeClass('toggle');
|
58
|
-
});
|
59
38
|
|
60
39
|
window.setTimeout(function() { $(".alert:not(.alert-error)").alert('close'); }, 2000);
|
61
|
-
})
|
40
|
+
});
|
62
41
|
|
@@ -10,10 +10,6 @@ var create_datepickers = function(){
|
|
10
10
|
}
|
11
11
|
|
12
12
|
|
13
|
-
$(document).on("ready
|
13
|
+
$(document).on("ready page:load cocoon:after-insert", function () {
|
14
14
|
create_datepickers();
|
15
|
-
|
16
|
-
$(document).on('cocoon:after-insert', function(e, insertedItem) {
|
17
|
-
create_datepickers();
|
18
|
-
});
|
19
15
|
});
|
@@ -55,7 +55,7 @@ var rich_text_editor_defaults = {
|
|
55
55
|
useLineBreaks: false
|
56
56
|
}
|
57
57
|
|
58
|
-
$(document).on("ready
|
58
|
+
$(document).on("ready page:load", function(e){
|
59
59
|
if($(".wysihtml5").length) {
|
60
60
|
$('.wysihtml5').wysihtml5(rich_text_editor_defaults);
|
61
61
|
$('iframe.wysihtml5-sandbox').wysihtml5_size_matters();
|
@@ -1,13 +1,31 @@
|
|
1
1
|
require_dependency "cardboard/application_controller"
|
2
|
+
require_dependency Cardboard::Engine.root.join('lib/cardboard/helpers/seed.rb').to_s
|
2
3
|
|
3
4
|
module Cardboard
|
4
5
|
class PagesController < ApplicationController
|
5
6
|
before_filter :check_ability
|
6
7
|
|
8
|
+
def new
|
9
|
+
@page = Cardboard::Page.new
|
10
|
+
end
|
11
|
+
|
7
12
|
def edit
|
8
13
|
@page = Cardboard::Page.find(params[:id])
|
9
14
|
end
|
10
15
|
|
16
|
+
def create
|
17
|
+
@page = Cardboard::Page.new(params.require(:page).permit(:title, :template_id))
|
18
|
+
@page.identifier = @page.title.to_url.underscore if @page.identifier.blank?
|
19
|
+
if @page.save
|
20
|
+
Cardboard::Seed.populate_parts(@page.template.fields, @page)
|
21
|
+
@page.reload
|
22
|
+
redirect_to edit_page_path(@page)
|
23
|
+
else
|
24
|
+
@page.errors.add(:title, "is reserved or is already used") if @page.errors[:identifier].present?
|
25
|
+
render :new
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
11
29
|
def update
|
12
30
|
@page = Cardboard::Page.find(params[:id])
|
13
31
|
|
@@ -20,10 +38,16 @@ module Cardboard
|
|
20
38
|
end
|
21
39
|
|
22
40
|
def sort
|
23
|
-
Page.find(params[:id]).update_attribute(:position_position, params[:index])
|
41
|
+
Cardboard::Page.find(params[:id]).update_attribute(:position_position, params[:index])
|
24
42
|
render nothing: true
|
25
43
|
end
|
26
44
|
|
45
|
+
def destroy
|
46
|
+
@page = Cardboard::Page.find(params[:id])
|
47
|
+
@page.destroy
|
48
|
+
redirect_to pages_path
|
49
|
+
end
|
50
|
+
|
27
51
|
private
|
28
52
|
def check_ability
|
29
53
|
unless cardboard_user_can_manage?(:pages)
|
@@ -1,15 +1,17 @@
|
|
1
1
|
class PagesController < ApplicationController
|
2
2
|
def show
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
if current_page.using_slug_backup?
|
7
|
-
redirect_to current_page.url, status: :moved_permanently
|
3
|
+
if current_page.nil?
|
4
|
+
flash[:error] = "No root page! Make sure to add a page first"
|
5
|
+
redirect_to cardboard.dashboard_path
|
8
6
|
else
|
9
|
-
|
10
|
-
|
7
|
+
if current_page.using_slug_backup?
|
8
|
+
redirect_to current_page.url, status: :moved_permanently
|
9
|
+
else
|
10
|
+
# call controller hook
|
11
|
+
self.send(current_page.identifier) if self.respond_to? current_page.identifier
|
11
12
|
|
12
|
-
|
13
|
+
render "cardboard/pages/show", layout: @layout || "layouts/application"
|
14
|
+
end
|
13
15
|
end
|
14
16
|
end
|
15
17
|
|
@@ -21,9 +23,8 @@ private
|
|
21
23
|
# helper_method :edit_link
|
22
24
|
|
23
25
|
def current_page
|
24
|
-
@page ||= Cardboard::Page.find_by_url(params[:id]) ||
|
25
|
-
|
26
|
-
raise(ActionController::RoutingError.new("No root page, make sure to run `rake cardboard:seed`"))
|
26
|
+
@page ||= Cardboard::Page.find_by_url(params[:id]) || Cardboard::Page.root
|
27
|
+
# || raise(ActionController::RoutingError.new("No root page, make sure to run `rake cardboard:seed`"))
|
27
28
|
end
|
28
29
|
|
29
30
|
end
|
@@ -63,7 +63,7 @@ module Cardboard
|
|
63
63
|
end
|
64
64
|
end
|
65
65
|
|
66
|
-
render "cardboard/resources/search_helper", klass: klass.to_s
|
66
|
+
render "cardboard/resources/search_helper", klass: klass.to_s, options: options, main_element: main_element #,elements: elements
|
67
67
|
end
|
68
68
|
|
69
69
|
|
@@ -6,27 +6,33 @@ module Cardboard
|
|
6
6
|
belongs_to :object_with_field, :polymorphic => true, :inverse_of => :fields
|
7
7
|
|
8
8
|
#gem
|
9
|
-
include RankedModel
|
10
|
-
ranks :position, :with_same => [:object_with_field_id, :object_with_field_type], :class_name => 'Cardboard::Field'
|
11
9
|
|
12
10
|
#validations
|
13
|
-
validates :identifier, :type, presence:true
|
11
|
+
validates :identifier, :type, :object_with_field, presence:true
|
14
12
|
validates :identifier, uniqueness: {:case_sensitive => false, :scope => [:object_with_field_id, :object_with_field_type]},
|
15
13
|
:format => { :with => /\A[a-z\_0-9]+\z/,
|
16
|
-
:message => "Only
|
14
|
+
:message => "Only lowercase letters, numbers and underscores are allowed" }
|
17
15
|
|
18
|
-
default_scope {rank(:position)}
|
19
16
|
|
20
17
|
class << self
|
21
18
|
# Allow "type" to be passed in nested forms
|
22
|
-
def
|
19
|
+
def new_with_castnew(*attributes, &block)
|
23
20
|
if (h = attributes.first).is_a?(Hash) && !h.nil? && (type = h.delete(:type) || h.delete('type')) && type.present? && (klass = type.constantize) != self
|
24
21
|
raise "Field type #{type} does not inherit from Cardboard::Field" unless klass <= self
|
25
22
|
return klass.new(*attributes, &block)
|
26
23
|
end
|
27
|
-
|
24
|
+
new_without_castnew(*attributes, &block)
|
28
25
|
end
|
29
|
-
alias_method_chain :new, :
|
26
|
+
alias_method_chain :new, :castnew
|
27
|
+
|
28
|
+
# def build_with_castbuild(*attributes, &block)
|
29
|
+
# if (h = attributes.first).is_a?(Hash) && !h.nil? && (type = h.delete(:type) || h.delete('type')) && type.present? && (klass = type.constantize) != self
|
30
|
+
# raise "Field type #{type} does not inherit from Cardboard::Field" unless klass <= self
|
31
|
+
# return klass.build(*attributes, &block)
|
32
|
+
# end
|
33
|
+
# new_without_castbuild(*attributes, &block)
|
34
|
+
# end
|
35
|
+
# alias_method_chain :build, :castbuild
|
30
36
|
end
|
31
37
|
|
32
38
|
# overwritten setter
|
@@ -53,6 +59,12 @@ module Cardboard
|
|
53
59
|
end
|
54
60
|
end
|
55
61
|
|
62
|
+
def required?
|
63
|
+
required = self.object_with_field.template[self.identifier.to_sym][:required]
|
64
|
+
required = true if required.nil?
|
65
|
+
required
|
66
|
+
end
|
67
|
+
|
56
68
|
private
|
57
69
|
|
58
70
|
def is_required
|
@@ -60,7 +72,7 @@ module Cardboard
|
|
60
72
|
end
|
61
73
|
|
62
74
|
def required_field?
|
63
|
-
self.required?
|
75
|
+
!self.seeding && required?
|
64
76
|
end
|
65
77
|
|
66
78
|
end
|
@@ -1,10 +1,15 @@
|
|
1
1
|
module Cardboard
|
2
2
|
class Page < ActiveRecord::Base
|
3
|
+
|
3
4
|
has_many :parts, class_name: "Cardboard::PagePart", :dependent => :destroy, :validate => true
|
5
|
+
|
6
|
+
belongs_to :template, class_name: "Cardboard::Template"
|
4
7
|
|
5
8
|
attr_accessor :parent_url, :is_root
|
6
9
|
|
7
10
|
accepts_nested_attributes_for :parts, allow_destroy: true, :reject_if => :all_blank
|
11
|
+
# TODO: allow destroy and allow all blank only if repeatable
|
12
|
+
|
8
13
|
serialize :meta_seo, Hash
|
9
14
|
serialize :slugs_backup, Array
|
10
15
|
|
@@ -18,16 +23,16 @@ module Cardboard
|
|
18
23
|
ranks :position, :with_same => :path
|
19
24
|
|
20
25
|
#validations
|
21
|
-
|
26
|
+
# validates_associated :parts
|
27
|
+
validates :title, :path, :template, presence:true
|
22
28
|
validates :slug, uniqueness: { :case_sensitive => false, :scope => :path }, presence: true
|
23
29
|
validates :identifier, uniqueness: {:case_sensitive => false}, :format => { :with => /\A[a-z\_0-9]+\z/,
|
24
|
-
|
30
|
+
:message => "Only downcase letters, numbers and underscores are allowed" }, presence: true
|
25
31
|
#validate all seo keys are valid meta keys + title
|
26
32
|
|
27
|
-
# validates_associated :parts, on: :update #breaks seed, should work
|
28
|
-
|
29
33
|
#scopes
|
30
|
-
scope :preordered, -> {order("path ASC, position ASC, slug ASC")}
|
34
|
+
scope :preordered, -> {order("path ASC, position ASC, slug ASC")}
|
35
|
+
|
31
36
|
|
32
37
|
#class variables
|
33
38
|
after_commit do
|
@@ -80,6 +85,10 @@ module Cardboard
|
|
80
85
|
|
81
86
|
#instance methods
|
82
87
|
|
88
|
+
def template_hash
|
89
|
+
@template_hash ||= self.template.fields
|
90
|
+
end
|
91
|
+
|
83
92
|
# @page.get("slideshow.image1")
|
84
93
|
# @page.get("slideshow").first.image1
|
85
94
|
# @page.get("slideshow").each...
|
@@ -90,38 +99,18 @@ module Cardboard
|
|
90
99
|
# slideshow.get("slide1")
|
91
100
|
def get(field)
|
92
101
|
f = field.split(".")
|
93
|
-
|
94
|
-
return nil unless parent_part
|
102
|
+
parts = self.parts.where(identifier: f.first)
|
95
103
|
|
96
|
-
|
97
|
-
if parent_part.repeatable?
|
104
|
+
if template_hash[f.first.to_sym][:repeatable]
|
98
105
|
raise "Part is repeatable, expected each loop" unless f.size == 1
|
99
|
-
|
106
|
+
parts
|
100
107
|
else
|
108
|
+
part = parts.first
|
101
109
|
return nil unless part
|
102
|
-
f.size == 1 ? part
|
110
|
+
f.size == 1 ? part : part.attr(f.last)
|
103
111
|
end
|
104
112
|
end
|
105
113
|
|
106
|
-
# def page_hash
|
107
|
-
# return {} if self.parts.blank?
|
108
|
-
# self.parts.rank(:part_position).inject(ActiveSupport::OrderedHash.new) do |part_hash, part|
|
109
|
-
# part_hash[part.identifier] = if part.repeatable?
|
110
|
-
# part.subparts.rank(:subpart_position).inject([]) do |sub_array, subpart|
|
111
|
-
# sub_array << subpart.fields.rank(:position).inject(ActiveSupport::OrderedHash.new) do |fields_hash, field|
|
112
|
-
# fields_hash[field.identifier] = subpart.attr(field.identifier)
|
113
|
-
# fields_hash
|
114
|
-
# end
|
115
|
-
# end
|
116
|
-
# else
|
117
|
-
# get(part.identifier).fields.rank(:position).inject(ActiveSupport::OrderedHash.new) do |fields_hash, field|
|
118
|
-
# fields_hash[field.identifier] = part.attr(field.identifier)
|
119
|
-
# fields_hash
|
120
|
-
# end
|
121
|
-
# end
|
122
|
-
# part_hash
|
123
|
-
# end
|
124
|
-
# end
|
125
114
|
|
126
115
|
# SEO
|
127
116
|
# children inherit their parent's SEO settings (these can be overwritten)
|
@@ -1,54 +1,32 @@
|
|
1
1
|
module Cardboard
|
2
2
|
class PagePart < ActiveRecord::Base
|
3
3
|
has_many :fields, :as => :object_with_field, class_name: "Cardboard::Field", :dependent => :destroy, :inverse_of => :object_with_field
|
4
|
-
has_many :subparts, class_name: "Cardboard::PagePart", :dependent => :destroy, :foreign_key => "parent_part_id", :inverse_of => :parent
|
5
4
|
|
6
|
-
belongs_to :parent, class_name: "Cardboard::PagePart", :foreign_key => "parent_part_id", :inverse_of => :subparts
|
7
5
|
belongs_to :page
|
8
6
|
|
9
|
-
accepts_nested_attributes_for :subparts, :allow_destroy => true #, :reject_if => :all_blank
|
10
7
|
accepts_nested_attributes_for :fields #, :allow_destroy => true (maybe for super admin?)
|
11
8
|
|
12
|
-
validates :identifier, uniqueness: {:case_sensitive => false, :scope => :page_id},
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
# validates :subparts, presence:true, unless: -> {new_record? || subpart?}
|
17
|
-
validate :at_least_one_subpart
|
18
|
-
|
19
|
-
# Scopes
|
20
|
-
scope :is_subparts, ->{ where("parent_part_id IS NOT NULL")}
|
21
|
-
scope :is_parent, ->{where("parent_part_id IS NULL")}
|
9
|
+
validates :identifier, :format => {:with => /\A[a-z\_0-9]+\z/, :message => "Only downcase letters, numbers and underscores are allowed"} # uniqueness: {:case_sensitive => false, :scope => :page_id},
|
10
|
+
validates :page, :identifier, presence: true
|
11
|
+
# validates_associated :fields
|
12
|
+
|
22
13
|
|
23
14
|
#gem
|
24
15
|
include RankedModel
|
25
|
-
ranks :
|
26
|
-
ranks :part_position, :with_same => :page_id, :column => :position, :scope => :is_parent
|
16
|
+
ranks :part_position, :with_same => :page_id, :column => :position
|
27
17
|
default_scope {order("position ASC")}
|
28
18
|
|
29
19
|
|
30
|
-
def
|
31
|
-
|
20
|
+
def repeatable?
|
21
|
+
template_hash[:repeatable]
|
32
22
|
end
|
33
23
|
|
34
|
-
def
|
35
|
-
|
24
|
+
def template_hash
|
25
|
+
@template ||= self.page.template.fields[self.identifier.to_sym]
|
36
26
|
end
|
37
27
|
|
38
|
-
def
|
39
|
-
|
40
|
-
master = self.subparts.first
|
41
|
-
master_hash = master.attributes.select do |key, value|
|
42
|
-
["parent_part_id"].include? key
|
43
|
-
end
|
44
|
-
subpart = Cardboard::PagePart.new(master_hash)
|
45
|
-
for field in master.fields
|
46
|
-
field_hash = field.attributes.select do |key, value|
|
47
|
-
["identifier", "label", "type", "required", "hint", "placeholder"].include? key
|
48
|
-
end
|
49
|
-
subpart.fields << Cardboard::Field.new(field_hash)
|
50
|
-
end
|
51
|
-
return subpart
|
28
|
+
def template
|
29
|
+
template_hash[:fields]
|
52
30
|
end
|
53
31
|
|
54
32
|
def attr(field)
|
@@ -63,17 +41,6 @@ module Cardboard
|
|
63
41
|
end
|
64
42
|
end
|
65
43
|
|
66
|
-
|
67
|
-
|
68
|
-
def at_least_one_subpart
|
69
|
-
return true if subpart? || new_record?
|
70
|
-
# require a minimum of one task
|
71
|
-
undestroyed_part_count = 0
|
72
|
-
|
73
|
-
subparts.each { |t| undestroyed_part_count += 1 unless t.marked_for_destruction? }
|
74
|
-
if undestroyed_part_count < 1
|
75
|
-
errors.add(:base, 'There must be at least one')
|
76
|
-
end
|
77
|
-
end
|
44
|
+
|
78
45
|
end
|
79
|
-
end
|
46
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module Cardboard
|
2
|
+
class Template < ActiveRecord::Base
|
3
|
+
|
4
|
+
serialize :fields, Hash
|
5
|
+
|
6
|
+
has_many :pages
|
7
|
+
|
8
|
+
validates :identifier, uniqueness: {:case_sensitive => false}, :format => { :with => /\A[a-z\_0-9]+\z/,
|
9
|
+
:message => "Only downcase letters, numbers and underscores are allowed" }
|
10
|
+
|
11
|
+
def name
|
12
|
+
self[:name] || self.identifier
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -1 +1 @@
|
|
1
|
-
= f.input :value, label:
|
1
|
+
= f.input :value, label: field[:label] || identifier.titleize, as: field[:type], hint: field[:hint], placeholder: field[:placeholder], required: field[:required] != false
|
@@ -1,4 +1,4 @@
|
|
1
1
|
- label = ""
|
2
2
|
/ - label += '<abbr title="required">*</abbr> ' if f.object.required
|
3
|
-
- label +=
|
4
|
-
= f.input :value, inline_label: label.html_safe, as:
|
3
|
+
- label += field[:label] || identifier.titleize
|
4
|
+
= f.input :value, inline_label: label.html_safe, as: field[:type], hint: field[:hint], placeholder: field[:placeholder], required: field[:required] != false, label: false
|