constructor-pages 0.6.1 → 0.6.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/app/controllers/constructor_pages/pages_controller.rb +11 -6
- data/app/controllers/constructor_pages/templates_controller.rb +2 -1
- data/app/helpers/constructor_pages/move_helper.rb +2 -2
- data/app/helpers/constructor_pages/pages_helper.rb +2 -0
- data/app/helpers/constructor_pages/templates_helper.rb +2 -0
- data/app/helpers/constructor_pages/treeview_helper.rb +33 -0
- data/app/models/constructor_pages/page.rb +4 -2
- data/app/views/constructor_pages/fields/_form.haml +10 -10
- data/app/views/constructor_pages/fields/types/_html.haml +1 -1
- data/app/views/constructor_pages/fields/types/_image.haml +1 -1
- data/app/views/constructor_pages/fields/types/_integer.haml +1 -1
- data/app/views/constructor_pages/fields/types/_string.haml +1 -1
- data/app/views/constructor_pages/fields/types/_text.haml +1 -1
- data/app/views/constructor_pages/pages/_breadcrumbs.haml +2 -2
- data/app/views/constructor_pages/pages/_form.haml +30 -30
- data/app/views/constructor_pages/pages/index.haml +35 -45
- data/app/views/constructor_pages/partials/_arrow_buttons.haml +6 -0
- data/app/views/constructor_pages/templates/_form.haml +23 -18
- data/app/views/constructor_pages/templates/index.haml +11 -30
- data/config/locales/en.yml +1 -0
- data/config/locales/ru.yml +1 -0
- data/config/routes.rb +16 -21
- data/spec/features/constructor_pages/pages_controller_spec.rb +280 -0
- data/spec/models/constructor_pages/field_model_spec.rb +12 -16
- data/spec/models/constructor_pages/page_model_spec.rb +2 -1
- data/spec/models/constructor_pages/template_model_spec.rb +1 -1
- metadata +8 -6
- data/spec/requests/constructor_pages/pages_controller_spec.rb +0 -12
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: fe557ed858d29dafe8d2604a3041d4d72b362ab1
|
4
|
+
data.tar.gz: 417ab41ff118cafbabaac37ba4759de5d263a862
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c44421fa1db38795a17b89dda405d54bbea75366510b319940e1740178fbe7497d5d285876ae3575e718e5900cabaa6f973ed4bfe4920a810aae779cb56dbed4
|
7
|
+
data.tar.gz: 3b463ce126e2b123d6e41bad1bbad7b84dd95e68884bf05fbd06b4853c77112ebd9f43f13c0bd3748aa5543037e31888f4f27caf787e2bae719161d71921c8b8
|
@@ -6,6 +6,11 @@ module ConstructorPages
|
|
6
6
|
|
7
7
|
before_filter {@roots = Page.roots}
|
8
8
|
|
9
|
+
def index
|
10
|
+
@template_exists = Template.count > 0
|
11
|
+
flash.notice = 'Create at least one template' unless @template_exists
|
12
|
+
end
|
13
|
+
|
9
14
|
def new
|
10
15
|
@page, @template_id, @multipart = Page.new, Template.first.id, false
|
11
16
|
|
@@ -15,7 +20,7 @@ module ConstructorPages
|
|
15
20
|
end
|
16
21
|
|
17
22
|
def show
|
18
|
-
@page = Page.find_by_request_or_first(
|
23
|
+
@page = Page.find_by_request_or_first("/#{params[:all]}")
|
19
24
|
|
20
25
|
error_404 and return if @page.nil? or !@page.active?
|
21
26
|
|
@@ -102,12 +107,12 @@ module ConstructorPages
|
|
102
107
|
def update
|
103
108
|
@page = Page.find params[:id]
|
104
109
|
|
105
|
-
|
106
|
-
|
107
|
-
|
110
|
+
_template_changed = @page.template.id != params[:page][:template_id].to_i
|
111
|
+
|
112
|
+
@page.remove_fields_values if _template_changed
|
108
113
|
|
109
114
|
if @page.update page_params
|
110
|
-
@page.create_fields_values
|
115
|
+
@page.create_fields_values if _template_changed
|
111
116
|
@page.update_fields_values params[:fields]
|
112
117
|
|
113
118
|
redirect_to pages_url, notice: t(:page_success_updated, name: @page.name)
|
@@ -123,7 +128,7 @@ module ConstructorPages
|
|
123
128
|
redirect_to pages_url, notice: t(:page_success_removed, name: _name)
|
124
129
|
end
|
125
130
|
|
126
|
-
%w{up down}.each {|m| define_method "move_#{m}" do move_to :page, m.to_sym end}
|
131
|
+
%w{up down}.each {|m| define_method "move_#{m}" do move_to :page, params[:id], m.to_sym end}
|
127
132
|
|
128
133
|
private
|
129
134
|
|
@@ -3,6 +3,7 @@
|
|
3
3
|
module ConstructorPages
|
4
4
|
class TemplatesController < ConstructorCore::ApplicationController
|
5
5
|
include MoveHelper
|
6
|
+
include TreeviewHelper
|
6
7
|
|
7
8
|
before_filter {@roots = Template.roots}
|
8
9
|
|
@@ -41,7 +42,7 @@ module ConstructorPages
|
|
41
42
|
redirect_to templates_url, notice: t(:template_success_removed, name: name)
|
42
43
|
end
|
43
44
|
|
44
|
-
%w{up down}.each {|m| define_method "move_#{m}" do move_to :template, m.to_sym end}
|
45
|
+
%w{up down}.each {|m| define_method "move_#{m}" do move_to :template, params[:id], m.to_sym end}
|
45
46
|
|
46
47
|
private
|
47
48
|
|
@@ -1,7 +1,7 @@
|
|
1
1
|
module ConstructorPages
|
2
2
|
module MoveHelper
|
3
|
-
def move_to(what, to)
|
4
|
-
from = ('constructor_pages/'+what.to_s).classify.constantize.find(
|
3
|
+
def move_to(what, id, to)
|
4
|
+
from = ('constructor_pages/'+what.to_s).classify.constantize.find(id)
|
5
5
|
to_sibling = to == :up ? from.left_sibling : from.right_sibling
|
6
6
|
|
7
7
|
if not to_sibling.nil? and from.move_possible?(to_sibling)
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module ConstructorPages
|
2
|
+
module TreeviewHelper
|
3
|
+
def render_tree(roots, &block)
|
4
|
+
output = '<ul>'
|
5
|
+
|
6
|
+
roots.each do |root|
|
7
|
+
level, last = root.level, nil
|
8
|
+
|
9
|
+
root.self_and_descendants.each do |item|
|
10
|
+
if item.level > level
|
11
|
+
output += '<ul>'
|
12
|
+
elsif item.level < level
|
13
|
+
output += '</li>'
|
14
|
+
output += '</ul></li>' * (level-item.level)
|
15
|
+
elsif !item.root?
|
16
|
+
output += '</li>'
|
17
|
+
end
|
18
|
+
|
19
|
+
output += '<li>'
|
20
|
+
|
21
|
+
output += capture(item, &block)
|
22
|
+
|
23
|
+
level, last = item.level, item
|
24
|
+
end
|
25
|
+
|
26
|
+
output += '</li>'
|
27
|
+
output += '</ul></li>' * last.level
|
28
|
+
end
|
29
|
+
|
30
|
+
output.html_safe
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -24,10 +24,10 @@ module ConstructorPages
|
|
24
24
|
|
25
25
|
acts_as_nested_set
|
26
26
|
|
27
|
-
# Used for find page by request. It return first page if no request given
|
27
|
+
# Used for find page by request. It return first page if no request given or request is home page
|
28
28
|
# @param request for example <tt>'/conditioners/split-systems/zanussi'</tt>
|
29
29
|
def self.find_by_request_or_first(request = nil)
|
30
|
-
request.nil? ? Page.first : Page.where(full_url: request).first
|
30
|
+
request.nil? || request == '/' ? Page.first : Page.where(full_url: request).first
|
31
31
|
end
|
32
32
|
|
33
33
|
# Generate full_url from parent id and url
|
@@ -72,6 +72,8 @@ module ConstructorPages
|
|
72
72
|
# @param params should looks like <tt>{price: 500, content: 'Hello'}</tt>
|
73
73
|
# @param reset_booleans reset all boolean fields to false before assign params
|
74
74
|
def update_fields_values(params, reset_booleans = true)
|
75
|
+
return if params.nil?
|
76
|
+
|
75
77
|
fields.each do |field|
|
76
78
|
value = params[field.code_name.to_sym]
|
77
79
|
|
@@ -1,28 +1,28 @@
|
|
1
1
|
= form_for @field do |f|
|
2
2
|
- if @field.errors.any?
|
3
3
|
.alert.alert-error.fade.in.span12
|
4
|
-
= link_to
|
4
|
+
= link_to '×', '#', class: 'close', 'data-dismiss' => 'alert'
|
5
5
|
- @field.errors.full_messages.each do |m|
|
6
6
|
= m
|
7
7
|
|
8
8
|
.form-horizontal
|
9
9
|
.control-group
|
10
|
-
= f.label :name, :
|
11
|
-
.controls= f.text_field :name, :
|
10
|
+
= f.label :name, class: 'control-label'
|
11
|
+
.controls= f.text_field :name, class: 'span4'
|
12
12
|
|
13
13
|
.control-group
|
14
|
-
= f.label :code_name, :
|
15
|
-
.controls= f.text_field :code_name, :
|
16
|
-
= f.hidden_field :template_id, :
|
14
|
+
= f.label :code_name, class: 'control-label'
|
15
|
+
.controls= f.text_field :code_name, class: 'span4'
|
16
|
+
= f.hidden_field :template_id, value: @field.template.id, class: 'span4'
|
17
17
|
|
18
18
|
- unless @field.type_value == 'image'
|
19
19
|
.control-group
|
20
|
-
= f.label :type_value, :
|
20
|
+
= f.label :type_value, class: 'control-label'
|
21
21
|
.controls
|
22
|
-
= f.select :type_value, options_for_select(types_value, :
|
22
|
+
= f.select :type_value, options_for_select(types_value, selected: @field.type_value), class: 'span4'
|
23
23
|
|
24
24
|
.row-fluid
|
25
25
|
.span12
|
26
26
|
.form-actions
|
27
|
-
= f.submit :
|
28
|
-
= link_to t(:cancel), edit_template_url(@field.template), :
|
27
|
+
= f.submit class: 'btn btn-primary'
|
28
|
+
= link_to t(:cancel), edit_template_url(@field.template), class: 'btn'
|
@@ -1 +1 @@
|
|
1
|
-
= text_area_tag "fields[#{field.code_name}]", page.get_field_value(field.code_name), :
|
1
|
+
= text_area_tag "fields[#{field.code_name}]", page.get_field_value(field.code_name), rows: 10, class: 'span9 ckeditor'
|
@@ -1 +1 @@
|
|
1
|
-
= text_field_tag "fields[#{field.code_name}]", page.get_field_value(field.code_name), :
|
1
|
+
= text_field_tag "fields[#{field.code_name}]", page.get_field_value(field.code_name), class: 'span2'
|
@@ -1 +1 @@
|
|
1
|
-
= text_field_tag "fields[#{field.code_name}]", page.get_field_value(field.code_name), :
|
1
|
+
= text_field_tag "fields[#{field.code_name}]", page.get_field_value(field.code_name), class: 'span6'
|
@@ -1 +1 @@
|
|
1
|
-
= text_area_tag "fields[#{field.code_name}]", page.get_field_value(field.code_name), :
|
1
|
+
= text_area_tag "fields[#{field.code_name}]", page.get_field_value(field.code_name), rows: 10, class: 'span6'
|
@@ -1,97 +1,97 @@
|
|
1
|
-
= form_for @page, :
|
1
|
+
= form_for @page, html: {multipart: @multipart} do |f|
|
2
2
|
- if @page.errors.any?
|
3
3
|
.alert.alert-error.fade.in.span12
|
4
|
-
= link_to
|
4
|
+
= link_to '×', '#', class: 'close', 'data-dismiss' => 'alert'
|
5
5
|
- @page.errors.full_messages.each do |m|
|
6
6
|
= m
|
7
7
|
|
8
8
|
.form-horizontal
|
9
9
|
.control-group
|
10
|
-
= f.label :active, :
|
11
|
-
.controls= f.check_box :active, :
|
10
|
+
= f.label :active, class: 'control-label'
|
11
|
+
.controls= f.check_box :active, class: 'span6'
|
12
12
|
|
13
13
|
.control-group
|
14
|
-
= f.label :name, :
|
15
|
-
.controls= f.text_field :name, :
|
14
|
+
= f.label :name, class: 'control-label'
|
15
|
+
.controls= f.text_field :name, class: 'span4'
|
16
16
|
|
17
17
|
.control-group.auto_url
|
18
|
-
= f.label :auto_url, :
|
18
|
+
= f.label :auto_url, class: 'control-label'
|
19
19
|
.controls
|
20
|
-
= f.check_box :auto_url, :
|
20
|
+
= f.check_box :auto_url, class: 'span9'
|
21
21
|
|
22
22
|
.control-group.url
|
23
|
-
= f.label :url, :
|
23
|
+
= f.label :url, class: 'control-label'
|
24
24
|
.controls
|
25
25
|
.full_url
|
26
26
|
%span.path>= @page.parent.full_url unless @page.parent.nil?
|
27
27
|
\/
|
28
28
|
%span.address>= @page.url
|
29
|
-
= f.text_field :url, :
|
29
|
+
= f.text_field :url, class: 'span3'
|
30
30
|
%i.address_icon.icon-pencil
|
31
31
|
|
32
32
|
- unless @page.new_record?
|
33
33
|
- @page.template.fields.each do |field|
|
34
34
|
.control-group
|
35
|
-
= label_tag "", field.name, :
|
35
|
+
= label_tag "fields[#{field.code_name}]", field.name, class: 'control-label'
|
36
36
|
.controls
|
37
|
-
= render :partial => "constructor_pages/fields/types/#{field.type_value}", :
|
37
|
+
= render :partial => "constructor_pages/fields/types/#{field.type_value}", locals: {field: field, page: @page}
|
38
38
|
|
39
39
|
.accordion
|
40
40
|
.accordion-group
|
41
41
|
.accordion-heading.text-center
|
42
|
-
= link_to t(:settings), '#collapse', :
|
42
|
+
= link_to t(:settings), '#collapse', class: 'accordion-toggle', 'data-toggle' => 'collapse'
|
43
43
|
.accordion-body.in.collapse#collapse
|
44
44
|
.accordion-inner
|
45
45
|
.control-group
|
46
|
-
= f.label :
|
46
|
+
= f.label :parent_id, class: 'control-label'
|
47
47
|
.controls
|
48
|
-
= f.select :parent_id, options_for_select(for_select(@roots), :
|
48
|
+
= f.select :parent_id, options_for_select(for_select(@roots), selected: @page.parent_id), disabled: @page.self_and_descendants.map(&:id), include_blank: t(:no)
|
49
49
|
|
50
50
|
.control-group
|
51
|
-
= f.label :
|
51
|
+
= f.label :template_id, :class => 'control-label'
|
52
52
|
.controls
|
53
|
-
= f.select :template_id,
|
53
|
+
= f.select :template_id, options_for_select(templates, selected: @template_id)
|
54
54
|
.control-group
|
55
|
-
= f.label :link, :
|
55
|
+
= f.label :link, class: 'control-label'
|
56
56
|
.controls
|
57
|
-
= f.text_field :link, :
|
57
|
+
= f.text_field :link, class: 'span9'
|
58
58
|
.control-group
|
59
59
|
%label.control-label=t :display_in
|
60
60
|
.controls
|
61
|
-
%label.checkbox.inline.span2{:
|
61
|
+
%label.checkbox.inline.span2{for: 'in_menu'}
|
62
62
|
= f.check_box :in_menu
|
63
63
|
=t :menu
|
64
64
|
|
65
|
-
%label.checkbox.inline.span2{:
|
65
|
+
%label.checkbox.inline.span2{for: 'in_map'}
|
66
66
|
= f.check_box :in_map
|
67
67
|
=t :sitemap
|
68
68
|
|
69
|
-
%label.checkbox.inline.span2{:
|
69
|
+
%label.checkbox.inline.span2{for: 'in_nav'}
|
70
70
|
= f.check_box :in_nav
|
71
71
|
=t :breadcrumbs
|
72
72
|
|
73
73
|
.accordion
|
74
74
|
.accordion-group
|
75
75
|
.accordion-heading.text-center
|
76
|
-
= link_to t(:seo), '#collapse-three', :
|
76
|
+
= link_to t(:seo), '#collapse-three', class: 'accordion-toggle', 'data-toggle' => 'collapse'
|
77
77
|
.accordion-body.in.collapse#collapse-three
|
78
78
|
.accordion-inner
|
79
79
|
.control-group
|
80
|
-
= f.label :title, :
|
80
|
+
= f.label :title, class: 'control-label'
|
81
81
|
.controls
|
82
|
-
= f.text_field :title, :
|
82
|
+
= f.text_field :title, class: 'span9'
|
83
83
|
.control-group
|
84
|
-
= f.label :keywords, :
|
84
|
+
= f.label :keywords, class: 'control-label'
|
85
85
|
.controls
|
86
|
-
= f.text_field :keywords, :
|
86
|
+
= f.text_field :keywords, class: 'span9'
|
87
87
|
.control-group
|
88
|
-
= f.label :description, :
|
88
|
+
= f.label :description, class: 'control-label'
|
89
89
|
.controls
|
90
|
-
= f.text_area :description, :
|
90
|
+
= f.text_area :description, class: 'span9', rows: 8
|
91
91
|
|
92
92
|
.row-fluid
|
93
93
|
.span12
|
94
94
|
.form-actions
|
95
|
-
= f.submit :
|
95
|
+
= f.submit class: 'btn btn-primary'
|
96
96
|
= link_to t(:cancel), pages_url, class: 'btn'
|
97
97
|
= link_to t(:delete_page), @page, method: :delete, data: {confirm: t(:are_you_sure?)}, class: 'btn btn-danger pull-right' unless @page.new_record?
|
@@ -2,51 +2,41 @@
|
|
2
2
|
=t :structure
|
3
3
|
|
4
4
|
- content_for :actions do
|
5
|
-
|
6
|
-
|
5
|
+
- if @template_exists
|
6
|
+
.span4.clearfix.text-right
|
7
|
+
= link_to pages.new_page_path, class: 'btn btn-large btn-link' do
|
8
|
+
%i.icon-plus
|
9
|
+
=t :new_page
|
7
10
|
|
8
11
|
%section.b-tree.span12
|
9
12
|
%ul
|
10
|
-
|
11
|
-
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
=
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
-
|
39
|
-
|
40
|
-
- if !page.template.leaf?
|
41
|
-
= link_to "<i class='icon-chevron-down'></i> #{t :add} #{page.template.descendants.first.name.downcase}".html_safe, new_child_page_path(page), :class => "btn btn-success btn-mini"
|
42
|
-
- else
|
43
|
-
= link_to "<i class='icon-chevron-down'></i> #{t :add} #{ConstructorPages::Template.find(page.template.child_id).name.downcase}".html_safe, new_child_page_path(page), :class => "btn btn-success btn-mini"
|
44
|
-
|
45
|
-
= link_to "<i class='icon-remove'></i> #{t :delete}".html_safe, page_path(page), method: :delete, class: 'btn btn-danger btn-mini pull-right', data: {confirm: t(:are_you_sure?)}
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
- level = page.level
|
50
|
-
- last_page = page
|
51
|
-
</li>
|
52
|
-
= raw "</ul></li>" * last_page.level
|
13
|
+
= render_tree @roots do |page|
|
14
|
+
- if page.published?
|
15
|
+
= link_to page.name, page.full_url, class: 'btn btn-link'
|
16
|
+
- else
|
17
|
+
%button.btn.disabled= page.name
|
18
|
+
|
19
|
+
.b-tree__buttons
|
20
|
+
= render partial: 'constructor_pages/partials/arrow_buttons', locals: {item: page}
|
21
|
+
|
22
|
+
= link_to edit_page_path(page), class: 'btn btn-primary btn-mini' do
|
23
|
+
%i.icon-pencil
|
24
|
+
=t :edit
|
25
|
+
= page.template.name.downcase
|
26
|
+
|
27
|
+
- unless page.template.nil?
|
28
|
+
- if page.template.child_id.nil?
|
29
|
+
- if !page.template.leaf?
|
30
|
+
= link_to new_child_page_path(page), class: 'btn btn-success btn-mini' do
|
31
|
+
%i.icon-chevron-down
|
32
|
+
=t :add
|
33
|
+
= page.template.descendants.first.name.downcase
|
34
|
+
- else
|
35
|
+
= link_to new_child_page_path(page), class: 'btn btn-success btn-mini' do
|
36
|
+
%i.icon-chevron-down
|
37
|
+
=t :add
|
38
|
+
= ConstructorPages::Template.find(page.template.child_id).name.downcase
|
39
|
+
|
40
|
+
= link_to page_path(page), method: :delete, class: 'btn btn-danger btn-mini pull-right', data: {confirm: t(:are_you_sure?)} do
|
41
|
+
%i.icon-remove
|
42
|
+
=t :delete
|
@@ -0,0 +1,6 @@
|
|
1
|
+
.btn-group
|
2
|
+
- {down: :right, up: :left}.each_pair do |a, b|
|
3
|
+
- sibling = item.send(b.to_s+'_sibling')
|
4
|
+
- if sibling and item.move_possible?(sibling)
|
5
|
+
= link_to "/admin/#{item.class.to_s.demodulize.downcase.pluralize}/move/#{a}/#{item.id}", class: 'btn btn-mini' do
|
6
|
+
%i{class: "icon-arrow-#{a}"}
|
@@ -1,47 +1,52 @@
|
|
1
1
|
= form_for @template do |f|
|
2
2
|
- if @template.errors.any?
|
3
3
|
.alert.alert-error.fade.in.span12
|
4
|
-
= link_to
|
4
|
+
= link_to '×', '#', class: 'close', 'data-dismiss' => 'alert'
|
5
5
|
- @template.errors.full_messages.each do |m|
|
6
6
|
= m
|
7
7
|
|
8
8
|
.form-horizontal
|
9
9
|
.control-group
|
10
|
-
= f.label :name, :
|
11
|
-
.controls= f.text_field :name, :
|
10
|
+
= f.label :name, class: 'control-label'
|
11
|
+
.controls= f.text_field :name, class: 'span4'
|
12
12
|
|
13
13
|
.control-group
|
14
|
-
= f.label :code_name, :
|
15
|
-
.controls= f.text_field :code_name, :
|
14
|
+
= f.label :code_name, class: 'control-label'
|
15
|
+
.controls= f.text_field :code_name, class: 'span4'
|
16
16
|
|
17
17
|
.control-group
|
18
|
-
= f.label :parent, :
|
18
|
+
= f.label :parent, class: 'control-label'
|
19
19
|
.controls
|
20
|
-
= f.select :parent_id, options_for_select(for_select(@roots), :
|
20
|
+
= f.select :parent_id, options_for_select(for_select(@roots), selected: @template.parent_id), disabled: @template.self_and_descendants.map(&:id), include_blank: t(:no)
|
21
21
|
|
22
22
|
.control-group
|
23
|
-
= f.label :child, :
|
23
|
+
= f.label :child, class: 'control-label'
|
24
24
|
.controls
|
25
|
-
= f.select :child_id, options_for_select(for_select(@roots), :
|
25
|
+
= f.select :child_id, options_for_select(for_select(@roots), selected: @template.child_id), include_blank: t(:no)
|
26
26
|
|
27
27
|
- unless @template.new_record?
|
28
28
|
.control-group
|
29
29
|
.controls
|
30
|
-
= link_to
|
30
|
+
= link_to new_field_path(@template.id), class: 'btn btn-mini btn-link' do
|
31
|
+
%i.icon-plus
|
32
|
+
=t :new_field
|
31
33
|
|
32
34
|
- @template.fields.each do |field|
|
33
35
|
.control-group
|
34
|
-
= label_tag
|
36
|
+
= label_tag '', field.name, class: 'control-label'
|
35
37
|
.controls
|
36
|
-
= link_to
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
= link_to
|
38
|
+
= link_to field_move_down_path(field), class: "btn btn-mini #{'disabled' if field.last?}" do
|
39
|
+
%i.icon-arrow-down
|
40
|
+
= link_to field_move_up_path(field), class: "btn btn-mini #{'disabled' if field.first?}" do
|
41
|
+
%i.icon-arrow-up
|
42
|
+
= link_to edit_field_path(field, field.template), class: 'btn btn-mini btn-primary' do
|
43
|
+
%i.icon-pencil
|
44
|
+
= link_to field_path(field), method: :delete, data: {confirm: t(:are_you_sure?)}, class: 'btn btn-mini btn-danger' do
|
45
|
+
%i.icon-remove
|
41
46
|
|
42
47
|
.row-fluid
|
43
48
|
.span12
|
44
49
|
.form-actions
|
45
|
-
= f.submit :
|
46
|
-
= link_to t(:cancel), templates_url, :
|
50
|
+
= f.submit class: 'btn btn-primary'
|
51
|
+
= link_to t(:cancel), templates_url, class: 'btn'
|
47
52
|
= link_to t(:delete_template), @template, method: :delete, data: {confirm: t(:are_you_sure?)}, class: 'btn btn-danger pull-right' unless @template.new_record?
|
@@ -3,37 +3,18 @@
|
|
3
3
|
|
4
4
|
- content_for :actions do
|
5
5
|
.span4.clearfix.text-right
|
6
|
-
= link_to
|
6
|
+
= link_to new_template_path, class: 'btn btn-link btn-large' do
|
7
|
+
%i.icon-plus
|
8
|
+
=t :new_template
|
7
9
|
|
8
10
|
%section.b-tree.span12
|
9
|
-
|
10
|
-
-
|
11
|
-
- level = root.level
|
12
|
-
- last_template = nil
|
11
|
+
= render_tree(@roots) do |template|
|
12
|
+
%button.btn.btn-link.disabled= template.name
|
13
13
|
|
14
|
-
|
15
|
-
|
16
|
-
<ul>
|
17
|
-
- elsif template.level < level
|
18
|
-
</li>
|
19
|
-
= raw "</ul></li>" * (level-template.level)
|
20
|
-
- elsif !template.root?
|
21
|
-
</li>
|
14
|
+
.b-tree__buttons
|
15
|
+
= render partial: 'constructor_pages/partials/arrow_buttons', locals: {item: template}
|
22
16
|
|
23
|
-
|
24
|
-
%
|
25
|
-
|
26
|
-
.
|
27
|
-
.btn-group
|
28
|
-
- if not template.right_sibling.nil? and template.move_possible?(template.right_sibling)
|
29
|
-
= link_to "<i class='icon-arrow-down'></i>".html_safe, template_move_down_path(template), :method => :post, :class => "btn btn-mini"
|
30
|
-
- if not template.left_sibling.nil? and template.move_possible?(template.left_sibling)
|
31
|
-
= link_to "<i class='icon-arrow-up'></i>".html_safe, template_move_up_path(template), :method => :post, :class => "btn btn-mini"
|
32
|
-
|
33
|
-
= link_to "<i class='icon-pencil'></i> #{t :edit} #{ t(:template).downcase}".html_safe, edit_template_path(template), :class => "btn btn-primary btn-mini"
|
34
|
-
|
35
|
-
|
36
|
-
- level = template.level
|
37
|
-
- last_template = template
|
38
|
-
</li>
|
39
|
-
= raw "</ul></li>" * last_template.level
|
17
|
+
= link_to edit_template_path(template), class: 'btn btn-primary btn-mini' do
|
18
|
+
%i.icon-pencil
|
19
|
+
=t :edit
|
20
|
+
= t(:template).downcase
|
data/config/locales/en.yml
CHANGED
data/config/locales/ru.yml
CHANGED
data/config/routes.rb
CHANGED
@@ -1,32 +1,27 @@
|
|
1
1
|
ConstructorPages::Engine.routes.draw do
|
2
2
|
scope '/admin' do
|
3
|
-
resources :pages, :
|
4
|
-
resources :templates, :
|
5
|
-
resources :fields, :
|
3
|
+
resources :pages, except: [:show]
|
4
|
+
resources :templates, except: [:show]
|
5
|
+
resources :fields, except: [:show, :new, :edit]
|
6
6
|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
get 'move/up/:id' => "fields#move_up", :as => :field_move_up
|
12
|
-
get 'move/down/:id' => "fields#move_down", :as => :field_move_down
|
7
|
+
%w{page template field}.each do |c|
|
8
|
+
%w{up down}.each do |d|
|
9
|
+
get "#{c.pluralize}/move/#{d}/:id" => "#{c.pluralize}#move_#{d}", as: "#{c}_move_#{d}"
|
10
|
+
end
|
13
11
|
end
|
14
12
|
|
15
|
-
scope '/
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
get ':page/new' => "pages#new", :as => :new_child_page
|
13
|
+
scope '/fields' do
|
14
|
+
get ':template_id/new/' => 'fields#new', as: :new_field
|
15
|
+
get ':id/:template_id/edit/' => 'fields#edit', as: :edit_field
|
20
16
|
end
|
21
17
|
|
22
|
-
scope '/
|
23
|
-
|
24
|
-
post 'move/down/:id' => "templates#move_down", :as => :template_move_down
|
18
|
+
scope '/pages' do
|
19
|
+
get ':page/new' => 'pages#new', as: :new_child_page
|
25
20
|
end
|
26
21
|
end
|
27
22
|
|
28
|
-
root :to =>
|
29
|
-
get '*all/search/:what_search' =>
|
30
|
-
get '*all.:format' =>
|
31
|
-
get '*all' =>
|
23
|
+
root :to => 'pages#show'
|
24
|
+
get '*all/search/:what_search' => 'pages#search', format: false
|
25
|
+
get '*all.:format' => 'pages#show'
|
26
|
+
get '*all' => 'pages#show'
|
32
27
|
end
|
@@ -0,0 +1,280 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
module ConstructorPages
|
6
|
+
describe 'Pages Controller' do
|
7
|
+
before :all do
|
8
|
+
@user = ConstructorCore::User.create email: 'ivanzotov@gmail.com', password: '123qweASD'
|
9
|
+
@template = Template.create name: 'Page', code_name: 'page'
|
10
|
+
end
|
11
|
+
|
12
|
+
before :each do
|
13
|
+
Page.delete_all
|
14
|
+
Field.delete_all
|
15
|
+
|
16
|
+
Field::TYPES.each do |t|
|
17
|
+
"constructor_pages/types/#{t}_type".classify.constantize.delete_all
|
18
|
+
end
|
19
|
+
|
20
|
+
login_as @user
|
21
|
+
end
|
22
|
+
|
23
|
+
describe 'Index' do
|
24
|
+
context 'Access' do
|
25
|
+
it 'should be accessed by pages_path if loggen in' do
|
26
|
+
visit pages.pages_path
|
27
|
+
current_path.should == pages.pages_path
|
28
|
+
status_code.should == 200
|
29
|
+
end
|
30
|
+
|
31
|
+
it 'should not be accessed by pages_path if not loggen in' do
|
32
|
+
logout
|
33
|
+
visit pages.pages_path
|
34
|
+
current_path.should == '/'
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
it 'should notice if no template exists' do
|
39
|
+
Template.delete_all
|
40
|
+
visit pages.pages_path
|
41
|
+
page.should_not have_link 'New page'
|
42
|
+
page.should have_content 'Create at least one template'
|
43
|
+
end
|
44
|
+
|
45
|
+
it 'should not notice if template exists' do
|
46
|
+
visit pages.pages_path
|
47
|
+
page.should have_link 'New page'
|
48
|
+
page.should_not have_text 'Create at least one template'
|
49
|
+
end
|
50
|
+
|
51
|
+
it 'should has pages list' do
|
52
|
+
Page.create name: 'Zanussi'
|
53
|
+
visit pages.pages_path
|
54
|
+
page.should have_selector 'ul li'
|
55
|
+
page.should have_link 'Zanussi'
|
56
|
+
end
|
57
|
+
|
58
|
+
it 'should has new page link' do
|
59
|
+
visit pages.pages_path
|
60
|
+
page.should have_link 'New page', pages.new_page_path
|
61
|
+
end
|
62
|
+
|
63
|
+
it 'should has edit_page link' do
|
64
|
+
_page = Page.create name: 'Zanussi'
|
65
|
+
visit pages.pages_path
|
66
|
+
page.should have_link 'Edit page', pages.edit_page_path(_page)
|
67
|
+
end
|
68
|
+
|
69
|
+
it 'should has delete_page link' do
|
70
|
+
_page = Page.create name: 'Zanussi'
|
71
|
+
visit pages.pages_path
|
72
|
+
page.should have_link 'Delete', pages.page_path(_page)
|
73
|
+
end
|
74
|
+
|
75
|
+
it 'should has Add child' do
|
76
|
+
_template = Template.create name: 'Child', code_name: 'child_page', parent: @template
|
77
|
+
_page = Page.create name: 'Zanussi', template: @template
|
78
|
+
visit pages.pages_path
|
79
|
+
page.should have_link 'Add child', pages.new_child_page_path(_page)
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
describe 'Moving' do
|
84
|
+
it 'should move up' do
|
85
|
+
_page_first = Page.create name: 'First'
|
86
|
+
_page_second = Page.create name: 'Second'
|
87
|
+
_page_third = Page.create name: 'Third'
|
88
|
+
|
89
|
+
# test
|
90
|
+
_page_first.lft.should == 1
|
91
|
+
_page_first.rgt.should == 2
|
92
|
+
|
93
|
+
_page_second.lft.should == 3
|
94
|
+
_page_second.rgt.should == 4
|
95
|
+
|
96
|
+
_page_third.lft.should == 5
|
97
|
+
_page_third.rgt.should == 6
|
98
|
+
|
99
|
+
|
100
|
+
# test
|
101
|
+
|
102
|
+
_page_first.left_sibling.should be_nil
|
103
|
+
_page_first.right_sibling.should == _page_second
|
104
|
+
|
105
|
+
_page_second.left_sibling.should == _page_first
|
106
|
+
_page_second.right_sibling.should == _page_third
|
107
|
+
|
108
|
+
_page_third.left_sibling.should == _page_second
|
109
|
+
_page_third.right_sibling.should be_nil
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
describe 'New page' do
|
114
|
+
it 'should be accessed by new_page_path if logged in' do
|
115
|
+
visit pages.new_page_path
|
116
|
+
current_path.should == pages.new_page_path
|
117
|
+
status_code.should == 200
|
118
|
+
end
|
119
|
+
|
120
|
+
it 'should not be accessed by new_page_path if not logged in' do
|
121
|
+
logout
|
122
|
+
visit pages.new_page_path
|
123
|
+
current_path.should == '/'
|
124
|
+
end
|
125
|
+
|
126
|
+
it 'should has child template of parent page' do
|
127
|
+
_template = Template.create name: 'Child', code_name: 'child_page', parent: @template
|
128
|
+
_page = Page.create name: 'Zanussi', template: @template
|
129
|
+
visit pages.pages_path
|
130
|
+
click_link 'Add child'
|
131
|
+
current_path.should == pages.new_child_page_path(_page)
|
132
|
+
page.should have_select 'Template', selected: '-- Child'
|
133
|
+
end
|
134
|
+
|
135
|
+
it 'should has published checkbox' do
|
136
|
+
visit pages.new_page_path
|
137
|
+
page.should have_checked_field 'Active'
|
138
|
+
end
|
139
|
+
|
140
|
+
it 'should has name field' do
|
141
|
+
visit pages.new_page_path
|
142
|
+
page.should have_field 'Name'
|
143
|
+
end
|
144
|
+
|
145
|
+
it 'should has not delete link' do
|
146
|
+
visit pages.new_page_path
|
147
|
+
page.should_not have_link 'Delete'
|
148
|
+
end
|
149
|
+
|
150
|
+
it 'should has create button' do
|
151
|
+
visit pages.new_page_path
|
152
|
+
page.should have_button 'Create Page'
|
153
|
+
end
|
154
|
+
|
155
|
+
it 'should save new page' do
|
156
|
+
visit pages.new_page_path
|
157
|
+
fill_in 'Name', with: 'Hello world'
|
158
|
+
Page.count.should == 0
|
159
|
+
page.click_button 'Create Page'
|
160
|
+
Page.count.should == 1
|
161
|
+
_page = Page.first
|
162
|
+
_page.name.should == 'Hello world'
|
163
|
+
_page.url.should == 'hello-world'
|
164
|
+
current_path.should == pages.pages_path
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
168
|
+
describe 'Edit page' do
|
169
|
+
before :each do
|
170
|
+
@page = Page.create name: 'Hello world'
|
171
|
+
end
|
172
|
+
|
173
|
+
it 'should be accessed by edit_page_path if logged in' do
|
174
|
+
visit pages.edit_page_path(@page)
|
175
|
+
status_code.should == 200
|
176
|
+
end
|
177
|
+
|
178
|
+
it 'should not be accessed by edit_page_path if not logged in' do
|
179
|
+
logout
|
180
|
+
visit pages.edit_page_path(@page)
|
181
|
+
current_path.should == '/'
|
182
|
+
end
|
183
|
+
|
184
|
+
it 'should has delete link' do
|
185
|
+
visit pages.edit_page_path(@page)
|
186
|
+
page.should have_link 'Delete'
|
187
|
+
end
|
188
|
+
|
189
|
+
it 'should edit page' do
|
190
|
+
visit pages.edit_page_path(@page)
|
191
|
+
fill_in 'Name', with: 'Zanussi'
|
192
|
+
fill_in 'Title', with: 'Zanussi conditioners'
|
193
|
+
fill_in 'Keywords', with: 'Zanussi, conditioners, Voronezh'
|
194
|
+
fill_in 'Description', with: 'Zanussi conditioners Voronezh'
|
195
|
+
@page.name.should == 'Hello world'
|
196
|
+
click_button 'Update Page'
|
197
|
+
@page.reload
|
198
|
+
@page.name.should == 'Zanussi'
|
199
|
+
@page.url.should == 'zanussi'
|
200
|
+
@page.title.should == 'Zanussi conditioners'
|
201
|
+
@page.keywords.should == 'Zanussi, conditioners, Voronezh'
|
202
|
+
@page.description.should == 'Zanussi conditioners Voronezh'
|
203
|
+
end
|
204
|
+
end
|
205
|
+
|
206
|
+
describe 'Delete page' do
|
207
|
+
it 'should delete from pages index' do
|
208
|
+
Page.create name: 'Page'
|
209
|
+
visit pages.pages_path
|
210
|
+
Page.count.should == 1
|
211
|
+
click_link 'Delete'
|
212
|
+
Page.count.should == 0
|
213
|
+
end
|
214
|
+
|
215
|
+
it 'should delete from page' do
|
216
|
+
_page = Page.create name: 'Page'
|
217
|
+
visit pages.edit_page_path(_page)
|
218
|
+
Page.count.should == 1
|
219
|
+
click_link 'Delete'
|
220
|
+
Page.count.should == 0
|
221
|
+
end
|
222
|
+
end
|
223
|
+
|
224
|
+
describe 'Fields' do
|
225
|
+
it 'should create fields after create page' do
|
226
|
+
Field.create name: 'Short description', code_name: 'short_description', template: @template, type_value: 'text'
|
227
|
+
Field.create name: 'Long description', code_name: 'long_description', template: @template, type_value: 'html'
|
228
|
+
|
229
|
+
visit pages.new_page_path
|
230
|
+
fill_in 'Name', with: 'Page'
|
231
|
+
click_button 'Create Page'
|
232
|
+
page.should have_content 'added successfully'
|
233
|
+
|
234
|
+
_page = Page.first
|
235
|
+
_page.short_description.should == ''
|
236
|
+
|
237
|
+
visit pages.edit_page_path(_page)
|
238
|
+
|
239
|
+
fill_in 'Short description', with: 'This is short description'
|
240
|
+
fill_in 'Long description', with: 'This is long description'
|
241
|
+
|
242
|
+
click_button 'Update Page'
|
243
|
+
|
244
|
+
_page.reload
|
245
|
+
_page.short_description.should == 'This is short description'
|
246
|
+
end
|
247
|
+
|
248
|
+
it 'should change fields if template change' do
|
249
|
+
Field.create name: 'Price', code_name: 'price', template: @template, type_value: 'float'
|
250
|
+
_template = Template.create name: 'Brand', code_name: 'brand'
|
251
|
+
Field.create name: 'Amount', code_name: 'amount', template: _template, type_value: 'integer'
|
252
|
+
|
253
|
+
visit pages.new_page_path
|
254
|
+
fill_in 'Name', with: 'Simple page'
|
255
|
+
click_button 'Create Page'
|
256
|
+
_page = Page.first
|
257
|
+
visit pages.edit_page_path(_page)
|
258
|
+
page.should have_selector('#fields_price')
|
259
|
+
fill_in 'Price', with: '250.20'
|
260
|
+
click_button 'Update Page'
|
261
|
+
_page.reload
|
262
|
+
_page.price.should == 250.2
|
263
|
+
visit pages.edit_page_path(_page)
|
264
|
+
select 'Brand', from: 'Template'
|
265
|
+
click_button 'Update Page'
|
266
|
+
_page.reload
|
267
|
+
_page.template.should == _template
|
268
|
+
_page.price.should be_nil
|
269
|
+
_page.amount.should == 0
|
270
|
+
visit pages.edit_page_path(_page)
|
271
|
+
page.should_not have_selector('#fields_price')
|
272
|
+
page.should have_selector('#fields_amount')
|
273
|
+
fill_in 'Amount', with: 200
|
274
|
+
click_button 'Update Page'
|
275
|
+
_page.reload
|
276
|
+
_page.amount.should == 200
|
277
|
+
end
|
278
|
+
end
|
279
|
+
end
|
280
|
+
end
|
@@ -8,27 +8,23 @@ module ConstructorPages
|
|
8
8
|
Template.delete_all
|
9
9
|
@template = Template.create name: 'Page', code_name: 'page'
|
10
10
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
11
|
+
Field.delete_all
|
12
|
+
Field::TYPES.each do |t|
|
13
|
+
"constructor_pages/types/#{t}_type".classify.constantize.delete_all
|
14
|
+
end
|
15
15
|
end
|
16
16
|
|
17
17
|
describe '.create' do
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
18
|
+
it 'should be valid' do
|
19
|
+
_field = Field.create name: 'Content', code_name: 'content', template: @template, type_value: 'text'
|
20
|
+
_field.should be_valid
|
21
|
+
end
|
22
22
|
|
23
23
|
it 'should create page fields' do
|
24
|
-
|
25
|
-
|
26
|
-
@template.
|
27
|
-
|
28
|
-
#_page.save.should be_true
|
29
|
-
#_page = Page.create name: 'Page'#, template_id: @template.id
|
30
|
-
#_page.template_id.should_not be_nil
|
31
|
-
#_page.price.should == ''
|
24
|
+
_field = Field.create name: 'Price', code_name: 'price', template: @template, type_value: 'text'
|
25
|
+
|
26
|
+
_page = Page.create name: 'Page', template_id: @template.id
|
27
|
+
_page.price.should == ''
|
32
28
|
end
|
33
29
|
end
|
34
30
|
|
@@ -36,8 +36,9 @@ module ConstructorPages
|
|
36
36
|
Page.find_by_request_or_first('/new-page').should == @page
|
37
37
|
end
|
38
38
|
|
39
|
-
it 'should return first page if no given request' do
|
39
|
+
it 'should return first page if no given request or request is home page' do
|
40
40
|
Page.find_by_request_or_first.should == @page
|
41
|
+
Page.find_by_request_or_first('/').should == @page
|
41
42
|
end
|
42
43
|
end
|
43
44
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: constructor-pages
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.6.
|
4
|
+
version: 0.6.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ivan Zotov
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2013-06-
|
11
|
+
date: 2013-06-20 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: constructor-core
|
@@ -16,14 +16,14 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - '='
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: 0.6.
|
19
|
+
version: 0.6.2
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - '='
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: 0.6.
|
26
|
+
version: 0.6.2
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: dragonfly
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -157,6 +157,7 @@ files:
|
|
157
157
|
- app/helpers/constructor_pages/move_helper.rb
|
158
158
|
- app/helpers/constructor_pages/pages_helper.rb
|
159
159
|
- app/helpers/constructor_pages/templates_helper.rb
|
160
|
+
- app/helpers/constructor_pages/treeview_helper.rb
|
160
161
|
- app/models/constructor_pages/field.rb
|
161
162
|
- app/models/constructor_pages/page.rb
|
162
163
|
- app/models/constructor_pages/template.rb
|
@@ -187,6 +188,7 @@ files:
|
|
187
188
|
- app/views/constructor_pages/pages/index.haml
|
188
189
|
- app/views/constructor_pages/pages/new.haml
|
189
190
|
- app/views/constructor_pages/pages/show.haml
|
191
|
+
- app/views/constructor_pages/partials/_arrow_buttons.haml
|
190
192
|
- app/views/constructor_pages/templates/_form.haml
|
191
193
|
- app/views/constructor_pages/templates/edit.haml
|
192
194
|
- app/views/constructor_pages/templates/index.haml
|
@@ -211,10 +213,10 @@ files:
|
|
211
213
|
- lib/constructor-pages.rb
|
212
214
|
- lib/constructor_pages/engine.rb
|
213
215
|
- public/hello.txt
|
216
|
+
- spec/features/constructor_pages/pages_controller_spec.rb
|
214
217
|
- spec/models/constructor_pages/field_model_spec.rb
|
215
218
|
- spec/models/constructor_pages/page_model_spec.rb
|
216
219
|
- spec/models/constructor_pages/template_model_spec.rb
|
217
|
-
- spec/requests/constructor_pages/pages_controller_spec.rb
|
218
220
|
homepage: http://ivanzotov.github.com/constructor
|
219
221
|
licenses: []
|
220
222
|
metadata: {}
|
@@ -239,8 +241,8 @@ signing_key:
|
|
239
241
|
specification_version: 4
|
240
242
|
summary: Pages for Constructor CMS
|
241
243
|
test_files:
|
244
|
+
- spec/features/constructor_pages/pages_controller_spec.rb
|
242
245
|
- spec/models/constructor_pages/field_model_spec.rb
|
243
246
|
- spec/models/constructor_pages/page_model_spec.rb
|
244
247
|
- spec/models/constructor_pages/template_model_spec.rb
|
245
|
-
- spec/requests/constructor_pages/pages_controller_spec.rb
|
246
248
|
has_rdoc:
|