udongo 5.8.0 → 5.9.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 (56) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/javascripts/backend/general.js +1 -0
  3. data/app/assets/javascripts/backend/tree.js +2 -2
  4. data/app/controllers/backend/forms/base_controller.rb +9 -0
  5. data/app/controllers/backend/forms/fields_controller.rb +63 -0
  6. data/app/controllers/backend/forms/submissions_controller.rb +23 -0
  7. data/app/controllers/backend/forms_controller.rb +58 -0
  8. data/app/decorators/form_decorator.rb +7 -0
  9. data/app/decorators/form_submission_data_decorator.rb +9 -0
  10. data/app/forms/backend/form_field_translation_form.rb +8 -0
  11. data/app/forms/backend/form_translation_form.rb +7 -0
  12. data/app/helpers/link_helper.rb +21 -11
  13. data/app/models/form.rb +10 -0
  14. data/app/models/form_field.rb +13 -0
  15. data/app/models/form_submission.rb +19 -0
  16. data/app/models/form_submission_data.rb +17 -0
  17. data/app/views/backend/articles/index.html.erb +1 -1
  18. data/app/views/backend/email_templates/index.html.erb +1 -1
  19. data/app/views/backend/forms/_fields.html.erb +42 -0
  20. data/app/views/backend/forms/_form.html.erb +24 -0
  21. data/app/views/backend/forms/_tabs.html.erb +29 -0
  22. data/app/views/backend/forms/edit.html.erb +5 -0
  23. data/app/views/backend/forms/edit_translation.html.erb +20 -0
  24. data/app/views/backend/forms/fields/_form.html.erb +34 -0
  25. data/app/views/backend/forms/fields/_tabs.html.erb +21 -0
  26. data/app/views/backend/forms/fields/edit.html.erb +6 -0
  27. data/app/views/backend/forms/fields/edit_translation.html.erb +25 -0
  28. data/app/views/backend/forms/fields/index.html.erb +44 -0
  29. data/app/views/backend/forms/fields/new.html.erb +5 -0
  30. data/app/views/backend/forms/index.html.erb +51 -0
  31. data/app/views/backend/forms/new.html.erb +4 -0
  32. data/app/views/backend/forms/submissions/_form.html.erb +0 -0
  33. data/app/views/backend/forms/submissions/index.html.erb +40 -0
  34. data/app/views/backend/forms/submissions/show.html.erb +20 -0
  35. data/app/views/backend/navigations/index.html.erb +2 -2
  36. data/app/views/backend/snippets/index.html.erb +3 -3
  37. data/app/views/layouts/backend/_top_navigation.html.erb +1 -0
  38. data/changelog.md +11 -0
  39. data/config/locales/en_backend.yml +25 -0
  40. data/config/locales/en_forms.yml +3 -0
  41. data/config/locales/nl_backend.yml +25 -0
  42. data/config/locales/nl_forms.yml +4 -0
  43. data/config/routes.rb +9 -0
  44. data/db/migrate/20170407115044_readd_forms.rb +39 -0
  45. data/db/migrate/20170410115600_rename_name_to_identifier_for_form_field.rb +5 -0
  46. data/db/migrate/20170410120608_remove_placeholder_from_form_fields.rb +5 -0
  47. data/db/migrate/20170410121055_remove_default_value_from_form_fields.rb +5 -0
  48. data/db/migrate/20170411161008_add_validation_fields_to_form_fields.rb +6 -0
  49. data/lib/udongo/configs/forms.rb +18 -0
  50. data/lib/udongo/pages/tree_node.rb +1 -1
  51. data/lib/udongo/version.rb +1 -1
  52. data/spec/factories/form_fields.rb +7 -0
  53. data/spec/factories/form_submission_data.rb +7 -0
  54. data/spec/factories/form_submissions.rb +5 -0
  55. data/spec/factories/forms.rb +5 -0
  56. metadata +40 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: e012e2dccbe75d74ea00c84ab30ae20423be0be1
4
- data.tar.gz: b7b476f535941b05b5b7d857f15819af1c5f2753
3
+ metadata.gz: 3ce4d4a15bc9ca2173d65611f6cfe39d92c8a2aa
4
+ data.tar.gz: 5545139075d1cac88213402b77c12d6d43f12137
5
5
  SHA512:
6
- metadata.gz: e1e04b226920a07f783df0bd889920bc137905ce349df750acd05f9b056462cf55addd1f357e6b966cb200a0b65cb6fe585a40a4d398572a751bd94d1be7e047
7
- data.tar.gz: 90bed388b48beb7a0e1a19b44209558cfc01928b112490064f251dfade8204bbd2065995f6c612d96bf9c9a9362c9f7fd40204c5011e33df480a76df022ffaaa
6
+ metadata.gz: 0724a9d61b1b0418ca16b73843b7688d48babe0c8147b4c4c6472712f280bfbfb79e73572f8617cc9aeea95b5d0694ebe03720427d112c503ade039455e2286a
7
+ data.tar.gz: 4940bb72cb0f5e2644e03f125a0dcbd6245e334d8c77040577d59cf3bc737d95c9921c9e9838a8a49f1002cf3e1e12f2c7f7a6e47d4b449a9d863617dea037aa
@@ -1,6 +1,7 @@
1
1
  var general = general || {
2
2
  init: function() {
3
3
  $('form:not(.no-focus) input:visible:not(.no-focus):first').focus();
4
+ $('[data-toggle="tooltip"]').tooltip();
4
5
  }
5
6
  };
6
7
 
@@ -63,7 +63,7 @@ var tree = tree || {
63
63
 
64
64
  contextmenu_remove_listener: function(obj) {
65
65
  var instance = tree.vars.container.jstree(true);
66
- var node = instance.get_node(obj.reference.prevObject.selector);
66
+ var node = instance.get_node(obj.reference);
67
67
 
68
68
  $.ajax({
69
69
  data: { id: node.data.id },
@@ -80,7 +80,7 @@ var tree = tree || {
80
80
 
81
81
  contextmenu_toggle_visibility_listener: function(obj) {
82
82
  var instance = tree.vars.container.jstree(true);
83
- var node = instance.get_node(obj.reference.prevObject.selector);
83
+ var node = instance.get_node(obj.reference);
84
84
 
85
85
  $.ajax({
86
86
  data: { id: node.data.id },
@@ -0,0 +1,9 @@
1
+ class Backend::Forms::BaseController < Backend::BaseController
2
+ before_action :find_form
3
+
4
+ private
5
+
6
+ def find_form
7
+ @form = Form.find(params[:form_id]).decorate
8
+ end
9
+ end
@@ -0,0 +1,63 @@
1
+ class Backend::Forms::FieldsController < Backend::Forms::BaseController
2
+ include Concerns::Backend::TranslatableController
3
+ include Concerns::Backend::PositionableController
4
+ include Concerns::PaginationController
5
+
6
+ before_action :find_model, only: [:edit, :update, :destroy]
7
+ before_action -> do
8
+ breadcrumb.add t('b.forms'), backend_forms_path
9
+ breadcrumb.add @form.description, edit_backend_form_path(@form)
10
+ end
11
+
12
+ def new
13
+ @field = @form.fields.new
14
+ end
15
+
16
+ def create
17
+ @field = @form.fields.new(allowed_params)
18
+
19
+ if @field.save
20
+ redirect_to edit_translation_backend_form_field_path(@form, @field, locale),
21
+ notice: translate_notice(:added, :form_field)
22
+ else
23
+ render :new
24
+ end
25
+ end
26
+
27
+ def update
28
+ if @field.update_attributes allowed_params
29
+ redirect_to backend_form_fields_path(@form),
30
+ notice: translate_notice(:edited, :form_field)
31
+ else
32
+ render :edit
33
+ end
34
+ end
35
+
36
+ def destroy
37
+ @field.destroy
38
+ redirect_to backend_form_fields_path(@form),
39
+ notice: translate_notice(:deleted, :form_field)
40
+ end
41
+
42
+ private
43
+
44
+ def allowed_params
45
+ params[:form_field].permit(:identifier, :field_type, :presence, :email)
46
+ end
47
+
48
+ def find_model
49
+ @field ||= @form.fields.find(params[:id])
50
+ end
51
+
52
+ def translation_form
53
+ Backend::FormFieldTranslationForm.new(
54
+ @field,
55
+ @field.translation(params[:translation_locale])
56
+ )
57
+ end
58
+
59
+ def translatable_path
60
+ method = "edit_translation_backend_#{model_name}_path"
61
+ @translatable_path || send(method, @form, @model, params[:translation_locale])
62
+ end
63
+ end
@@ -0,0 +1,23 @@
1
+ class Backend::Forms::SubmissionsController < Backend::Forms::BaseController
2
+ include Concerns::PaginationController
3
+
4
+ before_action :find_model, except: [:index]
5
+ before_action -> do
6
+ breadcrumb.add t('b.forms'), backend_forms_path
7
+ breadcrumb.add @form.description, edit_backend_form_path(@form)
8
+ end
9
+
10
+ def index
11
+ @submissions = paginate(@form.submissions)
12
+ end
13
+
14
+ def destroy
15
+ @model.destroy
16
+ redirect_to backend_forms_path,
17
+ notice: translate_notice(:deleted, :form_submission)
18
+ end
19
+
20
+ def find_model
21
+ @model = FormSubmission.find(params[:id])
22
+ end
23
+ end
@@ -0,0 +1,58 @@
1
+ class Backend::FormsController < Backend::BaseController
2
+ include Concerns::Backend::TranslatableController
3
+
4
+ before_action :find_model, only: [:edit, :update, :destroy]
5
+ before_action -> { breadcrumb.add t('b.forms'), backend_forms_path}
6
+
7
+ def index
8
+ @forms = Form.all
9
+ end
10
+
11
+ def new
12
+ @model = Form.new
13
+ end
14
+
15
+ def create
16
+ @model = Form.new(allowed_params)
17
+
18
+ if @model.save
19
+ redirect_to backend_forms_path, notice: translate_notice(:added, :form)
20
+ else
21
+ render :new
22
+ end
23
+ end
24
+
25
+ def edit
26
+ @model = Form.find(params[:id])
27
+ end
28
+
29
+ def update
30
+ if @model.update_attributes allowed_params
31
+ redirect_to backend_forms_path, notice: translate_notice(:edited, :form)
32
+ else
33
+ render :edit
34
+ end
35
+ end
36
+
37
+ def destroy
38
+ @model.destroy
39
+ redirect_to backend_forms_path, notice: translate_notice(:deleted, :form)
40
+ end
41
+
42
+ private
43
+
44
+ def allowed_params
45
+ params[:form].permit(:identifier, :description)
46
+ end
47
+
48
+ def find_model
49
+ @model = Form.find(params[:id].to_i)
50
+ end
51
+
52
+ def translation_form
53
+ Backend::FormTranslationForm.new(
54
+ @model,
55
+ @model.translation(params[:translation_locale])
56
+ )
57
+ end
58
+ end
@@ -0,0 +1,7 @@
1
+ class FormDecorator < ApplicationDecorator
2
+ delegate_all
3
+
4
+ def email_present?
5
+ data.select('DISTINCT name').map(&:name).include?('email')
6
+ end
7
+ end
@@ -0,0 +1,9 @@
1
+ class FormSubmissionDataDecorator < ApplicationDecorator
2
+ delegate_all
3
+
4
+ def label
5
+ field = form_submission.form.fields.find_by(identifier: name)
6
+ return field.label if field && field.label.present?
7
+ name
8
+ end
9
+ end
@@ -0,0 +1,8 @@
1
+ class Backend::FormFieldTranslationForm < Backend::TranslationForm
2
+ attribute :label, String
3
+ attribute :default_value, String
4
+
5
+ def self.model_name
6
+ FormField.model_name
7
+ end
8
+ end
@@ -0,0 +1,7 @@
1
+ class Backend::FormTranslationForm < Backend::TranslationForm
2
+ attribute :success_message, String
3
+
4
+ def self.model_name
5
+ Form.model_name
6
+ end
7
+ end
@@ -1,33 +1,43 @@
1
1
  module LinkHelper
2
- def link_to_show(object)
3
- str = Udongo::ObjectPath.find(object)
4
-
2
+ def link_to_show(value)
5
3
  link_to(
6
4
  icon(:search),
7
- send(str, *Udongo::ObjectPath.remove_symbols(object)),
5
+ path_from_string_or_object(value),
8
6
  title: t('b.view')
9
7
  )
10
8
  end
11
9
 
12
- def link_to_edit(object)
13
- str = "edit_#{Udongo::ObjectPath.find(object)}"
14
-
10
+ def link_to_edit(value)
15
11
  link_to(
16
12
  icon(:pencil_square_o),
17
- send(str, *Udongo::ObjectPath.remove_symbols(object)),
13
+ path_from_string_or_object(value, 'edit_'),
18
14
  title: t('b.edit')
19
15
  )
20
16
  end
21
17
 
22
- def link_to_delete(object)
23
- str = Udongo::ObjectPath.find(object)
18
+ def link_to_edit_translation(object, locale = Udongo.config.i18n.app.default_locale)
19
+ str = "edit_translation_#{Udongo::ObjectPath.find(object)}"
20
+ url = send(str, *Udongo::ObjectPath.remove_symbols(object), locale)
21
+
22
+ link_to_edit(url)
23
+ end
24
24
 
25
+ def link_to_delete(value)
25
26
  link_to(
26
27
  icon(:trash),
27
- send(str, *Udongo::ObjectPath.remove_symbols(object)),
28
+ path_from_string_or_object(value),
28
29
  method: :delete,
29
30
  data: { confirm: t('b.msg.confirm') },
30
31
  title: t('b.delete')
31
32
  )
32
33
  end
34
+
35
+ private
36
+
37
+ def path_from_string_or_object(value, prefix = nil)
38
+ return value if value.is_a?(String)
39
+
40
+ str = "#{prefix}#{Udongo::ObjectPath.find(value)}"
41
+ send(str, *Udongo::ObjectPath.remove_symbols(value))
42
+ end
33
43
  end
@@ -0,0 +1,10 @@
1
+ class Form < ApplicationRecord
2
+ include Concerns::Translatable
3
+ translatable_fields :success_message
4
+
5
+ has_many :fields, class_name: 'FormField', dependent: :destroy
6
+ has_many :submissions, class_name: 'FormSubmission', dependent: :destroy
7
+ has_many :data, through: :submissions
8
+
9
+ validates :description, presence: true
10
+ end
@@ -0,0 +1,13 @@
1
+ class FormField < ApplicationRecord
2
+ include Concerns::Sortable
3
+ sortable scope: [:form_id]
4
+
5
+ include Concerns::Translatable
6
+ translatable_fields :label, :default_value
7
+
8
+ belongs_to :form
9
+
10
+ validates :form, :identifier, :field_type, presence: true
11
+
12
+ validates_uniqueness_of :identifier, scope: :form_id
13
+ end
@@ -0,0 +1,19 @@
1
+ class FormSubmission < ApplicationRecord
2
+ include Concerns::Emailable
3
+ include Concerns::Searchable
4
+
5
+ # TODO: Make this searchable by adding the key/value columns on data
6
+ # as accessible attributes on FormSubmission.
7
+
8
+ belongs_to :form
9
+ has_many :data, class_name: 'FormSubmissionData'
10
+
11
+ validates :form, presence: true
12
+
13
+ def data_object
14
+ data.inject(OpenStruct.new) do |stack, d|
15
+ stack.send("#{d.name}=", d.value)
16
+ stack
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,17 @@
1
+ class FormSubmissionData < ApplicationRecord
2
+ # By saving the form submission data as a search index, you work around
3
+ # possible slow searches for the form submissions.
4
+ after_save do
5
+ next if value.blank?
6
+ index = form_submission.search_indices.find_or_initialize_by(
7
+ locale: Udongo.config.i18n.app.default_locale,
8
+ name: name
9
+ )
10
+ index.value = value
11
+ index.save!
12
+ end
13
+
14
+ belongs_to :form_submission
15
+
16
+ validates :form_submission, presence: true
17
+ end
@@ -41,7 +41,7 @@
41
41
  <td><%= t a.visible?.to_s %></td>
42
42
  <td><%= t a.press_release?.to_s %></td>
43
43
  <td class="text-xs-right">
44
- <%= link_to_edit [:backend, a] %>
44
+ <%= link_to_edit_translation [:backend, a] %>
45
45
  <%= link_to_delete [:backend, a] %>
46
46
  </td>
47
47
  </tr>
@@ -15,7 +15,7 @@
15
15
  <tr data-update-position="<%= update_position_backend_email_template_path(s) %>">
16
16
  <td><%= s.description %></td>
17
17
  <td class="text-xs-right">
18
- <%= link_to_edit [:backend, s] %>
18
+ <%= link_to_edit_translation [:backend, s] %>
19
19
  </td>
20
20
  </tr>
21
21
  <% end %>
@@ -0,0 +1,42 @@
1
+ <% javascript 'backend/sortable' %>
2
+
3
+ <div id="form-fields" class="card">
4
+ <div class="card-header">
5
+ <%= t 'b.msg.form_fields.index_header_html', form: form.description %>
6
+ <% if form.fields.any? %>
7
+ <div class="pull-right">
8
+ <%= link_to icon(:plus, t('b.msg.form_fields.add')), new_backend_form_field_path(form), class: 'btn btn-primary btn-sm' %>
9
+ </div>
10
+ <% end %>
11
+ </div>
12
+
13
+ <div class="card-block">
14
+ <% if form.fields.any? %>
15
+ <table class="table table-hover">
16
+ <thead>
17
+ <tr>
18
+ <th><%= t('b.name') %></th>
19
+ <th>&nbsp;</th>
20
+ </tr>
21
+ </thead>
22
+
23
+ <tbody>
24
+ <% form.fields.each do |f| %>
25
+ <tr data-update-position="<%= update_position_backend_form_field_path(form, f) %>">
26
+ <td><%= f.identifier %></td>
27
+ <td class="text-xs-right">
28
+ <%= link_to icon(:pencil_square_o), edit_backend_form_field_path(form, f) %>
29
+ <%= link_to icon(:trash), backend_form_field_path(form, f), method: :delete, data: { confirm: t('b.msg.confirm') }, title: t('b.delete') %>
30
+ </td>
31
+ </tr>
32
+ <% end %>
33
+ </tbody>
34
+ </table>
35
+ <% else %>
36
+ <p>
37
+ <%= t('b.msg.form_fields.explanation') %>
38
+ <%= link_to t('b.msg.form_fields.add_first'), new_backend_form_field_path(form) %>.
39
+ </p>
40
+ <% end %>
41
+ </div>
42
+ </div>
@@ -0,0 +1,24 @@
1
+ <%= render 'backend/general_form_error', object: @model %>
2
+
3
+ <%= simple_form_for [:backend, @model] do |f| %>
4
+ <div class="row">
5
+ <div class="col-md-12">
6
+ <div class="card">
7
+ <div class="card-header">
8
+ <%= t 'b.general' %>
9
+ </div>
10
+
11
+ <div class="card-block">
12
+ <%= f.input :description, as: :string %>
13
+ </div>
14
+ </div>
15
+ </div>
16
+ </div>
17
+
18
+ <% unless @model.new_record? %>
19
+ <%# TODO: rendered form preview instead of formfields datagrid %>
20
+ <%# render 'backend/forms/fields', form: @model %>
21
+ <% end %>
22
+
23
+ <%= render 'backend/form_actions', cancel_url: backend_forms_path %>
24
+ <% end %>