udongo 5.8.0 → 5.9.0

Sign up to get free protection for your applications and to get access to all the features.
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 %>