rad_kit 0.0.9 → 0.0.10

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 (61) hide show
  1. data/Rakefile +3 -2
  2. data/app/controllers/app.rb +5 -0
  3. data/app/controllers/base.rb +47 -0
  4. data/app/controllers/base_app.rb +18 -0
  5. data/app/controllers/comments.rb +49 -0
  6. data/app/controllers/items.rb +208 -0
  7. data/app/helpers/kit/authorization.rb +121 -0
  8. data/app/helpers/kit/captcha.rb +10 -0
  9. data/app/helpers/kit/controller_helper.rb +76 -0
  10. data/app/helpers/kit/item_helper.rb +110 -0
  11. data/app/helpers/kit/navigation_helper.rb +15 -0
  12. data/app/helpers/kit/pagination.rb +62 -0
  13. data/app/models/_item/attachments.rb +15 -0
  14. data/app/models/_item/container.rb +30 -0
  15. data/app/models/_item/slug.rb +28 -0
  16. data/app/models/attachment.rb +9 -0
  17. data/app/models/comment.rb +30 -0
  18. data/app/models/item.rb +136 -0
  19. data/app/models/secure_token.rb +45 -0
  20. data/app/models/tag.rb +71 -0
  21. data/app/static/kit/highlight.css +48 -0
  22. data/app/static/kit.css +3 -0
  23. data/app/static/kit.js +0 -0
  24. data/app/static/themes/default/objects.less +28 -0
  25. data/app/views/controllers/comments/_embedded.html.haml +13 -0
  26. data/app/views/controllers/comments/_form.html.haml +8 -0
  27. data/app/views/controllers/comments/actions.js.haml +22 -0
  28. data/app/views/controllers/comments/show.html.haml +11 -0
  29. data/app/views/controllers/items/_items.html.haml +2 -0
  30. data/app/views/controllers/items/actions.js.haml +23 -0
  31. data/app/views/controllers/items/all.html.haml +4 -0
  32. data/app/views/controllers/items/inherited_action.html.haml +1 -0
  33. data/app/views/kit/_bottom_panel.html.haml +9 -0
  34. data/app/views/kit/_debug.html.haml +13 -0
  35. data/app/views/kit/_messages.html.haml +4 -0
  36. data/app/views/kit/_navigation.html.haml +19 -0
  37. data/app/views/kit/_not_found.html.haml +1 -0
  38. data/app/views/kit/_top_panel.html.haml +19 -0
  39. data/app/views/kit/_web_analytics.html.erb +14 -0
  40. data/app/views/kit/aspects/_comments.html.haml +8 -0
  41. data/app/views/kit/captcha/_action.js.haml +2 -0
  42. data/app/views/kit/captcha/_form.html.haml +10 -0
  43. data/app/views/kit/layout.html.haml +22 -0
  44. data/app/views/kit/layout.js.haml +15 -0
  45. data/app/views/previews/_line.html.haml +8 -0
  46. data/app/views/previews/_thumb.html.haml +5 -0
  47. data/app/views/themes/default/file.html.haml +19 -0
  48. data/app/views/themes/default/folder.html.haml +15 -0
  49. data/app/views/themes/default/layout_definitions/default.yml +27 -0
  50. data/app/views/themes/default/list.html.haml +21 -0
  51. data/app/views/themes/default/list_item.html.haml +14 -0
  52. data/app/views/themes/default/page.html.haml +23 -0
  53. data/app/views/tools/_access.html.haml +12 -0
  54. data/app/views/tools/_buttons.html.haml +11 -0
  55. data/app/views/tools/_context_menu.html.haml +12 -0
  56. data/app/views/tools/_search.html.haml +5 -0
  57. data/app/views/tools/_tags.html.haml +10 -0
  58. data/config/locales/en.yml +136 -0
  59. data/config/locales/ru.yml +142 -0
  60. data/config/routes.rb +44 -0
  61. metadata +82 -23
data/Rakefile CHANGED
@@ -2,9 +2,10 @@ require 'rake_ext'
2
2
 
3
3
  project(
4
4
  name: "kit",
5
- official_name: 'rad_kit',
6
- gem: true,
5
+ official_name: 'rad_kit',
7
6
  summary: "Rapid Application Development Kit for Rad Framework",
7
+ dirs: ['app', 'config'],
8
+ gem: true,
8
9
 
9
10
  author: "Alexey Petrushin",
10
11
  homepage: "http://github.com/alexeypetrushin/rad_kit"
@@ -0,0 +1,5 @@
1
+ class App < Controllers::BaseApp
2
+ inherit Rad::Controller::Captcha
3
+
4
+ rad.extension :kit_app, self
5
+ end
@@ -0,0 +1,47 @@
1
+ class Base
2
+ inherit Rad::Controller::Http
3
+
4
+ def smoke_test
5
+ render inline: 'ok'
6
+ end
7
+
8
+ protected
9
+ allow_get_for %()
10
+
11
+ inherit Rad::Controller::Localized
12
+
13
+ before :prepare_current_user
14
+
15
+ inherit Rad::Controller::Authorized
16
+
17
+ helper Helpers::Kit::NavigationHelper
18
+
19
+ #
20
+ # User Error
21
+ #
22
+ def catch_user_error
23
+ begin
24
+ yield
25
+ rescue UserError => e
26
+ msg = e.message || ""
27
+ flash.error = msg
28
+ flash.sticky_error = msg
29
+
30
+ if request.xhr? or params.format == 'js'
31
+ render inline: %(rad.error("#{msg.js_escape.html_escape}");), layout: false
32
+ else
33
+ dont_persist_params{redirect_to default_path}
34
+ end
35
+ end
36
+ end
37
+ around :catch_user_error
38
+
39
+
40
+ #
41
+ # Interface Builder
42
+ #
43
+ def set_theme
44
+ theme.name = params.theme || rad.face.theme # || 'default'
45
+ end
46
+ before :set_theme
47
+ end
@@ -0,0 +1,18 @@
1
+ class BaseApp < Controllers::Base
2
+ inherit Helpers::Kit::ControllerHelper
3
+
4
+ helper Helpers::Kit::Authorization, Helpers::Kit::Captcha, Helpers::Kit::Pagination
5
+
6
+ def prepare_general_params
7
+ if params._tags
8
+ @selected_tags = params._tags.split('-').select{|tag| Models::Tag.valid_name?(tag)}
9
+ else
10
+ @selected_tags = []
11
+ end
12
+ @selected_tags.freeze
13
+ @selected_tags
14
+ end
15
+ before :prepare_general_params
16
+ attr_reader :selected_tags
17
+ helper_method :selected_tags
18
+ end
@@ -0,0 +1,49 @@
1
+ class Comments < Items
2
+ # prepare_model Comment, finder: :by_slug!, only: %w(show edit update destroy)
3
+
4
+ allow_get_for :show, :new, :edit
5
+
6
+ def show
7
+ require_permission :view, @model
8
+ end
9
+
10
+ def new
11
+ require_permission :create_comment
12
+ params.item_id.must_not_be.nil
13
+ @model = Models::Comment.new
14
+ end
15
+
16
+ def create
17
+ require_permission :create_comment
18
+ @item = Models::Item.by_param! params.item_id
19
+ @model = Models::Comment.new params.model
20
+ @model.item = @item
21
+ @model.owner = Models::User.current
22
+ if @model.save
23
+ flash.info = t :comment_created
24
+ # render action: :new
25
+ else
26
+ render action: :new
27
+ end
28
+ end
29
+
30
+ def edit
31
+ require_permission :update_comment, @model
32
+ end
33
+
34
+ def update
35
+ require_permission :update_comment, @model
36
+ if @model.set(params.model).save
37
+ flash.info = t :comment_updated
38
+ # render action: :update
39
+ else
40
+ render action: :edit
41
+ end
42
+ end
43
+
44
+ def destroy
45
+ require_permission :destroy_comment, @model
46
+ @model.destroy
47
+ flash.info = t :comment_destroyed
48
+ end
49
+ end
@@ -0,0 +1,208 @@
1
+ class Items < Controllers::App
2
+ persist_params
3
+
4
+ before do |c|
5
+ model = workspace.model
6
+ model ||= Models::Item.by_param workspace.params.id if workspace.params.id?
7
+ c.instance_variable_set '@model', model
8
+ end
9
+
10
+ partials do
11
+ show :buttons, only: [:all, :show]
12
+ show :search, only: [:all, :show]
13
+ show :tags, only: [:all, :show]
14
+ show :context_menu, only: :show
15
+
16
+ show :comments, only: :show
17
+ end
18
+
19
+ helper Helpers::Kit::ItemHelper
20
+
21
+ layout '/kit/layout'
22
+
23
+ allow_get_for :redirect, :all
24
+ protect_from_forgery
25
+
26
+ allow_get_for :show, :new, :edit, :redirect
27
+
28
+ def redirect
29
+ url = rad.router.default_url
30
+ url = url_for(:all) if url == '/' or url.blank?
31
+ redirect_to url
32
+ end
33
+
34
+ def show
35
+ respond_to do |f|
36
+ if @model
37
+ require_permission :view, @model
38
+
39
+ f.html{@html_title = @model.name}
40
+ f.json{render json: @model}
41
+ else
42
+ f.html{render :not_found}
43
+ f.json{render :not_found}
44
+ end
45
+ end
46
+ end
47
+
48
+ def new
49
+ require_permission :create
50
+ @model = model_class.new
51
+
52
+ respond_to do |f|
53
+ f.js
54
+ f.json{render json: @model}
55
+ end
56
+ end
57
+
58
+ def create
59
+ require_permission :create
60
+ @model = model_class.new params.model
61
+
62
+ respond_to do |f|
63
+ if @model.save
64
+ flash.info = t :"#{model_class.alias.underscore}_created"
65
+
66
+ f.js{redirect_to(path(@model))}
67
+ f.json{render json: @model}
68
+ else
69
+ f.js{render action: :new}
70
+ f.json{render json: {errors: @model.errors}, status: :failed}
71
+ end
72
+ end
73
+ end
74
+
75
+ def edit
76
+ require_permission :update, @model
77
+
78
+ respond_to do |f|
79
+ f.js
80
+ end
81
+ end
82
+
83
+ def update
84
+ require_permission :update, @model
85
+
86
+ respond_to do |f|
87
+ if @model.set(params.model).save
88
+ flash.info = t :"#{model_class.alias.underscore}_updated"
89
+
90
+ f.js
91
+ f.json{render :ok}
92
+ else
93
+ f.js{render action: :edit}
94
+ f.json{render json: {errors: @model.errors}, status: :failed}
95
+ end
96
+ end
97
+ end
98
+
99
+ def destroy
100
+ require_permission :destroy, @model
101
+ @model.destroy
102
+ flash.info = t :"#{model_class.alias.underscore}_destroyed"
103
+
104
+ respond_to do |f|
105
+ f.js{redirect_to(default_path)}
106
+ f.json{render :ok}
107
+ end
108
+ end
109
+
110
+ def all
111
+ respond_to do |f|
112
+ @page, @per_page = (params.page || 1).to_i, Models::Item::PER_PAGE
113
+
114
+ query = self.class.model_class.where(viewers: {_in: rad.user.major_roles}, dependent: {_exists: false})
115
+ query = query.where tags: {_all: selected_tags} unless selected_tags.empty?
116
+ @models = query.sort([:created_at, -1]).paginate(@page, @per_page).all
117
+
118
+ f.html{@html_title = rad.config.title}
119
+ f.json{render json: @models}
120
+ end
121
+ end
122
+
123
+
124
+ #
125
+ # Viewers and Collaborators
126
+ #
127
+ def viewers
128
+ require_permission :update_access, @model
129
+ remove_roles = (params.remove_roles || '').split("\n")
130
+ add_roles = (params.add_roles || '').split("\n")
131
+ partials.show :context_menu
132
+
133
+ remove_roles.each{|role| @model.remove_viewer role}
134
+ add_roles.each{|role| @model.add_viewer role}
135
+
136
+ respond_to do |format|
137
+ if @model.save
138
+ flash.info = t :viewers_updated
139
+
140
+ format.js{render action: :access} # "models/access"
141
+ format.json{render :ok}
142
+ else
143
+ flash.info = t :failed
144
+
145
+ format.js{render action: :access} # "models/access"
146
+ format.json{render :failed}
147
+ end
148
+ end
149
+ end
150
+
151
+ def collaborators
152
+ require_permission :update_access, @model
153
+ remove_roles = (params.remove_roles || '').split("\n")
154
+ add_roles = (params.add_roles || '').split("\n")
155
+ partials.show :context_menu
156
+
157
+ remove_roles.each{|role| @model.remove_collaborator role}
158
+ add_roles.each{|role| @model.add_collaborator role}
159
+
160
+ respond_to do |format|
161
+ if @model.save
162
+ flash.info = t :collaborators_updated
163
+
164
+ format.js{render action: :access} # "models/access"
165
+ format.json{render :ok}
166
+ else
167
+ flash.info = t :failed
168
+
169
+ format.js{render action: :access} # "models/access"
170
+ format.json{render :failed}
171
+ end
172
+ end
173
+ end
174
+
175
+
176
+ #
177
+ # Layout
178
+ #
179
+ def layout
180
+ require_permission :update, @model
181
+
182
+ @model.layout = params.value
183
+
184
+ respond_to do |format|
185
+ if @model.save
186
+ flash.info = t :layout_updated
187
+
188
+ format.js{reload_page}
189
+ format.json{render :ok}
190
+ else
191
+ flash.info = t :failed
192
+
193
+ format.js{}
194
+ format.json{render :failed}
195
+ end
196
+ end
197
+ end
198
+
199
+
200
+ #
201
+ # model_class
202
+ #
203
+ def self.model_class
204
+ @model_class ||= "Models::#{self.alias.singularize}".constantize
205
+ end
206
+ def model_class; self.class.model_class end
207
+ helper_method :model_class
208
+ end
@@ -0,0 +1,121 @@
1
+ module Authorization
2
+ def viewers_controls_for object
3
+ object.must_not_be.nil
4
+
5
+ all_selected_roles = []
6
+ all_avaliable_roles = []
7
+
8
+ # Ordinary Roles
9
+ controls = {
10
+ 'member' => link_to(
11
+ t(:member_role),
12
+ viewers_path(object, remove_roles: 'user', add_roles: 'member', format: :js), method: :post
13
+ ),
14
+ 'user' => link_to(
15
+ t(:user_role),
16
+ viewers_path(object, remove_roles: 'member', add_roles: 'user', format: :js), method: :post
17
+ ),
18
+ }
19
+
20
+ selected_role = Role.lower_role object.viewers
21
+ selected_role = nil if selected_role == 'manager'
22
+ avaliable_roles = Role::ORDERED_ROLES.select{|role| role != selected_role and role != 'manager'}
23
+ avaliable_roles = avaliable_roles.collect{|role| controls[role]}
24
+
25
+ all_selected_roles << t("#{selected_role}_role") if selected_role
26
+ all_avaliable_roles.push *avaliable_roles
27
+
28
+ # Custom Roles
29
+ custom_roles = rad.config.custom_roles
30
+ selected_roles = custom_roles.select{|role| object.viewers.include? role}
31
+ avaliable_roles = custom_roles - selected_roles
32
+
33
+ # selected_roles.collect! do |role|
34
+ # link_to(role, viewers_path(object, remove_roles: role, format: :js), method: :post)
35
+ # end
36
+ avaliable_roles.collect! do |role|
37
+ link_to(role, viewers_path(object, add_roles: role, format: :js), method: :post)
38
+ end
39
+
40
+ all_selected_roles.push *selected_roles
41
+ all_avaliable_roles.push *avaliable_roles
42
+
43
+ # Clear All
44
+ if all_selected_roles.blank?
45
+ all_selected_roles << t(:only_owner)
46
+ else
47
+ current_roles = object.viewers.select{|r| r != 'manager' and r != "user:#{object.owner_name}"}
48
+ all_avaliable_roles.unshift(
49
+ link_to(
50
+ t(:only_owner),
51
+ viewers_path(object, remove_roles: current_roles.join("\n"), format: :js), method: :post
52
+ )
53
+ )
54
+ end
55
+
56
+ [
57
+ %[#{t(:viewers)}: <span class='m_bold'>#{all_selected_roles.join(', ')}</span>],
58
+ %[<span class='m_tiny'>(#{all_avaliable_roles.join(', ')})</span>]
59
+ ]
60
+ end
61
+
62
+ def collaborators_controls_for object
63
+ object.must_not_be.nil
64
+
65
+ all_selected_roles = []
66
+ all_avaliable_roles = []
67
+
68
+ # Ordinary Roles
69
+ controls = {
70
+ 'member' => link_to(
71
+ t(:member_role),
72
+ collaborators_path(object, remove_roles: 'user', add_roles: 'member', format: :js), method: :post
73
+ ),
74
+ 'user' => link_to(
75
+ t(:user_role),
76
+ collaborators_path(object, remove_roles: 'member', add_roles: 'user', format: :js), method: :post
77
+ ),
78
+ }
79
+
80
+ selected_role = Role.lower_role object.collaborators
81
+ selected_role = nil if selected_role == 'manager'
82
+ avaliable_roles = Role::ORDERED_ROLES.select{|role| role != selected_role and role != 'manager'}
83
+ avaliable_roles = avaliable_roles.collect{|role| controls[role]}
84
+
85
+ all_selected_roles << t("#{selected_role}_role") if selected_role
86
+ all_avaliable_roles.push *avaliable_roles
87
+
88
+ # Custom Roles
89
+ custom_roles = rad.config.custom_roles
90
+ selected_roles = custom_roles.select{|role| object.collaborators.include? role}
91
+ avaliable_roles = custom_roles - selected_roles
92
+
93
+ # selected_roles.collect! do |role|
94
+ # link_to(role, collaborators_path(object, remove_roles: role, format: :js), method: :post)
95
+ # end
96
+ avaliable_roles.collect! do |role|
97
+ link_to(role, collaborators_path(object, add_roles: role, format: :js), method: :post)
98
+ end
99
+
100
+ all_selected_roles.push *selected_roles
101
+ all_avaliable_roles.push *avaliable_roles
102
+
103
+ # Clear All
104
+ if all_selected_roles.blank?
105
+ all_selected_roles << t(:only_owner)
106
+ else
107
+ current_roles = object.collaborators.select{|r| r != 'manager' and r != "user:#{object.owner_name}"}
108
+ all_avaliable_roles.unshift(
109
+ link_to(
110
+ t(:only_owner),
111
+ collaborators_path(object, remove_roles: current_roles.join("\n"), format: :js), method: :post
112
+ )
113
+ )
114
+ end
115
+
116
+ [
117
+ %[#{t(:collaborators)}: <span class='m_bold'>#{all_selected_roles.join(', ')}</span>],
118
+ %[<span class='m_tiny'>(#{all_avaliable_roles.join(', ')})</span>]
119
+ ]
120
+ end
121
+ end
@@ -0,0 +1,10 @@
1
+ module Captcha
2
+ def captcha_tag
3
+ return "" if rad.test?
4
+
5
+ captcha_html = recaptcha_tags public_key: config.recaptcha[:public_key],
6
+ display: {theme: :custom, custom_theme_widget: 'recaptcha_widget'}
7
+
8
+ render "/kit/captcha", locals: {captcha_html: captcha_html}
9
+ end
10
+ end
@@ -0,0 +1,76 @@
1
+ module ControllerHelper
2
+ inherited do
3
+ helper_method :partials
4
+ end
5
+
6
+ class Partials
7
+ attr_reader :controller
8
+
9
+ def initialize controller
10
+ @controller = controller
11
+ end
12
+
13
+ def show? name
14
+ partials.include? name
15
+ end
16
+
17
+ def hide? name
18
+ !show?(name)
19
+ end
20
+
21
+ def show name
22
+ partials[name] = true
23
+ end
24
+
25
+ def hide name
26
+ partials.delete name
27
+ end
28
+
29
+ protected
30
+ def partials; controller.send(:_partials) end
31
+ end
32
+
33
+ def _partials
34
+ @_partials ||= {}
35
+ end
36
+ protected :_partials
37
+
38
+ def partials &block
39
+ if block
40
+ partials.instance_eval &block
41
+ else
42
+ @partials ||= ::Helpers::Kit::ControllerHelper::Partials.new self
43
+ end
44
+ end
45
+ protected :partials
46
+
47
+ module ClassMethods
48
+ class Partials
49
+ attr_reader :controller_class
50
+
51
+ def initialize controller_class
52
+ @controller_class = controller_class
53
+ end
54
+
55
+ def show name, options = {}
56
+ controller_class.send :before, options do |controller|
57
+ controller.send(:_partials)[name] = true
58
+ end
59
+ end
60
+
61
+ def hide name, options = {}
62
+ controller_class.send :before, options do |controller|
63
+ controller.send(:_partials).delete name
64
+ end
65
+ end
66
+ end
67
+
68
+ def partials &block
69
+ if block
70
+ partials.instance_eval &block
71
+ else
72
+ @partials ||= ::Helpers::Kit::ControllerHelper::ClassMethods::Partials.new self
73
+ end
74
+ end
75
+ end
76
+ end
@@ -0,0 +1,110 @@
1
+ module ItemHelper
2
+
3
+ #
4
+ # Tag Selector
5
+ #
6
+ def add_tag name
7
+ (selected_tags + [name]).join('-')
8
+ end
9
+
10
+ def remove_tag name
11
+ list = (selected_tags - [name]).join('-')
12
+ return nil if list.empty?
13
+ list
14
+ end
15
+
16
+ def render_item_tags item
17
+ # Tags
18
+
19
+ tags = item.tags.topic.collect{|tag_name| tag_link tag_name}
20
+
21
+ # Visibility
22
+ viewers = item.minor_viewers
23
+ owner_role = "user:#{item.owner_name}"
24
+ viewers = viewers.select{|role| role != owner_role}
25
+ if viewers.blank? # visible only to owner
26
+ tags << tag(:div, t(:owner_visibility), class: :m_owner_visibility)
27
+ else
28
+ viewers.each do |role|
29
+ if role == 'user'
30
+ # don't show public visibility
31
+ elsif role == 'member'
32
+ tags << tag(:div, t(:member_visibility), class: :m_member_visibility)
33
+ else
34
+ tags << tag(:div, role, class: :m_custom_visibility)
35
+ end
36
+ end
37
+ end
38
+
39
+ tags
40
+ end
41
+
42
+ def tag_link tag_name, count = nil
43
+ # link = if current_item and current_item.is_a?(Selector)
44
+ # url_for(action_name, _tags: tag_name)
45
+ # else
46
+ # items_path(_tags: tag_name)
47
+ # end
48
+
49
+ link = items_path(_tags: tag_name)
50
+
51
+ if count
52
+ link_to(tag_name, link, title: t(:tags_count, count: count))
53
+ else
54
+ link_to(tag_name, link)
55
+ end
56
+ end
57
+
58
+ def render_item_details item, opt = {}
59
+ skip = Array(opt[:skip])
60
+
61
+ item.must_be.a Models::Item
62
+ details = []
63
+ details << item.created_at.time_ago_in_words unless skip.include? :created_at
64
+ details << t(:created_by, owner: link_to(item.owner_name, user_path(item.owner_name))) unless skip.include? :owner
65
+ details << t(:comments_count, count: item.comments_count) if item.comments_count > 0 and !skip.include?(:comments)
66
+ details
67
+ end
68
+
69
+ def form_title_for item
70
+ # return if embedded? or !item.new_record?
71
+ return unless item.new_record?
72
+
73
+ model_name = item.class.alias.underscore
74
+ t "create_#{model_name}"
75
+ end
76
+
77
+ def common_fields_for_item form, opt = {}, &extra_fields
78
+ object = form.model #instance_variable_get '@object'
79
+ skip = Array(opt[:skip])
80
+
81
+ html = ""
82
+ html << form.text_field(:topics_as_string, label: t(:tags)) unless skip.include? :tags
83
+ more = ""
84
+ unless skip.include? :slug
85
+ slug_opt = object.new_record? ? {label: t(:slug)} : {label: t(:slug), description: t(:slug_description)}
86
+ # more << form.text_field(:slug, (object.new_record? ? '' : object.slug), slug_opt)
87
+ more << form.text_field(:slug, slug_opt)
88
+ end
89
+ more << capture(&extra_fields) if extra_fields
90
+ html << b.more(id: "form_for_#{object.class.name.underscore}", name: t(:show_more), 'content' => more)
91
+ # if extra_fields
92
+ # html << capture{b.more(id: "form_for_#{object.class.name.underscore}", name: t(:show_more), &extra_fields)}
93
+ # else
94
+
95
+ if extra_fields
96
+ concat html
97
+ else
98
+ html
99
+ end
100
+ end
101
+
102
+ def item_layout_selector
103
+ current = (@model.layout || :default).to_sym
104
+ layouts = rad.face.availiable_layouts[theme.name] || []
105
+ layouts << current unless layouts.include? current
106
+
107
+ html_options = {class: 'm_autosubmit_on_change', 'data-action' => layout_path(@model, format: :js), 'data-remote' => true}
108
+ "#{t(:layout)}: #{select_tag(:layout, current, layouts.collect{|l| [l, l]}, html_options)}"
109
+ end
110
+ end
@@ -0,0 +1,15 @@
1
+ module NavigationHelper
2
+ #
3
+ # [
4
+ # ['Users', user_path],
5
+ # ['Roles']
6
+ # ]
7
+ #
8
+ def breadcrumb
9
+ Array(@breadcrumb).collect{|item| item.is_a?(Array) ? link_to(*item) : item}
10
+ end
11
+
12
+ def breadcrumb?
13
+ breadcrumb.empty?
14
+ end
15
+ end