para 0.4.0

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 (203) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.md +65 -0
  4. data/Rakefile +21 -0
  5. data/app/assets/images/para/admin/bg.png +0 -0
  6. data/app/assets/javascripts/admin/app.coffee +1 -0
  7. data/app/assets/javascripts/para/admin/table.coffee +46 -0
  8. data/app/assets/javascripts/para/admin/theme_actions.coffee +26 -0
  9. data/app/assets/javascripts/para/admin/tree.coffee +53 -0
  10. data/app/assets/javascripts/para/admin.coffee +18 -0
  11. data/app/assets/javascripts/para/application.js +13 -0
  12. data/app/assets/javascripts/para/inputs/nested_many.coffee +57 -0
  13. data/app/assets/javascripts/para/lib/ajax.coffee +11 -0
  14. data/app/assets/stylesheets/admin/app.sass +0 -0
  15. data/app/assets/stylesheets/admin/theme.sass +0 -0
  16. data/app/assets/stylesheets/para/admin/theme/_base.sass +170 -0
  17. data/app/assets/stylesheets/para/admin/theme/_breadcrumb.sass +29 -0
  18. data/app/assets/stylesheets/para/admin/theme/_buttons.sass +24 -0
  19. data/app/assets/stylesheets/para/admin/theme/_checkable.sass +107 -0
  20. data/app/assets/stylesheets/para/admin/theme/_commonds.sass +213 -0
  21. data/app/assets/stylesheets/para/admin/theme/_dropdown.sass +53 -0
  22. data/app/assets/stylesheets/para/admin/theme/_form.sass +141 -0
  23. data/app/assets/stylesheets/para/admin/theme/_list.sass +138 -0
  24. data/app/assets/stylesheets/para/admin/theme/_navigation.sass +287 -0
  25. data/app/assets/stylesheets/para/admin/theme/_navtabs.sass +127 -0
  26. data/app/assets/stylesheets/para/admin/theme/_orderable.sass +44 -0
  27. data/app/assets/stylesheets/para/admin/theme/_panel.sass +288 -0
  28. data/app/assets/stylesheets/para/admin/theme/_responsive.sass +123 -0
  29. data/app/assets/stylesheets/para/admin/theme/_sorting.sass +30 -0
  30. data/app/assets/stylesheets/para/admin/theme/_table.sass +24 -0
  31. data/app/assets/stylesheets/para/admin/theme/_tree.sass +74 -0
  32. data/app/assets/stylesheets/para/admin/theme/_variables.sass +31 -0
  33. data/app/assets/stylesheets/para/admin/theme.sass +22 -0
  34. data/app/assets/stylesheets/para/admin.sass +10 -0
  35. data/app/assets/stylesheets/para/application.css +15 -0
  36. data/app/assets/stylesheets/para/lib/_variables.scss +646 -0
  37. data/app/assets/stylesheets/para/overrides/datetimepicker.sass +17 -0
  38. data/app/assets/stylesheets/para/overrides/fuelux.sass +43 -0
  39. data/app/assets/stylesheets/para/overrides/jasny.bootstrap.sass +41 -0
  40. data/app/assets/stylesheets/para/overrides/redactor.sass +88 -0
  41. data/app/assets/stylesheets/para/overrides/responsive.sass +63 -0
  42. data/app/assets/stylesheets/para/overrides/selectize.sass +45 -0
  43. data/app/assets/stylesheets/para/overrides/slider.sass +13 -0
  44. data/app/assets/stylesheets/para/overrides/theme.sass +172 -0
  45. data/app/controllers/concerns/para/admin/resource_controller_concerns.rb +17 -0
  46. data/app/controllers/para/admin/base_controller.rb +46 -0
  47. data/app/controllers/para/admin/component_controller.rb +9 -0
  48. data/app/controllers/para/admin/crud_component_controller.rb +17 -0
  49. data/app/controllers/para/admin/crud_resources_controller.rb +71 -0
  50. data/app/controllers/para/admin/main_controller.rb +8 -0
  51. data/app/controllers/para/admin/resources_controller.rb +163 -0
  52. data/app/controllers/para/admin/settings_component_controller.rb +11 -0
  53. data/app/controllers/para/admin/settings_form_controller.rb +21 -0
  54. data/app/controllers/para/admin/singleton_resource_component_controller.rb +14 -0
  55. data/app/controllers/para/admin/singleton_resources_controller.rb +30 -0
  56. data/app/controllers/para/application_controller.rb +7 -0
  57. data/app/decorators/para/component/base_decorator.rb +48 -0
  58. data/app/decorators/para/component/crud_decorator.rb +32 -0
  59. data/app/decorators/para/component/settings_decorator.rb +11 -0
  60. data/app/decorators/para/component/singleton_resource_decorator.rb +11 -0
  61. data/app/decorators/para/component_section_decorator.rb +4 -0
  62. data/app/helpers/para/admin/base_helper.rb +57 -0
  63. data/app/helpers/para/admin/component_groups_helper.rb +4 -0
  64. data/app/helpers/para/admin/components_helper.rb +4 -0
  65. data/app/helpers/para/admin/resources_helper.rb +27 -0
  66. data/app/helpers/para/application_helper.rb +14 -0
  67. data/app/helpers/para/exports_helper.rb +11 -0
  68. data/app/helpers/para/flash_helper.rb +48 -0
  69. data/app/helpers/para/form_helper.rb +28 -0
  70. data/app/helpers/para/markup_helper.rb +15 -0
  71. data/app/helpers/para/model_helper.rb +38 -0
  72. data/app/helpers/para/navigation_helper.rb +8 -0
  73. data/app/helpers/para/ordering_helper.rb +20 -0
  74. data/app/helpers/para/search_helper.rb +22 -0
  75. data/app/helpers/para/tag_helper.rb +50 -0
  76. data/app/helpers/para/tree_helper.rb +41 -0
  77. data/app/models/para/component/base.rb +70 -0
  78. data/app/models/para/component/crud.rb +45 -0
  79. data/app/models/para/component/resource.rb +33 -0
  80. data/app/models/para/component/settings.rb +17 -0
  81. data/app/models/para/component/singleton_resource.rb +25 -0
  82. data/app/models/para/component_resource.rb +6 -0
  83. data/app/models/para/component_section.rb +18 -0
  84. data/app/views/layouts/para/admin.html.haml +32 -0
  85. data/app/views/layouts/para/application.html.erb +14 -0
  86. data/app/views/para/admin/component_sections/_form.html.haml +10 -0
  87. data/app/views/para/admin/component_sections/edit.html.haml +5 -0
  88. data/app/views/para/admin/component_sections/new.html.haml +5 -0
  89. data/app/views/para/admin/components/_form.html.haml +15 -0
  90. data/app/views/para/admin/components/new.html.haml +4 -0
  91. data/app/views/para/admin/crud_component/show.html.haml +4 -0
  92. data/app/views/para/admin/dashboard.html.haml +10 -0
  93. data/app/views/para/admin/main/index.html.haml +1 -0
  94. data/app/views/para/admin/resources/_exports_menu.html.haml +12 -0
  95. data/app/views/para/admin/resources/_fields.html.haml +5 -0
  96. data/app/views/para/admin/resources/_filters.html.haml +9 -0
  97. data/app/views/para/admin/resources/_form.html.haml +6 -0
  98. data/app/views/para/admin/resources/_list.html.haml +22 -0
  99. data/app/views/para/admin/resources/_table.html.haml +8 -0
  100. data/app/views/para/admin/resources/_tree.html.haml +15 -0
  101. data/app/views/para/admin/resources/_tree_item.html.haml +16 -0
  102. data/app/views/para/admin/resources/edit.html.haml +6 -0
  103. data/app/views/para/admin/resources/new.html.haml +6 -0
  104. data/app/views/para/admin/settings_component/show.html.haml +12 -0
  105. data/app/views/para/admin/shared/_breadcrumb.html.haml +3 -0
  106. data/app/views/para/admin/shared/_header.html.haml +27 -0
  107. data/app/views/para/admin/shared/_navigation.html.haml +21 -0
  108. data/app/views/para/admin/singleton_resource_component/show.html.haml +5 -0
  109. data/app/views/para/inputs/_nested_many.html.haml +10 -0
  110. data/app/views/para/inputs/_nested_many_container.html.haml +19 -0
  111. data/app/views/para/inputs/_nested_one.html.haml +3 -0
  112. data/config/locales/en.yml +86 -0
  113. data/config/locales/fr.yml +101 -0
  114. data/db/migrate/20140911091225_create_para_components.rb +19 -0
  115. data/db/migrate/20140911112150_add_slug_to_para_components.rb +6 -0
  116. data/db/migrate/20140929125733_create_para_component_sections.rb +8 -0
  117. data/db/migrate/20140929131111_add_identifier_to_para_component_sections.rb +5 -0
  118. data/db/migrate/20140930121822_add_position_to_para_component_section.rb +5 -0
  119. data/db/migrate/20150129170710_create_para_component_resources.rb +13 -0
  120. data/db/migrate/20150203173219_add_identifier_to_para_components.rb +5 -0
  121. data/lib/generators/para/admin_user/admin_user_generator.rb +16 -0
  122. data/lib/generators/para/component/component_generator.rb +59 -0
  123. data/lib/generators/para/component/templates/component.rb +3 -0
  124. data/lib/generators/para/component/templates/component_controller.rb +7 -0
  125. data/lib/generators/para/component/templates/show.html.haml +2 -0
  126. data/lib/generators/para/exporter/exporter_generator.rb +42 -0
  127. data/lib/generators/para/exporter/templates/base_exporter.rb +15 -0
  128. data/lib/generators/para/exporter/templates/csv_exporter.rb +13 -0
  129. data/lib/generators/para/form/form_generator.rb +15 -0
  130. data/lib/generators/para/form/templates/_form.html.haml +7 -0
  131. data/lib/generators/para/install/install_generator.rb +112 -0
  132. data/lib/generators/para/install/templates/components.rb +13 -0
  133. data/lib/generators/para/install/templates/initializer.rb +23 -0
  134. data/lib/generators/para/nested_fields/nested_fields_generator.rb +15 -0
  135. data/lib/generators/para/nested_fields/templates/_nested_fields.html.haml +3 -0
  136. data/lib/generators/para/orderable/orderable_generator.rb +53 -0
  137. data/lib/generators/para/orderable/templates/orderable_migration.rb +6 -0
  138. data/lib/generators/para/resource/resource_generator.rb +71 -0
  139. data/lib/generators/para/resource/templates/resource_controller.rb +5 -0
  140. data/lib/generators/para/table/table_generator.rb +34 -0
  141. data/lib/generators/para/table/templates/_table.html.haml +10 -0
  142. data/lib/para/attribute_field/base.rb +77 -0
  143. data/lib/para/attribute_field/belongs_to.rb +29 -0
  144. data/lib/para/attribute_field/boolean.rb +15 -0
  145. data/lib/para/attribute_field/datetime.rb +9 -0
  146. data/lib/para/attribute_field/file.rb +20 -0
  147. data/lib/para/attribute_field/has_many.rb +31 -0
  148. data/lib/para/attribute_field/image.rb +25 -0
  149. data/lib/para/attribute_field/nested_many.rb +26 -0
  150. data/lib/para/attribute_field/nested_one.rb +27 -0
  151. data/lib/para/attribute_field/password.rb +18 -0
  152. data/lib/para/attribute_field/redactor.rb +20 -0
  153. data/lib/para/attribute_field/relation.rb +52 -0
  154. data/lib/para/attribute_field/translation.rb +9 -0
  155. data/lib/para/attribute_field_mappings.rb +82 -0
  156. data/lib/para/cloneable.rb +20 -0
  157. data/lib/para/component/exportable.rb +25 -0
  158. data/lib/para/component.rb +27 -0
  159. data/lib/para/components_configuration.rb +156 -0
  160. data/lib/para/config.rb +21 -0
  161. data/lib/para/engine.rb +59 -0
  162. data/lib/para/errors.rb +15 -0
  163. data/lib/para/exporter/base.rb +27 -0
  164. data/lib/para/exporter/csv.rb +49 -0
  165. data/lib/para/exporter.rb +57 -0
  166. data/lib/para/ext/cancan.rb +26 -0
  167. data/lib/para/ext/paperclip.rb +67 -0
  168. data/lib/para/ext.rb +13 -0
  169. data/lib/para/form_builder/containers.rb +70 -0
  170. data/lib/para/form_builder/field_mappings.rb +9 -0
  171. data/lib/para/form_builder/nested_form.rb +80 -0
  172. data/lib/para/form_builder/ordering.rb +15 -0
  173. data/lib/para/form_builder/settings.rb +24 -0
  174. data/lib/para/form_builder.rb +22 -0
  175. data/lib/para/generators/field_helpers.rb +32 -0
  176. data/lib/para/generators/name_helpers.rb +9 -0
  177. data/lib/para/generators/named_base.rb +7 -0
  178. data/lib/para/generators.rb +11 -0
  179. data/lib/para/inputs/nested_many_input.rb +40 -0
  180. data/lib/para/inputs/nested_one_input.rb +24 -0
  181. data/lib/para/inputs.rb +11 -0
  182. data/lib/para/markup/alert.rb +37 -0
  183. data/lib/para/markup/component.rb +20 -0
  184. data/lib/para/markup/modal.rb +52 -0
  185. data/lib/para/markup/panel.rb +41 -0
  186. data/lib/para/markup/resources_table.rb +178 -0
  187. data/lib/para/markup.rb +10 -0
  188. data/lib/para/model_field_parsers/base.rb +20 -0
  189. data/lib/para/model_field_parsers/devise.rb +37 -0
  190. data/lib/para/model_field_parsers/globalize.rb +23 -0
  191. data/lib/para/model_field_parsers/orderable.rb +15 -0
  192. data/lib/para/model_field_parsers/paperclip.rb +51 -0
  193. data/lib/para/model_field_parsers/redactor.rb +19 -0
  194. data/lib/para/model_field_parsers/relations.rb +67 -0
  195. data/lib/para/model_field_parsers.rb +22 -0
  196. data/lib/para/orderable.rb +44 -0
  197. data/lib/para/routes.rb +49 -0
  198. data/lib/para/version.rb +3 -0
  199. data/lib/para.rb +65 -0
  200. data/lib/rails/relation_length_validator.rb +45 -0
  201. data/lib/rails/routing_mapper.rb +27 -0
  202. data/lib/tasks/para_tasks.rake +22 -0
  203. metadata +595 -0
@@ -0,0 +1,163 @@
1
+ require_dependency "para/application_controller"
2
+
3
+ module Para
4
+ module Admin
5
+ class ResourcesController < Para::Admin::BaseController
6
+ include Para::ModelHelper
7
+
8
+ class_attribute :resource_name, :resource_class
9
+ load_and_authorize_component
10
+ helper_method :resource
11
+
12
+ def new
13
+ render 'para/admin/resources/new'
14
+ end
15
+
16
+ def create
17
+ # Assign component the resource belongs to it
18
+ resource.component = @component if resource.respond_to?(:component=)
19
+
20
+ if resource.save
21
+ flash_message(:success, resource)
22
+ redirect_to after_form_submit_path
23
+ else
24
+ flash_message(:error, resource)
25
+ render 'new'
26
+ end
27
+ end
28
+
29
+ def edit
30
+ render 'para/admin/resources/edit'
31
+ end
32
+
33
+ def update
34
+ if resource.update_attributes(resource_params)
35
+ flash_message(:success, resource)
36
+ redirect_to after_form_submit_path
37
+ else
38
+ flash_message(:error, resource)
39
+ render 'edit'
40
+ end
41
+ end
42
+
43
+ def destroy
44
+ resource.destroy
45
+ flash_message(:success, resource)
46
+ redirect_to @component.path
47
+ end
48
+
49
+ def order
50
+ ActiveRecord::Base.transaction do
51
+ resources_data.each do |resource_params|
52
+ resource = resources_hash[resource_params[:id]]
53
+ resource.position = resource_params[:position].to_i
54
+ resource.save(validate: false)
55
+ end
56
+ end
57
+
58
+ head 200
59
+ end
60
+
61
+ def tree
62
+ ActiveRecord::Base.transaction do
63
+ resources_data.each do |resource_params|
64
+ resource = resources_hash[resource_params[:id]]
65
+ resource.assign_attributes(
66
+ position: resource_params[:position].to_i,
67
+ parent_id: resource_params[:parent_id]
68
+ )
69
+ resource.save(validate: false)
70
+ end
71
+ end
72
+
73
+ head 200
74
+ end
75
+
76
+ private
77
+
78
+ def after_form_submit_path
79
+ if params[:_save_and_edit]
80
+ { action: 'edit', id: resource.to_param }
81
+ elsif params[:_save_and_add_another]
82
+ { action: 'new' }
83
+ else
84
+ params.delete(:return_to).presence || @component.path
85
+ end
86
+ end
87
+
88
+ def resource_model
89
+ self.class.resource_model
90
+ end
91
+
92
+ def resource
93
+ @resource ||= begin
94
+ self.class.ensure_resource_name_defined!
95
+ instance_variable_get(:"@#{ self.class.resource_name }")
96
+ end
97
+ end
98
+
99
+ def resource_params
100
+ @resource_params ||= parse_resource_params(
101
+ params.require(:resource).permit!
102
+ )
103
+ end
104
+
105
+ def parse_resource_params(hash)
106
+ model_field_mappings(resource_model).fields.each do |field|
107
+ field.parse_input(hash)
108
+ end
109
+
110
+ hash
111
+ end
112
+
113
+ def self.resource(name, options = {})
114
+ default_options = {
115
+ class: name.to_s.camelize,
116
+ through: :component,
117
+ parent: false
118
+ }
119
+
120
+ default_options.each do |key, value|
121
+ options[key] = value unless options.key?(key)
122
+ end
123
+
124
+ self.resource_name = name
125
+ self.resource_class = options[:class]
126
+
127
+ load_and_authorize_resource(name, options)
128
+ end
129
+
130
+ def self.resource_model
131
+ @resource_model ||= begin
132
+ ensure_resource_name_defined!
133
+ Para.const_get(resource_class)
134
+ end
135
+ end
136
+
137
+ def self.ensure_resource_name_defined!
138
+ unless resource_name.presence
139
+ raise "Resource not defined in your controller. " \
140
+ "You can define the resource of your controller with the " \
141
+ "`resource :resource_name` macro when subclassing " \
142
+ "Para::Admin::ResourcesController"
143
+ end
144
+ end
145
+
146
+ def resources_data
147
+ @resources_data ||= params[:resources].values
148
+ end
149
+
150
+ def resources_hash
151
+ @resources_hash ||= begin
152
+
153
+ ids = resources_data.map { |resource| resource[:id] }
154
+
155
+ resources = resource_model.where(id: ids)
156
+ resources.each_with_object({}) do |resource, hash|
157
+ hash[resource.id.to_s] = resource
158
+ end
159
+ end
160
+ end
161
+ end
162
+ end
163
+ end
@@ -0,0 +1,11 @@
1
+ module Para
2
+ module Admin
3
+ class SettingsComponentController < Para::Admin::BaseController
4
+ load_and_authorize_component
5
+
6
+ def show
7
+ @settings = SettingsRails::Form.new
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,21 @@
1
+ module Para
2
+ module Admin
3
+ class SettingsFormController < Para::Admin::BaseController
4
+ load_and_authorize_component
5
+
6
+ def update
7
+ form = SettingsRails::Form.new
8
+ form.settings_attributes = settings_params[:settings_attributes]
9
+ form.save
10
+ flash_message(:success, form)
11
+ redirect_to admin_settings_path(@component)
12
+ end
13
+
14
+ private
15
+
16
+ def settings_params
17
+ params.require(:resource).permit(settings_attributes: [:key, :_type, :value])
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,14 @@
1
+ module Para
2
+ module Admin
3
+ class SingletonResourceComponentController < Para::Admin::BaseController
4
+ load_and_authorize_component
5
+
6
+ attr_accessor :resource
7
+ helper_method :resource
8
+
9
+ def show
10
+ self.resource = @component.resource
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,30 @@
1
+ require_dependency "para/application_controller"
2
+
3
+ module Para
4
+ module Admin
5
+ class SingletonResourcesController < Para::Admin::ResourcesController
6
+ include Para::Admin::ResourceControllerConcerns
7
+
8
+ before_filter :load_and_authorize_singleton_resource
9
+ after_filter :attach_resource_to_component, only: [:create]
10
+
11
+ private
12
+
13
+ def attach_resource_to_component
14
+ return unless resource.persisted?
15
+ @component.resource = resource
16
+ @component.save
17
+ end
18
+
19
+ def load_and_authorize_singleton_resource
20
+ loader = self.class.cancan_resource_class.new(
21
+ self, :resource, parent: false, class: resource_model.name,
22
+ singleton: true, through: :component
23
+ )
24
+
25
+ loader.load_and_authorize_resource
26
+ instance_variable_set(:"@#{ resource_name }", @resource)
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,7 @@
1
+ module Para
2
+ class ApplicationController < ActionController::Base
3
+ def current_ability
4
+ @current_ability ||= Ability.new(current_admin_user)
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,48 @@
1
+ module Para
2
+ module Component
3
+ module BaseDecorator
4
+ include Rails.application.routes.mounted_helpers
5
+ include ActionDispatch::Routing::PolymorphicRoutes
6
+
7
+ def path(options = {})
8
+ find_path([:admin, self], options)
9
+ end
10
+
11
+ def relation_path(controller_or_resource, options = {})
12
+ find_path([:admin, self, controller_or_resource], options)
13
+ end
14
+
15
+ private
16
+
17
+ # Try to find a polymorphic path for the given arguments
18
+ #
19
+ # If no route exist, we try all the existing engines too
20
+ # This is quite dirty but for now should work as desired
21
+ # The only problem is if we have engines that declare the same routes
22
+ #
23
+ def find_path(path, options)
24
+ polymorphic_path(path, options)
25
+ rescue NoMethodError, NameError => original_error
26
+ mounted_proxy_methods.each do |proxy_method|
27
+ begin
28
+ proxy = send(proxy_method)
29
+ return polymorphic_path(([proxy] + path), options)
30
+ rescue NoMethodError, NameError => e
31
+ next
32
+ end
33
+ end
34
+
35
+ raise original_error
36
+ end
37
+
38
+ def mounted_proxy_methods
39
+ @mounted_proxy_methods ||= begin
40
+ routes = Rails.application.routes
41
+ routes.mounted_helpers.instance_methods.select do |name|
42
+ /^[^_]/ =~ name
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,32 @@
1
+ module Para
2
+ module Component
3
+ module CrudDecorator
4
+ include Para::Component::BaseDecorator
5
+
6
+ def relation_path(controller_or_resource, options = {})
7
+ if (id = extract_id_from(controller_or_resource))
8
+ options[:id] = id
9
+ end
10
+
11
+ route_key = route_key_for(options[:id], options)
12
+ options[:model] = model.model_name.singular_route_key
13
+
14
+ polymorphic_path([:admin, self, route_key].compact, options)
15
+ end
16
+
17
+ private
18
+
19
+ def extract_id_from(object)
20
+ object.id if object.respond_to?(:persisted?) && object.persisted?
21
+ end
22
+
23
+ def route_key_for(id, options)
24
+ if id || options[:action].presence && options[:action].to_sym == :new
25
+ :crud_resource
26
+ else
27
+ :crud_resources
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,11 @@
1
+ module Para
2
+ module Component
3
+ module SettingsDecorator
4
+ include Para::Component::BaseDecorator
5
+
6
+ def path(options = {})
7
+ admin_settings_path(self, options)
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,11 @@
1
+ module Para
2
+ module Component
3
+ module SingletonResourceDecorator
4
+ include Para::Component::BaseDecorator
5
+
6
+ def relation_path(controller_or_resource, options = {})
7
+ polymorphic_path([:admin, self, :singleton_resource].compact, options)
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,4 @@
1
+ module Para
2
+ module ComponentSectionDecorator
3
+ end
4
+ end
@@ -0,0 +1,57 @@
1
+ module Para
2
+ module Admin
3
+ module BaseHelper
4
+ include Para::ApplicationHelper
5
+
6
+ def find_partial_for(relation, partial)
7
+ if relation.kind_of? ActiveRecord::Base
8
+ relation = relation.class
9
+ end
10
+
11
+ relation = relation.to_s.underscore.pluralize
12
+
13
+ if lookup_context.find_all("admin/#{relation}/_#{ partial }").any?
14
+ "admin/#{ relation }/#{ partial }"
15
+ else
16
+ "para/admin/resources/#{ partial }"
17
+ end
18
+ end
19
+
20
+ def template_path_lookup(*paths)
21
+ paths.find do |path|
22
+ lookup_context.find_all(path).any?
23
+ end
24
+ end
25
+
26
+ def resource_title_for(resource)
27
+ resource.try(:title) || resource.try(:name) ||
28
+ t('para.form.shared.edit.title', model: resource.class.model_name.human)
29
+ end
30
+
31
+ def registered_components_options
32
+ Para::Component.registered_components.keys.map do |identifier|
33
+ [
34
+ t("para.component.#{ identifier }.name", default: identifier.to_s.humanize),
35
+ identifier
36
+ ]
37
+ end
38
+ end
39
+
40
+ def flash_message(type, resource = nil)
41
+ key = "#{ flash_shared_key }.#{ params[:action] }.#{ type }"
42
+
43
+ translation = if resource
44
+ I18n.t(key, model: resource.class.model_name.human)
45
+ else
46
+ I18n.t(key)
47
+ end
48
+
49
+ flash[type] = translation
50
+ end
51
+
52
+ def flash_shared_key
53
+ 'para.flash.shared'
54
+ end
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,4 @@
1
+ module Para
2
+ module Admin::ComponentGroupsHelper
3
+ end
4
+ end
@@ -0,0 +1,4 @@
1
+ module Para
2
+ module Admin::ComponentsHelper
3
+ end
4
+ end
@@ -0,0 +1,27 @@
1
+ module Para
2
+ module Admin
3
+ module ResourcesHelper
4
+ def resource_form_path(resource)
5
+ if resource.new_record?
6
+ resource_path(resource, :index)
7
+ else
8
+ resource_path(resource, :show)
9
+ end
10
+ end
11
+
12
+ def resource_path(resource, action =:index)
13
+ resource = resource.kind_of?(Class) ? resource.new : resource
14
+ route_key = resource.class.model_name.route_key
15
+
16
+ component_path = @component && @component.to_param
17
+ id = resource.id
18
+
19
+ if [:index, :show, :create, :update, :destroy].include?(action)
20
+ action = nil
21
+ end
22
+
23
+ ["", "admin", component_path, route_key, id, action].compact.join('/')
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,14 @@
1
+ module Para
2
+ module ApplicationHelper
3
+ include Para::SearchHelper
4
+ include Para::ModelHelper
5
+ include Para::OrderingHelper
6
+ include Para::NavigationHelper
7
+ include Para::FormHelper
8
+ include Para::MarkupHelper
9
+ include Para::TagHelper
10
+ include Para::TreeHelper
11
+ include Para::FlashHelper
12
+ include Para::ExportsHelper
13
+ end
14
+ end
@@ -0,0 +1,11 @@
1
+ module Para
2
+ module ExportsHelper
3
+ def export_name_for(model, export)
4
+ model_name = (
5
+ export[:model] && export[:model].constantize.model_name.human
6
+ ) || model.model_name.human
7
+
8
+ t('para.export.name', name: model_name)
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,48 @@
1
+ module Para
2
+ module FlashHelper
3
+ def display_admin_flash
4
+ # Render empty string if no flash
5
+ return "" if flash.empty?
6
+
7
+ # Make a div.alert for each message and join the whole
8
+ messages = flash.map do |type, message|
9
+ flash.delete(type)
10
+ type = homogenize_flash_type(type)
11
+
12
+ icon = content_tag(:div, class: "alert-icon-container pull-left") do
13
+ content_tag(:i, "", class: "fa #{ icon_class_for(type) }") +
14
+ '&nbsp;'.html_safe
15
+ end
16
+
17
+ alert(type: type) do
18
+ icon + content_tag(:p, message.html_safe)
19
+ end
20
+ end
21
+
22
+ # Join the messages and make sure markup is correctly displayed
23
+ messages.join.html_safe
24
+ end
25
+
26
+ private
27
+
28
+ # Converts flash types to :success or :error to conform to what
29
+ # twitter bootstrap can handle
30
+ #
31
+ def homogenize_flash_type type
32
+ case type.to_sym
33
+ when :notice then :success
34
+ when :alert then :warning
35
+ when :error then :danger
36
+ else type
37
+ end
38
+ end
39
+
40
+ def icon_class_for type
41
+ case type
42
+ when :success then "fa-check"
43
+ when :error then "fa-warning"
44
+ else "fa-exclamation-triangle"
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,28 @@
1
+ module Para
2
+ module FormHelper
3
+ def para_form_for(resource, options = {}, &block)
4
+ default_options = {
5
+ as: :resource,
6
+ wrapper: :horizontal_form,
7
+ html: { class: '' }
8
+ }
9
+
10
+ options = default_options.deep_merge(options)
11
+
12
+ options[:html][:class] = [
13
+ options[:html][:class].presence,
14
+ 'form-horizontal form-group-separated'
15
+ ].compact.join(' ')
16
+
17
+ unless options.key?(:url)
18
+ options[:url] = @component.relation_path(resource)
19
+ end
20
+
21
+ if options.fetch(:fixed_actions, true)
22
+ default_options[:html][:class] << ' form-fixed-actions'
23
+ end
24
+
25
+ simple_form_for(resource, options, &block)
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,15 @@
1
+ module Para
2
+ module MarkupHelper
3
+ def alert(message, options = {}, &block)
4
+ Para::Markup::Alert.new(self).container(message, options, &block)
5
+ end
6
+
7
+ def resources_table(options = {}, &block)
8
+ Para::Markup::ResourcesTable.new(self).container(options, &block)
9
+ end
10
+
11
+ def panel(options = {}, &block)
12
+ Para::Markup::Panel.new(self).container(options, &block)
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,38 @@
1
+ module Para
2
+ module ModelHelper
3
+ def attribute_field_mappings_for(component, relation)
4
+ model = relation_klass_for(component, relation)
5
+ model_field_mappings(model).fields
6
+ end
7
+
8
+ def model_field_mappings(model, attributes = nil)
9
+ store_key = ['model', 'mappings', model.name.underscore].join(':')
10
+
11
+ Para.store[store_key] ||= Para::AttributeFieldMappings.new(
12
+ model, whitelist_attributes: attributes
13
+ )
14
+ end
15
+
16
+ def relation_klass_for(component, relation)
17
+ component.class.reflect_on_association(relation).klass
18
+ end
19
+
20
+ def field_value_for(object, field_name, type = nil)
21
+ field = model_field_mappings(object.class).field_for(field_name, type)
22
+ value = field.value_for(object)
23
+ excerpt_value_for(value)
24
+ end
25
+
26
+ def excerpt_value_for(value)
27
+ return value unless value.kind_of?(String)
28
+
29
+ value = sanitize(value, tags: [])
30
+
31
+ if (truncated = value[0..100]) != value
32
+ "#{ truncated }..."
33
+ else
34
+ value
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,8 @@
1
+ module Para
2
+ module NavigationHelper
3
+ def component_section_active?(component_section)
4
+ (@component_section && @component_section == component_section) ||
5
+ (@component && @component.component_section_id == component_section.id)
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,20 @@
1
+ module Para
2
+ module OrderingHelper
3
+ def reorder_anchor(options = {})
4
+ options[:class] ||= ''
5
+ options[:class] = [options[:class], 'order-anchor'].join(' ')
6
+
7
+ field = if (form = options.delete(:form))
8
+ form.hidden_field(:position, class: 'resource-position-field')
9
+ else
10
+ value = options.delete(:value) || 0
11
+ hidden_field_tag(:position, value, class: 'resource-position-field')
12
+ end
13
+
14
+ content_tag(:span, options) do
15
+ content_tag(:i, '', class: 'fa fa-bars') +
16
+ field
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,22 @@
1
+ module Para
2
+ module SearchHelper
3
+ def fulltext_search_param_for(attributes)
4
+ "#{ searchable_attributes(attributes) }_cont"
5
+ end
6
+
7
+ def filtered?(attributes)
8
+ params[:q] && params[:q][fulltext_search_param_for(attributes)].present?
9
+ end
10
+
11
+ def searchable_attributes(attributes)
12
+ whitelist = attributes.select do |attribute|
13
+ [:string, :text].include?(attribute.type.to_sym) &&
14
+ !attribute.name.match(/password/)
15
+ end
16
+
17
+ whitelist.map do |attribute|
18
+ attribute.attribute_column_path.join('_')
19
+ end.join('_or_')
20
+ end
21
+ end
22
+ end