releaf-core 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (288) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +24 -0
  3. data/app/assets/fonts/releaf/RobotoRegular_normal_400.ttf +0 -0
  4. data/app/assets/fonts/releaf/RobotoRegular_normal_400.woff +0 -0
  5. data/app/assets/fonts/releaf/RobotoRegular_normal_400.woff2 +0 -0
  6. data/app/assets/images/releaf/icons/apple-touch-icon-114x114-precomposed.png +0 -0
  7. data/app/assets/images/releaf/icons/apple-touch-icon-152x152-precomposed.png +0 -0
  8. data/app/assets/images/releaf/icons/apple-touch-icon-72x72-precomposed.png +0 -0
  9. data/app/assets/images/releaf/icons/favicon.ico +0 -0
  10. data/app/assets/images/releaf/icons/favicon.png +0 -0
  11. data/app/assets/images/releaf/icons/msapplication-tile-144x144.png +0 -0
  12. data/app/assets/images/releaf/logo-login.png +0 -0
  13. data/app/assets/images/releaf/logo.png +0 -0
  14. data/app/assets/javascripts/ckeditor/plugins/mediaembed/icons/hidpi/mediaembed.png +0 -0
  15. data/app/assets/javascripts/ckeditor/plugins/mediaembed/icons/mediaembed.png +0 -0
  16. data/app/assets/javascripts/ckeditor/plugins/mediaembed/lang/en.js +12 -0
  17. data/app/assets/javascripts/ckeditor/plugins/mediaembed/lang/es.js +12 -0
  18. data/app/assets/javascripts/ckeditor/plugins/mediaembed/plugin.js +63 -0
  19. data/app/assets/javascripts/releaf/3rd_party/jquery-ui-timepicker-addon.js +1882 -0
  20. data/app/assets/javascripts/releaf/3rd_party/jquery.magnific-popup.min.js +4 -0
  21. data/app/assets/javascripts/releaf/application.js +13 -0
  22. data/app/assets/javascripts/releaf/include/ajax.js +66 -0
  23. data/app/assets/javascripts/releaf/include/ajaxbox.js +179 -0
  24. data/app/assets/javascripts/releaf/include/dialogs.js +13 -0
  25. data/app/assets/javascripts/releaf/include/field.type_associated_set.js +32 -0
  26. data/app/assets/javascripts/releaf/include/field.type_date_or_datetime_or_time.js +73 -0
  27. data/app/assets/javascripts/releaf/include/field.type_richtext.js +188 -0
  28. data/app/assets/javascripts/releaf/include/loader.js +45 -0
  29. data/app/assets/javascripts/releaf/include/localization.js +213 -0
  30. data/app/assets/javascripts/releaf/include/nested_fields.js +295 -0
  31. data/app/assets/javascripts/releaf/include/notifications.js +267 -0
  32. data/app/assets/javascripts/releaf/include/pagination.js +19 -0
  33. data/app/assets/javascripts/releaf/include/profile_settings.js +28 -0
  34. data/app/assets/javascripts/releaf/include/remote_validator.js +437 -0
  35. data/app/assets/javascripts/releaf/include/search.js +140 -0
  36. data/app/assets/javascripts/releaf/include/sidebar.js +149 -0
  37. data/app/assets/javascripts/releaf/include/sortable.js +69 -0
  38. data/app/assets/javascripts/releaf/include/toolbox.js +221 -0
  39. data/app/assets/javascripts/releaf/include/url_builder.js +193 -0
  40. data/app/assets/stylesheets/releaf/application.scss +9 -0
  41. data/app/assets/stylesheets/releaf/environment/extras.scss +11 -0
  42. data/app/assets/stylesheets/releaf/environment/functions/units.scss +12 -0
  43. data/app/assets/stylesheets/releaf/environment/functions.scss +1 -0
  44. data/app/assets/stylesheets/releaf/environment/mixins/blocks.scss +133 -0
  45. data/app/assets/stylesheets/releaf/environment/mixins/elements.scss +64 -0
  46. data/app/assets/stylesheets/releaf/environment/mixins/text.scss +61 -0
  47. data/app/assets/stylesheets/releaf/environment/mixins.scss +3 -0
  48. data/app/assets/stylesheets/releaf/environment/variables/colors.scss +93 -0
  49. data/app/assets/stylesheets/releaf/environment/variables/dimensions.scss +0 -0
  50. data/app/assets/stylesheets/releaf/environment/variables/magnific-popup.scss +6 -0
  51. data/app/assets/stylesheets/releaf/environment/variables.scss +5 -0
  52. data/app/assets/stylesheets/releaf/environment.scss +4 -0
  53. data/app/assets/stylesheets/releaf/layout/base.scss +32 -0
  54. data/app/assets/stylesheets/releaf/layout/breadcrumbs.scss +47 -0
  55. data/app/assets/stylesheets/releaf/layout/buttons.scss +107 -0
  56. data/app/assets/stylesheets/releaf/layout/deprecated.scss +29 -0
  57. data/app/assets/stylesheets/releaf/layout/dialogs.scss +138 -0
  58. data/app/assets/stylesheets/releaf/layout/errors.scss +28 -0
  59. data/app/assets/stylesheets/releaf/layout/extras.scss +10 -0
  60. data/app/assets/stylesheets/releaf/layout/fields.scss +305 -0
  61. data/app/assets/stylesheets/releaf/layout/fonts.scss +16 -0
  62. data/app/assets/stylesheets/releaf/layout/footer.scss +80 -0
  63. data/app/assets/stylesheets/releaf/layout/forms.scss +23 -0
  64. data/app/assets/stylesheets/releaf/layout/header.scss +55 -0
  65. data/app/assets/stylesheets/releaf/layout/icons.scss +4 -0
  66. data/app/assets/stylesheets/releaf/layout/images.scss +4 -0
  67. data/app/assets/stylesheets/releaf/layout/links.scss +7 -0
  68. data/app/assets/stylesheets/releaf/layout/localization.scss +79 -0
  69. data/app/assets/stylesheets/releaf/layout/main.scss +43 -0
  70. data/app/assets/stylesheets/releaf/layout/notifications.scss +67 -0
  71. data/app/assets/stylesheets/releaf/layout/pagination.scss +18 -0
  72. data/app/assets/stylesheets/releaf/layout/search.scss +70 -0
  73. data/app/assets/stylesheets/releaf/layout/sections.scss +138 -0
  74. data/app/assets/stylesheets/releaf/layout/sidebar.scss +306 -0
  75. data/app/assets/stylesheets/releaf/layout/tables.scss +99 -0
  76. data/app/assets/stylesheets/releaf/layout/text.scss +31 -0
  77. data/app/assets/stylesheets/releaf/layout/toolboxes.scss +69 -0
  78. data/app/assets/stylesheets/releaf/layout.scss +35 -0
  79. data/app/assets/stylesheets/releaf/vendor/magnific-popup/main.scss +596 -0
  80. data/app/assets/stylesheets/releaf/vendor/magnific-popup/settings.scss +45 -0
  81. data/app/builders/releaf/builders/association_reflector.rb +58 -0
  82. data/app/builders/releaf/builders/base.rb +80 -0
  83. data/app/builders/releaf/builders/collection.rb +8 -0
  84. data/app/builders/releaf/builders/confirm_destroy_dialog_builder.rb +25 -0
  85. data/app/builders/releaf/builders/confirm_dialog_builder.rb +54 -0
  86. data/app/builders/releaf/builders/edit_builder.rb +66 -0
  87. data/app/builders/releaf/builders/form_builder.rb +594 -0
  88. data/app/builders/releaf/builders/index_builder.rb +118 -0
  89. data/app/builders/releaf/builders/orderer.rb +5 -0
  90. data/app/builders/releaf/builders/page/header_builder.rb +70 -0
  91. data/app/builders/releaf/builders/page/layout_builder.rb +155 -0
  92. data/app/builders/releaf/builders/page/menu_builder.rb +140 -0
  93. data/app/builders/releaf/builders/pagination_builder.rb +107 -0
  94. data/app/builders/releaf/builders/refused_destroy_dialog_builder.rb +68 -0
  95. data/app/builders/releaf/builders/resource.rb +9 -0
  96. data/app/builders/releaf/builders/resource_dialog.rb +8 -0
  97. data/app/builders/releaf/builders/resource_view.rb +54 -0
  98. data/app/builders/releaf/builders/show_builder.rb +3 -0
  99. data/app/builders/releaf/builders/table_builder.rb +280 -0
  100. data/app/builders/releaf/builders/tags/releaf_associated_set_field.rb +40 -0
  101. data/app/builders/releaf/builders/template.rb +8 -0
  102. data/app/builders/releaf/builders/toolbox.rb +23 -0
  103. data/app/builders/releaf/builders/toolbox_builder.rb +27 -0
  104. data/app/builders/releaf/builders/view.rb +132 -0
  105. data/app/builders/releaf/builders.rb +38 -0
  106. data/app/builders/releaf/core/settings/form_builder.rb +21 -0
  107. data/app/builders/releaf/core/settings/table_builder.rb +11 -0
  108. data/app/controllers/concerns/releaf/breadcrumbs.rb +42 -0
  109. data/app/controllers/concerns/releaf/richtext_attachments.rb +20 -0
  110. data/app/controllers/releaf/base_controller.rb +458 -0
  111. data/app/controllers/releaf/core/errors_controller.rb +5 -0
  112. data/app/controllers/releaf/core/settings_controller.rb +50 -0
  113. data/app/helpers/releaf/application_helper.rb +53 -0
  114. data/app/helpers/releaf/button_helper.rb +50 -0
  115. data/app/helpers/releaf/javascript_helper.rb +75 -0
  116. data/app/lib/releaf/core/assets_resolver.rb +58 -0
  117. data/app/lib/releaf/core/default_searchable_fields.rb +43 -0
  118. data/app/lib/releaf/core/error_formatter.rb +103 -0
  119. data/app/lib/releaf/core/item_orderer.rb +102 -0
  120. data/app/lib/releaf/core/resource_base.rb +66 -0
  121. data/app/lib/releaf/core/resource_fields.rb +6 -0
  122. data/app/lib/releaf/core/resource_params.rb +47 -0
  123. data/app/lib/releaf/core/resource_table_fields.rb +10 -0
  124. data/app/lib/releaf/core/resource_utilities.rb +36 -0
  125. data/app/lib/releaf/core/responders/access_denied_responder.rb +9 -0
  126. data/app/lib/releaf/core/responders/after_save_responder.rb +28 -0
  127. data/app/lib/releaf/core/responders/confirm_destroy_responder.rb +13 -0
  128. data/app/lib/releaf/core/responders/destroy_responder.rb +10 -0
  129. data/app/lib/releaf/core/responders/error_responder.rb +9 -0
  130. data/app/lib/releaf/core/responders/feature_disabled_responder.rb +9 -0
  131. data/app/lib/releaf/core/responders/page_not_found_responder.rb +9 -0
  132. data/app/lib/releaf/core/responders.rb +31 -0
  133. data/app/lib/releaf/core/search.rb +147 -0
  134. data/app/lib/releaf/core/template_field_type_mapper.rb +127 -0
  135. data/app/models/releaf/richtext_attachment.rb +6 -0
  136. data/app/models/releaf/settings.rb +27 -0
  137. data/app/views/layouts/releaf/admin.html.erb +1 -0
  138. data/app/views/releaf/base/confirm_destroy.ruby +1 -0
  139. data/app/views/releaf/base/create_releaf_richtext_attachment.haml +1 -0
  140. data/app/views/releaf/base/edit.ruby +1 -0
  141. data/app/views/releaf/base/index.ruby +1 -0
  142. data/app/views/releaf/base/new.ruby +1 -0
  143. data/app/views/releaf/base/refused_destroy.ruby +1 -0
  144. data/app/views/releaf/base/show.ruby +1 -0
  145. data/app/views/releaf/base/toolbox.ruby +1 -0
  146. data/app/views/releaf/error_pages/_error.html.haml +10 -0
  147. data/app/views/releaf/error_pages/access_denied.html.haml +1 -0
  148. data/app/views/releaf/error_pages/feature_disabled.html.haml +1 -0
  149. data/app/views/releaf/error_pages/page_not_found.html.haml +2 -0
  150. data/lib/generators/dummy/install_generator.rb +18 -0
  151. data/lib/generators/dummy/templates/builders/admin/books/form_builder.rb +13 -0
  152. data/lib/generators/dummy/templates/builders/admin/books/index_builder.rb +30 -0
  153. data/lib/generators/dummy/templates/builders/admin/books/table_builder.rb +7 -0
  154. data/lib/generators/dummy/templates/builders/admin/nodes/form_builder.rb +7 -0
  155. data/lib/generators/dummy/templates/config/routes.rb +19 -0
  156. data/lib/generators/dummy/templates/controllers/admin/authors_controller.rb +12 -0
  157. data/lib/generators/dummy/templates/controllers/admin/books_controller.rb +17 -0
  158. data/lib/generators/dummy/templates/controllers/admin/chapters_controller.rb +3 -0
  159. data/lib/generators/dummy/templates/controllers/admin/publishers_controller.rb +3 -0
  160. data/lib/generators/dummy/templates/controllers/application_controller.rb +39 -0
  161. data/lib/generators/dummy/templates/controllers/concerns/.keep +0 -0
  162. data/lib/generators/dummy/templates/controllers/concerns/node_controller.rb +37 -0
  163. data/lib/generators/dummy/templates/controllers/contacts_controller.rb +3 -0
  164. data/lib/generators/dummy/templates/controllers/home_pages_controller.rb +3 -0
  165. data/lib/generators/dummy/templates/controllers/text_pages_controller.rb +3 -0
  166. data/lib/generators/dummy/templates/initializers/releaf.rb +35 -0
  167. data/lib/generators/dummy/templates/migrations/create_authors.rb +14 -0
  168. data/lib/generators/dummy/templates/migrations/create_banners.rb +11 -0
  169. data/lib/generators/dummy/templates/migrations/create_book_sequels.rb +14 -0
  170. data/lib/generators/dummy/templates/migrations/create_books.rb +27 -0
  171. data/lib/generators/dummy/templates/migrations/create_bundles.rb +7 -0
  172. data/lib/generators/dummy/templates/migrations/create_chapters.rb +13 -0
  173. data/lib/generators/dummy/templates/migrations/create_home_pages.rb +9 -0
  174. data/lib/generators/dummy/templates/migrations/create_node_extra_fields.rb +5 -0
  175. data/lib/generators/dummy/templates/migrations/create_publishers.rb +8 -0
  176. data/lib/generators/dummy/templates/migrations/create_text_pages.rb +9 -0
  177. data/lib/generators/dummy/templates/models/author.rb +10 -0
  178. data/lib/generators/dummy/templates/models/banner.rb +5 -0
  179. data/lib/generators/dummy/templates/models/book.rb +19 -0
  180. data/lib/generators/dummy/templates/models/book_sequel.rb +4 -0
  181. data/lib/generators/dummy/templates/models/bundle.rb +17 -0
  182. data/lib/generators/dummy/templates/models/chapter.rb +7 -0
  183. data/lib/generators/dummy/templates/models/home_page.rb +5 -0
  184. data/lib/generators/dummy/templates/models/node.rb +10 -0
  185. data/lib/generators/dummy/templates/models/publisher.rb +9 -0
  186. data/lib/generators/dummy/templates/models/text_page.rb +5 -0
  187. data/lib/generators/dummy/templates/views/contacts/show.html.haml +1 -0
  188. data/lib/generators/dummy/templates/views/home_pages/show.haml +1 -0
  189. data/lib/generators/dummy/templates/views/layouts/application.html.haml +22 -0
  190. data/lib/generators/dummy/templates/views/text_pages/show.haml +1 -0
  191. data/lib/generators/releaf/install_generator.rb +93 -0
  192. data/lib/generators/releaf/templates/initializers/haml.rb +1 -0
  193. data/lib/generators/releaf/templates/initializers/releaf.rb +30 -0
  194. data/lib/generators/releaf/templates/migrations/create_releaf_nodes.rb +28 -0
  195. data/lib/generators/releaf/templates/migrations/create_releaf_permissions.rb +12 -0
  196. data/lib/generators/releaf/templates/migrations/create_releaf_richtext_attachments.rb +12 -0
  197. data/lib/generators/releaf/templates/migrations/create_releaf_roles.rb +9 -0
  198. data/lib/generators/releaf/templates/migrations/create_releaf_settings.rb +17 -0
  199. data/lib/generators/releaf/templates/migrations/create_releaf_translations.rb +21 -0
  200. data/lib/generators/releaf/templates/migrations/create_releaf_users.rb +52 -0
  201. data/lib/generators/releaf/templates/models/node.rb +3 -0
  202. data/lib/generators/releaf/templates/seeds/seeds.rb +54 -0
  203. data/lib/releaf/core/application.rb +17 -0
  204. data/lib/releaf/core/builders_autoload.rb +27 -0
  205. data/lib/releaf/core/component.rb +9 -0
  206. data/lib/releaf/core/configuration.rb +101 -0
  207. data/lib/releaf/core/engine.rb +35 -0
  208. data/lib/releaf/core/exceptions.rb +38 -0
  209. data/lib/releaf/core/route_mapper.rb +59 -0
  210. data/lib/releaf/core/settings_ui_component.rb +7 -0
  211. data/lib/releaf/core/validation_error_codes.rb +36 -0
  212. data/lib/releaf/version.rb +3 -0
  213. data/lib/releaf-core.rb +14 -0
  214. data/lib/tasks/releaf_tasks.rake +4 -0
  215. data/releaf-core.gemspec +35 -0
  216. data/spec/builders/builders/association_reflector_spec.rb +138 -0
  217. data/spec/builders/builders/base_spec.rb +276 -0
  218. data/spec/builders/builders/collection_spec.rb +18 -0
  219. data/spec/builders/builders/confirm_destroy_dialog_builder_spec.rb +71 -0
  220. data/spec/builders/builders/confirm_dialog_builder_spec.rb +105 -0
  221. data/spec/builders/builders/edit_builder_spec.rb +215 -0
  222. data/spec/builders/builders/form_builder_spec.rb +562 -0
  223. data/spec/builders/builders/index_builder_spec.rb +345 -0
  224. data/spec/builders/builders/orderer_spec.rb +22 -0
  225. data/spec/builders/builders/page/header_builder_spec.rb +143 -0
  226. data/spec/builders/builders/page/layout_builder_spec.rb +73 -0
  227. data/spec/builders/builders/page/menu_builder_spec.rb +160 -0
  228. data/spec/builders/builders/pagination_builder_spec.rb +330 -0
  229. data/spec/builders/builders/resource_dialog_spec.rb +21 -0
  230. data/spec/builders/builders/resource_view_spec.rb +158 -0
  231. data/spec/builders/builders/show_builder_spec.rb +7 -0
  232. data/spec/builders/builders/table_builder_spec.rb +638 -0
  233. data/spec/builders/builders/template_spec.rb +12 -0
  234. data/spec/builders/builders/toolbox_builder_spec.rb +67 -0
  235. data/spec/builders/builders/toolbox_spec.rb +48 -0
  236. data/spec/builders/builders/view_spec.rb +281 -0
  237. data/spec/builders/builders_spec.rb +134 -0
  238. data/spec/builders/core/settings/form_builder_spec.rb +69 -0
  239. data/spec/builders/core/settings/table_builder_spec.rb +21 -0
  240. data/spec/controllers/concerns/releaf/richtext_attachments_spec.rb +51 -0
  241. data/spec/controllers/releaf/base_controller_spec.rb +447 -0
  242. data/spec/controllers/releaf/core/settings_controller_spec.rb +31 -0
  243. data/spec/features/ajaxbox_spec.rb +111 -0
  244. data/spec/features/authorization_spec.rb +50 -0
  245. data/spec/features/dragonfly_integration_spec.rb +24 -0
  246. data/spec/features/edit_actions_spec.rb +142 -0
  247. data/spec/features/errors_spec.rb +29 -0
  248. data/spec/features/index_actions_spec.rb +85 -0
  249. data/spec/features/index_table_spec.rb +32 -0
  250. data/spec/features/menu_spec.rb +71 -0
  251. data/spec/features/richtext_attachments_spec.rb +64 -0
  252. data/spec/features/richtext_embed_spec.rb +29 -0
  253. data/spec/features/richtext_spec.rb +19 -0
  254. data/spec/features/search_spec.rb +825 -0
  255. data/spec/features/settings_spec.rb +38 -0
  256. data/spec/features/title_spec.rb +13 -0
  257. data/spec/fixtures/common_fields.yml +17 -0
  258. data/spec/fixtures/cs.png +0 -0
  259. data/spec/fixtures/time.formats.xlsx +0 -0
  260. data/spec/fixtures/unicorn.jpg +0 -0
  261. data/spec/helpers/application_helper_spec.rb +75 -0
  262. data/spec/helpers/button_helper_spec.rb +146 -0
  263. data/spec/lib/releaf/core/application_spec.rb +42 -0
  264. data/spec/lib/releaf/core/assets_resolver_spec.rb +113 -0
  265. data/spec/lib/releaf/core/configuration_spec.rb +230 -0
  266. data/spec/lib/releaf/core/default_searchable_fields_spec.rb +161 -0
  267. data/spec/lib/releaf/core/error_formatter_spec.rb +242 -0
  268. data/spec/lib/releaf/core/item_orderer_spec.rb +142 -0
  269. data/spec/lib/releaf/core/resource_base_spec.rb +174 -0
  270. data/spec/lib/releaf/core/resource_fields_spec.rb +12 -0
  271. data/spec/lib/releaf/core/resource_params_spec.rb +117 -0
  272. data/spec/lib/releaf/core/resource_table_fields_spec.rb +18 -0
  273. data/spec/lib/releaf/core/resource_utilities_spec.rb +87 -0
  274. data/spec/lib/releaf/core/responders/access_denied_responder_spec.rb +12 -0
  275. data/spec/lib/releaf/core/responders/after_save_responder_spec.rb +102 -0
  276. data/spec/lib/releaf/core/responders/confirm_destroy_responder_spec.rb +26 -0
  277. data/spec/lib/releaf/core/responders/destroy_responder_spec.rb +30 -0
  278. data/spec/lib/releaf/core/responders/error_responder_spec.rb +26 -0
  279. data/spec/lib/releaf/core/responders/feature_disabled_responder_spec.rb +12 -0
  280. data/spec/lib/releaf/core/responders/page_not_found_responder_spec.rb +12 -0
  281. data/spec/lib/releaf/core/responders_spec.rb +60 -0
  282. data/spec/lib/releaf/core/template_field_type_mapper_spec.rb +311 -0
  283. data/spec/lib/validation_error_codes_spec.rb +56 -0
  284. data/spec/misc/factories_spec.rb +43 -0
  285. data/spec/models/settings_spec.rb +58 -0
  286. data/spec/routing/route_mapper_spec.rb +185 -0
  287. data/spec/rspec_helpers/test_helpers_spec.rb +20 -0
  288. metadata +657 -0
@@ -0,0 +1,59 @@
1
+ module Releaf::Core::RouteMapper
2
+ # Pass given resource to "resources" mount method and
3
+ # add extra routes for members and collections needed by releaf
4
+ def releaf_resources(*args, &block)
5
+ resources *args do
6
+ yield if block_given?
7
+ member do
8
+ get :confirm_destroy if route_enabled?(:destroy, args.last)
9
+ get :toolbox if route_enabled?(:toolbox, args.last)
10
+ end
11
+ collection do
12
+ post :create_releaf_richtext_attachment if route_enabled?(:releaf_richtext_attachments, args.last)
13
+ end
14
+ end
15
+ end
16
+
17
+ def initialize_releaf_components
18
+ Releaf.application.config.components.each do|component_class|
19
+ if component_class.respond_to? :draw_component_routes
20
+ component_class.draw_component_routes(self)
21
+ end
22
+ end
23
+ end
24
+
25
+ def mount_releaf_at(mount_location, options={}, &block)
26
+ mount_location_namespace = mount_location.gsub("/", "").to_sym
27
+ Releaf.application.config.mount_location = mount_location_namespace.to_s
28
+ scope mount_location do
29
+ initialize_releaf_components
30
+
31
+ if mount_location_namespace.empty?
32
+ yield if block_given?
33
+ else
34
+ namespace mount_location_namespace, path: nil do
35
+ yield if block_given?
36
+ end
37
+ end
38
+
39
+ namespace :releaf, path: nil do
40
+ get '/*path' => 'core/errors#page_not_found'
41
+ end
42
+ end
43
+ end
44
+
45
+ private
46
+
47
+ def route_enabled?(route, options)
48
+ include_route = true
49
+ if options.is_a? Hash
50
+ if options[:only] && !options[:only].include?(route.to_sym)
51
+ include_route = false
52
+ elsif options[:except].try(:include?, route.to_sym)
53
+ include_route = false
54
+ end
55
+ end
56
+
57
+ include_route
58
+ end
59
+ end
@@ -0,0 +1,7 @@
1
+ module Releaf::Core::SettingsUIComponent
2
+ extend Releaf::Core::Component
3
+
4
+ def self.draw_component_routes router
5
+ resource_route(router, :core, :settings)
6
+ end
7
+ end
@@ -0,0 +1,36 @@
1
+ module ActiveModel
2
+ class ErrorMessage < String
3
+ attr_accessor :error_code, :data
4
+
5
+ def initialize(message, error_code = nil, data = nil)
6
+ super message
7
+ @error_code = error_code
8
+ @data = data
9
+ end
10
+ end
11
+
12
+ class Errors
13
+ def add(attribute, message = nil, options = {})
14
+ # build error code from message symbol
15
+ error_code = normalize_error_code(attribute, message, options)
16
+ message = normalize_message(attribute, message, options)
17
+ if exception = options[:strict]
18
+ exception = ActiveModel::StrictValidationFailed if exception == true
19
+ raise exception, full_message(attribute, message)
20
+ end
21
+
22
+ # use customized String subclass with "error_code" attribute
23
+ self[attribute] << ErrorMessage.new(message, error_code, options[:data])
24
+ end
25
+
26
+ def normalize_error_code(attribute, message, options)
27
+ if !options[:error_code].blank?
28
+ options[:error_code]
29
+ elsif message.class == Symbol
30
+ message
31
+ else
32
+ :invalid
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,3 @@
1
+ module Releaf
2
+ VERSION = "0.2.1"
3
+ end
@@ -0,0 +1,14 @@
1
+ module Releaf
2
+ require 'releaf/core/engine'
3
+ require 'releaf/core/configuration'
4
+ require 'releaf/core/application'
5
+ require 'releaf/core/route_mapper'
6
+ require 'releaf/core/exceptions'
7
+ require 'releaf/core/validation_error_codes'
8
+
9
+ class << self
10
+ def application
11
+ @@application ||= Releaf::Core::Application.new
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,4 @@
1
+ # desc "Explaining what the task does"
2
+ # task :releaf do
3
+ # # Task goes here
4
+ # end
@@ -0,0 +1,35 @@
1
+ require File.expand_path('../lib/releaf/version', __FILE__)
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = "releaf-core"
5
+ s.version = Releaf::VERSION
6
+
7
+ s.summary = "core gem for releaf"
8
+ s.description = "Admin interface for RubyOnRails projects inspired by Leaf CMS"
9
+ s.authors = ["CubeSystems"]
10
+ s.email = 'info@cubesystems.lv'
11
+ s.homepage = 'https://github.com/cubesystems/releaf'
12
+
13
+ s.files = `git ls-files`.split("\n")
14
+ s.test_files = Dir["spec/**/*"]
15
+
16
+ s.add_dependency 'rails', '~> 4.2', '>= 4.2.0'
17
+ s.add_dependency 'i18n', '~> 0.7', '>= 0.7.0'
18
+ s.add_dependency 'sprockets-rails', '~> 3.0', '>= 3.0.0'
19
+ s.add_dependency 'sass-rails'
20
+ s.add_dependency 'jquery-rails'
21
+ s.add_dependency 'jquery-ui-rails'
22
+ s.add_dependency 'railties'
23
+ s.add_dependency 'haml-rails'
24
+ s.add_dependency 'dragonfly'
25
+ s.add_dependency 'rails-settings-cached', '>= 0.4.5'
26
+ s.add_dependency 'ckeditor_rails'
27
+ s.add_dependency 'acts_as_list'
28
+ s.add_dependency 'will_paginate'
29
+ s.add_dependency 'font-awesome-rails'
30
+ s.add_dependency 'jquery-cookie-rails'
31
+ s.add_dependency 'globalize-accessors'
32
+ s.add_dependency 'rack-cache'
33
+
34
+ s.required_ruby_version = '>= 2.2.0'
35
+ end
@@ -0,0 +1,138 @@
1
+ require 'rails_helper'
2
+
3
+ describe Releaf::Builders::AssociationReflector, type: :class do
4
+ let(:reflection){ Book.reflect_on_association("chapters") }
5
+ subject{ described_class.new(reflection, :b, "xx") }
6
+
7
+ describe "#initialize" do
8
+ it "assigns given reflection" do
9
+ expect(subject.reflection).to eq(reflection)
10
+ end
11
+
12
+ it "assigns given fields" do
13
+ expect(subject.fields).to eq(:b)
14
+ end
15
+
16
+ it "normalizes to symbol and assigns given sortable name" do
17
+ expect(subject.sortable_column_name).to eq(:xx)
18
+ end
19
+ end
20
+
21
+ describe "#destroyable?" do
22
+ context "when reflection allow to destroy through nested attributes" do
23
+ it "returns true" do
24
+ subject.reflection = Book.reflect_on_association("book_sequels")
25
+ expect(subject.destroyable?).to be true
26
+ end
27
+ end
28
+
29
+ context "when reflection does not allow to destroy through nested attributes" do
30
+ it "returns false" do
31
+ expect(subject.destroyable?).to be false
32
+ end
33
+ end
34
+
35
+ it "caches result" do
36
+ expect(subject.reflection.active_record).to receive(:nested_attributes_options).and_call_original.once
37
+ subject.destroyable?
38
+ subject.destroyable?
39
+ subject.destroyable?
40
+ end
41
+ end
42
+
43
+ describe "#sortable?" do
44
+ context "when expected and actual order clauses are same" do
45
+ it "returns true" do
46
+ allow(subject).to receive(:expected_order_clause).and_return(:a)
47
+ allow(subject).to receive(:actual_order_clause).and_return(:a)
48
+ expect(subject.sortable?).to be true
49
+ end
50
+ end
51
+
52
+ context "when expected and actual order clauses differs" do
53
+ it "returns false" do
54
+ allow(subject).to receive(:expected_order_clause).and_return(:a)
55
+ allow(subject).to receive(:actual_order_clause).and_return(:b)
56
+ expect(subject.sortable?).to be false
57
+ end
58
+ end
59
+
60
+ it "caches result" do
61
+ expect(subject).to receive(:expected_order_clause).and_return(:x).once
62
+ expect(subject).to receive(:actual_order_clause).and_return(:y).once
63
+ subject.sortable?
64
+ subject.sortable?
65
+ subject.sortable?
66
+ end
67
+ end
68
+
69
+ describe "#actual_order_clause" do
70
+ context "when scope exists within reflection" do
71
+ it "returns actual reflection klass order clause with evaluated scope" do
72
+ relation = reflection.klass.all.order(:item_position)
73
+ allow(subject).to receive(:extract_order_clause).with(relation).and_return(:y)
74
+ expect(subject.actual_order_clause).to eq(:y)
75
+ end
76
+ end
77
+
78
+ context "when no scope exists within reflection" do
79
+ it "returns actual reflection klass order clause" do
80
+ subject.reflection = Book.reflect_on_association("sequels")
81
+ relation = subject.reflection.klass.all
82
+ allow(subject).to receive(:extract_order_clause).with(relation).and_return(:y)
83
+ expect(subject.actual_order_clause).to eq(:y)
84
+ end
85
+ end
86
+ end
87
+
88
+ describe "#expected_order_clause" do
89
+ it "returns expected reflection klass order clause for sortable column name" do
90
+ subject.sortable_column_name = :title
91
+ relation = reflection.klass.all.order(:title)
92
+ allow(subject).to receive(:extract_order_clause).with(relation).and_return(:y)
93
+ expect(subject.expected_order_clause).to eq(:y)
94
+ end
95
+ end
96
+
97
+ describe "#extract_order_clause" do
98
+ it "returns order clauses normalized to string for given relation" do
99
+ relation = Book.order(genre: :desc)
100
+ expected_result = if mysql?
101
+ "`books`.`genre` DESC"
102
+ elsif postgresql?
103
+ '"books"."genre" DESC'
104
+ else
105
+ fail
106
+ end
107
+ expect(subject.extract_order_clause(relation)).to eq(expected_result)
108
+ end
109
+
110
+ context "when relation has no order clauses" do
111
+ it "returns empty string" do
112
+ relation = Book.all
113
+ expect(subject.extract_order_clause(relation)).to eq("")
114
+ end
115
+ end
116
+ end
117
+
118
+ describe "#value_as_sql" do
119
+ context "when given value respond to sql" do
120
+ it "return resulting sql" do
121
+ expected_result = if mysql?
122
+ "SELECT `books`.* FROM `books`"
123
+ elsif postgresql?
124
+ 'SELECT "books".* FROM "books"'
125
+ else
126
+ fail
127
+ end
128
+ expect(subject.value_as_sql(Book.all)).to eq(expected_result)
129
+ end
130
+ end
131
+
132
+ context "when given value does not respond to sql" do
133
+ it "return given value" do
134
+ expect(subject.value_as_sql(12)).to eq(12)
135
+ end
136
+ end
137
+ end
138
+ end
@@ -0,0 +1,276 @@
1
+ require "rails_helper"
2
+
3
+ describe Releaf::Builders::Base, type: :module do
4
+ class FormBuilderTestHelper < ActionView::Base
5
+ include Releaf::ButtonHelper
6
+ include Releaf::ApplicationHelper
7
+ include FontAwesome::Rails::IconHelper
8
+ end
9
+ class BuilderIncluder
10
+ include Releaf::Builders::Base
11
+ attr_accessor :template
12
+ end
13
+
14
+ let(:subject){ BuilderIncluder.new }
15
+ let(:template){ FormBuilderTestHelper.new }
16
+
17
+ before do
18
+ subject.template = template
19
+ end
20
+
21
+ describe "delegations" do
22
+ [:controller, :controller_name, :url_for, :form_for,
23
+ :releaf_button, :params, :form_tag, :file_field_tag,
24
+ :request, :check_box_tag, :label_tag, :content_tag, :hidden_field_tag,
25
+ :render, :link_to, :flash, :truncate, :radio_button_tag,
26
+ :options_for_select, :action_name, :options_from_collection_for_select,
27
+ :select_tag, :text_field_tag,
28
+ :image_tag, :jquery_date_format, :cookies, :button_tag, :merge_attributes
29
+ ].each do|method_name|
30
+ it "deletages #{method_name} to template" do
31
+ expect(subject).to delegate_method(method_name).to(:template)
32
+ end
33
+ end
34
+
35
+ [:layout_settings, :access_control, :controller_scope_name, :feature_available?,
36
+ :index_url].each do|method_name|
37
+ it "delegates #{method_name} to controller" do
38
+ expect(subject).to delegate_method(method_name).to(:controller)
39
+ end
40
+ end
41
+ end
42
+
43
+ describe "#html_escape" do
44
+ it "escapes given value with " do
45
+ allow(ERB::Util).to receive(:html_escape).with("a").and_return("b")
46
+ expect(subject.html_escape("a")).to eq("b")
47
+ end
48
+ end
49
+
50
+
51
+ it "aliases #button to #releaf_button" do
52
+ allow(subject.template).to receive(:releaf_button).with("x", a: "y", b: "z").and_return("xx")
53
+ expect(subject.button("x", a: "y", b: "z")).to eq("xx")
54
+ end
55
+
56
+ describe "#icon" do
57
+ it "returns template fa_icon output" do
58
+ expect(subject.icon("check")).to eq('<i class="fa fa-check"></i>')
59
+ end
60
+ end
61
+
62
+ describe "#tag" do
63
+ context "when block is not given" do
64
+ context "when passing string as content" do
65
+ let(:output) do
66
+ subject.tag(:span, "<p>x</p>", class: "red")
67
+ end
68
+
69
+ it "returns an instance of ActiveSupport::SafeBuffer" do
70
+ expect( output ).to be_a ActiveSupport::SafeBuffer
71
+
72
+ end
73
+
74
+ it "passes all arguments to template #content_tag method and returns properly escaped result" do
75
+ expect( output ).to eq('<span class="red">&lt;p&gt;x&lt;/p&gt;</span>')
76
+ end
77
+ end
78
+
79
+ context "when passing safe buffer as content" do
80
+ let(:output) do
81
+ subject.tag(:span, ActiveSupport::SafeBuffer.new("<p>x</p>"), class: "red")
82
+ end
83
+
84
+ it "returns an instance of ActiveSupport::SafeBuffer" do
85
+ expect( output ).to be_a ActiveSupport::SafeBuffer
86
+
87
+ end
88
+
89
+ it "passes all arguments to template #content_tag method and returns properly escaped result" do
90
+ expect( output ).to eq('<span class="red"><p>x</p></span>')
91
+ end
92
+ end
93
+
94
+ end
95
+
96
+ context "when block is given" do
97
+ context "when block evaluates to array" do
98
+ let(:content) do
99
+ [
100
+ '<p>foo</p>',
101
+ 'bar',
102
+ ActiveSupport::SafeBuffer.new('<p>baz</p>')
103
+ ]
104
+ end
105
+
106
+ let(:output) do
107
+ subject.tag(:div, class: 'important') { content }
108
+ end
109
+
110
+ it "returns an instance of ActiveSupport::SafeBuffer" do
111
+ expect( output ).to be_a ActiveSupport::SafeBuffer
112
+ end
113
+
114
+ it "safely joins array" do
115
+ expect( template ).to receive(:safe_join).with(content).and_call_original
116
+ output
117
+ end
118
+
119
+ it "passes joined result to #template#content_tag as content" do
120
+ allow( template ).to receive(:safe_join).with(content).and_return('super duper')
121
+ expect( output ).to eq('<div class="important">super duper</div>')
122
+ end
123
+
124
+ it "returns properly escaped result" do
125
+ expect( output ).to eq('<div class="important">&lt;p&gt;foo&lt;/p&gt;bar<p>baz</p></div>')
126
+ end
127
+
128
+ end
129
+
130
+ context "when block evaluates to other than array" do
131
+ let(:output) do
132
+ subject.tag(:div, class: 'important') { '<p>content</p>' }
133
+ end
134
+
135
+ it "returns an instance of ActiveSupport::SafeBuffer" do
136
+ expect( output ).to be_a ActiveSupport::SafeBuffer
137
+ end
138
+
139
+ it "doesn't call #template#safe_join" do
140
+ expect( template ).to_not receive(:safe_join)
141
+ output
142
+ end
143
+
144
+ it "keeps safe buffer unmodified and pass to #template#content_tag as content which won't be escaped" do
145
+ expect( subject.tag(:div, class: 'important') { ActiveSupport::SafeBuffer.new('<p>content</p>') } ).to eq '<div class="important"><p>content</p></div>'
146
+ end
147
+
148
+ it "passes block result to #template#content_tag as content which will be escaped" do
149
+ expect( output ).to eq '<div class="important">&lt;p&gt;content&lt;/p&gt;</div>'
150
+ end
151
+
152
+ it "casts block result to string" do
153
+ expect( subject.tag(:div, class: 'important') { 1 } ).to eq '<div class="important">1</div>'
154
+ end
155
+ end
156
+ end
157
+ end
158
+
159
+ describe "#wrapper" do
160
+ context "when block is given" do
161
+ let(:output) do
162
+ subject.wrapper(class: 'c') do
163
+ '<span class="a">b</span>'.html_safe
164
+ end
165
+ end
166
+
167
+ it "wrapps given content within div element with given attributes" do
168
+ expect(output).to eq('<div class="c"><span class="a">b</span></div>')
169
+ end
170
+ end
171
+
172
+ context "when block is not given" do
173
+ it "wrapps given content within div element with given attributes" do
174
+ expect(subject.wrapper('<span class="a">b</span>'.html_safe, class: "c")).to eq('<div class="c"><span class="a">b</span></div>')
175
+ end
176
+ end
177
+ end
178
+
179
+ describe "#template_variable" do
180
+ it "returns template instance variable value for given key" do
181
+ template.instance_variable_set("@test", "xx")
182
+ expect(subject.template_variable("test")).to eq("xx")
183
+ end
184
+ end
185
+
186
+ describe "#safe_join" do
187
+ let(:content) do
188
+ ['foo', '<p>bar</p>', ActiveSupport::SafeBuffer.new('<p>baz</p>')]
189
+ end
190
+
191
+ let(:output) do
192
+ subject.safe_join { content }
193
+ end
194
+
195
+ it "returns an instance of ActiveSupport::SafeBuffer" do
196
+ expect( output ).to be_a ActiveSupport::SafeBuffer
197
+ end
198
+
199
+ it "passes block result to #template#safe_join" do
200
+ expect( template ).to receive(:safe_join).with(content).and_call_original
201
+ output
202
+ end
203
+
204
+ it "returns correctly escaped result" do
205
+ expect( output ).to eq 'foo&lt;p&gt;bar&lt;/p&gt;<p>baz</p>'
206
+ end
207
+ end
208
+
209
+ describe "#t" do
210
+ before do
211
+ allow(subject).to receive(:default_translation_scope).and_return("_default_scope_")
212
+ end
213
+
214
+ it "passes all arguments to I18n.t and returns translation" do
215
+ allow(I18n).to receive(:t).with("x", default: "y", scope: "z").and_return("translated value")
216
+ expect(subject.t("x", default: "y", scope: "z")).to eq("translated value")
217
+ end
218
+
219
+ context "when :scope option passed" do
220
+ it "uses default translation scope controller translation scope" do
221
+ expect(I18n).to receive(:t).with("x", scope: "zzz").and_return("asd")
222
+ subject.t("x", scope: "zzz")
223
+ end
224
+ end
225
+
226
+ context "when no :scope option passed" do
227
+ it "adds controller translation scope" do
228
+ expect(I18n).to receive(:t).with("x", scope: "_default_scope_").and_return("asd")
229
+ subject.t("x")
230
+ end
231
+ end
232
+ end
233
+
234
+ describe "#translate_locale" do
235
+ it "returns translated locale within `locales` scope" do
236
+ allow(subject).to receive(:t).with("de", scope: "locales").and_return("dzerman")
237
+ expect(subject.translate_locale("de")).to eq("dzerman")
238
+ end
239
+ end
240
+
241
+ describe "#locale_options" do
242
+ it "returns array with translated locales usable for rails options helper" do
243
+ allow(subject).to receive(:t).with("de", scope: "locales").and_return("dzerman")
244
+ allow(subject).to receive(:t).with("lv", scope: "locales").and_return("latvian")
245
+ expect(subject.locale_options(["de", "lv"])).to eq([["dzerman", "de"], ["latvian", "lv"]])
246
+ end
247
+ end
248
+
249
+ describe "#resource_to_text" do
250
+ let(:resource){ Releaf::Permissions::User.new(name: "a", surname: "b") }
251
+
252
+ context "when given resource respond to #to_text method" do
253
+ it "returns resource #to_text output" do
254
+ expect(subject.resource_to_text(resource)).to eq("a b")
255
+ end
256
+ end
257
+
258
+ context "when given resource does not respond to #to_text method" do
259
+ it "returns resource #to_s output" do
260
+ allow(resource).to receive(:respond_to?).and_call_original
261
+ allow(resource).to receive(:respond_to?).with(:to_text).and_return(false)
262
+ allow(resource).to receive(:to_s).and_return("x")
263
+ expect(subject.resource_to_text(resource)).to eq("x")
264
+ end
265
+ end
266
+ end
267
+
268
+ describe "#default_translation_scope" do
269
+ it "returns controller scope" do
270
+ controller = Releaf::BaseController.new
271
+ allow(subject).to receive(:controller).and_return(controller)
272
+ allow(controller).to receive(:controller_scope_name).and_return("x")
273
+ expect(subject.default_translation_scope).to eq("x")
274
+ end
275
+ end
276
+ end