udongo 2.0.4 → 3.0.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 (119) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/javascripts/backend/application.js +1 -0
  3. data/app/assets/javascripts/backend/bootstrap.js +3 -3569
  4. data/app/assets/javascripts/backend/tree.js +106 -65
  5. data/app/assets/stylesheets/backend/application.scss +2 -0
  6. data/app/assets/stylesheets/backend/bootstrap.scss +29 -51
  7. data/app/assets/stylesheets/backend/components/_page_tree.scss +9 -0
  8. data/app/assets/stylesheets/backend/custom.scss +0 -0
  9. data/app/assets/stylesheets/backend/font-awesome.scss +644 -1977
  10. data/app/assets/stylesheets/backend/udongo.scss +1 -0
  11. data/app/controllers/backend/admins_controller.rb +2 -2
  12. data/app/controllers/{backend_controller.rb → backend/base_controller.rb} +13 -5
  13. data/app/controllers/backend/content/rows/columns_controller.rb +1 -1
  14. data/app/controllers/backend/content/rows/images_controller.rb +1 -1
  15. data/app/controllers/backend/content/rows/texts_controller.rb +1 -1
  16. data/app/controllers/backend/content/rows_controller.rb +1 -1
  17. data/app/controllers/backend/dashboard_controller.rb +1 -1
  18. data/app/controllers/backend/email_templates_controller.rb +12 -12
  19. data/app/controllers/backend/emails_controller.rb +1 -1
  20. data/app/controllers/backend/navigation/items_controller.rb +9 -11
  21. data/app/controllers/backend/navigations_controller.rb +1 -1
  22. data/app/controllers/backend/pages_controller.rb +17 -39
  23. data/app/controllers/backend/redirects_controller.rb +1 -1
  24. data/app/controllers/backend/seo_controller.rb +1 -1
  25. data/app/controllers/backend/sessions_controller.rb +1 -1
  26. data/app/controllers/backend/snippets_controller.rb +14 -13
  27. data/app/controllers/backend/tagbox_controller.rb +1 -1
  28. data/app/controllers/catch_all_controller.rb +1 -1
  29. data/app/controllers/concerns/backend/content_type_controller.rb +3 -1
  30. data/app/controllers/redirects_controller.rb +1 -1
  31. data/app/decorators/page_decorator.rb +1 -4
  32. data/app/forms/backend/email_template_translation_form.rb +1 -23
  33. data/app/forms/backend/navigation_item_translation_form.rb +1 -23
  34. data/app/forms/backend/page_translation_form.rb +13 -18
  35. data/app/forms/backend/snippet_translation_form.rb +1 -23
  36. data/app/forms/backend/translation_form.rb +22 -0
  37. data/app/helpers/udongo_helper.rb +0 -4
  38. data/app/mailers/general_mailer.rb +14 -4
  39. data/app/models/admin.rb +2 -2
  40. data/app/models/comment.rb +1 -2
  41. data/app/models/concerns/addressable.rb +40 -0
  42. data/app/models/concerns/addressable/config.rb +33 -0
  43. data/app/models/concerns/cacheable.rb +1 -1
  44. data/app/models/email.rb +2 -2
  45. data/app/models/email_template.rb +2 -1
  46. data/app/views/backend/_general_form_error.html.erb +6 -0
  47. data/app/views/backend/admins/_form.html.erb +3 -0
  48. data/app/views/backend/content/rows/columns/_dimension_fields.html.erb +3 -0
  49. data/app/views/backend/content/rows/columns/edit.html.erb +3 -5
  50. data/app/views/backend/content/rows/columns/new.html.erb +3 -5
  51. data/app/views/backend/content/rows/images/edit.html.erb +2 -0
  52. data/app/views/backend/dashboard/show.html.erb +1 -1
  53. data/app/views/backend/email_templates/_form.html.erb +29 -7
  54. data/app/views/backend/email_templates/_tabs.html.erb +1 -1
  55. data/app/views/backend/email_templates/edit_translation.html.erb +1 -0
  56. data/app/views/backend/navigation/items/_form.html.erb +4 -2
  57. data/app/views/backend/navigation/items/_tabs.html.erb +1 -1
  58. data/app/views/backend/navigation/items/edit_translation.html.erb +1 -0
  59. data/app/views/backend/pages/_form.html.erb +4 -2
  60. data/app/views/backend/pages/_tabs.html.erb +1 -1
  61. data/app/views/backend/pages/edit_translation.html.erb +1 -0
  62. data/app/views/backend/redirects/_form.html.erb +2 -0
  63. data/app/views/backend/snippets/_form.html.erb +3 -1
  64. data/app/views/backend/snippets/_tabs.html.erb +1 -1
  65. data/app/views/backend/snippets/edit.html.erb +1 -1
  66. data/app/views/backend/snippets/edit_translation.html.erb +1 -0
  67. data/app/views/backend/snippets/new.html.erb +1 -1
  68. data/app/views/layouts/backend/_top_navigation.html.erb +1 -2
  69. data/changelog.md +38 -0
  70. data/config/initializers/simple_form_bootstrap.rb +13 -9
  71. data/config/locales/en_backend.yml +1 -4
  72. data/config/locales/en_forms.yml +3 -0
  73. data/config/locales/nl_backend.yml +3 -4
  74. data/config/locales/nl_forms.yml +3 -0
  75. data/config/routes.rb +5 -7
  76. data/db/migrate/20160815100903_remove_form_models.rb +9 -0
  77. data/db/migrate/20161014135637_add_category_to_admin.rb +5 -0
  78. data/db/migrate/20161029124558_add_locale_to_admin.rb +6 -0
  79. data/db/migrate/20161029130557_add_bcc_and_cc_to_email_templates.rb +6 -0
  80. data/db/migrate/20161029171056_add_ccc_and_bcc_to_email.rb +6 -0
  81. data/lib/udongo/configs/flexible_content.rb +7 -0
  82. data/lib/udongo/configs/i18n.rb +5 -3
  83. data/lib/udongo/configs/i18ns/app.rb +12 -0
  84. data/lib/udongo/configs/i18ns/cms.rb +12 -0
  85. data/lib/udongo/flexible_content/column_width_calculator.rb +4 -2
  86. data/lib/udongo/pages/tree.rb +15 -0
  87. data/lib/udongo/pages/tree_node.rb +43 -0
  88. data/lib/udongo/version.rb +1 -1
  89. data/readme.md +103 -43
  90. data/vendor/assets/javascripts/backend/select2.min.js +3 -0
  91. data/vendor/assets/stylesheets/backend/jstree/default/style.scss +3 -3
  92. data/vendor/assets/stylesheets/backend/select2.min.scss +1 -0
  93. metadata +22 -30
  94. data/app/controllers/backend/forms/base_controller.rb +0 -14
  95. data/app/controllers/backend/forms/submissions_controller.rb +0 -8
  96. data/app/controllers/backend/forms_controller.rb +0 -7
  97. data/app/controllers/backend/webserver_controller.rb +0 -6
  98. data/app/decorators/form_decorator.rb +0 -16
  99. data/app/decorators/form_submission_decorator.rb +0 -3
  100. data/app/forms/backend/email_template_form.rb +0 -38
  101. data/app/forms/backend/navigation_item_form.rb +0 -23
  102. data/app/forms/backend/page_form.rb +0 -26
  103. data/app/forms/backend/snippet_form.rb +0 -35
  104. data/app/models/form.rb +0 -10
  105. data/app/models/form_field.rb +0 -15
  106. data/app/models/form_field_validation.rb +0 -11
  107. data/app/models/form_submission.rb +0 -15
  108. data/app/models/form_submission_data.rb +0 -5
  109. data/app/views/backend/_form_errors.html.erb +0 -15
  110. data/app/views/backend/forms/index.html.erb +0 -27
  111. data/app/views/backend/forms/submissions/_filter.html.erb +0 -16
  112. data/app/views/backend/forms/submissions/index.html.erb +0 -34
  113. data/lib/generators/udongo/form/form_generator.rb +0 -62
  114. data/lib/generators/udongo/form/templates/form.rb +0 -18
  115. data/lib/udongo/configs/forms.rb +0 -18
  116. data/lib/udongo/configs/routes.rb +0 -13
  117. data/lib/udongo/email_vars/form_submission.rb +0 -18
  118. data/lib/udongo/forms/submission_datagrid.rb +0 -27
  119. data/lib/udongo/forms/submission_filter.rb +0 -31
@@ -1,33 +1,11 @@
1
- class Backend::EmailTemplateTranslationForm < Udongo::Form
2
- attr_reader :email_template, :translation
3
-
1
+ class Backend::EmailTemplateTranslationForm < Backend::TranslationForm
4
2
  attribute :subject, String
5
3
  attribute :plain_content, String
6
4
  attribute :html_content, String
7
5
 
8
6
  validates :subject, :plain_content, :html_content, presence: true
9
7
 
10
- delegate :id, to: :email_template
11
-
12
- def initialize(email_template, translation)
13
- @email_template = email_template
14
- @translation = translation
15
-
16
- init_attribute_values(@translation)
17
- end
18
-
19
8
  def self.model_name
20
9
  EmailTemplate.model_name
21
10
  end
22
-
23
- def persisted?
24
- true
25
- end
26
-
27
- private
28
-
29
- def save_object
30
- init_object_values(@translation)
31
- @translation.save
32
- end
33
11
  end
@@ -1,30 +1,8 @@
1
- class Backend::NavigationItemTranslationForm < Udongo::Form
2
- attr_reader :navigation_item, :translation
3
-
1
+ class Backend::NavigationItemTranslationForm < Backend::TranslationForm
4
2
  attribute :label, String
5
3
  attribute :path, String
6
4
 
7
- delegate :id, to: :navigation_item
8
-
9
- def initialize(navigation_item, translation)
10
- @navigation_item = navigation_item
11
- @translation = translation
12
-
13
- init_attribute_values(translation)
14
- end
15
-
16
5
  def self.model_name
17
6
  NavigationItem.model_name
18
7
  end
19
-
20
- def persisted?
21
- true
22
- end
23
-
24
- private
25
-
26
- def save_object
27
- init_object_values(@translation)
28
- @translation.save
29
- end
30
8
  end
@@ -22,11 +22,9 @@ class Backend::PageTranslationForm < Udongo::Form
22
22
  self.title = @translation.title
23
23
  self.subtitle = @translation.subtitle
24
24
 
25
- self.seo_title = @seo.title
26
- self.seo_keywords = @seo.keywords
27
- self.seo_description = @seo.description
28
- self.seo_custom = @seo.custom
29
- self.seo_slug = @seo.slug
25
+ %w(title keywords description custom slug).each do |f|
26
+ self.send("seo_#{f}=", @seo.send(f))
27
+ end
30
28
  end
31
29
 
32
30
  def self.model_name
@@ -41,11 +39,9 @@ class Backend::PageTranslationForm < Udongo::Form
41
39
  self.title = params[:title]
42
40
  self.subtitle = params[:subtitle]
43
41
 
44
- self.seo_title = params[:seo_title]
45
- self.seo_keywords = params[:seo_keywords]
46
- self.seo_description = params[:seo_description]
47
- self.seo_custom = params[:seo_custom]
48
- self.seo_slug = params[:seo_slug]
42
+ %w(title keywords description custom slug).each do |f|
43
+ self.send("seo_#{f}=", params["seo_#{f}".to_sym])
44
+ end
49
45
 
50
46
  if valid?
51
47
  save_object
@@ -60,13 +56,12 @@ class Backend::PageTranslationForm < Udongo::Form
60
56
  def save_object
61
57
  @translation.title = title
62
58
  @translation.subtitle = subtitle
63
- @translation.save
64
-
65
- @seo.title = seo_title
66
- @seo.keywords = seo_keywords
67
- @seo.description = seo_description
68
- @seo.custom = seo_custom
69
- @seo.slug = seo_slug
70
- @seo.save
59
+
60
+ %w(title keywords description custom slug).each do |f|
61
+ @seo.send("#{f}=", send("seo_#{f}"))
62
+ end
63
+
64
+ # Saves the page, translation and SEO info all at once.
65
+ @page.save
71
66
  end
72
67
  end
@@ -1,30 +1,8 @@
1
- class Backend::SnippetTranslationForm < Udongo::Form
2
- attr_reader :snippet, :translation
3
-
1
+ class Backend::SnippetTranslationForm < Backend::TranslationForm
4
2
  attribute :title, String
5
3
  attribute :content, String
6
4
 
7
- delegate :id, to: :snippet
8
-
9
- def initialize(snippet, translation)
10
- @snippet = snippet
11
- @translation = translation
12
-
13
- init_attribute_values(translation)
14
- end
15
-
16
5
  def self.model_name
17
6
  Snippet.model_name
18
7
  end
19
-
20
- def persisted?
21
- true
22
- end
23
-
24
- private
25
-
26
- def save_object
27
- init_object_values(@translation)
28
- @translation.save
29
- end
30
8
  end
@@ -0,0 +1,22 @@
1
+ class Backend::TranslationForm < Udongo::Form
2
+ attr_reader :model, :translation
3
+ delegate :id, to: :model
4
+
5
+ def initialize(model, translation)
6
+ @model = model
7
+ @translation = translation
8
+
9
+ init_attribute_values(@translation)
10
+ end
11
+
12
+ def persisted?
13
+ true
14
+ end
15
+
16
+ private
17
+
18
+ def save_object
19
+ init_object_values(@translation)
20
+ @model.save
21
+ end
22
+ end
@@ -5,10 +5,6 @@ module UdongoHelper
5
5
  js_asset_loader.load_js file, target
6
6
  end
7
7
 
8
- def restart_webserver_button
9
- link_to I18n.t('b.restart_webserver'), backend_restart_webserver_path, class: 'btn btn-info', method: 'post'
10
- end
11
-
12
8
  # Before using: Put <%= yield(:stylesheets) %> in the <head> of your app's frontend
13
9
  def stylesheet(file, media = :screen)
14
10
  css_asset_loader.view = self
@@ -1,13 +1,23 @@
1
1
  class GeneralMailer < ActionMailer::Base
2
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|
3
+ mail(headers(email)) do |format|
7
4
  format.text { render text: email.plain_content }
8
5
  format.html { render html: email.html_content.html_safe }
9
6
  end
10
7
 
11
8
  email.mark_as_sent!
12
9
  end
10
+
11
+ private
12
+
13
+ def headers(email)
14
+ from = "#{email.from_name} <#{email.from_email}>"
15
+ to = "#{email.to_name} <#{email.to_email}>"
16
+
17
+ {
18
+ from: from,
19
+ to: to,
20
+ subject: email.subject
21
+ }
22
+ end
13
23
  end
data/app/models/admin.rb CHANGED
@@ -2,8 +2,8 @@ class Admin < ApplicationRecord
2
2
  include Concerns::Person
3
3
  has_secure_password
4
4
 
5
- validates :first_name, :last_name, presence: true
5
+ validates :locale, :first_name, :last_name, presence: true
6
6
  validates :email,
7
7
  uniqueness: { case_sensitive: false },
8
- format: { with: /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\Z/i }
8
+ email: true
9
9
  end
@@ -11,8 +11,7 @@ class Comment < ApplicationRecord
11
11
 
12
12
  validates :author, :message, presence: true
13
13
  validates :status, inclusion: { in: STATUSES }
14
- validates :email, presence: true,
15
- format: { with: /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\Z/i }
14
+ validates :email, presence: true, email: true
16
15
  validates :website, url: true, allow_blank: true
17
16
 
18
17
  def published?
@@ -0,0 +1,40 @@
1
+ module Concerns
2
+ module Addressable
3
+ extend ActiveSupport::Concern
4
+
5
+ included do
6
+ has_many :addresses, dependent: :destroy
7
+ end
8
+
9
+ module ClassMethods
10
+ def configure_adress(categories, default: nil)
11
+ address_config.update(categories, default: default)
12
+ end
13
+
14
+ def address_config
15
+ @address_config ||= Concerns::Addressable::Config.new
16
+ end
17
+ end
18
+
19
+ def address(category = nil)
20
+ category = self.class.address_config.default unless category.present?
21
+
22
+ unless self.class.address_config.allowed?(category)
23
+ raise "You can't select the '#{category}' address because it's not an allowed category"
24
+ end
25
+
26
+ @address_collections = {} unless @address_collections
27
+
28
+ unless @address_collections[category.to_sym]
29
+
30
+ @address_collections[category.to_sym] = Address.find_or_initialize_by(
31
+ category: category,
32
+ addressable_type: self.class.name,
33
+ addressable_id: id
34
+ )
35
+ end
36
+
37
+ @address_collections[category.to_sym]
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,33 @@
1
+ module Concerns
2
+ module Addressable
3
+ class Config
4
+ attr_reader :fields, :default
5
+
6
+ def initialize
7
+ @fields = []
8
+ @default = nil
9
+ end
10
+
11
+ def update(categories, default: nil)
12
+ unless categories.respond_to?(:each) && categories.any?
13
+ raise 'Please provide an array with address categories'
14
+ end
15
+
16
+ @fields = categories.map(&:to_sym).uniq
17
+ @default = @fields.first
18
+
19
+ if default
20
+ unless @fields.include?(default.to_sym)
21
+ raise "You can't make '#{default.to_s}' the default address category because it's not in the list of categories"
22
+ end
23
+
24
+ @default = default.to_sym
25
+ end
26
+ end
27
+
28
+ def allowed?(field)
29
+ @fields.include?(field.to_sym)
30
+ end
31
+ end
32
+ end
33
+ end
@@ -7,7 +7,7 @@ module Concerns
7
7
  after_touch :flush_cache
8
8
 
9
9
  scope :find_in_cache, ->(value) {
10
- Rails.cache.fetch [name, value] do
10
+ Rails.cache.fetch [name, value] do
11
11
  find_by!(@cache_field => value)
12
12
  end
13
13
  }
data/app/models/email.rb CHANGED
@@ -1,8 +1,8 @@
1
1
  class Email < ApplicationRecord
2
2
  validates :from_name, :to_name, :subject, :plain_content, :html_content,
3
3
  presence: true
4
- validates :from_email, :to_email,
5
- format: { with: /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\Z/i }
4
+ validates :from_email, :to_email, email: true
5
+ validates :cc, :bcc, email: true, allow_blank: true
6
6
 
7
7
  scope :sent, -> { where('sent_at IS NOT NULL') }
8
8
  scope :not_sent, -> { where('sent_at IS NULL') }
@@ -6,5 +6,6 @@ class EmailTemplate < ApplicationRecord
6
6
 
7
7
  validates :description, :from_name, presence: true
8
8
  validates :identifier, presence: true, uniqueness: { case_sensitive: false }
9
- validates :from_email, format: { with: /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\Z/i }
9
+ validates :from_email, email: true
10
+ validates :cc, :bcc, email: true, allow_blank: true
10
11
  end
@@ -0,0 +1,6 @@
1
+ <% if object.errors.any? %>
2
+ <div class="alert alert-danger" role="alert">
3
+ <%= t('b.msg.general_form_error').html_safe %>
4
+ </div>
5
+ <% end %>
6
+
@@ -1,3 +1,5 @@
1
+ <%= render 'backend/general_form_error', object: @admin %>
2
+
1
3
  <%= simple_form_for [:backend, @admin] do |f| %>
2
4
  <div class="row">
3
5
  <div class="col-md-6">
@@ -7,6 +9,7 @@
7
9
  </div>
8
10
 
9
11
  <div class="card-block">
12
+ <%= f.input :locale, collection: Udongo.config.i18n.cms.interface_locales, include_blank: false %>
10
13
  <%= f.input :first_name %>
11
14
  <%= f.input :last_name %>
12
15
  <%= f.input :email, required: true %>
@@ -0,0 +1,3 @@
1
+ <% Udongo::Configs::FlexibleContent::BREAKPOINTS.each do |bp| %>
2
+ <%= form.input "width_#{bp}", as: :integer, wrapper_html: { hidden: !Udongo.config.flexible_content.allowed_breakpoint?(bp) } %>
3
+ <% end %>
@@ -1,3 +1,5 @@
1
+ <%= render 'backend/general_form_error', object: @column %>
2
+
1
3
  <%= simple_form_for(@column, url: backend_content_row_column_path(@row, @column)) do |f| %>
2
4
  <div class="card">
3
5
  <div class="card-header">
@@ -7,11 +9,7 @@
7
9
  <div class="card-block">
8
10
  <div class="row">
9
11
  <div class="col-md-6">
10
- <%= f.input :width_xs, as: :integer %>
11
- <%= f.input :width_sm, as: :integer %>
12
- <%= f.input :width_md, as: :integer %>
13
- <%= f.input :width_lg, as: :integer %>
14
- <%= f.input :width_xl, as: :integer %>
12
+ <%= render 'backend/content/rows/columns/dimension_fields', form: f %>
15
13
  </div>
16
14
 
17
15
  <div class="col-md-6">
@@ -1,3 +1,5 @@
1
+ <%= render 'backend/general_form_error', object: @column %>
2
+
1
3
  <%= simple_form_for(@column, url: backend_content_row_columns_path(@row)) do |f| %>
2
4
  <div class="card">
3
5
  <div class="card-header">
@@ -7,11 +9,7 @@
7
9
  <div class="card-block">
8
10
  <div class="row">
9
11
  <div class="col-md-6">
10
- <%= f.input :width_xs, as: :integer %>
11
- <%= f.input :width_sm, as: :integer %>
12
- <%= f.input :width_md, as: :integer %>
13
- <%= f.input :width_lg, as: :integer %>
14
- <%= f.input :width_xl, as: :integer %>
12
+ <%= render 'backend/content/rows/columns/dimension_fields', form: f %>
15
13
  </div>
16
14
 
17
15
  <div class="col-md-6">
@@ -1,3 +1,5 @@
1
+ <%= render 'backend/general_form_error', object: @model %>
2
+
1
3
  <div class="card">
2
4
  <div class="card-header">
3
5
  <%= t 'b.msg.flexible_content.edit_image' %>
@@ -1 +1 @@
1
- Dashboard#show
1
+ <!-- Fine me in app/views/backend/dashboard/show.html.erb -->
@@ -1,27 +1,49 @@
1
- <%= simple_form_for [:backend, @form] do |f| %>
1
+ <%= render 'backend/general_form_error', object: @model %>
2
+
3
+ <%= simple_form_for [:backend, @model] do |f| %>
2
4
  <div class="row">
3
- <div class="col-md-6">
5
+ <div class="col-md-12">
4
6
  <div class="card">
5
7
  <div class="card-header">
6
8
  <%= t 'b.general' %>
7
9
  </div>
8
10
 
9
11
  <div class="card-block">
10
- <%= f.input :identifier %>
11
- <%= f.input :description, as: :string %>
12
+ <div class="row">
13
+ <div class="col-md-6">
14
+ <%= f.input :identifier %>
15
+ </div>
16
+ </div>
17
+
18
+ <div class="row">
19
+ <div class="col-md-12">
20
+ <%= f.input :description, as: :string %>
21
+ </div>
22
+ </div>
12
23
  </div>
13
24
  </div>
14
25
  </div>
26
+ </div>
15
27
 
16
- <div class="col-md-6">
28
+ <div class="row">
29
+ <div class="col-md-12">
17
30
  <div class="card">
18
31
  <div class="card-header">
19
32
  <%= t 'b.settings' %>
20
33
  </div>
21
34
 
22
35
  <div class="card-block">
23
- <%= f.input :from_name %>
24
- <%= f.input :from_email %>
36
+ <div class="row">
37
+ <div class="col-md-6">
38
+ <%= f.input :from_name %>
39
+ <%= f.input :from_email %>
40
+ </div>
41
+
42
+ <div class="col-md-6">
43
+ <%= f.input :cc %>
44
+ <%= f.input :bcc %>
45
+ </div>
46
+ </div>
25
47
  </div>
26
48
  </div>
27
49
  </div>