diff --git a/plugins/custom_forms/controllers/custom_forms_plugin_myprofile_controller.rb b/plugins/custom_forms/controllers/custom_forms_plugin_myprofile_controller.rb index fb91fdc..6aa9829 100644 --- a/plugins/custom_forms/controllers/custom_forms_plugin_myprofile_controller.rb +++ b/plugins/custom_forms/controllers/custom_forms_plugin_myprofile_controller.rb @@ -19,6 +19,8 @@ class CustomFormsPluginMyprofileController < MyProfileController params[:form][:profile_id] = profile.id @form = CustomFormsPlugin::Form.new(params[:form]) + normalize_positions(@form) + respond_to do |format| if @form.save flash[:notice] = _("Custom form #{@form.name} was successfully created.") @@ -35,9 +37,12 @@ class CustomFormsPluginMyprofileController < MyProfileController def update @form = CustomFormsPlugin::Form.find(params[:id]) + @form.attributes = params[:form] + + normalize_positions(@form) respond_to do |format| - if @form.update_attributes(params[:form]) + if @form.save flash[:notice] = _("Custom form #{@form.name} was successfully updated.") format.html { redirect_to(:action=>'index') } else @@ -84,4 +89,21 @@ class CustomFormsPluginMyprofileController < MyProfileController @form = @submission.form end + private + + def normalize_positions(form) + counter = 0 + form.fields.sort_by{ |f| f.position.to_i }.each do |field| + field.position = counter + counter += 1 + end + form.fields.each do |field| + counter = 0 + field.alternatives.sort_by{ |alt| alt.position.to_i }.each do |alt| + alt.position = counter + counter += 1 + end + end + end + end diff --git a/plugins/custom_forms/db/migrate/20131107050913_add_position_to_field_and_alternatives.rb b/plugins/custom_forms/db/migrate/20131107050913_add_position_to_field_and_alternatives.rb new file mode 100644 index 0000000..0b90a4e --- /dev/null +++ b/plugins/custom_forms/db/migrate/20131107050913_add_position_to_field_and_alternatives.rb @@ -0,0 +1,31 @@ +class AddPositionToFieldAndAlternatives < ActiveRecord::Migration + def self.up + change_table :custom_forms_plugin_fields do |t| + t.integer :position, :default => 0 + end + + change_table :custom_forms_plugin_alternatives do |t| + t.integer :position, :default => 0 + end + + CustomFormsPlugin::Field.find_each do |f| + f.position = f.id + f.save! + end + + CustomFormsPlugin::Alternative.find_each do |f| + f.position = f.id + f.save! + end + end + + def self.down + change_table :custom_forms_plugin_fields do |t| + t.remove :position + end + + change_table :custom_forms_plugin_alternatives do |t| + t.remove :position + end + end +end diff --git a/plugins/custom_forms/lib/custom_forms_plugin/field.rb b/plugins/custom_forms/lib/custom_forms_plugin/field.rb index 6f70f08..9cec849 100644 --- a/plugins/custom_forms/lib/custom_forms_plugin/field.rb +++ b/plugins/custom_forms/lib/custom_forms_plugin/field.rb @@ -6,7 +6,7 @@ class CustomFormsPlugin::Field < ActiveRecord::Base belongs_to :form, :class_name => 'CustomFormsPlugin::Form' has_many :answers, :class_name => 'CustomFormsPlugin::Answer' - has_many :alternatives, :class_name => 'CustomFormsPlugin::Alternative' + has_many :alternatives, :order => 'position', :class_name => 'CustomFormsPlugin::Alternative' accepts_nested_attributes_for :alternatives, :allow_destroy => true before_validation do |field| diff --git a/plugins/custom_forms/lib/custom_forms_plugin/form.rb b/plugins/custom_forms/lib/custom_forms_plugin/form.rb index 853c91b..6acbf27 100644 --- a/plugins/custom_forms/lib/custom_forms_plugin/form.rb +++ b/plugins/custom_forms/lib/custom_forms_plugin/form.rb @@ -1,7 +1,7 @@ class CustomFormsPlugin::Form < Noosfero::Plugin::ActiveRecord belongs_to :profile - has_many :fields, :class_name => 'CustomFormsPlugin::Field', :dependent => :destroy + has_many :fields, :order => 'position', :class_name => 'CustomFormsPlugin::Field', :dependent => :destroy accepts_nested_attributes_for :fields, :allow_destroy => true has_many :submissions, :class_name => 'CustomFormsPlugin::Submission' diff --git a/plugins/custom_forms/public/field.js b/plugins/custom_forms/public/field.js index 80afb8f..9f9a0b2 100644 --- a/plugins/custom_forms/public/field.js +++ b/plugins/custom_forms/public/field.js @@ -1,3 +1,40 @@ +var fixHelperSortable = function(e, tr) { + tr.children().each(function() { + jQuery(this).width(jQuery(this).width()); + }); + return tr; +}; + +var updatePosition = function(e, ui) { + var tag = ui.item[0].tagName.toLowerCase(); + var count = ui.item.prevAll(tag).eq(0).find('input').filter(function() {return /_position/.test(this.id); }).val(); + count = count ? ++count : 0; + + ui.item.find('input').filter(function() {return /_position/.test(this.id); }).eq(0).val(count); + + for (i = 0; i < ui.item.nextAll(tag).length; i++) { + count++; + ui.item.nextAll(tag).eq(i).find('input').filter(function() {return /_position/.test(this.id); }).val(count); + } +} + +jQuery('tbody.field-list').sortable({ + helper: fixHelperSortable, + update: updatePosition +}); + +jQuery("ul.field-list").sortable({ + placeholder: 'ui-state-highlight', + axis: 'y', + opacity: 0.8, + cursor: 'move', + tolerance: 'pointer', + forcePlaceholderSize: true, + update: updatePosition +}); + +jQuery("ul.field-list li").disableSelection(); + var customFormsPlugin = { removeFieldBox: function (button, confirmMsg) { if (confirm(confirmMsg)) { @@ -20,11 +57,17 @@ var customFormsPlugin = { addFields: function (button, association, content) { var new_id = new Date().getTime(); var regexp = new RegExp("new_" + association, "g"); - jQuery(content.replace(regexp, new_id)).insertBefore(jQuery(button).closest('.addition-buttons')).hide().slideDown(); + content = content.replace(regexp, new_id); if(association == 'alternatives') { + jQuery(content).appendTo(jQuery(button).closest('tfoot').next('tbody.field-list')).hide().slideDown(); jQuery(button).closest('table').find('tr:first').show(); + jQuery(button).closest('tfoot').next('tbody.field-list').sortable({ helper: fixHelperSortable, update: updatePosition}); + } else { + jQuery('
  • ').append(jQuery(content)).appendTo(jQuery(button).parent().prev('ul.field-list')).hide().slideDown(); } + + jQuery('input').filter(function () { return new RegExp(new_id + "_position", "g").test(this.id); }).val(new_id); }, checkHeaderDisplay: function(table) { diff --git a/plugins/custom_forms/public/style.css b/plugins/custom_forms/public/style.css index c52c719..feb85ce 100644 --- a/plugins/custom_forms/public/style.css +++ b/plugins/custom_forms/public/style.css @@ -4,7 +4,7 @@ } .action-table { - width: 100%; + width: 100%; overflow: hidden; } @@ -13,10 +13,6 @@ text-align: center; } -.action-table td{ - cursor: move; -} - .action-table .actions{ white-space: nowrap; } @@ -55,3 +51,22 @@ .field-text-default { margin-top: 10px; } + +.field-list { + list-style-type: none; + margin: 0px; + padding: 0px; + cursor: move; +} + +.field-list label, .field-list legend { + cursor: move; +} + +ul.field-list > li > fieldset:hover { + border: 2px dotted #BBB; +} + +tr.addition-buttons { + cursor: auto; +} diff --git a/plugins/custom_forms/test/functional/custom_forms_plugin_myprofile_controller_test.rb b/plugins/custom_forms/test/functional/custom_forms_plugin_myprofile_controller_test.rb index 3861f6c..f5b164f 100644 --- a/plugins/custom_forms/test/functional/custom_forms_plugin_myprofile_controller_test.rb +++ b/plugins/custom_forms/test/functional/custom_forms_plugin_myprofile_controller_test.rb @@ -76,8 +76,8 @@ class CustomFormsPluginMyprofileControllerTest < ActionController::TestCase assert_equal 'Cool form', form.description assert_equal 2, form.fields.count - f1 = form.fields.first - f2 = form.fields.last + f1 = form.fields[0] + f2 = form.fields[1] assert_equal 'Name', f1.name assert_equal 'Jack', f1.default_value @@ -89,15 +89,15 @@ class CustomFormsPluginMyprofileControllerTest < ActionController::TestCase assert f2.kind_of?(CustomFormsPlugin::SelectField) end - should 'create fields in the order they are sent' do + should 'create fields in the order they are sent when no position defined' do format = '%Y-%m-%d %H:%M' num_fields = 10 begining = Time.now.strftime(format) ending = (Time.now + 1.day).strftime(format) fields = {} num_fields.times do |i| - fields[i.to_s] = { - :name => i.to_s, + fields[i] = { + :name => (10-i).to_s, :default_value => '', :type => 'CustomFormsPlugin::TextField' } @@ -115,13 +115,47 @@ class CustomFormsPluginMyprofileControllerTest < ActionController::TestCase end form = CustomFormsPlugin::Form.find_by_name('My Form') assert_equal num_fields, form.fields.count - lst = -1 - form.fields.find_each do |f| - assert f.name.to_i > lst - lst = f.name.to_i + lst = 10 + form.fields.each do |f| + assert f.name.to_i == lst + lst = lst - 1 end end + should 'create fields in any position size' do + format = '%Y-%m-%d %H:%M' + begining = Time.now.strftime(format) + ending = (Time.now + 1.day).strftime(format) + fields = {} + fields['0'] = { + :name => '0', + :default_value => '', + :type => 'CustomFormsPlugin::TextField', + :position => '999999999999' + } + fields['1'] = { + :name => '1', + :default_value => '', + :type => 'CustomFormsPlugin::TextField', + :position => '1' + } + assert_difference CustomFormsPlugin::Form, :count, 1 do + post :create, :profile => profile.identifier, + :form => { + :name => 'My Form', + :access => 'logged', + :begining => begining, + :ending => ending, + :description => 'Cool form', + :fields_attributes => fields + } + end + form = CustomFormsPlugin::Form.find_by_name('My Form') + assert_equal 2, form.fields.count + assert form.fields.first.name == "1" + assert form.fields.last.name == "0" + end + should 'edit a form' do form = CustomFormsPlugin::Form.create!(:profile => profile, :name => 'Free Software') format = '%Y-%m-%d %H:%M' diff --git a/plugins/custom_forms/test/unit/custom_forms_plugin/field_test.rb b/plugins/custom_forms/test/unit/custom_forms_plugin/field_test.rb index ce2f42e..4154785 100644 --- a/plugins/custom_forms/test/unit/custom_forms_plugin/field_test.rb +++ b/plugins/custom_forms/test/unit/custom_forms_plugin/field_test.rb @@ -32,5 +32,13 @@ class CustomFormsPlugin::FieldTest < ActiveSupport::TestCase end assert_equal form.fields, [license_field] end + + should 'sort alternatives by position' do + field = CustomFormsPlugin::Field.create!(:name => 'field001') + second = CustomFormsPlugin::Alternative.create!(:label => 'second', :field => field, :position => 2) + first = CustomFormsPlugin::Alternative.create!(:label => 'first', :field => field, :position => 1) + + assert_equal field.alternatives, [first, second] + end end diff --git a/plugins/custom_forms/test/unit/custom_forms_plugin/form_test.rb b/plugins/custom_forms/test/unit/custom_forms_plugin/form_test.rb index dc38c21..bafb6d4 100644 --- a/plugins/custom_forms/test/unit/custom_forms_plugin/form_test.rb +++ b/plugins/custom_forms/test/unit/custom_forms_plugin/form_test.rb @@ -180,4 +180,12 @@ class CustomFormsPlugin::FormTest < ActiveSupport::TestCase end end + should 'sort fields by position' do + form = CustomFormsPlugin::Form.create!(:name => 'Free Software', :profile => fast_create(Profile)) + license_field = CustomFormsPlugin::Field.create!(:name => 'License', :form => form, :position => 2) + url_field = CustomFormsPlugin::Field.create!(:name => 'URL', :form => form, :position => 0) + + assert_equal form.fields, [url_field, license_field] + end + end diff --git a/plugins/custom_forms/views/custom_forms_plugin_myprofile/_field.html.erb b/plugins/custom_forms/views/custom_forms_plugin_myprofile/_field.html.erb index efaa266..1e1466e 100644 --- a/plugins/custom_forms/views/custom_forms_plugin_myprofile/_field.html.erb +++ b/plugins/custom_forms/views/custom_forms_plugin_myprofile/_field.html.erb @@ -9,6 +9,8 @@ <%= f.check_box :mandatory %> <%= f.label :mandatory, _('Mandatory') %> + <%= f.hidden_field(:position) %> + <%= f.hidden_field :_destroy, :class => 'destroy-field' %> <%= button_to_function :delete, _('Remove field'), "customFormsPlugin.removeFieldBox(this, #{_('Are you sure you want to remove this field?').to_json})" %> <%= yield %> diff --git a/plugins/custom_forms/views/custom_forms_plugin_myprofile/_form.html.erb b/plugins/custom_forms/views/custom_forms_plugin_myprofile/_form.html.erb index a4f1c98..63a8e21 100644 --- a/plugins/custom_forms/views/custom_forms_plugin_myprofile/_form.html.erb +++ b/plugins/custom_forms/views/custom_forms_plugin_myprofile/_form.html.erb @@ -17,9 +17,13 @@

    <%= _('Fields') %>

    -<% f.fields_for :fields do |builder| %> - <%= render partial_for_class(builder.object.class), :f => builder %> -<% end %> +
    <%= button(:add, _('Add a new text field'), '#', :onclick => "customFormsPlugin.addFields(this, 'fields', #{html_for_field(f, :fields, CustomFormsPlugin::TextField).to_json}); return false")%> diff --git a/plugins/custom_forms/views/custom_forms_plugin_myprofile/custom_forms_plugin/_alternative.html.erb b/plugins/custom_forms/views/custom_forms_plugin_myprofile/custom_forms_plugin/_alternative.html.erb index dc9d248..cd31867 100644 --- a/plugins/custom_forms/views/custom_forms_plugin_myprofile/custom_forms_plugin/_alternative.html.erb +++ b/plugins/custom_forms/views/custom_forms_plugin_myprofile/custom_forms_plugin/_alternative.html.erb @@ -3,8 +3,10 @@ <%= f.check_box(:selected_by_default) %> + <%= f.hidden_field(:position) %> + <%= f.hidden_field :_destroy, :class => 'destroy-field' %> <%= button_to_function_without_text :remove, _('Remove alternative'), "customFormsPlugin.removeAlternative(this, #{_('Are you sure you want to remove this alternative?').to_json})", :class => 'remove-field', :title => _('Remove alternative') %> -
    + diff --git a/plugins/custom_forms/views/custom_forms_plugin_myprofile/custom_forms_plugin/_select_field.html.erb b/plugins/custom_forms/views/custom_forms_plugin_myprofile/custom_forms_plugin/_select_field.html.erb index 1c6f1a0..5f74210 100644 --- a/plugins/custom_forms/views/custom_forms_plugin_myprofile/custom_forms_plugin/_select_field.html.erb +++ b/plugins/custom_forms/views/custom_forms_plugin_myprofile/custom_forms_plugin/_select_field.html.erb @@ -12,20 +12,25 @@ + > - <% f.fields_for :alternatives do |builder| %> - <%= render partial_for_class(builder.object.class), :f => builder %> - <% end %> + + + + + <% f.fields_for :alternatives do |builder| %> + <%= render partial_for_class(builder.object.class), :f => builder %> + <% end %> +
    <%= _('Alternative') %> <%= _('Preselected') %> <%= _('Remove') %>
    <%= button(:add, _('Add a new alternative'), '#', :onclick => "customFormsPlugin.addFields(this, 'alternatives', #{html_for_field(f, :alternatives, CustomFormsPlugin::Alternative).to_json}); return false") %>
    - <% end %> -- libgit2 0.21.2