releaf 0.1.1 → 0.1.2

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 (201) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +15 -12
  3. data/Rakefile +8 -0
  4. data/app/assets/javascripts/releaf/controllers/base.js +0 -40
  5. data/app/assets/javascripts/releaf/include/field.type_date_or_datetime_or_time.js +43 -0
  6. data/app/assets/javascripts/releaf/include/nested_fields.js +58 -65
  7. data/app/assets/javascripts/releaf/include/sortable.js +19 -17
  8. data/app/assets/stylesheets/releaf/controllers/releaf/content.css.erb +6 -0
  9. data/app/assets/stylesheets/releaf/include/field.css.erb +37 -13
  10. data/app/controllers/releaf/admins_controller.rb +13 -6
  11. data/app/controllers/releaf/base_application_controller.rb +4 -1
  12. data/app/controllers/releaf/base_controller.rb +415 -154
  13. data/app/controllers/releaf/content_controller.rb +62 -45
  14. data/app/controllers/releaf/roles_controller.rb +11 -9
  15. data/app/controllers/releaf/sessions_controller.rb +23 -1
  16. data/app/controllers/releaf/translations_controller.rb +21 -25
  17. data/app/helpers/releaf/admin_helper.rb +0 -20
  18. data/app/models/releaf/admin.rb +9 -0
  19. data/app/models/releaf/blank_node_base.rb +29 -0
  20. data/app/models/releaf/node.rb +6 -5
  21. data/app/models/releaf/node_base.rb +9 -3
  22. data/app/models/releaf/role.rb +9 -2
  23. data/app/views/layouts/releaf/admin.html.haml +12 -6
  24. data/app/views/layouts/releaf/devise.html.haml +32 -0
  25. data/app/views/releaf/aliases/{_edit.body.haml → _edit.body.html.haml} +0 -0
  26. data/app/views/releaf/aliases/{_edit.header.haml → _edit.header.html.haml} +1 -1
  27. data/app/views/releaf/aliases/_index.row.html.haml +5 -0
  28. data/app/views/releaf/aliases/{_secondary_panel.haml → _secondary_panel.html.haml} +0 -0
  29. data/app/views/releaf/base/_edit.body.html.haml +11 -0
  30. data/app/views/releaf/base/_edit.field.html.haml +23 -0
  31. data/app/views/releaf/base/{_edit.field.type_autocomplete.haml → _edit.field_type_autocomplete.html.haml} +1 -1
  32. data/app/views/releaf/base/{_edit.field.type_checkbox.haml → _edit.field_type_boolean.html.haml} +1 -1
  33. data/app/views/releaf/base/{_edit.field.type_date.haml → _edit.field_type_date.html.haml} +0 -0
  34. data/app/views/releaf/base/{_edit.field.type_datetime.haml → _edit.field_type_datetime.html.haml} +0 -0
  35. data/app/views/releaf/base/{_edit.field.type_delete_nested.haml → _edit.field_type_delete_nested.html.haml} +0 -0
  36. data/app/views/releaf/base/{_edit.field.type_file.haml → _edit.field_type_file.html.haml} +0 -0
  37. data/app/views/releaf/base/_edit.field_type_image.html.haml +12 -0
  38. data/app/views/releaf/base/_edit.field_type_item.html.haml +31 -0
  39. data/app/views/releaf/base/{_edit.field.type_link.haml → _edit.field_type_link.html.haml} +0 -0
  40. data/app/views/releaf/base/_edit.field_type_link_i18n.html.haml +26 -0
  41. data/app/views/releaf/base/{_edit.field.type_password.haml → _edit.field_type_password.html.haml} +0 -0
  42. data/app/views/releaf/base/{_edit.field.type_richtext.haml → _edit.field_type_richtext.html.haml} +0 -0
  43. data/app/views/releaf/base/{_edit.field.type_richtext_i18n.haml → _edit.field_type_richtext_i18n.html.haml} +0 -0
  44. data/app/views/releaf/base/{_edit.field.type_text.haml → _edit.field_type_text.html.haml} +0 -0
  45. data/app/views/releaf/base/{_edit.field.type_text_i18n.haml → _edit.field_type_text_i18n.html.haml} +0 -0
  46. data/app/views/releaf/base/{_edit.field.type_textarea.haml → _edit.field_type_textarea.html.haml} +0 -0
  47. data/app/views/releaf/base/{_edit.field.type_textarea_i18n.haml → _edit.field_type_textarea_i18n.html.haml} +0 -0
  48. data/app/views/releaf/base/{_edit.field.type_time.haml → _edit.field_type_time.html.haml} +0 -0
  49. data/app/views/releaf/base/_edit.fields.association.html.haml +48 -0
  50. data/app/views/releaf/base/_edit.fields.has_many_template.html.haml +15 -0
  51. data/app/views/releaf/base/_edit.fields.html.haml +20 -0
  52. data/app/views/releaf/base/{_edit.footer.haml → _edit.footer.html.haml} +2 -2
  53. data/app/views/releaf/base/_edit.form.html.haml +4 -0
  54. data/app/views/releaf/base/_edit.header.html.haml +3 -0
  55. data/app/views/releaf/base/{_index.body.haml → _index.body.html.haml} +2 -2
  56. data/app/views/releaf/base/_index.cell.html.haml +20 -0
  57. data/app/views/releaf/base/_index.footer.html.haml +28 -0
  58. data/app/views/releaf/base/_index.header.html.haml +4 -0
  59. data/app/views/releaf/base/_index.row.html.haml +6 -0
  60. data/app/views/releaf/base/_index.search.html.haml +5 -0
  61. data/app/views/releaf/base/_index.table.html.haml +24 -0
  62. data/app/views/releaf/base/_secondary_panel.html.haml +10 -0
  63. data/app/views/releaf/base/_show.body.html.haml +3 -0
  64. data/app/views/releaf/base/_show.field.html.haml +20 -0
  65. data/app/views/releaf/base/_show.field_type_date.html.haml +9 -0
  66. data/app/views/releaf/base/_show.field_type_date_time.html.haml +9 -0
  67. data/app/views/releaf/base/_show.field_type_email.html.haml +6 -0
  68. data/app/views/releaf/base/_show.field_type_file.html.haml +7 -0
  69. data/app/views/releaf/base/_show.field_type_image.html.haml +10 -0
  70. data/app/views/releaf/base/_show.field_type_item.html.haml +11 -0
  71. data/app/views/releaf/base/_show.field_type_link.html.haml +14 -0
  72. data/app/views/releaf/base/_show.field_type_password.html.haml +6 -0
  73. data/app/views/releaf/base/_show.field_type_richtext.html.haml +6 -0
  74. data/app/views/releaf/base/_show.field_type_text.html.haml +6 -0
  75. data/app/views/releaf/base/_show.field_type_textarea.html.haml +6 -0
  76. data/app/views/releaf/base/_show.field_type_time.html.haml +9 -0
  77. data/app/views/releaf/base/_show.field_type_url.html.haml +7 -0
  78. data/app/views/releaf/base/_show.fields.association.html.haml +36 -0
  79. data/app/views/releaf/base/_show.fields.has_many_template.html.haml +12 -0
  80. data/app/views/releaf/base/_show.fields.html.haml +17 -0
  81. data/app/views/releaf/base/{_show.footer.haml → _show.footer.html.haml} +6 -4
  82. data/app/views/releaf/base/_show.header.html.haml +3 -0
  83. data/app/views/releaf/base/confirm_destroy.html.haml +17 -0
  84. data/app/views/releaf/base/edit.html.haml +1 -0
  85. data/app/views/releaf/base/index.html.haml +3 -0
  86. data/app/views/releaf/base/new.html.haml +1 -0
  87. data/app/views/releaf/base/show.html.haml +3 -0
  88. data/app/views/releaf/content/{_edit.body.haml → _edit.body.html.haml} +7 -6
  89. data/app/views/releaf/content/_edit.content_fields.html.haml +11 -0
  90. data/app/views/releaf/content/_edit.fields.html.haml +17 -0
  91. data/app/views/releaf/content/{_edit.slug.haml → _edit.slug.html.haml} +0 -0
  92. data/app/views/releaf/content/{_get_content_form.haml → _get_content_form.html.haml} +2 -2
  93. data/app/views/releaf/content/{_secondary_panel.haml → _secondary_panel.html.haml} +0 -0
  94. data/app/views/releaf/content/{_tree_level.haml → _tree_level.html.haml} +0 -0
  95. data/app/views/releaf/content/{ajax.new.haml → ajax.new.html.haml} +0 -0
  96. data/app/views/releaf/content/{index.haml → index.html.haml} +0 -0
  97. data/app/views/releaf/roles/_edit.field.permissions.html.haml +5 -0
  98. data/app/views/releaf/roles/{_show.field.default.haml → _show.field.default.html.haml} +1 -1
  99. data/app/views/releaf/roles/{_show.field.permissions.haml → _show.field.permissions.html.haml} +2 -2
  100. data/app/views/releaf/translations/{_edit.body.haml → _edit.body.html.haml} +0 -0
  101. data/app/views/releaf/translations/{_edit.header.haml → _edit.header.html.haml} +1 -1
  102. data/app/views/releaf/translations/_index.row.html.haml +5 -0
  103. data/app/views/releaf/translations/{_secondary_panel.haml → _secondary_panel.html.haml} +0 -0
  104. data/lib/generators/releaf/templates/initializers/releaf.rb +0 -39
  105. data/lib/generators/releaf/templates/initializers/releaf_i18n.rb +17 -0
  106. data/lib/generators/releaf/templates/javascripts/3rd_party/jquery.jcarousel.js +1058 -0
  107. data/lib/generators/releaf/templates/javascripts/lib/init_jcarousel.js +40 -0
  108. data/lib/generators/releaf/templates/migrations/create_releaf_roles.rb +1 -0
  109. data/lib/generators/releaf/templates/migrations/create_releaf_tinymce_assets.rb +1 -0
  110. data/lib/generators/releaf/templates/models/admin_ability.rb +1 -1
  111. data/lib/i18n/backend/releaf.rb +5 -4
  112. data/lib/i18n/backend/releaf/translation.rb +5 -0
  113. data/lib/i18n/backend/releaf/translation_data.rb +7 -0
  114. data/lib/i18n/backend/releaf/translation_group.rb +4 -0
  115. data/lib/releaf.rb +4 -0
  116. data/lib/releaf/boolean_at.rb +77 -0
  117. data/lib/releaf/globalize3/fallbacks.rb +19 -0
  118. data/lib/releaf/resources.rb +101 -0
  119. data/lib/releaf/slug.rb +99 -60
  120. data/lib/releaf/version.rb +1 -1
  121. data/spec/spec_helper.rb +6 -0
  122. data/templates/releaf/installer.rb +15 -4
  123. metadata +275 -329
  124. data/app/views/releaf/aliases/_index.row.haml +0 -5
  125. data/app/views/releaf/base/_edit.body.haml +0 -19
  126. data/app/views/releaf/base/_edit.field.haml +0 -96
  127. data/app/views/releaf/base/_edit.field.type_image.haml +0 -14
  128. data/app/views/releaf/base/_edit.field.type_select.haml +0 -11
  129. data/app/views/releaf/base/_edit.form.haml +0 -4
  130. data/app/views/releaf/base/_edit.has_many_associations.haml +0 -45
  131. data/app/views/releaf/base/_edit.header.haml +0 -3
  132. data/app/views/releaf/base/_index.cell.haml +0 -19
  133. data/app/views/releaf/base/_index.footer.haml +0 -22
  134. data/app/views/releaf/base/_index.header.haml +0 -4
  135. data/app/views/releaf/base/_index.row.haml +0 -6
  136. data/app/views/releaf/base/_index.search.haml +0 -5
  137. data/app/views/releaf/base/_index.table.haml +0 -8
  138. data/app/views/releaf/base/_secondary_panel.haml +0 -9
  139. data/app/views/releaf/base/_show.body.haml +0 -7
  140. data/app/views/releaf/base/_show.field.haml +0 -78
  141. data/app/views/releaf/base/_show.field.type_html.haml +0 -1
  142. data/app/views/releaf/base/_show.header.haml +0 -3
  143. data/app/views/releaf/base/confirm_destroy.haml +0 -10
  144. data/app/views/releaf/base/edit.haml +0 -1
  145. data/app/views/releaf/base/index.haml +0 -3
  146. data/app/views/releaf/base/new.haml +0 -1
  147. data/app/views/releaf/base/show.haml +0 -3
  148. data/app/views/releaf/content/_edit.content_fields.haml +0 -19
  149. data/app/views/releaf/content/_show.field.content.haml +0 -11
  150. data/app/views/releaf/roles/_edit.field.admins.haml +0 -0
  151. data/app/views/releaf/roles/_edit.field.permissions.haml +0 -5
  152. data/app/views/releaf/translations/_index.row.haml +0 -5
  153. data/spec/dummy/README.rdoc +0 -261
  154. data/spec/dummy/Rakefile +0 -7
  155. data/spec/dummy/app/assets/images/rails.png +0 -0
  156. data/spec/dummy/app/assets/javascripts/application.js +0 -15
  157. data/spec/dummy/app/assets/stylesheets/application.css +0 -13
  158. data/spec/dummy/app/controllers/application_controller.rb +0 -3
  159. data/spec/dummy/app/helpers/application_helper.rb +0 -2
  160. data/spec/dummy/app/models/admin_ability.rb +0 -51
  161. data/spec/dummy/app/models/settings.rb +0 -2
  162. data/spec/dummy/app/views/layouts/application.html.haml +0 -10
  163. data/spec/dummy/config.ru +0 -4
  164. data/spec/dummy/config/application.rb +0 -68
  165. data/spec/dummy/config/boot.rb +0 -6
  166. data/spec/dummy/config/common_fields.yml.example +0 -17
  167. data/spec/dummy/config/database.yml +0 -42
  168. data/spec/dummy/config/environment.rb +0 -5
  169. data/spec/dummy/config/environments/development.rb +0 -37
  170. data/spec/dummy/config/environments/production.rb +0 -67
  171. data/spec/dummy/config/environments/test.rb +0 -37
  172. data/spec/dummy/config/initializers/backtrace_silencers.rb +0 -7
  173. data/spec/dummy/config/initializers/devise.rb +0 -232
  174. data/spec/dummy/config/initializers/dragonfly.rb +0 -1
  175. data/spec/dummy/config/initializers/inflections.rb +0 -15
  176. data/spec/dummy/config/initializers/mime_types.rb +0 -5
  177. data/spec/dummy/config/initializers/releaf.rb +0 -59
  178. data/spec/dummy/config/initializers/releaf_i18n.rb +0 -8
  179. data/spec/dummy/config/initializers/releaf_store_current_template.rb +0 -25
  180. data/spec/dummy/config/initializers/secret_token.rb +0 -7
  181. data/spec/dummy/config/initializers/session_store.rb +0 -8
  182. data/spec/dummy/config/initializers/wrap_parameters.rb +0 -14
  183. data/spec/dummy/config/locales/devise.en.yml +0 -58
  184. data/spec/dummy/config/locales/en.yml +0 -5
  185. data/spec/dummy/config/routes.rb +0 -11
  186. data/spec/dummy/db/migrate/20130204164516_create_settings.rb +0 -17
  187. data/spec/dummy/db/migrate/20130204164523_create_releaf_nodes.rb +0 -25
  188. data/spec/dummy/db/migrate/20130204164524_create_releaf_roles.rb +0 -11
  189. data/spec/dummy/db/migrate/20130204164525_create_releaf_translations.rb +0 -31
  190. data/spec/dummy/db/migrate/20130204164526_create_releaf_admins.rb +0 -53
  191. data/spec/dummy/db/schema.rb +0 -112
  192. data/spec/dummy/db/seeds.rb +0 -64
  193. data/spec/dummy/doc/README_FOR_APP +0 -2
  194. data/spec/dummy/log/development.log +0 -74
  195. data/spec/dummy/log/test.log +0 -129
  196. data/spec/dummy/public/404.html +0 -26
  197. data/spec/dummy/public/422.html +0 -26
  198. data/spec/dummy/public/500.html +0 -25
  199. data/spec/dummy/public/favicon.ico +0 -0
  200. data/spec/dummy/script/rails +0 -6
  201. data/spec/dummy/tmp/cache/9C5/660/settings%3Ai18n_updated_at +0 -1
@@ -1,11 +1,11 @@
1
1
  module Releaf
2
2
  class AdminsController < BaseController
3
3
 
4
- def current_object_class
4
+ def resource_class
5
5
  Releaf::Admin
6
6
  end
7
7
 
8
- def columns( view = nil )
8
+ def fields_to_display
9
9
  fields = super - %w[
10
10
  authentication_token
11
11
  confirmation_sent_at
@@ -26,21 +26,28 @@ module Releaf
26
26
  unlock_token
27
27
  ]
28
28
 
29
- if view == 'index'
29
+ if params[:action] == 'index'
30
30
  fields -= ['avatar_uid']
31
31
  end
32
32
 
33
- if %w[new create edit update].include? view
33
+ if %w[new create edit update].include? params[:action]
34
34
  fields += ['password', 'password_confirmation']
35
35
  end
36
36
 
37
37
  return fields
38
38
  end
39
39
 
40
+ def new
41
+ super
42
+ if Releaf::Role.default
43
+ @resource.role = Releaf::Role.default
44
+ end
45
+ end
46
+
40
47
  protected
41
48
 
42
- def admin_params( action )
43
- return [] unless [:create, :update].include? action
49
+ def resource_params
50
+ return [] unless %w[create update].include? params[:action]
44
51
  %w[name surname role_id email password password_confirmation phone avatar retained_avatar]
45
52
  end
46
53
 
@@ -1,6 +1,5 @@
1
1
  module Releaf
2
2
  class BaseApplicationController < ActionController::Base
3
- # include ReleafDeviseHelper
4
3
 
5
4
  before_filter "authenticate_#{ReleafDeviseHelper.devise_admin_model_name}!"
6
5
  # check_authorization :unless => :devise_controller?
@@ -11,5 +10,9 @@ module Releaf
11
10
  @current_ability ||= AdminAbility.new(self.send("current_#{ReleafDeviseHelper.devise_admin_model_name}"))
12
11
  end
13
12
 
13
+ def full_controller_name
14
+ self.class.name.sub(/Controller$/, '').underscore
15
+ end
16
+
14
17
  end
15
18
  end
@@ -1,127 +1,48 @@
1
1
  module Releaf
2
+ class FeatureDisabled < StandardError; end
3
+
2
4
  class BaseController < BaseApplicationController
5
+ helper_method :build_secondary_panel_variables,
6
+ :fields_to_display,
7
+ :resource_class,
8
+ :find_parent_template,
9
+ :has_template?,
10
+ :list_action,
11
+ :render_field_type,
12
+ :render_parent_template,
13
+ :secondary_panel,
14
+ :current_feature,
15
+ :resource_to_text,
16
+ :resource_to_text_method
17
+
3
18
  before_filter do
4
19
  filter_templates
5
20
  set_locale
6
21
  setup
7
22
  end
8
23
 
9
- def setup
10
- @controller = self # this is used later in views
11
- @features = { :create => true, :show => true, :edit => true, :destroy => true}
12
- @panel_layout = true
13
- @continuous_scroll = false
14
- @items_per_page = 40
15
- end
16
-
17
- def secondary_panel
18
- return '' unless @panel_layout
19
- @_secondary_panel ||= render_to_string( :partial => "secondary_panel", :layout => false, :locals => build_secondary_panel_variables)
20
- end
21
-
22
- def build_secondary_panel_variables
23
- menu_item_name = self.class.name.underscore.sub(/_controller$/, '')
24
-
25
- # if this item is defined in main menu, then there will be no altmenu
26
- # defined for it in alt menu, instead this method should be overriden in
27
- # particular controller to return structure needed to render alt menu
28
- return {} if Releaf.main_menu.include? menu_item_name
29
24
 
30
- # if this item was not found in main menu, then we need to find it in one
31
- # of alt menus. This way we'll know which alt menu to render.
32
- base_menus = Releaf.main_menu.reject { |item| item[0] != '*' }
33
- base_menus.each do |base_menu_name|
34
- if view_context.base_menu_items(base_menu_name).include?(menu_item_name)
35
- build_menu = { :menu => {} }
36
-
37
- base_menu = Releaf.base_menu[base_menu_name]
38
-
39
- base_menu.each do |section|
40
- section_name = section[0].to_sym
41
- build_menu[:menu][section_name] = []
42
- section[1].each do |item|
43
- build_menu[:menu][section_name].push({:controller => item.split(/#/, 2).first})
44
- end
45
- end
46
-
47
- return build_menu
48
- end
49
- end
50
-
51
- # coundn't find current controller in base_menu
52
- return {}
53
- end
54
-
55
- def current_object_class
56
- @_current_object_class ||= self.class.name.split('::').last.sub(/\s?Controller$/, '').classify.constantize
57
- end
58
-
59
- def current_object_class_name
60
- current_object_class.name.underscore.tr('/', '_')
61
- end
62
-
63
- def columns view=params[:action]
64
- cols = current_object_class.column_names - %w[id created_at updated_at encrypted_password position]
65
- unless %w[new edit update create].include? view
66
- cols -= %w[password password_confirmation]
67
- end
68
- return cols
69
- end
70
-
71
- def list_action
72
- if !cookies['base_module:list_action'].blank?
73
- feature = cookies['base_module:list_action']
74
- if feature == 'confirm_destroy'
75
- feature = 'destroy'
76
- end
77
- feature = feature.to_sym
78
- if !@features[ feature ].blank?
79
- return cookies['base_module:list_action']
80
- end
81
- end
82
- if !@features[ :show ].blank?
83
- return 'show'
84
- end
85
- return 'edit';
86
- end
87
-
88
- def has_template( name )
89
- lookup_context.template_exists?( name, lookup_context.prefixes, false )
90
- end
91
-
92
- def find_parent_template( name )
93
- lookup_context.find_template( name, lookup_context.prefixes.slice( 1, lookup_context.prefixes.length ), false )
94
- end
95
-
96
- def render_parent_template( name, locals = {} )
97
- template = find_parent_template( name )
98
- if template.blank?
99
- return 'blank'
100
- end
101
- arguments = { :layout => false, :locals => locals, :template => template.virtual_path }
102
- return render_to_string( arguments ).html_safe
103
- end
104
-
105
- def input_type_for( column_type, name )
106
- input_type = 'text'
107
- case column_type
108
- when :boolean
109
- input_type = 'checkbox'
110
- when :text
111
- input_type = 'textarea'
112
- if name.end_with?( '_html' )
113
- input_type = 'richtext'
114
- end
25
+ # Helper that returns current feature
26
+ def current_feature
27
+ case params[:action].to_sym
28
+ when :index
29
+ return :index
30
+ when :new, :create
31
+ return :create
32
+ when :edit, :update
33
+ return :edit
34
+ when :destroy, :confirm_destroy
35
+ return :destroy
36
+ else
37
+ return params[:action].to_sym
115
38
  end
116
- return input_type
117
39
  end
118
40
 
119
- # actions
120
41
 
121
42
  def autocomplete
122
- authorize! :edit, current_object_class
43
+ authorize! :edit, resource_class
123
44
 
124
- c_obj = current_object_class
45
+ c_obj = resource_class
125
46
 
126
47
  if params[:query_field] and params[:q] and params[:field] #and params[:field] =~ /_id\z/ and c_obj.column_names.include?(params[:field]) and c_obj.respond_to?(:reflect_on_association) and c_obj.reflect_on_association(params[:field].sub(/_id\z/, '').to_sym)
127
48
 
@@ -155,13 +76,13 @@ module Releaf
155
76
  matching_items_count = query.count
156
77
  list = query.limit(20)
157
78
 
158
- @items = []
159
- list.each do |item|
160
- @items.push({ :id => item.id, :text => item.to_text })
79
+ @resources = []
80
+ list.each do |resource|
81
+ @resources.push({ :id => resource.id, :text => resource.to_text })
161
82
  end
162
83
 
163
84
  respond_to do |format|
164
- format.json { render :json => {:matching_items_count => matching_items_count, :query => params[:q], :results => @items } }
85
+ format.json { render :json => {:matching_items_count => matching_items_count, :query => params[:q], :results => @resources } }
165
86
  end
166
87
 
167
88
  else
@@ -172,14 +93,20 @@ module Releaf
172
93
  end
173
94
 
174
95
  def index
175
- authorize! :list, current_object_class
176
- if current_object_class.respond_to?( :filter )
177
- @list = current_object_class.filter(:search => params[:search])
96
+ authorize! :list, resource_class
97
+ if resource_class.respond_to? :filter
98
+ @resources = resource_class.filter(:search => params[:search])
178
99
  else
179
- @list = current_object_class
100
+ @resources = resource_class
101
+ end
102
+
103
+ if resource_class.respond_to? :order_by
104
+ @resources = @resources.order_by(valid_order_by)
180
105
  end
181
- @list = @list.page( params[:page] ).per_page( @items_per_page )
182
- if !params[:ajax].blank?
106
+
107
+ @resources = @resources.includes(relations_for_includes).page( params[:page] ).per_page( @resources_per_page )
108
+
109
+ unless params[:ajax].blank?
183
110
  render :layout => false
184
111
  end
185
112
  end
@@ -197,37 +124,34 @@ module Releaf
197
124
  end
198
125
 
199
126
  def new
200
- authorize! :create, current_object_class
201
- @item = current_object_class.new
127
+ authorize! :create, resource_class
128
+ raise FeatureDisabled unless @features[:create]
129
+ @resource = resource_class.new
202
130
  end
203
131
 
204
132
  def show
205
- @item = current_object_class.find(params[:id])
206
- authorize! :show, @item
133
+ @resource = resource_class.includes(relations_for_includes).find(params[:id])
134
+ authorize! :show, @resource
135
+ raise FeatureDisabled unless @features[:show]
207
136
  end
208
137
 
209
138
  def edit
210
- @item = current_object_class.find(params[:id])
211
- authorize! :edit, @item
139
+ @resource = resource_class.includes(relations_for_includes).find(params[:id])
140
+ authorize! :edit, @resource
141
+ raise FeatureDisabled unless @features[:edit]
212
142
  end
213
143
 
214
144
  def create
215
- authorize! :create, current_object_class
216
- @item = current_object_class.new
145
+ authorize! :create, resource_class
146
+ raise FeatureDisabled unless @features[:create]
217
147
 
218
- if self.respond_to?(:"#{current_object_class_name}_params")
219
- variables = params.require( current_object_class_name ).permit( *self.send(:"#{current_object_class_name}_params", :update) )
220
- elsif @item.respond_to? :allowed_params
221
- variables = params.require( current_object_class_name ).permit( *@item.allowed_params(:create) )
222
- else
223
- variables = params.require( current_object_class_name ).permit( *current_object_class.column_names )
224
- end
148
+ @resource = resource_class.new
225
149
 
226
- @item.assign_attributes( variables )
150
+ @resource.assign_attributes required_params.permit(*resource_params)
227
151
 
228
152
  respond_to do |format|
229
- if @item.save
230
- format.html { redirect_to url_for( :action => 'show', :id => @item.id ) }
153
+ if @resource.save
154
+ format.html { redirect_to url_for( :action => @features[:show] ? 'show' : 'index', :id => @resource.id ) }
231
155
  else
232
156
  format.html { render :action => "new" }
233
157
  end
@@ -235,20 +159,13 @@ module Releaf
235
159
  end
236
160
 
237
161
  def update
238
- @item = current_object_class.find(params[:id])
239
- authorize! :edit, @item
240
-
241
- if self.respond_to?(:"#{current_object_class_name}_params")
242
- variables = params.require( current_object_class_name ).permit( *self.send(:"#{current_object_class_name}_params", :update) )
243
- elsif @item.respond_to? :allowed_params
244
- variables = params.require( current_object_class_name ).permit( *@item.allowed_params(:update) )
245
- else
246
- variables = params.require( current_object_class_name ).permit( *current_object_class.column_names )
247
- end
162
+ @resource = resource_class.find(params[:id])
163
+ authorize! :edit, @resource
164
+ raise FeatureDisabled unless @features[:edit]
248
165
 
249
166
  respond_to do |format|
250
- if @item.update_attributes( variables )
251
- format.html { redirect_to url_for( :action => 'show', :id => @item.id ) }
167
+ if @resource.update_attributes( required_params.permit(*resource_params) )
168
+ format.html { redirect_to url_for( :action => @features[:show] ? 'show' : 'index', :id => @resource.id ) }
252
169
  else
253
170
  format.html { render :action => "edit" }
254
171
  end
@@ -256,14 +173,16 @@ module Releaf
256
173
  end
257
174
 
258
175
  def confirm_destroy
259
- @item = current_object_class.find(params[:id])
260
- authorize! :destroy, @item
176
+ @resource = resource_class.find(params[:id])
177
+ authorize! :destroy, @resource
178
+ raise FeatureDisabled unless @features[:destroy]
261
179
  end
262
180
 
263
181
  def destroy
264
- @item = current_object_class.find(params[:id])
265
- authorize! :destroy, @item
266
- @item.destroy
182
+ @resource = resource_class.find(params[:id])
183
+ authorize! :destroy, @resource
184
+ raise FeatureDisabled unless @features[:destroy]
185
+ @resource.destroy
267
186
 
268
187
  respond_to do |format|
269
188
  format.html { redirect_to url_for( :action => 'index' ) }
@@ -271,8 +190,348 @@ module Releaf
271
190
  end
272
191
 
273
192
 
193
+
194
+
195
+
196
+
197
+ # Helper methods ##############################################################################
198
+
199
+
200
+ def list_action
201
+ if !cookies['base_module:list_action'].blank?
202
+ feature = cookies['base_module:list_action']
203
+ if feature == 'confirm_destroy'
204
+ feature = 'destroy'
205
+ end
206
+ feature = feature.to_sym
207
+ if @features[feature]
208
+ return cookies['base_module:list_action']
209
+ end
210
+ end
211
+
212
+ return 'show' if @features[:show]
213
+ return 'edit'
214
+ end
215
+
216
+ # Defines which fields/associations should be rendered.
217
+ #
218
+ # By default renders resource columns except few (check source).
219
+ #
220
+ # You can override this method to make it possible to render pretty complex
221
+ # views which inludes nested fields.
222
+ #
223
+ # To render field you simply need to add it's name to array.
224
+ #
225
+ # belongs_to relations will be automatically rendered (by default) as
226
+ # select field. For belongs_to to be recognized you need to use Integer
227
+ # field that ends with <tt>_id</tt>
228
+ #
229
+ # You can also render has_many associations. For these associations you
230
+ # need to add either association name, or a Hash. Hash keys must match
231
+ # association name, hash value must be array with nested fields to be
232
+ # rendered.
233
+ #
234
+ # NOTE: currently if you add has_many associations name to array, then it
235
+ # will render all fields (except created_at etc.) including <tt>belongs_to
236
+ # :parent</tt>. This is know bug https://github.com/cubesystems/releaf/issues/64
237
+ #
238
+ # @example
239
+ # def fields_to_display
240
+ # case params[:action]
241
+ # when 'edit', 'update', 'create', 'new'
242
+ # return [
243
+ # 'name',
244
+ # 'category_id',
245
+ # 'description',
246
+ # {'offer_card_types' => ['card_type_id', 'name', 'description']},
247
+ # 'show_banner',
248
+ # 'published',
249
+ # 'item_count',
250
+ # {'images' => ['image_uid']},
251
+ # 'partner_id',
252
+ # 'offer_checkout_places' => ['checkout_place_id']
253
+ # ]
254
+ # else
255
+ # return super
256
+ # end
257
+ # end
258
+ #
259
+ # Fields will be rendered in same order as specified in array
260
+ #
261
+ # @return array that represent which fields to render
262
+ def fields_to_display
263
+ cols = resource_class.column_names - %w[id created_at updated_at encrypted_password position]
264
+ unless %w[new edit update create].include? params[:action]
265
+ cols -= %w[password password_confirmation]
266
+ end
267
+ return cols
268
+ end
269
+
270
+
271
+ def secondary_panel
272
+ return '' unless @panel_layout
273
+ @_secondary_panel ||= render_to_string( :partial => "secondary_panel", :layout => false, :locals => build_secondary_panel_variables)
274
+ end
275
+
276
+ def build_secondary_panel_variables
277
+ menu_item_name = self.class.name.underscore.sub(/_controller$/, '')
278
+
279
+ # if this item is defined in main menu, then there will be no altmenu
280
+ # defined for it in alt menu, instead this method should be overriden in
281
+ # particular controller to return structure needed to render alt menu
282
+ return {} if Releaf.main_menu.include? menu_item_name
283
+
284
+ # if this item was not found in main menu, then we need to find it in one
285
+ # of alt menus. This way we'll know which alt menu to render.
286
+ base_menus = Releaf.main_menu.reject { |item| item[0] != '*' }
287
+ base_menus.each do |base_menu_name|
288
+ if view_context.base_menu_items(base_menu_name).include?(menu_item_name)
289
+ build_menu = { :menu => {} }
290
+
291
+ base_menu = Releaf.base_menu[base_menu_name]
292
+
293
+ base_menu.each do |section|
294
+ section_name = section[0].to_sym
295
+ build_menu[:menu][section_name] = []
296
+ section[1].each do |item|
297
+ build_menu[:menu][section_name].push({:controller => item.split(/#/, 2).first})
298
+ end
299
+ end
300
+
301
+ return build_menu
302
+ end
303
+ end
304
+
305
+ # coundn't find current controller in base_menu
306
+ return {}
307
+ end
308
+
309
+ # Tries to return resource class.
310
+ #
311
+ # If it fails to return proper resource class for your controller, or your
312
+ # controllers name has no relation to resource class name, then simply
313
+ # override this method to return class that you want.
314
+ #
315
+ # @return class
316
+ def resource_class
317
+ @resource_class ||= self.class.name.split('::').last.sub(/Controller$/, '').classify.constantize
318
+ end
319
+
320
+
321
+ # Cheheck if there is a template in lookup_context with given name.
322
+ #
323
+ # @return `true` or `false`
324
+ def has_template? name
325
+ lookup_context.template_exists?( name, lookup_context.prefixes, false )
326
+ end
327
+
328
+ def find_parent_template( name )
329
+ lookup_context.find_template( name, lookup_context.prefixes.slice( 1, lookup_context.prefixes.length ), false )
330
+ end
331
+
332
+ def render_parent_template( name, locals = {} )
333
+ template = find_parent_template( name )
334
+ if template.blank?
335
+ return 'blank'
336
+ end
337
+ arguments = { :layout => false, :locals => locals, :template => template.virtual_path }
338
+ return render_to_string( arguments ).html_safe
339
+ end
340
+
341
+ # Helps to determinate which template to render in :show and :edit feature
342
+ # for given objects attribute.
343
+ #
344
+ # @return [field_type, use_i18n]
345
+ #
346
+ # where field_type is a string representing field type
347
+ # and use_i18n is a `true` or `false`. If use_i18n is true, then template
348
+ # with localization features should be used (if exists)
349
+ #
350
+ # This helper is used by views.
351
+ #
352
+ # @todo document rendering conventions
353
+ def render_field_type( obj, attribute_name )
354
+ field_type = nil
355
+ use_i18n = false
356
+ obj_class = obj.class
357
+
358
+ if obj_class.respond_to?(:translations_table_name)
359
+ use_i18n = obj_class.translates.include?(attribute_name.to_sym)
360
+ end
361
+
362
+ column_type = :string
363
+ if attribute_name.to_s =~ /^#{Releaf::Node::COMMON_FIELD_NAME_PREFIX}/
364
+ column_type = obj.common_field_field_type(attribute_name)
365
+ else
366
+ column_type = obj_class.columns_hash[attribute_name.to_s].try(:type) || :string
367
+ end
368
+
369
+ case column_type.to_sym
370
+ when :boolean
371
+ field_type = 'boolean'
372
+
373
+ when :string
374
+ case attribute_name.to_s
375
+ when /(thumbnail|image|photo|picture|avatar|logo|banner|icon)_uid$/
376
+ field_type = 'image'
377
+
378
+ when /_uid$/
379
+ field_type = 'file'
380
+
381
+ when /password/, 'pin'
382
+ field_type = 'password'
383
+
384
+ when /_email$/, 'email'
385
+ field_type = 'email'
386
+
387
+ when /_link$/, 'link'
388
+ field_type = 'link'
389
+
390
+ else
391
+ field_type = 'text'
392
+ end
393
+
394
+ when :integer
395
+ if attribute_name.to_s =~ /_id$/ and obj_class.reflect_on_association( attribute_name[0..-4].to_sym )
396
+ field_type = 'item'
397
+ else
398
+ field_type = 'text'
399
+ end
400
+
401
+ when :text
402
+ case attribute_name.to_s
403
+ when /_(url|homepage)$/, 'homepage', 'url'
404
+ field_type = 'url'
405
+
406
+ when /_link$/, 'url'
407
+ field_type = 'link_or_url'
408
+
409
+ when /_html$/, 'html'
410
+ field_type = 'richtext'
411
+
412
+ else
413
+ field_type = 'textarea'
414
+ end
415
+
416
+ when :datetime
417
+ field_type = 'datetime'
418
+
419
+ when :date
420
+ field_type = 'date'
421
+
422
+ when :time
423
+ field_type = 'time'
424
+
425
+ end
426
+
427
+ return [field_type || 'text', use_i18n]
428
+ end
429
+
430
+ # calls `#to_text` on resource if resource supports it. Otherwise calls
431
+ # fallback method
432
+ def resource_to_text resource, fallback=:to_s
433
+ resource.send resource_to_text_method(resource, fallback)
434
+ end
435
+
436
+ # @return `:to_text` if resource supports `#to_text`, otherwise fallback.
437
+ def resource_to_text_method resource, fallback=:to_s
438
+ if resource.respond_to?(:to_text)
439
+ return :to_text
440
+ else
441
+ Rails.logger.warn "Re:Leaf: #{resource.class.name} doesn't support #to_text method. Please define it"
442
+ return fallback
443
+ end
444
+ end
445
+
446
+ protected
447
+
448
+ def required_params
449
+ params.require(:resource)
450
+ end
451
+
452
+ # Called before each request by before_filter.
453
+ # It sets various instance variables, that are later used in views and # controllers
454
+ #
455
+ # == Defines
456
+ # @fetures::
457
+ # Hash with symbol keys and boolean values. Each key represents action
458
+ # (currently only `:edit`, `:create`, `:show`, `:destroy` are supported). If one
459
+ # of features is disabled, then routing to it will raise <tt>Releaf::FeatureDisabled</tt>
460
+ # error
461
+ #
462
+ # @continuous_scroll::
463
+ # Boolean. If set to `true` will enable continuous scrool in `#index` view
464
+ #
465
+ # @resources_per_page::
466
+ # Integer - sets the number of resources to display on `#index` view
467
+ #
468
+ # To change controller settings `setup` method should be overriden like this
469
+ #
470
+ # @example
471
+ # def setup
472
+ # super
473
+ # @fetures[:show] = false
474
+ # @resources_per_page = 20
475
+ # end
476
+ def setup
477
+ @features = {
478
+ :edit => true,
479
+ :create => true,
480
+ :show => true,
481
+ :destroy => true
482
+ }
483
+ @continuous_scroll = false
484
+ @panel_layout = true
485
+ @resources_per_page = 40
486
+ end
487
+
488
+ # Returns which resource attributes can be updated with mass assignment.
489
+ #
490
+ # The resulting array will be passed to strong_parameters ``permit``
491
+ def resource_params
492
+ return unless %w[create update].include? params[:action]
493
+ resource_class.column_names
494
+ end
495
+
274
496
  private
275
497
 
498
+ def relations_for_includes
499
+ return nil
500
+ # XXX there's a problem with relations that have conditions with proc.
501
+ # If you refer to models attribute in proc, this function will break.
502
+ # As temp workaround we'll simply skip including relations that have conditions for now.
503
+ rels = []
504
+ fields_to_display.each do |field|
505
+ if (field.is_a? String or field.is_a? Symbol) and field =~ /_id$/
506
+ reflection = resource_class.reflect_on_association(field[0..-4].to_sym)
507
+ next if reflection.blank?
508
+ next unless reflection.conditions.blank?
509
+ rels.push field[0..-4]
510
+ elsif field.is_a? Hash
511
+ field.keys.each do |key|
512
+ if key =~ /_id$/
513
+ reflection = resource_class.reflect_on_association(key[0..-4].to_sym)
514
+ next if reflection.blank?
515
+ next unless reflection.conditions.blank?
516
+ rels.push key[0..-4] if resource_class.reflect_on_association(key[0..-4].to_sym)
517
+ else
518
+ reflection = resource_class.reflect_on_association(key.to_sym)
519
+ next if reflection.blank?
520
+ next unless reflection.conditions.blank?
521
+ rels.push key if resource_class.reflect_on_association(key.to_sym)
522
+ end
523
+ end
524
+ end
525
+ end
526
+ return rels
527
+ end
528
+
529
+ def valid_order_by
530
+ return nil if params[:order_by].blank?
531
+ return nil unless resource_class.column_names.include?(params[:order_by].sub(/-reverse$/, ''))
532
+ return resource_class.table_name + '.' + params[:order_by].sub(/-reverse$/, ' DESC')
533
+ end
534
+
276
535
  def set_locale
277
536
  I18n.locale = if params[:locale] && Settings.i18n_locales.include?(params[:locale])
278
537
  params[:locale]
@@ -281,6 +540,8 @@ module Releaf
281
540
  else
282
541
  I18n.default_locale
283
542
  end
543
+
544
+ Releaf::Globalize3::Fallbacks.set
284
545
  end
285
546
 
286
547
  def filter_templates