udongo 0.1.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 (280) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/Rakefile +26 -0
  4. data/app/assets/fonts/FontAwesome.otf +0 -0
  5. data/app/assets/fonts/fontawesome-webfont.eot +0 -0
  6. data/app/assets/fonts/fontawesome-webfont.svg +685 -0
  7. data/app/assets/fonts/fontawesome-webfont.ttf +0 -0
  8. data/app/assets/fonts/fontawesome-webfont.woff +0 -0
  9. data/app/assets/fonts/fontawesome-webfont.woff2 +0 -0
  10. data/app/assets/javascripts/backend/application.js +22 -0
  11. data/app/assets/javascripts/backend/bootstrap.js +3560 -0
  12. data/app/assets/javascripts/backend/datepickers.js +67 -0
  13. data/app/assets/javascripts/backend/general.js +7 -0
  14. data/app/assets/javascripts/backend/pages.js +7 -0
  15. data/app/assets/javascripts/backend/plugins/autocomplete.js +147 -0
  16. data/app/assets/javascripts/backend/plugins/tagbox.js +52 -0
  17. data/app/assets/javascripts/backend/sortable.js +46 -0
  18. data/app/assets/javascripts/backend/tags.js +37 -0
  19. data/app/assets/javascripts/backend/tree.js +158 -0
  20. data/app/assets/stylesheets/backend/application.scss +18 -0
  21. data/app/assets/stylesheets/backend/bootstrap.scss +6211 -0
  22. data/app/assets/stylesheets/backend/components/_breadcrumb.scss +7 -0
  23. data/app/assets/stylesheets/backend/components/_form.scss +23 -0
  24. data/app/assets/stylesheets/backend/components/_nav.scss +3 -0
  25. data/app/assets/stylesheets/backend/components/_navbar.scss +3 -0
  26. data/app/assets/stylesheets/backend/components/_tabs.scss +3 -0
  27. data/app/assets/stylesheets/backend/font-awesome.scss +2182 -0
  28. data/app/assets/stylesheets/backend/pages/_flexible_content.scss +11 -0
  29. data/app/assets/stylesheets/backend/pages/_logged_in.scss +3 -0
  30. data/app/assets/stylesheets/backend/pages/_login.scss +3 -0
  31. data/app/assets/stylesheets/backend/udongo.scss +17 -0
  32. data/app/controllers/backend/admins_controller.rb +56 -0
  33. data/app/controllers/backend/content/rows/columns_controller.rb +75 -0
  34. data/app/controllers/backend/content/rows/images_controller.rb +6 -0
  35. data/app/controllers/backend/content/rows/texts_controller.rb +6 -0
  36. data/app/controllers/backend/content/rows_controller.rb +45 -0
  37. data/app/controllers/backend/dashboard_controller.rb +2 -0
  38. data/app/controllers/backend/email_templates_controller.rb +50 -0
  39. data/app/controllers/backend/emails_controller.rb +18 -0
  40. data/app/controllers/backend/navigation/items_controller.rb +64 -0
  41. data/app/controllers/backend/navigations_controller.rb +7 -0
  42. data/app/controllers/backend/pages_controller.rb +89 -0
  43. data/app/controllers/backend/redirects_controller.rb +50 -0
  44. data/app/controllers/backend/seo_controller.rb +6 -0
  45. data/app/controllers/backend/sessions_controller.rb +22 -0
  46. data/app/controllers/backend/snippets_controller.rb +49 -0
  47. data/app/controllers/backend/tagbox_controller.rb +52 -0
  48. data/app/controllers/backend/webserver_controller.rb +6 -0
  49. data/app/controllers/backend_controller.rb +34 -0
  50. data/app/controllers/catch_all_controller.rb +12 -0
  51. data/app/controllers/concerns/backend/content_type_controller.rb +44 -0
  52. data/app/controllers/concerns/backend/positionable_controller.rb +12 -0
  53. data/app/controllers/concerns/backend/translatable_controller.rb +41 -0
  54. data/app/controllers/concerns/pagination_controller.rb +38 -0
  55. data/app/controllers/redirects_controller.rb +18 -0
  56. data/app/decorators/content_image_decorator.rb +7 -0
  57. data/app/decorators/content_text_decorator.rb +11 -0
  58. data/app/decorators/navigation_item_decorator.rb +29 -0
  59. data/app/decorators/page_decorator.rb +29 -0
  60. data/app/decorators/redirect_decorator.rb +13 -0
  61. data/app/decorators/snippet_decorator.rb +11 -0
  62. data/app/forms/backend/email_template_translation_form.rb +11 -0
  63. data/app/forms/backend/navigation_item_translation_form.rb +8 -0
  64. data/app/forms/backend/page_translation_form.rb +17 -0
  65. data/app/forms/backend/snippet_translation_form.rb +8 -0
  66. data/app/helpers/backend/dropdown_helper.rb +9 -0
  67. data/app/helpers/backend/pagination_helper.rb +17 -0
  68. data/app/helpers/icon_helper.rb +6 -0
  69. data/app/helpers/link_helper.rb +33 -0
  70. data/app/helpers/snippet_helper.rb +5 -0
  71. data/app/helpers/udongo_helper.rb +27 -0
  72. data/app/inputs/date_picker_input.rb +30 -0
  73. data/app/inputs/date_range_picker_input.rb +13 -0
  74. data/app/mailers/general_mailer.rb +13 -0
  75. data/app/models/address.rb +5 -0
  76. data/app/models/admin.rb +9 -0
  77. data/app/models/ckeditor/asset.rb +7 -0
  78. data/app/models/ckeditor/attachment_file.rb +7 -0
  79. data/app/models/ckeditor/picture.rb +7 -0
  80. data/app/models/comment.rb +39 -0
  81. data/app/models/concerns/cacheable.rb +37 -0
  82. data/app/models/concerns/commentable.rb +9 -0
  83. data/app/models/concerns/content_type.rb +13 -0
  84. data/app/models/concerns/deletable.rb +13 -0
  85. data/app/models/concerns/draggable.rb +13 -0
  86. data/app/models/concerns/emailable.rb +7 -0
  87. data/app/models/concerns/flexible_content.rb +9 -0
  88. data/app/models/concerns/locale.rb +10 -0
  89. data/app/models/concerns/loggable.rb +13 -0
  90. data/app/models/concerns/notable.rb +9 -0
  91. data/app/models/concerns/parentable.rb +39 -0
  92. data/app/models/concerns/person.rb +7 -0
  93. data/app/models/concerns/publishable.rb +22 -0
  94. data/app/models/concerns/seo.rb +31 -0
  95. data/app/models/concerns/sortable.rb +30 -0
  96. data/app/models/concerns/spammable.rb +38 -0
  97. data/app/models/concerns/storable/collection.rb +117 -0
  98. data/app/models/concerns/storable/config.rb +40 -0
  99. data/app/models/concerns/storable.rb +32 -0
  100. data/app/models/concerns/taggable.rb +29 -0
  101. data/app/models/concerns/translatable/collection.rb +60 -0
  102. data/app/models/concerns/translatable/config.rb +19 -0
  103. data/app/models/concerns/translatable.rb +39 -0
  104. data/app/models/concerns/visible.rb +24 -0
  105. data/app/models/content_column.rb +14 -0
  106. data/app/models/content_image.rb +9 -0
  107. data/app/models/content_row.rb +11 -0
  108. data/app/models/content_text.rb +7 -0
  109. data/app/models/email.rb +13 -0
  110. data/app/models/email_template.rb +10 -0
  111. data/app/models/form.rb +9 -0
  112. data/app/models/form_field.rb +15 -0
  113. data/app/models/form_field_validation.rb +11 -0
  114. data/app/models/form_submission.rb +16 -0
  115. data/app/models/form_submission_data.rb +5 -0
  116. data/app/models/log.rb +7 -0
  117. data/app/models/meta.rb +11 -0
  118. data/app/models/navigation.rb +6 -0
  119. data/app/models/navigation_item.rb +12 -0
  120. data/app/models/note.rb +7 -0
  121. data/app/models/page.rb +23 -0
  122. data/app/models/queued_task.rb +45 -0
  123. data/app/models/redirect.rb +16 -0
  124. data/app/models/setting.rb +13 -0
  125. data/app/models/snippet.rb +10 -0
  126. data/app/models/store.rb +10 -0
  127. data/app/models/tag.rb +6 -0
  128. data/app/models/tagged_item.rb +8 -0
  129. data/app/models/translation.rb +10 -0
  130. data/app/uploaders/ckeditor_attachment_file_uploader.rb +36 -0
  131. data/app/uploaders/ckeditor_picture_uploader.rb +47 -0
  132. data/app/uploaders/content_image_uploader.rb +52 -0
  133. data/app/validators/email_validator.rb +7 -0
  134. data/app/validators/url_validator.rb +13 -0
  135. data/app/views/backend/_breadcrumbs.html.erb +18 -0
  136. data/app/views/backend/_flash_messages.html.erb +9 -0
  137. data/app/views/backend/_form_actions.html.erb +4 -0
  138. data/app/views/backend/_form_errors.html.erb +15 -0
  139. data/app/views/backend/_navigation.html.erb +8 -0
  140. data/app/views/backend/_seo_form.html.erb +13 -0
  141. data/app/views/backend/_tags.html.erb +18 -0
  142. data/app/views/backend/admins/_form.html.erb +32 -0
  143. data/app/views/backend/admins/edit.html.erb +4 -0
  144. data/app/views/backend/admins/index.html.erb +33 -0
  145. data/app/views/backend/admins/new.html.erb +4 -0
  146. data/app/views/backend/content/_image.html.erb +17 -0
  147. data/app/views/backend/content/_rows.html.erb +63 -0
  148. data/app/views/backend/content/_text.html.erb +1 -0
  149. data/app/views/backend/content/rows/columns/edit.html.erb +25 -0
  150. data/app/views/backend/content/rows/columns/new.html.erb +25 -0
  151. data/app/views/backend/content/rows/images/edit.html.erb +22 -0
  152. data/app/views/backend/content/rows/texts/edit.html.erb +13 -0
  153. data/app/views/backend/dashboard/show.html.erb +1 -0
  154. data/app/views/backend/email_templates/_form.html.erb +31 -0
  155. data/app/views/backend/email_templates/_tabs.html.erb +21 -0
  156. data/app/views/backend/email_templates/edit.html.erb +6 -0
  157. data/app/views/backend/email_templates/edit_translation.html.erb +51 -0
  158. data/app/views/backend/email_templates/index.html.erb +27 -0
  159. data/app/views/backend/email_templates/new.html.erb +4 -0
  160. data/app/views/backend/emails/index.html.erb +50 -0
  161. data/app/views/backend/emails/show.html.erb +68 -0
  162. data/app/views/backend/navigation/items/_form.html.erb +22 -0
  163. data/app/views/backend/navigation/items/_tabs.html.erb +21 -0
  164. data/app/views/backend/navigation/items/edit.html.erb +7 -0
  165. data/app/views/backend/navigation/items/edit_translation.html.erb +21 -0
  166. data/app/views/backend/navigation/items/new.html.erb +4 -0
  167. data/app/views/backend/navigations/index.html.erb +59 -0
  168. data/app/views/backend/pages/_form.html.erb +30 -0
  169. data/app/views/backend/pages/_tabs.html.erb +21 -0
  170. data/app/views/backend/pages/edit.html.erb +6 -0
  171. data/app/views/backend/pages/edit_translation.html.erb +35 -0
  172. data/app/views/backend/pages/index.html.erb +19 -0
  173. data/app/views/backend/pages/new.html.erb +4 -0
  174. data/app/views/backend/redirects/_filter.html.erb +21 -0
  175. data/app/views/backend/redirects/_form.html.erb +36 -0
  176. data/app/views/backend/redirects/edit.html.erb +4 -0
  177. data/app/views/backend/redirects/index.html.erb +50 -0
  178. data/app/views/backend/redirects/new.html.erb +3 -0
  179. data/app/views/backend/sessions/new.html.erb +19 -0
  180. data/app/views/backend/snippets/_form.html.erb +18 -0
  181. data/app/views/backend/snippets/_tabs.html.erb +21 -0
  182. data/app/views/backend/snippets/edit.html.erb +6 -0
  183. data/app/views/backend/snippets/edit_translation.html.erb +23 -0
  184. data/app/views/backend/snippets/index.html.erb +26 -0
  185. data/app/views/backend/snippets/new.html.erb +4 -0
  186. data/app/views/layouts/backend/_top_navigation.html.erb +27 -0
  187. data/app/views/layouts/backend/application.html.erb +27 -0
  188. data/app/views/layouts/backend/lightbox.html.erb +21 -0
  189. data/app/views/layouts/backend/login.html.erb +21 -0
  190. data/app/views/layouts/frontend/application.html.erb +16 -0
  191. data/config/initializers/assets.rb +13 -0
  192. data/config/initializers/ckeditor.rb +38 -0
  193. data/config/initializers/core_ext/string.rb +8 -0
  194. data/config/initializers/inflections.rb +20 -0
  195. data/config/initializers/simple_form_bootstrap.rb +150 -0
  196. data/config/locales/de.yml +196 -0
  197. data/config/locales/en.yml +206 -0
  198. data/config/locales/fr.yml +214 -0
  199. data/config/locales/nl.yml +212 -0
  200. data/config/locales/nl_backend.yml +106 -0
  201. data/config/locales/nl_forms.yml +68 -0
  202. data/config/routes.rb +83 -0
  203. data/config/spring.rb +1 -0
  204. data/db/migrate/20150404133314_create_udongo_admins.rb +12 -0
  205. data/db/migrate/20150404203549_remove_udongo_admins.rb +5 -0
  206. data/db/migrate/20150404203648_add_admins_table.rb +12 -0
  207. data/db/migrate/20150405202002_create_logs.rb +15 -0
  208. data/db/migrate/20150411152042_create_addresses.rb +19 -0
  209. data/db/migrate/20150411152619_create_comments.rb +21 -0
  210. data/db/migrate/20150411200227_create_notes.rb +14 -0
  211. data/db/migrate/20150412094419_create_settings.rb +13 -0
  212. data/db/migrate/20150412095257_create_meta.rb +21 -0
  213. data/db/migrate/20150413190019_create_tags.rb +15 -0
  214. data/db/migrate/20150413190713_create_tagged_items.rb +14 -0
  215. data/db/migrate/20150417113400_create_translations.rb +15 -0
  216. data/db/migrate/20150515113332_content_tables.rb +42 -0
  217. data/db/migrate/20150515134044_create_pages.rb +22 -0
  218. data/db/migrate/20150620121834_remove_trashed_from_page.rb +5 -0
  219. data/db/migrate/20150629120253_add_locales_to_translatables.rb +5 -0
  220. data/db/migrate/20150706083925_create_snippets.rb +13 -0
  221. data/db/migrate/20150706084145_add_locales_to_snippet.rb +5 -0
  222. data/db/migrate/20150706085213_add_description_to_snippet.rb +5 -0
  223. data/db/migrate/20150706085733_change_snippet_desc_field.rb +5 -0
  224. data/db/migrate/20150706093016_change_desc_column_for_snippet.rb +5 -0
  225. data/db/migrate/20150706113918_create_ckeditor_assets.rb +26 -0
  226. data/db/migrate/20150824090457_create_redirects.rb +12 -0
  227. data/db/migrate/20150824113723_rename_source_and_destination_to_redirects.rb +6 -0
  228. data/db/migrate/20150825094254_create_shortened_urls.rb +11 -0
  229. data/db/migrate/20150826084004_remove_shortened_urls.rb +5 -0
  230. data/db/migrate/20150826084234_add_times_used_to_redirect.rb +5 -0
  231. data/db/migrate/20150826134153_add_index_on_page_visible.rb +5 -0
  232. data/db/migrate/20151003191846_add_some_indexes.rb +15 -0
  233. data/db/migrate/20151006131720_add_editable_content_to_page.rb +5 -0
  234. data/db/migrate/20151007090541_create_navigations.rb +10 -0
  235. data/db/migrate/20151007091131_create_navigation_items.rb +12 -0
  236. data/db/migrate/20151007092529_add_index_to_nav_items.rb +5 -0
  237. data/db/migrate/20151007093812_change_nav_description_type.rb +5 -0
  238. data/db/migrate/20151007173557_add_route_to_page.rb +5 -0
  239. data/db/migrate/20151008114433_add_extra_to_navigation_item.rb +5 -0
  240. data/db/migrate/20151009114823_create_forms.rb +9 -0
  241. data/db/migrate/20151009115326_create_form_fields.rb +12 -0
  242. data/db/migrate/20151009115803_create_form_field_validations.rb +11 -0
  243. data/db/migrate/20151009131957_create_form_submissions.rb +10 -0
  244. data/db/migrate/20151009132657_create_form_submission_data.rb +11 -0
  245. data/db/migrate/20151009140754_rename_form_field_id_to_field_id_for_form_field_validations.rb +5 -0
  246. data/db/migrate/20151009141123_rename_form_submission_id_to_submission_id_for_form_submission_data.rb +5 -0
  247. data/db/migrate/20151009141822_add_locales_to_form_fields.rb +5 -0
  248. data/db/migrate/20151009142242_add_locales_to_form_field_validations.rb +5 -0
  249. data/db/migrate/20151023135358_add_locales_to_forms.rb +5 -0
  250. data/db/migrate/20151117190950_add_external_reference_to_tags.rb +6 -0
  251. data/db/migrate/20151205202815_rename_nav_name_to_identifier.rb +5 -0
  252. data/db/migrate/20160108100104_create_stores.rb +13 -0
  253. data/db/migrate/20160125154648_rename_name_to_identifier_for_forms.rb +5 -0
  254. data/db/migrate/20160128080029_create_email_templates.rb +18 -0
  255. data/db/migrate/20160201121021_create_emails.rb +17 -0
  256. data/db/migrate/20160201123128_create_queued_tasks.rb +13 -0
  257. data/db/migrate/20160205132009_reoraganize_snippet_html_fields.rb +7 -0
  258. data/db/migrate/20160303141417_add_data_to_logs.rb +5 -0
  259. data/db/migrate/20160513110925_addd_more_column_widths.rb +9 -0
  260. data/lib/generators/udongo/form/form_generator.rb +63 -0
  261. data/lib/generators/udongo/form/templates/form.rb +18 -0
  262. data/lib/tasks/task_extras.rb +10 -0
  263. data/lib/tasks/udongo_tasks.rake +41 -0
  264. data/lib/udongo/active_model_simulator.rb +21 -0
  265. data/lib/udongo/assets/loader.rb +40 -0
  266. data/lib/udongo/assets/precompiler.rb +50 -0
  267. data/lib/udongo/breadcrumb.rb +27 -0
  268. data/lib/udongo/config.rb +26 -0
  269. data/lib/udongo/crypt.rb +19 -0
  270. data/lib/udongo/cryptography.rb +5 -0
  271. data/lib/udongo/email_vars/address.rb +19 -0
  272. data/lib/udongo/email_vars/form_submission.rb +18 -0
  273. data/lib/udongo/email_vars_parser.rb +31 -0
  274. data/lib/udongo/engine.rb +10 -0
  275. data/lib/udongo/meta_info.rb +12 -0
  276. data/lib/udongo/object_path.rb +24 -0
  277. data/lib/udongo/version.rb +3 -0
  278. data/lib/udongo/will_paginate/renderer.rb +26 -0
  279. data/lib/udongo.rb +44 -0
  280. metadata +772 -0
@@ -0,0 +1,12 @@
1
+ class CatchAllController < ActionController::Base
2
+ def resolve
3
+ redirect = ::Redirect.find_by(source_uri: request.path)
4
+
5
+ if redirect && redirect.enabled?
6
+ redirect.used!
7
+ redirect_to redirect.destination_uri, status: redirect.status_code
8
+ else
9
+ render text: 'Page not found', status: 404
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,44 @@
1
+ module Concerns
2
+ module Backend
3
+ module ContentTypeController
4
+ extend ActiveSupport::Concern
5
+
6
+ included do
7
+ layout 'backend/lightbox'
8
+ before_action :find_model
9
+ helper_method :content_path
10
+ end
11
+
12
+ module ClassMethods
13
+ def model(value)
14
+ define_method(:model) { value }
15
+ end
16
+
17
+ def allowed_params(*args)
18
+ define_method(:allowed_params) do
19
+ params.require(model.name.tableize.singularize).permit(*args)
20
+ end
21
+ end
22
+ end
23
+
24
+ def find_model
25
+ @model = model.find(params[:id]).decorate
26
+ end
27
+
28
+ # TODO refactor?
29
+ def content_path
30
+ column = @model.column
31
+ path = "edit_translation_backend_#{column.row.rowable.class.to_s.downcase}_path"
32
+ send(path, column.row.rowable, locale, anchor: "content-row-#{column.row.id}")
33
+ end
34
+
35
+ def update
36
+ if @model.update_attributes allowed_params
37
+ redirect_to content_path
38
+ else
39
+ render :edit
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,12 @@
1
+ module Concerns
2
+ module Backend
3
+ module PositionableController
4
+ extend ActiveSupport::Concern
5
+
6
+ def update_position
7
+ find_model.set_list_position params[:position]
8
+ render nothing: true
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,41 @@
1
+ module Concerns
2
+ module Backend
3
+ module TranslatableController
4
+ extend ActiveSupport::Concern
5
+
6
+ included do
7
+ before_action :find_models, only: [:edit_translation, :update_translation]
8
+ helper_method :translatable_path
9
+ end
10
+
11
+ def update_translation
12
+ if @translation.validate(params[model_name])
13
+ @translation.save
14
+ redirect_to translatable_path, notice: t('b.msg.changes_saved')
15
+ else
16
+ render :edit_translation
17
+ end
18
+ end
19
+
20
+ private
21
+
22
+ def find_models
23
+ @model ||= find_model
24
+ @translation = translation_form
25
+ end
26
+
27
+ def model_name
28
+ @model.class.to_s.underscore.gsub('_decorator', '')
29
+ end
30
+
31
+ def set_translatable_path(path)
32
+ @translatable_path ||= path
33
+ end
34
+
35
+ def translatable_path
36
+ method = "edit_translation_backend_#{model_name}_path"
37
+ @translatable_path || send(method, @model, params[:translation_locale])
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,38 @@
1
+ require 'will_paginate/array'
2
+
3
+ module Concerns
4
+ module PaginationController
5
+ extend ActiveSupport::Concern
6
+
7
+ included do
8
+ # The respond_to? is added because of issues in our specs.
9
+ if respond_to?(:helper_method)
10
+ helper_method :per_page, :page_number
11
+ end
12
+ end
13
+
14
+ def page_number
15
+ return 1 unless params[:page].respond_to?(:to_i)
16
+ page = params[:page].to_i.abs
17
+ page == 0 ? 1 : page
18
+ end
19
+
20
+ def paginate(records, options = {})
21
+ options.reverse_merge!(page: page_number, per_page: per_page)
22
+
23
+ if records.is_a?(Array)
24
+ records.paginate options
25
+ else
26
+ records.page(options[:page]).per_page(options[:per_page])
27
+ end
28
+ end
29
+
30
+ def per_page
31
+ [5, 10, 25, 30, 50, 100].each do |i|
32
+ return i if params[:per_page].to_i == i
33
+ end
34
+
35
+ 30
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,18 @@
1
+ class RedirectsController < ActionController::Base
2
+ def go
3
+ redirect = ::Redirect.find_by(source_uri: source_uri)
4
+
5
+ if redirect && redirect.enabled?
6
+ redirect.used!
7
+ redirect_to redirect.destination_uri, status: redirect.status_code
8
+ else
9
+ render text: 'No such redirect or disabled.', status: 404
10
+ end
11
+ end
12
+
13
+ private
14
+
15
+ def source_uri
16
+ "/go/#{params[:slug]}"
17
+ end
18
+ end
@@ -0,0 +1,7 @@
1
+ class ContentImageDecorator < Draper::Decorator
2
+ delegate_all
3
+
4
+ def content_type_is?(value)
5
+ value.to_sym == :image
6
+ end
7
+ end
@@ -0,0 +1,11 @@
1
+ class ContentTextDecorator < Draper::Decorator
2
+ delegate_all
3
+
4
+ def render
5
+ content.to_s.html_safe
6
+ end
7
+
8
+ def content_type_is?(value)
9
+ value.to_sym == :text
10
+ end
11
+ end
@@ -0,0 +1,29 @@
1
+ class NavigationItemDecorator < Draper::Decorator
2
+ delegate_all
3
+
4
+ def label
5
+ result = ''
6
+ result = object.translation.label if object.translation.label
7
+ result = object.page.translation.title if object.page && result.blank?
8
+ result
9
+ end
10
+
11
+ def path(options = {})
12
+ result = '/'
13
+
14
+ if object.translation.path.present?
15
+ result = object.translation.path
16
+
17
+ elsif object.page.present?
18
+ result = object.page.decorate.path(options)
19
+ end
20
+
21
+ result
22
+ end
23
+
24
+ def options_for_page
25
+ ::Page.order(:description).map do |p|
26
+ [p.description, p.id]
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,29 @@
1
+ class PageDecorator < Draper::Decorator
2
+ delegate_all
3
+
4
+ def options_for_parents
5
+ ::Page.flat_tree.map do |p|
6
+ ["#{'-' * p.depth} #{p.description}".strip, p.id]
7
+ end
8
+ end
9
+
10
+ def path(locale: I18n.locale, options: {})
11
+ return h.send(route, options) if route.present?
12
+
13
+ slugs = []
14
+
15
+ parents.each do |p|
16
+ if p.route.present?
17
+ slugs << h.send(p.route, options)
18
+ return slugs.reverse.join('/')
19
+ else
20
+ slugs << p.seo(locale).slug
21
+ end
22
+ end
23
+
24
+ str = ''
25
+ str << "/#{locale}" if Udongo.config.prefix_routes_with_locale?
26
+ str << "/#{slugs.reverse.join('/')}"
27
+ str
28
+ end
29
+ end
@@ -0,0 +1,13 @@
1
+ class RedirectDecorator < Draper::Decorator
2
+ delegate_all
3
+
4
+ def status_code_collection
5
+ %w(301 303 307).map do |code|
6
+ [I18n.t("b.msg.status_codes.#{code}"), code]
7
+ end
8
+ end
9
+
10
+ def summary
11
+ "#{I18n.t('b.from')} #{object.source_uri} #{I18n.t('b.to')} #{object.destination_uri}"
12
+ end
13
+ end
@@ -0,0 +1,11 @@
1
+ class SnippetDecorator < Draper::Decorator
2
+ def title
3
+ string = object.title.to_s
4
+ object.allow_html_in_title? ? string.html_safe : string
5
+ end
6
+
7
+ def content
8
+ string = object.content.to_s
9
+ object.allow_html_in_content? ? string.html_safe : string
10
+ end
11
+ end
@@ -0,0 +1,11 @@
1
+ class Backend::EmailTemplateTranslationForm < Reform::Form
2
+ include Composition
3
+
4
+ model :email_template
5
+
6
+ property :subject, on: :translation
7
+ property :plain_content, on: :translation
8
+ property :html_content, on: :translation
9
+
10
+ validates :subject, :plain_content, :html_content, presence: true
11
+ end
@@ -0,0 +1,8 @@
1
+ class Backend::NavigationItemTranslationForm < Reform::Form
2
+ include Composition
3
+
4
+ model :navigation_item
5
+
6
+ property :label, on: :translation
7
+ property :path, on: :translation
8
+ end
@@ -0,0 +1,17 @@
1
+ class Backend::PageTranslationForm < Reform::Form
2
+ include Composition
3
+
4
+ model :page
5
+
6
+ property :title, on: :translation
7
+ property :subtitle, on: :translation
8
+
9
+ property :seo_title, on: :seo
10
+ property :seo_keywords, on: :seo
11
+ property :seo_description, on: :seo
12
+ property :seo_custom, on: :seo
13
+ property :seo_slug, on: :seo
14
+
15
+ validates :title, presence: true
16
+ validates :seo_slug, presence: true # TODO only if necessary!
17
+ end
@@ -0,0 +1,8 @@
1
+ class Backend::SnippetTranslationForm < Reform::Form
2
+ include Composition
3
+
4
+ model :snippet
5
+
6
+ property :title, on: :translation
7
+ property :content, on: :translation
8
+ end
@@ -0,0 +1,9 @@
1
+ module Backend
2
+ module DropdownHelper
3
+ def options_for_content_types
4
+ Udongo.config.flexible_content_types.map do |content_type|
5
+ [I18n.t("b.msg.content_types.#{content_type}"), "Content#{content_type.to_s.camelcase}"]
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,17 @@
1
+ module Backend
2
+ module PaginationHelper
3
+
4
+ def udongo_paginate(collection, options = {})
5
+ options.merge!(
6
+ class: 'pagination',
7
+ inner_window: 1,
8
+ outer_window: 0,
9
+ renderer: Udongo::WillPaginate::Renderer,
10
+ previous_label: '&lt;'.html_safe,
11
+ next_label: '&gt;'.html_safe
12
+ )
13
+
14
+ will_paginate collection, options
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,6 @@
1
+ module IconHelper
2
+ def icon(name, label = nil)
3
+ markup = content_tag :i, nil, class: "fa fa-#{name.to_s.gsub('_', '-')}"
4
+ label ? "#{markup}&nbsp;#{label}".html_safe : markup
5
+ end
6
+ end
@@ -0,0 +1,33 @@
1
+ module LinkHelper
2
+ def link_to_show(object)
3
+ str = Udongo::ObjectPath.find(object)
4
+
5
+ link_to(
6
+ icon(:search),
7
+ send(str, *Udongo::ObjectPath.remove_symbols(object)),
8
+ title: t('b.view')
9
+ )
10
+ end
11
+
12
+ def link_to_edit(object)
13
+ str = "edit_#{Udongo::ObjectPath.find(object)}"
14
+
15
+ link_to(
16
+ icon(:pencil_square_o),
17
+ send(str, *Udongo::ObjectPath.remove_symbols(object)),
18
+ title: t('b.edit')
19
+ )
20
+ end
21
+
22
+ def link_to_delete(object)
23
+ str = Udongo::ObjectPath.find(object)
24
+
25
+ link_to(
26
+ icon(:trash),
27
+ send(str, *Udongo::ObjectPath.remove_symbols(object)),
28
+ method: :delete,
29
+ data: { confirm: t('b.msg.confirm') },
30
+ title: t('b.delete')
31
+ )
32
+ end
33
+ end
@@ -0,0 +1,5 @@
1
+ module SnippetHelper
2
+ def snippet(identifier)
3
+ ::Snippet.find_in_cache(identifier).decorate
4
+ end
5
+ end
@@ -0,0 +1,27 @@
1
+ module UdongoHelper
2
+ # Before using: Put <%= yield(:javascripts) %> in the <head> of your app's frontend
3
+ def javascript(file, target = :javascripts)
4
+ js_asset_loader.view = self
5
+ js_asset_loader.load_js file, target
6
+ end
7
+
8
+ def restart_webserver_button
9
+ link_to I18n.t('b.restart_webserver'), backend_restart_webserver_path, class: 'button', method: 'post'
10
+ end
11
+
12
+ # Before using: Put <%= yield(:stylesheets) %> in the <head> of your app's frontend
13
+ def stylesheet(file, media = :screen)
14
+ css_asset_loader.view = self
15
+ css_asset_loader.load_css file, media
16
+ end
17
+
18
+ private
19
+
20
+ def css_asset_loader
21
+ @css_asset_loader ||= Udongo::Assets::Loader.new
22
+ end
23
+
24
+ def js_asset_loader
25
+ @js_asset_loader ||= Udongo::Assets::Loader.new
26
+ end
27
+ end
@@ -0,0 +1,30 @@
1
+ class DatePickerInput < SimpleForm::Inputs::Base
2
+ def input
3
+ template.content_tag(:div, class: 'input-group') do
4
+ template.concat @builder.text_field(attribute_name, input_html_options)
5
+ template.concat span_table
6
+ end
7
+ end
8
+
9
+ def data_attributes
10
+ attributes = {}
11
+ attributes.reverse_merge!(
12
+ date_language: I18n.locale,
13
+ date_format: 'dd/mm/yyyy'
14
+ )
15
+ end
16
+
17
+ def icon_table
18
+ template.content_tag(:span, '', class: 'fa fa-th')
19
+ end
20
+
21
+ def input_html_options
22
+ super.merge(class: 'form-control', readonly: true, data: data_attributes)
23
+ end
24
+
25
+ def span_table
26
+ template.content_tag(:span, class: 'input-group-addon') do
27
+ template.concat icon_table
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,13 @@
1
+ class DateRangePickerInput < DatePickerInput
2
+ def data_attributes
3
+ super.reverse_merge!(
4
+ range_picker: range_picker?,
5
+ start: self.options[:start],
6
+ stop: self.options[:stop]
7
+ )
8
+ end
9
+
10
+ def range_picker?
11
+ self.options[:start].present? || self.options[:stop].present?
12
+ end
13
+ end
@@ -0,0 +1,13 @@
1
+ class GeneralMailer < ActionMailer::Base
2
+ def email(email)
3
+ from = "#{email.from_name} <#{email.from_email}>"
4
+ to = "#{email.to_name} <#{email.to_email}>"
5
+
6
+ mail(from: from, to: to, subject: email.subject) do |format|
7
+ format.text { render text: email.plain_content }
8
+ format.html { render html: email.html_content.html_safe }
9
+ end
10
+
11
+ email.mark_as_sent!
12
+ end
13
+ end
@@ -0,0 +1,5 @@
1
+ class Address < ActiveRecord::Base
2
+ include Concerns::Emailable
3
+
4
+ belongs_to :addressable, polymorphic: true
5
+ end
@@ -0,0 +1,9 @@
1
+ class Admin < ActiveRecord::Base
2
+ include Concerns::Person
3
+ has_secure_password
4
+
5
+ validates :first_name, :last_name, presence: true
6
+ validates :email,
7
+ uniqueness: { case_sensitive: false },
8
+ format: { with: /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\Z/i }
9
+ end
@@ -0,0 +1,7 @@
1
+ class Ckeditor::Asset < ActiveRecord::Base
2
+ include Ckeditor::Orm::ActiveRecord::AssetBase
3
+
4
+ delegate :url, :current_path, :content_type, to: :data
5
+
6
+ validates_presence_of :data
7
+ end
@@ -0,0 +1,7 @@
1
+ class Ckeditor::AttachmentFile < Ckeditor::Asset
2
+ mount_uploader :data, CkeditorAttachmentFileUploader, mount_on: :data_file_name
3
+
4
+ def url_thumb
5
+ @url_thumb ||= Ckeditor::Utils.filethumb(filename)
6
+ end
7
+ end
@@ -0,0 +1,7 @@
1
+ class Ckeditor::Picture < Ckeditor::Asset
2
+ mount_uploader :data, CkeditorPictureUploader, mount_on: :data_file_name
3
+
4
+ def url_content
5
+ url(:content)
6
+ end
7
+ end
@@ -0,0 +1,39 @@
1
+ class Comment < ActiveRecord::Base
2
+ include Concerns::Parentable
3
+ include Concerns::Locale
4
+
5
+ include Concerns::Spammable
6
+ spammable author_email: :email, content: :message
7
+
8
+ STATUSES = %w(pending_moderation published)
9
+
10
+ after_initialize :default_values
11
+
12
+ belongs_to :commentable, polymorphic: true
13
+
14
+ validates :author, :message, presence: true
15
+ validates :status, inclusion: { in: STATUSES }
16
+ validates :email, presence: true,
17
+ format: { with: /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\Z/i }
18
+ validates :website, url: true, allow_blank: true
19
+
20
+ def published?
21
+ status.to_s == 'published'
22
+ end
23
+
24
+ def publish!
25
+ update_attribute :status, :published
26
+ end
27
+
28
+ def unpublish!
29
+ update_attribute :status, :pending_moderation
30
+ end
31
+
32
+ private
33
+
34
+ def default_values
35
+ if self.new_record?
36
+ self.status = 'pending_moderation' if status.nil?
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,37 @@
1
+ module Concerns
2
+ module Cacheable
3
+ extend ActiveSupport::Concern
4
+
5
+ included do
6
+ after_save :flush_cache
7
+ after_touch :flush_cache
8
+
9
+ scope :find_in_cache, ->(value) {
10
+ Rails.cache.fetch([name, value]) do
11
+ o = find_by!(@cache_field => value)
12
+
13
+ # If the model is translatable, we want all the translation fields in
14
+ # every locale to be initialized. This way we avoid a separate query
15
+ # for each of the fields in the translation collection.
16
+ if o.respond_to?(:translatable?) && o.translatable?
17
+ Udongo.config.locales.each do |l|
18
+ name.constantize.translation_config.fields.each { |f| o.translation(l).send(f) }
19
+ end
20
+ end
21
+
22
+ o
23
+ end
24
+ }
25
+ end
26
+
27
+ module ClassMethods
28
+ def cache_by(field)
29
+ @cache_field = field
30
+
31
+ define_method(:flush_cache) do
32
+ Rails.cache.delete [self.class.name, self.send(field)]
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,9 @@
1
+ module Concerns
2
+ module Commentable
3
+ extend ActiveSupport::Concern
4
+
5
+ included do
6
+ has_many :comments, as: :commentable, dependent: :destroy
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,13 @@
1
+ module Concerns
2
+ module ContentType
3
+ extend ActiveSupport::Concern
4
+
5
+ included do
6
+ after_save -> { column.touch if column.present? }
7
+ end
8
+
9
+ def column
10
+ ::ContentColumn.where(content_type: self.class.name, content_id: id).take
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,13 @@
1
+ # If you want to use this concern, you need to add a boolean field 'deletable' to
2
+ # the model.
3
+ module Concerns
4
+ module Deletable
5
+ extend ActiveSupport::Concern
6
+
7
+ included do
8
+ after_initialize do
9
+ self.deletable = true if self.new_record? && deletable.nil?
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,13 @@
1
+ # If you want to use this concern, you need to add a boolean field 'draggable' to
2
+ # the model.
3
+ module Concerns
4
+ module Draggable
5
+ extend ActiveSupport::Concern
6
+
7
+ included do
8
+ after_initialize do
9
+ self.draggable = true if self.new_record? && draggable.nil?
10
+ end
11
+ end
12
+ end
13
+ end