Commit c224f8a93b63bb7c02398390218daba4303a41d1
1 parent
103b7ebe
Exists in
master
and in
29 other branches
custom_forms: use rails nested forms in form partial
AI2780
Showing
36 changed files
with
420 additions
and
475 deletions
Show diff stats
plugins/custom_forms/controllers/custom_forms_plugin_myprofile_controller.rb
1 | class CustomFormsPluginMyprofileController < MyProfileController | 1 | class CustomFormsPluginMyprofileController < MyProfileController |
2 | - | ||
3 | protect 'post_content', :profile | 2 | protect 'post_content', :profile |
3 | + | ||
4 | def index | 4 | def index |
5 | @forms = CustomFormsPlugin::Form.from(profile) | 5 | @forms = CustomFormsPlugin::Form.from(profile) |
6 | end | 6 | end |
7 | 7 | ||
8 | + def new | ||
9 | + @form = CustomFormsPlugin::Form.new | ||
10 | + | ||
11 | + respond_to do |format| | ||
12 | + format.html | ||
13 | + end | ||
14 | + end | ||
15 | + | ||
8 | def create | 16 | def create |
9 | - @form = CustomFormsPlugin::Form.new(:profile => profile) | ||
10 | - @fields = [] | ||
11 | - @empty_field = CustomFormsPlugin::Field.new | ||
12 | - if request.post? | ||
13 | - begin | ||
14 | - @form.update_attributes!(params[:form]) | ||
15 | - params[:fields] = format_kind(params[:fields]) | ||
16 | - params[:fields] = format_choices(params[:fields]) | ||
17 | - params[:fields] = set_form_id(params[:fields], @form.id) | ||
18 | - create_fields(new_fields(params)) | ||
19 | - session['notice'] = _('Form created') | ||
20 | - redirect_to :action => 'index' | ||
21 | - rescue Exception => exception | ||
22 | - logger.error(exception.to_s) | ||
23 | - session['notice'] = _('Form could not be created') | 17 | + params[:form][:profile_id] = profile.id |
18 | + @form = CustomFormsPlugin::Form.new(params[:form]) | ||
19 | + | ||
20 | + respond_to do |format| | ||
21 | + if @form.save | ||
22 | + flash[:notice] = _("Custom form #{@form.name} was successfully created.") | ||
23 | + format.html { redirect_to(:action=>'index') } | ||
24 | + else | ||
25 | + format.html { render :action => 'new' } | ||
24 | end | 26 | end |
25 | end | 27 | end |
26 | end | 28 | end |
27 | 29 | ||
28 | def edit | 30 | def edit |
29 | @form = CustomFormsPlugin::Form.find(params[:id]) | 31 | @form = CustomFormsPlugin::Form.find(params[:id]) |
30 | - @fields = @form.fields | ||
31 | - @empty_field = CustomFormsPlugin::TextField.new | ||
32 | - if request.post? | ||
33 | - begin | ||
34 | - @form.update_attributes!(params[:form]) | ||
35 | - params[:fields] = format_kind(params[:fields]) | ||
36 | - params[:fields] = format_choices(params[:fields]) | ||
37 | - remove_fields(params, @form) | ||
38 | - create_fields(new_fields(params)) | ||
39 | - update_fields(edited_fields(params)) | ||
40 | - session['notice'] = _('Form updated') | ||
41 | - redirect_to :action => 'index' | ||
42 | - rescue Exception => exception | ||
43 | - logger.error(exception.to_s) | 32 | + end |
33 | + | ||
34 | + def update | ||
35 | + @form = CustomFormsPlugin::Form.find(params[:id]) | ||
36 | + | ||
37 | + respond_to do |format| | ||
38 | + if @form.update_attributes(params[:form]) | ||
39 | + flash[:notice] = _("Custom form #{@form.name} was successfully updated.") | ||
40 | + format.html { redirect_to(:action=>'index') } | ||
41 | + else | ||
44 | session['notice'] = _('Form could not be updated') | 42 | session['notice'] = _('Form could not be updated') |
43 | + format.html { render :action => 'edit' } | ||
45 | end | 44 | end |
46 | end | 45 | end |
47 | end | 46 | end |
@@ -67,82 +66,4 @@ class CustomFormsPluginMyprofileController < MyProfileController | @@ -67,82 +66,4 @@ class CustomFormsPluginMyprofileController < MyProfileController | ||
67 | @form = @submission.form | 66 | @form = @submission.form |
68 | end | 67 | end |
69 | 68 | ||
70 | - private | ||
71 | - | ||
72 | - def new_fields(params) | ||
73 | - keys = params[:fields].keys.sort{|a, b| a.to_i <=> b.to_i} | ||
74 | - result = keys.map { |id| (hash = params[:fields][id]).has_key?(:real_id) ? nil : hash}.compact | ||
75 | - result.delete_if {|field| field[:name].blank?} | ||
76 | - result | ||
77 | - end | ||
78 | - | ||
79 | - def edited_fields(params) | ||
80 | - params[:fields].map {|id, hash| hash.has_key?(:real_id) ? hash : nil}.compact | ||
81 | - end | ||
82 | - | ||
83 | - def create_fields(fields) | ||
84 | - fields.each do |field| | ||
85 | - case field[:type] | ||
86 | - when 'text_field' | ||
87 | - CustomFormsPlugin::TextField.create!(field) | ||
88 | - when 'select_field' | ||
89 | - CustomFormsPlugin::SelectField.create!(field) | ||
90 | - else | ||
91 | - CustomFormsPlugin::Field.create!(field) | ||
92 | - end | ||
93 | - end | ||
94 | - end | ||
95 | - | ||
96 | - def update_fields(fields) | ||
97 | - fields.each do |field_attrs| | ||
98 | - field = CustomFormsPlugin::Field.find(field_attrs.delete(:real_id)) | ||
99 | - field.attributes = field_attrs | ||
100 | - field.save! if field.changed? | ||
101 | - end | ||
102 | - end | ||
103 | - | ||
104 | - def format_kind(fields) | ||
105 | - fields.each do |id, field| | ||
106 | - next if field[:kind].blank? | ||
107 | - kind = field.delete(:kind) | ||
108 | - case kind | ||
109 | - when 'radio' | ||
110 | - field[:list] = false | ||
111 | - field[:multiple] = false | ||
112 | - when 'check_box' | ||
113 | - field[:list] = false | ||
114 | - field[:multiple] = true | ||
115 | - when 'select' | ||
116 | - field[:list] = true | ||
117 | - field[:multiple] = false | ||
118 | - when 'multiple_select' | ||
119 | - field[:list] = true | ||
120 | - field[:multiple] = true | ||
121 | - end | ||
122 | - end | ||
123 | - fields | ||
124 | - end | ||
125 | - | ||
126 | - def format_choices(fields) | ||
127 | - fields.each do |id, field| | ||
128 | - next if !field.has_key?(:choices) | ||
129 | - field[:choices] = field[:choices].map {|key, value| value}.inject({}) do |result, choice| | ||
130 | - hash = (choice[:name].blank? || choice[:value].blank?) ? {} : {choice[:name] => choice[:value]} | ||
131 | - result.merge!(hash) | ||
132 | - end | ||
133 | - end | ||
134 | - fields | ||
135 | - end | ||
136 | - | ||
137 | - def remove_fields(params, form) | ||
138 | - present_fields = params[:fields].map{|id, value| value}.collect {|field| field[:real_id]}.compact | ||
139 | - form.fields.each {|field| field.destroy if !present_fields.include?(field.id.to_s) } | ||
140 | - end | ||
141 | - | ||
142 | - def set_form_id(fields, form_id) | ||
143 | - fields.each do |id, field| | ||
144 | - field[:form_id] = form_id | ||
145 | - end | ||
146 | - fields | ||
147 | - end | ||
148 | end | 69 | end |
plugins/custom_forms/controllers/custom_forms_plugin_profile_controller.rb
1 | class CustomFormsPluginProfileController < ProfileController | 1 | class CustomFormsPluginProfileController < ProfileController |
2 | - | ||
3 | before_filter :has_access, :show | 2 | before_filter :has_access, :show |
4 | 3 | ||
5 | def show | 4 | def show |
5 | + extend(CustomFormsPlugin::Helper) | ||
6 | + | ||
6 | @form = CustomFormsPlugin::Form.find(params[:id]) | 7 | @form = CustomFormsPlugin::Form.find(params[:id]) |
7 | if user | 8 | if user |
8 | @submission ||= CustomFormsPlugin::Submission.find_by_form_id_and_profile_id(@form.id,user.id) | 9 | @submission ||= CustomFormsPlugin::Submission.find_by_form_id_and_profile_id(@form.id,user.id) |
@@ -10,22 +11,33 @@ class CustomFormsPluginProfileController < ProfileController | @@ -10,22 +11,33 @@ class CustomFormsPluginProfileController < ProfileController | ||
10 | else | 11 | else |
11 | @submission ||= CustomFormsPlugin::Submission.new(:form_id => @form.id) | 12 | @submission ||= CustomFormsPlugin::Submission.new(:form_id => @form.id) |
12 | end | 13 | end |
14 | + | ||
15 | + # build the answers | ||
16 | + @submission.answers.push(*(answers = build_answers(params[:submission], @form))) if params[:submission] | ||
17 | + | ||
13 | if request.post? | 18 | if request.post? |
14 | begin | 19 | begin |
15 | - extend(CustomFormsPlugin::Helper) | ||
16 | - answers = build_answers(params[:submission], @form) | 20 | + raise 'Submission already present!' if CustomFormsPlugin::Submission.find_by_form_id_and_profile_id(@form.id,user.id) |
21 | + | ||
22 | + # @submission.answers for some reason has the same answer twice | ||
17 | failed_answers = answers.select {|answer| !answer.valid? } | 23 | failed_answers = answers.select {|answer| !answer.valid? } |
24 | + | ||
18 | if failed_answers.empty? | 25 | if failed_answers.empty? |
19 | - if !user | ||
20 | - @submission.author_name = params[:author_name] | ||
21 | - @submission.author_email = params[:author_email] | 26 | + # Save the submission |
27 | + ActiveRecord::Base.transaction do | ||
28 | + if !user | ||
29 | + @submission.author_name = params[:author_name] | ||
30 | + @submission.author_email = params[:author_email] | ||
31 | + end | ||
32 | + @submission.save! | ||
22 | end | 33 | end |
23 | - @submission.save! | ||
24 | - answers.map {|answer| answer.submission = @submission; answer.save!} | ||
25 | else | 34 | else |
26 | - @submission.valid? | 35 | + @submission.errors.clear |
27 | failed_answers.each do |answer| | 36 | failed_answers.each do |answer| |
28 | - @submission.errors.add(answer.field.name.to_sym, answer.errors[answer.field.slug.to_sym]) | 37 | + answer.valid? |
38 | + answer.errors.each do |attribute, msg| | ||
39 | + @submission.errors.add(answer.field.id.to_s.to_sym, msg) | ||
40 | + end | ||
29 | end | 41 | end |
30 | raise 'Submission failed: answers not valid' | 42 | raise 'Submission failed: answers not valid' |
31 | end | 43 | end |
plugins/custom_forms/db/migrate/20130823134700_create_custom_forms_plugin_alternatives.rb
0 → 100644
@@ -0,0 +1,12 @@ | @@ -0,0 +1,12 @@ | ||
1 | +class CreateCustomFormsPluginAlternatives < ActiveRecord::Migration | ||
2 | + def self.up | ||
3 | + create_table :custom_forms_plugin_alternatives do |t| | ||
4 | + t.string :label | ||
5 | + t.references :field | ||
6 | + end | ||
7 | + end | ||
8 | + | ||
9 | + def self.down | ||
10 | + drop_table :custom_forms_plugin_alternatives | ||
11 | + end | ||
12 | +end |
plugins/custom_forms/db/migrate/20130823135600_add_select_field_type_to_custom_forms_plugin_fields.rb
0 → 100644
@@ -0,0 +1,29 @@ | @@ -0,0 +1,29 @@ | ||
1 | +class AddSelectFieldTypeToCustomFormsPluginFields < ActiveRecord::Migration | ||
2 | + def self.up | ||
3 | + change_table :custom_forms_plugin_fields do |t| | ||
4 | + t.remove :position | ||
5 | + t.string :select_field_type | ||
6 | + end | ||
7 | + | ||
8 | + CustomFormsPlugin::Field.find_each do |f| | ||
9 | + if !f.list && !f.multiple | ||
10 | + f.select_field_type = :radio | ||
11 | + elsif !f.list && f.multiple | ||
12 | + f.select_field_type = :check_box | ||
13 | + elsif f.list && !f.multiple | ||
14 | + f.select_field_type = :select | ||
15 | + else | ||
16 | + f.select_field_type = :multiple_select | ||
17 | + end | ||
18 | + f.save! | ||
19 | + end | ||
20 | + | ||
21 | + change_table :custom_forms_plugin_fields do |t| | ||
22 | + t.remove :multiple, :list | ||
23 | + end | ||
24 | + end | ||
25 | + | ||
26 | + def self.down | ||
27 | + raise ActiveRecord::IrreversibleMigration | ||
28 | + end | ||
29 | +end |
plugins/custom_forms/db/migrate/20130823151900_associate_fields_to_alternatives.rb
0 → 100644
@@ -0,0 +1,25 @@ | @@ -0,0 +1,25 @@ | ||
1 | +class AssociateFieldsToAlternatives < ActiveRecord::Migration | ||
2 | + class CustomFormsPlugin::Field < ActiveRecord::Base | ||
3 | + set_table_name :custom_forms_plugin_fields | ||
4 | + has_many :alternatives, :class_name => 'CustomFormsPlugin::Alternative' | ||
5 | + serialize :choices, Hash | ||
6 | + end | ||
7 | + | ||
8 | + def self.up | ||
9 | + CustomFormsPlugin::Field.reset_column_information | ||
10 | + | ||
11 | + CustomFormsPlugin::Field.find_each do |f| | ||
12 | + f.choices.each do |key, value| | ||
13 | + CustomFormsPlugin::Alternative.create!(:label => key, :field_id => f.id) | ||
14 | + end | ||
15 | + end | ||
16 | + | ||
17 | + change_table :custom_forms_plugin_fields do |t| | ||
18 | + t.remove :choices | ||
19 | + end | ||
20 | + end | ||
21 | + | ||
22 | + def self.down | ||
23 | + raise ActiveRecord::IrreversibleMigration | ||
24 | + end | ||
25 | +end |
plugins/custom_forms/db/migrate/20131002155900_update_select_field_type_in_custom_forms_plugin_fields.rb
0 → 100644
@@ -0,0 +1,9 @@ | @@ -0,0 +1,9 @@ | ||
1 | +class UpdateSelectFieldTypeInCustomFormsPluginFields < ActiveRecord::Migration | ||
2 | + def self.up | ||
3 | + change_column :custom_forms_plugin_fields, :select_field_type, :string, :null => false, :default => 'radio' | ||
4 | + end | ||
5 | + | ||
6 | + def self.down | ||
7 | + raise ActiveRecord::IrreversibleMigration | ||
8 | + end | ||
9 | +end |
plugins/custom_forms/db/migrate/20131007120600_add_selected_by_default_to_custom_forms_plugin_alternatives.rb
0 → 100644
@@ -0,0 +1,14 @@ | @@ -0,0 +1,14 @@ | ||
1 | +class AddSelectedByDefaultToCustomFormsPluginAlternatives < ActiveRecord::Migration | ||
2 | + def self.up | ||
3 | + add_column :custom_forms_plugin_alternatives, :selected_by_default, :boolean, :null => false, :default => false | ||
4 | + CustomFormsPlugin::Field.find_each do |f| | ||
5 | + f.alternatives.each do |a| | ||
6 | + a.update_attribute(:selected_by_default, true) if a.label == f.default_value | ||
7 | + end | ||
8 | + end | ||
9 | + end | ||
10 | + | ||
11 | + def self.down | ||
12 | + raise ActiveRecord::IrreversibleMigration | ||
13 | + end | ||
14 | +end |
plugins/custom_forms/lib/custom_forms_plugin/alternative.rb
0 → 100644
plugins/custom_forms/lib/custom_forms_plugin/answer.rb
@@ -7,7 +7,7 @@ class CustomFormsPlugin::Answer < Noosfero::Plugin::ActiveRecord | @@ -7,7 +7,7 @@ class CustomFormsPlugin::Answer < Noosfero::Plugin::ActiveRecord | ||
7 | 7 | ||
8 | def value_mandatory | 8 | def value_mandatory |
9 | if field.mandatory && value.blank? | 9 | if field.mandatory && value.blank? |
10 | - errors.add(field.slug.to_sym, _("is mandatory.").fix_i18n) | 10 | + errors.add(:value, _("is mandatory.").fix_i18n) |
11 | end | 11 | end |
12 | end | 12 | end |
13 | end | 13 | end |
plugins/custom_forms/lib/custom_forms_plugin/field.rb
1 | class CustomFormsPlugin::Field < ActiveRecord::Base | 1 | class CustomFormsPlugin::Field < ActiveRecord::Base |
2 | set_table_name :custom_forms_plugin_fields | 2 | set_table_name :custom_forms_plugin_fields |
3 | 3 | ||
4 | - validates_presence_of :form, :name | ||
5 | - validates_uniqueness_of :slug, :scope => :form_id | 4 | + validates_presence_of :name |
6 | 5 | ||
7 | belongs_to :form, :class_name => 'CustomFormsPlugin::Form' | 6 | belongs_to :form, :class_name => 'CustomFormsPlugin::Form' |
8 | has_many :answers, :class_name => 'CustomFormsPlugin::Answer' | 7 | has_many :answers, :class_name => 'CustomFormsPlugin::Answer' |
9 | 8 | ||
10 | - serialize :choices, Hash | 9 | + has_many :alternatives, :class_name => 'CustomFormsPlugin::Alternative' |
10 | + accepts_nested_attributes_for :alternatives, :allow_destroy => true | ||
11 | 11 | ||
12 | before_validation do |field| | 12 | before_validation do |field| |
13 | field.slug = field.name.to_slug if field.name.present? | 13 | field.slug = field.name.to_slug if field.name.present? |
14 | end | 14 | end |
15 | 15 | ||
16 | - before_create do |field| | ||
17 | - if field.form.fields.exists? | ||
18 | - field.position = field.form.fields.order(:position).last.position + 1 | ||
19 | - end | ||
20 | - end | 16 | + private |
21 | 17 | ||
22 | - def position | ||
23 | - self[:position] || 0 | 18 | + def attributes_protected_by_default |
19 | + super - [self.class.inheritance_column] | ||
24 | end | 20 | end |
21 | + | ||
25 | end | 22 | end |
26 | 23 |
plugins/custom_forms/lib/custom_forms_plugin/form.rb
1 | class CustomFormsPlugin::Form < Noosfero::Plugin::ActiveRecord | 1 | class CustomFormsPlugin::Form < Noosfero::Plugin::ActiveRecord |
2 | belongs_to :profile | 2 | belongs_to :profile |
3 | 3 | ||
4 | - has_many :fields, :class_name => 'CustomFormsPlugin::Field', :dependent => :destroy, :order => 'position' | 4 | + has_many :fields, :class_name => 'CustomFormsPlugin::Field', :dependent => :destroy |
5 | + accepts_nested_attributes_for :fields, :allow_destroy => true | ||
6 | + | ||
5 | has_many :submissions, :class_name => 'CustomFormsPlugin::Submission' | 7 | has_many :submissions, :class_name => 'CustomFormsPlugin::Submission' |
6 | 8 | ||
7 | serialize :access | 9 | serialize :access |
plugins/custom_forms/lib/custom_forms_plugin/helper.rb
1 | module CustomFormsPlugin::Helper | 1 | module CustomFormsPlugin::Helper |
2 | + def html_for_field(builder, association, klass) | ||
3 | + new_object = klass.new | ||
4 | + builder.fields_for(association, new_object, :child_index => "new_#{association}") do |f| | ||
5 | + render(partial_for_class(klass), :f => f) | ||
6 | + end | ||
7 | + end | ||
8 | + | ||
2 | def access_text(form) | 9 | def access_text(form) |
3 | return _('Public') if form.access.nil? | 10 | return _('Public') if form.access.nil? |
4 | return _('Logged users') if form.access == 'logged' | 11 | return _('Logged users') if form.access == 'logged' |
@@ -48,8 +55,8 @@ module CustomFormsPlugin::Helper | @@ -48,8 +55,8 @@ module CustomFormsPlugin::Helper | ||
48 | 55 | ||
49 | def type_to_label(type) | 56 | def type_to_label(type) |
50 | map = { | 57 | map = { |
51 | - 'text_field' => _('Text'), | ||
52 | - 'select_field' => _('Select') | 58 | + 'text_field' => _('Text field'), |
59 | + 'select_field' => _('Select field') | ||
53 | } | 60 | } |
54 | map[type_for_options(type)] | 61 | map[type_for_options(type)] |
55 | end | 62 | end |
@@ -61,52 +68,53 @@ module CustomFormsPlugin::Helper | @@ -61,52 +68,53 @@ module CustomFormsPlugin::Helper | ||
61 | def display_custom_field(field, submission, form) | 68 | def display_custom_field(field, submission, form) |
62 | answer = submission.answers.select{|answer| answer.field == field}.first | 69 | answer = submission.answers.select{|answer| answer.field == field}.first |
63 | field_tag = send("display_#{type_for_options(field.class)}",field, answer, form) | 70 | field_tag = send("display_#{type_for_options(field.class)}",field, answer, form) |
64 | - if field.mandatory? && !radio_button?(field) && !check_box?(field) && submission.id.nil? | 71 | + if field.mandatory? && submission.id.nil? |
65 | required(labelled_form_field(field.name, field_tag)) | 72 | required(labelled_form_field(field.name, field_tag)) |
66 | - else | 73 | + else |
67 | labelled_form_field(field.name, field_tag) | 74 | labelled_form_field(field.name, field_tag) |
68 | end | 75 | end |
69 | end | 76 | end |
70 | 77 | ||
71 | def display_text_field(field, answer, form) | 78 | def display_text_field(field, answer, form) |
72 | value = answer.present? ? answer.value : field.default_value | 79 | value = answer.present? ? answer.value : field.default_value |
73 | - text_field(form, field.name.to_slug, :value => value, :disabled => answer.present?) | 80 | + text_field(form, "#{field.id}", :value => value, :disabled => answer.present? && answer.id.present?) |
74 | end | 81 | end |
75 | 82 | ||
76 | def display_select_field(field, answer, form) | 83 | def display_select_field(field, answer, form) |
77 | - if field.list && field.multiple | ||
78 | - selected = answer.present? ? answer.value.split(',') : [] | ||
79 | - select_tag "#{form}[#{field.name.to_slug}]", options_for_select(field.choices.to_a, selected), :multiple => true, :size => field.choices.size, :disabled => answer.present? | ||
80 | - elsif !field.list && field.multiple | ||
81 | - field.choices.map do |name, value| | ||
82 | - default = answer.present? ? answer.value.split(',').include?(value) : false | ||
83 | - labelled_check_box name, "#{form}[#{field.name.to_slug}][#{value}]", '1', default, :disabled => answer.present? | 84 | + case field.select_field_type |
85 | + when 'multiple_select' | ||
86 | + selected = answer.present? ? answer.value.split(',') : field.alternatives.select {|a| a.selected_by_default}.map{|a| a.id.to_s} | ||
87 | + select_tag "submission[#{field.id}]", options_for_select(field.alternatives.map{|a| [a.label, a.id.to_s]}, selected), :multiple => true, :size => field.alternatives.size, :disabled => answer.present? && answer.id.present? | ||
88 | + when 'check_box' | ||
89 | + field.alternatives.map do |alternative| | ||
90 | + default = answer.present? ? answer.value.split(',').include?(alternative.id.to_s) : alternative.selected_by_default | ||
91 | + labelled_check_box alternative.label, "submission[#{field.id}][#{alternative.id}]", '1', default, :disabled => answer.present? && answer.id.present? | ||
84 | end.join("\n") | 92 | end.join("\n") |
85 | - elsif field.list && !field.multiple | ||
86 | - selected = answer.present? ? answer.value.split(',') : [] | ||
87 | - select_tag "#{form}[#{field.name.to_slug}]", options_for_select([['','']] + field.choices.to_a, selected), :disabled => answer.present? | ||
88 | - elsif !field.list && !field.multiple | ||
89 | - field.choices.map do |name, value| | ||
90 | - default = answer.present? ? answer.value == value : true | ||
91 | - labelled_radio_button name, "#{form}[#{field.name.to_slug}]", value, default, :disabled => answer.present? | 93 | + when 'select' |
94 | + selected = answer.present? ? answer.value.split(',') : field.alternatives.select {|a| a.selected_by_default}.map{|a| a.id.to_s} | ||
95 | + select_tag "submission[#{field.id}]", options_for_select([['','']] + field.alternatives.map {|a| [a.label, a.id.to_s]}, selected), :disabled => answer.present? && answer.id.present? | ||
96 | + when 'radio' | ||
97 | + field.alternatives.map do |alternative| | ||
98 | + default = answer.present? ? answer.value == alternative.id.to_s : alternative.selected_by_default | ||
99 | + labelled_radio_button alternative.label, "submission[#{field.id}]", alternative.id, default, :disabled => answer.present? && answer.id.present? | ||
92 | end.join("\n") | 100 | end.join("\n") |
93 | end | 101 | end |
94 | end | 102 | end |
95 | 103 | ||
96 | def radio_button?(field) | 104 | def radio_button?(field) |
97 | - type_for_options(field.class) == 'select_field' && !field.list && !field.multiple | 105 | + type_for_options(field.class) == 'select_field' && field.select_field_type == 'radio' |
98 | end | 106 | end |
99 | 107 | ||
100 | def check_box?(field) | 108 | def check_box?(field) |
101 | - type_for_options(field.class) == 'select_field' && !field.list && field.multiple | 109 | + type_for_options(field.class) == 'select_field' && field.select_field_type == 'check_box' |
102 | end | 110 | end |
103 | 111 | ||
104 | def build_answers(submission, form) | 112 | def build_answers(submission, form) |
105 | answers = [] | 113 | answers = [] |
106 | form.fields.each do |field| | 114 | form.fields.each do |field| |
107 | final_value = '' | 115 | final_value = '' |
108 | - if submission.has_key?(field.slug) | ||
109 | - value = submission[field.slug] | 116 | + if submission.has_key?(field.id.to_s) |
117 | + value = submission[field.id.to_s] | ||
110 | if value.kind_of?(String) | 118 | if value.kind_of?(String) |
111 | final_value = value | 119 | final_value = value |
112 | elsif value.kind_of?(Array) | 120 | elsif value.kind_of?(Array) |
plugins/custom_forms/lib/custom_forms_plugin/select_field.rb
1 | class CustomFormsPlugin::SelectField < CustomFormsPlugin::Field | 1 | class CustomFormsPlugin::SelectField < CustomFormsPlugin::Field |
2 | set_table_name :custom_forms_plugin_fields | 2 | set_table_name :custom_forms_plugin_fields |
3 | - validates_presence_of :choices | 3 | + |
4 | + validates_length_of :select_field_type, :minimum => 1, :allow_nil => false | ||
5 | + validates_inclusion_of :select_field_type, :in => %w(radio check_box select multiple_select) | ||
4 | end | 6 | end |
plugins/custom_forms/lib/custom_forms_plugin/submission.rb
@@ -2,11 +2,20 @@ class CustomFormsPlugin::Submission < Noosfero::Plugin::ActiveRecord | @@ -2,11 +2,20 @@ class CustomFormsPlugin::Submission < Noosfero::Plugin::ActiveRecord | ||
2 | belongs_to :form, :class_name => 'CustomFormsPlugin::Form' | 2 | belongs_to :form, :class_name => 'CustomFormsPlugin::Form' |
3 | belongs_to :profile | 3 | belongs_to :profile |
4 | 4 | ||
5 | - has_many :answers, :class_name => 'CustomFormsPlugin::Answer' | 5 | + has_many :answers, :class_name => 'CustomFormsPlugin::Answer', :dependent => :destroy |
6 | 6 | ||
7 | validates_presence_of :form | 7 | validates_presence_of :form |
8 | validates_presence_of :author_name, :author_email, :if => lambda {|submission| submission.profile.nil?} | 8 | validates_presence_of :author_name, :author_email, :if => lambda {|submission| submission.profile.nil?} |
9 | validates_uniqueness_of :author_email, :scope => :form_id, :allow_nil => true | 9 | validates_uniqueness_of :author_email, :scope => :form_id, :allow_nil => true |
10 | validates_format_of :author_email, :with => Noosfero::Constants::EMAIL_FORMAT, :if => (lambda {|submission| !submission.author_email.blank?}) | 10 | validates_format_of :author_email, :with => Noosfero::Constants::EMAIL_FORMAT, :if => (lambda {|submission| !submission.author_email.blank?}) |
11 | + | ||
12 | + def self.human_attribute_name(attrib) | ||
13 | + if /\d+/ =~ attrib and (f = CustomFormsPlugin::Field.find_by_id(attrib.to_i)) | ||
14 | + f.name | ||
15 | + else | ||
16 | + attrib | ||
17 | + end | ||
18 | + end | ||
19 | + | ||
11 | end | 20 | end |
12 | 21 |
plugins/custom_forms/public/field.js
1 | -jQuery('.icon-edit').live('click', function() { | ||
2 | - elem = this; | ||
3 | - jQuery.fn.colorbox({ | ||
4 | - overlayClose: false, | ||
5 | - escKey: false, | ||
6 | - inline: true, | ||
7 | - href: function(){ | ||
8 | - id = jQuery(elem).attr('field_id'); | ||
9 | - type = jQuery('#fields_'+id+'_type').val().split('_')[0]; | ||
10 | - selector = '#edit-'+type+'-'+id | ||
11 | - return selector | 1 | +var customFormsPlugin = { |
2 | + removeFieldBox: function (button, confirmMsg) { | ||
3 | + if (confirm(confirmMsg)) { | ||
4 | + fb = jQuery(button).closest('.field-box'); | ||
5 | + jQuery('input.destroy-field', fb).val(1); | ||
6 | + jQuery('> div', fb).slideUp({easing:'linear', complete:function(){fb.slideUp({easing:'linear', duration:250})}}); | ||
12 | } | 7 | } |
13 | - }); | ||
14 | - return false; | ||
15 | -}); | ||
16 | - | ||
17 | -jQuery('.remove-field').live('click', function(){ | ||
18 | - id = jQuery(this).attr('field_id'); | ||
19 | - jQuery('#field-'+id).slideDown(function(){ | ||
20 | - jQuery('#field-'+id).remove(); | ||
21 | - }); | ||
22 | - return false | ||
23 | -}); | ||
24 | - | ||
25 | -jQuery('.remove-option').live('click', function(){ | ||
26 | - field_id = jQuery(this).attr('field_id'); | ||
27 | - option_id = jQuery(this).attr('option_id'); | ||
28 | - selector = '#field-'+field_id+'-option-'+option_id | ||
29 | - jQuery(selector).slideDown(function(){ | ||
30 | - jQuery(selector).remove(); | ||
31 | - jQuery.colorbox.resize(); | ||
32 | - }); | ||
33 | - return false | ||
34 | -}); | ||
35 | - | ||
36 | -function updateEditText(id){ | ||
37 | - new_id = id+1 | ||
38 | - jQuery('#edit-text-'+id).attr('id', 'edit-text-'+new_id); | ||
39 | - input = jQuery('#edit-text-'+new_id+' input'); | ||
40 | - jQuery('#edit-text-'+new_id+' .colorbox-ok-button').attr('div_id', 'edit-text-'+new_id); | ||
41 | - input.attr('id', input.attr('id').replace(id,new_id)); | ||
42 | - input.attr('name', input.attr('name').replace(id,new_id)); | ||
43 | - label = jQuery('#edit-text-'+new_id+' label'); | ||
44 | - label.attr('for', label.attr('for').replace(id,new_id)); | ||
45 | -} | ||
46 | - | ||
47 | -function updateEditSelect(id){ | ||
48 | - new_id = id+1 | ||
49 | - jQuery('#edit-select-'+id).attr('id', 'edit-select-'+new_id); | ||
50 | - jQuery('#edit-select-'+new_id+' .colorbox-ok-button').attr('div_id', 'edit-select-'+new_id); | ||
51 | - jQuery('tr[id^=field-'+id+'-option').each(function(id, element){ | ||
52 | - jQuery(element).attr('id', jQuery(element).attr('id').replace('field-'+id,'field-'+new_id)); | ||
53 | - }); | ||
54 | - jQuery('#edit-select-'+new_id+' label').each(function(index, element){ | ||
55 | - label = jQuery(element); | ||
56 | - label.attr('for', label.attr('for').replace(id,new_id)); | ||
57 | - }); | ||
58 | - jQuery('#edit-select-'+new_id+' input').each(function(index, element){ | ||
59 | - input = jQuery(element); | ||
60 | - input.attr('id', input.attr('id').replace(id,new_id)); | ||
61 | - input.attr('name', input.attr('name').replace(id,new_id)); | ||
62 | - }); | ||
63 | - jQuery('#edit-select-'+new_id+' .remove-option').each(function(index, element){ | ||
64 | - jQuery(element).attr('field_id',new_id); | ||
65 | - }); | ||
66 | - jQuery('#edit-select-'+new_id+' .new-option').attr('field_id',new_id); | ||
67 | - jQuery('#edit-select-'+new_id+' #empty-option-'+id).attr('id','empty-option-'+new_id); | ||
68 | -} | ||
69 | - | ||
70 | -function updateEmptyField(id){ | ||
71 | - id = parseInt(id); | ||
72 | - empty_field = jQuery('#empty-field'); | ||
73 | - empty_field.attr('last_id', (id + 1).toString()); | ||
74 | - jQuery('#empty-field input').each(function(index, element){ | ||
75 | - new_id = jQuery(element).attr('id').replace(id,id+1); | ||
76 | - jQuery(element).attr('id', new_id); | ||
77 | - new_name = jQuery(element).attr('name').replace(id,id+1); | ||
78 | - jQuery(element).attr('name', new_name); | ||
79 | - }); | ||
80 | - jQuery('#empty-field select').each(function(index, element){ | ||
81 | - new_id = jQuery(element).attr('id').replace(id,id+1); | ||
82 | - jQuery(element).attr('id', new_id); | ||
83 | - new_name = jQuery(element).attr('name').replace(id,id+1); | ||
84 | - jQuery(element).attr('name', new_name); | ||
85 | - }); | ||
86 | - jQuery('#empty-field a').each(function(index, element){ | ||
87 | - jQuery(element).attr('field_id', id+1); | ||
88 | - }); | ||
89 | - updateEditText(id); | ||
90 | - updateEditSelect(id); | ||
91 | -} | ||
92 | - | ||
93 | -function updateEmptyOption(field_id, option_id){ | ||
94 | - field_id = parseInt(field_id); | ||
95 | - option_id = parseInt(option_id); | ||
96 | - new_option_id = option_id+1; | ||
97 | - empty_option = jQuery('#empty-option-'+field_id); | ||
98 | - empty_option.attr('option_id',new_option_id); | ||
99 | - jQuery('#empty-option-'+field_id+' .remove-option').attr('option_id', new_option_id); | 8 | + }, |
9 | + | ||
10 | + removeAlternative: function (button, confirmMsg) { | ||
11 | + if (confirm(confirmMsg)) { | ||
12 | + alt = jQuery(button).closest('tr.alternative'); | ||
13 | + jQuery('input.destroy-field', alt).val(1); | ||
14 | + alt.fadeOut(500, function() { | ||
15 | + customFormsPlugin.checkHeaderDisplay(jQuery(button).closest('table')); | ||
16 | + }); | ||
17 | + } | ||
18 | + }, | ||
100 | 19 | ||
101 | - name_id = ' #fields_'+field_id+'_choices_'+option_id+'_name'; | ||
102 | - jQuery('#empty-option-'+field_id+name_id).attr('name', 'fields['+field_id+'][choices]['+new_option_id+'][name]'); | ||
103 | - jQuery('#empty-option-'+field_id+name_id).attr('id', 'fields_'+field_id+'_choices_'+new_option_id+'_name'); | 20 | + addFields: function (button, association, content) { |
21 | + var new_id = new Date().getTime(); | ||
22 | + var regexp = new RegExp("new_" + association, "g"); | ||
23 | + jQuery(content.replace(regexp, new_id)).insertBefore(jQuery(button).closest('.addition-buttons')).hide().slideDown(); | ||
104 | 24 | ||
105 | - value_id = ' #fields_'+field_id+'_choices_'+option_id+'_value'; | ||
106 | - jQuery('#empty-option-'+field_id+value_id).attr('name', 'fields['+field_id+'][choices]['+new_option_id+'][value]'); | ||
107 | - jQuery('#empty-option-'+field_id+value_id).attr('id', 'fields_'+field_id+'_choices_'+new_option_id+'_value'); | 25 | + if(association == 'alternatives') { |
26 | + jQuery(button).closest('table').find('tr:first').show(); | ||
27 | + } | ||
28 | + }, | ||
29 | + | ||
30 | + checkHeaderDisplay: function(table) { | ||
31 | + trs =jQuery('tr:visible', table); | ||
32 | + if (trs.length <= 2) { | ||
33 | + trs[0].style.display = 'none'; | ||
34 | + } else { | ||
35 | + trs[0].style.display = 'table-row'; | ||
36 | + } | ||
37 | + } | ||
108 | } | 38 | } |
109 | - | ||
110 | -jQuery('#new-field').live('click', function(){ | ||
111 | - empty_field = jQuery('#empty-field'); | ||
112 | - id = empty_field.attr('last_id'); | ||
113 | - edit_text = jQuery('#edit-text-'+id); | ||
114 | - edit_select = jQuery('#edit-select-'+id); | ||
115 | - new_field = empty_field.clone(); | ||
116 | - new_field.attr('id','field-'+id); | ||
117 | - new_field.insertBefore(empty_field).slideDown(); | ||
118 | - edit_text.clone().insertAfter(edit_text); | ||
119 | - edit_select.clone().insertAfter(edit_select); | ||
120 | - updateEmptyField(id); | ||
121 | - return false | ||
122 | -}); | ||
123 | - | ||
124 | -jQuery('.new-option').live('click', function(){ | ||
125 | - field_id = jQuery(this).attr('field_id'); | ||
126 | - empty_option = jQuery('#empty-option-'+field_id); | ||
127 | - option_id = empty_option.attr('option_id'); | ||
128 | - new_option = empty_option.clone(); | ||
129 | - new_option.attr('id','field-'+field_id+'-option-'+option_id); | ||
130 | - new_option.insertBefore(empty_option).slideDown(); | ||
131 | - jQuery.colorbox.resize(); | ||
132 | - updateEmptyOption(field_id, option_id); | ||
133 | - return false | ||
134 | -}); | ||
135 | - | ||
136 | -jQuery('.colorbox-ok-button').live('click', function(){ | ||
137 | - jQuery('#'+jQuery(this).attr('div_id')).hide(); | ||
138 | - jQuery.colorbox.close(); | ||
139 | - return false | ||
140 | -}); |
plugins/custom_forms/public/style.css
@@ -31,3 +31,27 @@ | @@ -31,3 +31,27 @@ | ||
31 | #colorbox .edit-information { | 31 | #colorbox .edit-information { |
32 | display: block; | 32 | display: block; |
33 | } | 33 | } |
34 | + | ||
35 | +.field-box { | ||
36 | + margin: 10px 0; | ||
37 | +} | ||
38 | + | ||
39 | +.field-box > div { | ||
40 | + overflow: hide; | ||
41 | +} | ||
42 | + | ||
43 | +.field-box .button { | ||
44 | + margin-left: 15px; | ||
45 | +} | ||
46 | + | ||
47 | +.field-box .addition-buttons .button { | ||
48 | + margin: 0px; | ||
49 | +} | ||
50 | + | ||
51 | +.field-select-type { | ||
52 | + margin: 10px 0; | ||
53 | +} | ||
54 | + | ||
55 | +.field-text-default { | ||
56 | + margin-top: 10px; | ||
57 | +} |
plugins/custom_forms/test/functional/custom_forms_plugin_myprofile_controller_test.rb
@@ -48,21 +48,22 @@ class CustomFormsPluginMyprofileControllerTest < ActionController::TestCase | @@ -48,21 +48,22 @@ class CustomFormsPluginMyprofileControllerTest < ActionController::TestCase | ||
48 | :access => 'logged', | 48 | :access => 'logged', |
49 | :begining => begining, | 49 | :begining => begining, |
50 | :ending => ending, | 50 | :ending => ending, |
51 | - :description => 'Cool form'}, | ||
52 | - :fields => { | ||
53 | - 1 => { | ||
54 | - :name => 'Name', | ||
55 | - :default_value => 'Jack', | ||
56 | - :type => 'text_field' | ||
57 | - }, | ||
58 | - 2 => { | ||
59 | - :name => 'Color', | ||
60 | - :list => '1', | ||
61 | - :type => 'select_field', | ||
62 | - :choices => { | ||
63 | - 1 => {:name => 'Red', :value => 'red'}, | ||
64 | - 2 => {:name => 'Blue', :value => 'blue'}, | ||
65 | - 3 => {:name => 'Black', :value => 'black'} | 51 | + :description => 'Cool form', |
52 | + :fields_attributes => { | ||
53 | + 1 => { | ||
54 | + :name => 'Name', | ||
55 | + :default_value => 'Jack', | ||
56 | + :type => 'CustomFormsPlugin::TextField' | ||
57 | + }, | ||
58 | + 2 => { | ||
59 | + :name => 'Color', | ||
60 | + :select_field_type => 'radio', | ||
61 | + :type => 'CustomFormsPlugin::SelectField', | ||
62 | + :alternatives_attributes => { | ||
63 | + 1 => {:label => 'Red'}, | ||
64 | + 2 => {:label => 'Blue'}, | ||
65 | + 3 => {:label => 'Black'} | ||
66 | + } | ||
66 | } | 67 | } |
67 | } | 68 | } |
68 | } | 69 | } |
@@ -83,10 +84,8 @@ class CustomFormsPluginMyprofileControllerTest < ActionController::TestCase | @@ -83,10 +84,8 @@ class CustomFormsPluginMyprofileControllerTest < ActionController::TestCase | ||
83 | assert f1.kind_of?(CustomFormsPlugin::TextField) | 84 | assert f1.kind_of?(CustomFormsPlugin::TextField) |
84 | 85 | ||
85 | assert_equal 'Color', f2.name | 86 | assert_equal 'Color', f2.name |
86 | - assert_equal 'red', f2.choices['Red'] | ||
87 | - assert_equal 'blue', f2.choices['Blue'] | ||
88 | - assert_equal 'black', f2.choices['Black'] | ||
89 | - assert f2.list | 87 | + assert_equal f2.alternatives.map(&:label).sort, ['Red', 'Blue', 'Black'].sort |
88 | + assert_equal f2.select_field_type, 'radio' | ||
90 | assert f2.kind_of?(CustomFormsPlugin::SelectField) | 89 | assert f2.kind_of?(CustomFormsPlugin::SelectField) |
91 | end | 90 | end |
92 | 91 | ||
@@ -100,7 +99,7 @@ class CustomFormsPluginMyprofileControllerTest < ActionController::TestCase | @@ -100,7 +99,7 @@ class CustomFormsPluginMyprofileControllerTest < ActionController::TestCase | ||
100 | fields[i.to_s] = { | 99 | fields[i.to_s] = { |
101 | :name => i.to_s, | 100 | :name => i.to_s, |
102 | :default_value => '', | 101 | :default_value => '', |
103 | - :type => 'text_field' | 102 | + :type => 'CustomFormsPlugin::TextField' |
104 | } | 103 | } |
105 | end | 104 | end |
106 | assert_difference CustomFormsPlugin::Form, :count, 1 do | 105 | assert_difference CustomFormsPlugin::Form, :count, 1 do |
@@ -110,29 +109,35 @@ class CustomFormsPluginMyprofileControllerTest < ActionController::TestCase | @@ -110,29 +109,35 @@ class CustomFormsPluginMyprofileControllerTest < ActionController::TestCase | ||
110 | :access => 'logged', | 109 | :access => 'logged', |
111 | :begining => begining, | 110 | :begining => begining, |
112 | :ending => ending, | 111 | :ending => ending, |
113 | - :description => 'Cool form'}, | ||
114 | - :fields => fields | 112 | + :description => 'Cool form', |
113 | + :fields_attributes => fields | ||
114 | + } | ||
115 | end | 115 | end |
116 | form = CustomFormsPlugin::Form.find_by_name('My Form') | 116 | form = CustomFormsPlugin::Form.find_by_name('My Form') |
117 | assert_equal num_fields, form.fields.count | 117 | assert_equal num_fields, form.fields.count |
118 | + lst = -1 | ||
118 | form.fields.find_each do |f| | 119 | form.fields.find_each do |f| |
119 | - assert_equal f.position, f.name.to_i | 120 | + assert f.name.to_i > lst |
121 | + lst = f.name.to_i | ||
120 | end | 122 | end |
121 | end | 123 | end |
122 | 124 | ||
123 | should 'edit a form' do | 125 | should 'edit a form' do |
124 | form = CustomFormsPlugin::Form.create!(:profile => profile, :name => 'Free Software') | 126 | form = CustomFormsPlugin::Form.create!(:profile => profile, :name => 'Free Software') |
125 | - field = CustomFormsPlugin::TextField.create!(:form => form, :name => 'License') | ||
126 | format = '%Y-%m-%d %H:%M' | 127 | format = '%Y-%m-%d %H:%M' |
127 | begining = Time.now.strftime(format) | 128 | begining = Time.now.strftime(format) |
128 | ending = (Time.now + 1.day).strftime(format) | 129 | ending = (Time.now + 1.day).strftime(format) |
129 | 130 | ||
130 | - post :edit, :profile => profile.identifier, :id => form.id, | ||
131 | - :form => {:name => 'My Form', :access => 'logged', :begining => begining, :ending => ending, :description => 'Cool form'}, | ||
132 | - :fields => {1 => {:real_id => field.id.to_s, :name => 'Source'}} | 131 | + assert_equal form.fields.length, 0 |
132 | + | ||
133 | + post :update, :profile => profile.identifier, :id => form.id, | ||
134 | + :form => {:name => 'My Form', :access => 'logged', :begining => begining, :ending => ending, :description => 'Cool form', | ||
135 | + :fields_attributes => {1 => {:name => 'Source'}}} | ||
133 | 136 | ||
134 | form.reload | 137 | form.reload |
135 | - field.reload | 138 | + assert_equal form.fields.length, 1 |
139 | + | ||
140 | + field = form.fields.last | ||
136 | 141 | ||
137 | assert_equal 'logged', form.access | 142 | assert_equal 'logged', form.access |
138 | assert_equal begining, form.begining.strftime(format) | 143 | assert_equal begining, form.begining.strftime(format) |
plugins/custom_forms/test/functional/custom_forms_plugin_profile_controller_test.rb
@@ -23,7 +23,7 @@ class CustomFormsPluginProfileControllerTest < ActionController::TestCase | @@ -23,7 +23,7 @@ class CustomFormsPluginProfileControllerTest < ActionController::TestCase | ||
23 | field2 = CustomFormsPlugin::TextField.create(:name => 'License', :form => form) | 23 | field2 = CustomFormsPlugin::TextField.create(:name => 'License', :form => form) |
24 | 24 | ||
25 | assert_difference CustomFormsPlugin::Submission, :count, 1 do | 25 | assert_difference CustomFormsPlugin::Submission, :count, 1 do |
26 | - post :show, :profile => profile.identifier, :id => form.id, :submission => {field1.name.to_slug => 'Noosfero', field2.name.to_slug => 'GPL'} | 26 | + post :show, :profile => profile.identifier, :id => form.id, :submission => {field1.id.to_s => 'Noosfero', field2.id.to_s => 'GPL'} |
27 | end | 27 | end |
28 | assert !session[:notice].include?('not saved') | 28 | assert !session[:notice].include?('not saved') |
29 | assert_redirected_to :action => 'show' | 29 | assert_redirected_to :action => 'show' |
plugins/custom_forms/test/unit/custom_forms_plugin/answer_test.rb
@@ -27,11 +27,11 @@ class CustomFormsPlugin::AnswerTest < ActiveSupport::TestCase | @@ -27,11 +27,11 @@ class CustomFormsPlugin::AnswerTest < ActiveSupport::TestCase | ||
27 | field = CustomFormsPlugin::Field.create!(:name => 'License', :form => form, :mandatory => true) | 27 | field = CustomFormsPlugin::Field.create!(:name => 'License', :form => form, :mandatory => true) |
28 | answer = CustomFormsPlugin::Answer.new(:field => field) | 28 | answer = CustomFormsPlugin::Answer.new(:field => field) |
29 | answer.valid? | 29 | answer.valid? |
30 | - assert answer.errors.invalid?(field.slug.to_sym) | 30 | + assert answer.errors.invalid?(:value) |
31 | 31 | ||
32 | answer.value = "GPL" | 32 | answer.value = "GPL" |
33 | answer.valid? | 33 | answer.valid? |
34 | - assert !answer.errors.invalid?(field.slug.to_sym) | 34 | + assert !answer.errors.invalid?(:value) |
35 | end | 35 | end |
36 | 36 | ||
37 | end | 37 | end |
plugins/custom_forms/test/unit/custom_forms_plugin/field_test.rb
1 | require File.dirname(__FILE__) + '/../../../../../test/test_helper' | 1 | require File.dirname(__FILE__) + '/../../../../../test/test_helper' |
2 | 2 | ||
3 | class CustomFormsPlugin::FieldTest < ActiveSupport::TestCase | 3 | class CustomFormsPlugin::FieldTest < ActiveSupport::TestCase |
4 | - should 'validate presence of form' do | ||
5 | - field = CustomFormsPlugin::Field.new | ||
6 | - field.valid? | ||
7 | - assert field.errors.invalid?(:form) | ||
8 | - assert field.errors.invalid?(:name) | ||
9 | - | ||
10 | - form = CustomFormsPlugin::Form.create!(:name => 'Free Software', :profile => fast_create(Profile)) | ||
11 | - field.form = form | ||
12 | - field.name = 'License' | ||
13 | - field.valid? | ||
14 | - assert !field.errors.invalid?(:form) | ||
15 | - assert !field.errors.invalid?(:name) | ||
16 | - end | ||
17 | - | ||
18 | should 'set slug before validation based on name' do | 4 | should 'set slug before validation based on name' do |
19 | field = CustomFormsPlugin::Field.new(:name => 'Name') | 5 | field = CustomFormsPlugin::Field.new(:name => 'Name') |
20 | field.valid? | 6 | field.valid? |
21 | assert_equal field.name.to_slug, field.slug | 7 | assert_equal field.name.to_slug, field.slug |
22 | end | 8 | end |
23 | 9 | ||
24 | - should 'validate uniqueness of slug scoped on the form' do | ||
25 | - form1 = CustomFormsPlugin::Form.create!(:name => 'Free Software', :profile => fast_create(Profile)) | ||
26 | - form2 = CustomFormsPlugin::Form.create!(:name => 'Open Source', :profile => fast_create(Profile)) | ||
27 | - f1 = CustomFormsPlugin::Field.create!(:name => 'License', :form => form1) | ||
28 | - f2 = CustomFormsPlugin::Field.new(:name => 'License', :form => form1) | ||
29 | - f3 = CustomFormsPlugin::Field.new(:name => 'License', :form => form2) | ||
30 | - | ||
31 | - f2.valid? | ||
32 | - f3.valid? | ||
33 | - | ||
34 | - assert f2.errors.invalid?(:slug) | ||
35 | - assert !f3.errors.invalid?(:slug) | ||
36 | - end | ||
37 | - | ||
38 | should 'set mandatory field as false by default' do | 10 | should 'set mandatory field as false by default' do |
39 | field = CustomFormsPlugin::Field.new | 11 | field = CustomFormsPlugin::Field.new |
40 | assert !field.mandatory | 12 | assert !field.mandatory |
@@ -50,17 +22,6 @@ class CustomFormsPlugin::FieldTest < ActiveSupport::TestCase | @@ -50,17 +22,6 @@ class CustomFormsPlugin::FieldTest < ActiveSupport::TestCase | ||
50 | assert_includes field.answers, a2 | 22 | assert_includes field.answers, a2 |
51 | end | 23 | end |
52 | 24 | ||
53 | - should 'serialize choices into a hash' do | ||
54 | - form = CustomFormsPlugin::Form.create!(:name => 'Free Software', :profile => fast_create(Profile)) | ||
55 | - field = CustomFormsPlugin::Field.create!(:name => 'License', :form => form) | ||
56 | - field.choices = {'First' => 1, 'Second' => 2, 'Third' => 3} | ||
57 | - field.save! | ||
58 | - | ||
59 | - assert_equal 1, field.choices['First'] | ||
60 | - assert_equal 2, field.choices['Second'] | ||
61 | - assert_equal 3, field.choices['Third'] | ||
62 | - end | ||
63 | - | ||
64 | should 'not destroy form after removing a field' do | 25 | should 'not destroy form after removing a field' do |
65 | form = CustomFormsPlugin::Form.create!(:name => 'Free Software', :profile => fast_create(Profile)) | 26 | form = CustomFormsPlugin::Form.create!(:name => 'Free Software', :profile => fast_create(Profile)) |
66 | license_field = CustomFormsPlugin::Field.create!(:name => 'License', :form => form) | 27 | license_field = CustomFormsPlugin::Field.create!(:name => 'License', :form => form) |
@@ -71,27 +32,5 @@ class CustomFormsPlugin::FieldTest < ActiveSupport::TestCase | @@ -71,27 +32,5 @@ class CustomFormsPlugin::FieldTest < ActiveSupport::TestCase | ||
71 | end | 32 | end |
72 | assert_equal form.fields, [license_field] | 33 | assert_equal form.fields, [license_field] |
73 | end | 34 | end |
74 | - | ||
75 | - should 'give positions by creation order' do | ||
76 | - form = CustomFormsPlugin::Form.create!(:name => 'Free Software', :profile => fast_create(Profile)) | ||
77 | - field_0 = CustomFormsPlugin::Field.create!(:name => 'License', :form => form) | ||
78 | - field_1 = CustomFormsPlugin::Field.create!(:name => 'URL', :form => form) | ||
79 | - field_2 = CustomFormsPlugin::Field.create!(:name => 'Wiki', :form => form) | ||
80 | - assert_equal 0, field_0.position | ||
81 | - assert_equal 1, field_1.position | ||
82 | - assert_equal 2, field_2.position | ||
83 | - end | ||
84 | - | ||
85 | - should 'not crash when adding new fields on a form with fields without position' do | ||
86 | - form = CustomFormsPlugin::Form.create(:name => 'Free Software', :profile => fast_create(Profile)) | ||
87 | - field_0 = CustomFormsPlugin::Field.create(:name => 'License', :form => form) | ||
88 | - field_0.position = nil | ||
89 | - field_0.save | ||
90 | - | ||
91 | - assert_nothing_raised do | ||
92 | - field_1 = CustomFormsPlugin::Field.create!(:name => 'URL', :form => form) | ||
93 | - end | ||
94 | - end | ||
95 | - | ||
96 | end | 35 | end |
97 | 36 |
plugins/custom_forms/test/unit/custom_forms_plugin/membership_survey_test.rb
@@ -16,7 +16,7 @@ class CustomFormsPlugin::MembershipSurveyTest < ActiveSupport::TestCase | @@ -16,7 +16,7 @@ class CustomFormsPlugin::MembershipSurveyTest < ActiveSupport::TestCase | ||
16 | person = fast_create(Person) | 16 | person = fast_create(Person) |
17 | form = CustomFormsPlugin::Form.create!(:name => 'Simple Form', :profile => profile) | 17 | form = CustomFormsPlugin::Form.create!(:name => 'Simple Form', :profile => profile) |
18 | field = CustomFormsPlugin::Field.create!(:name => 'Name', :form => form) | 18 | field = CustomFormsPlugin::Field.create!(:name => 'Name', :form => form) |
19 | - task = CustomFormsPlugin::MembershipSurvey.create!(:form_id => form.id, :submission => {'name' => 'Jack'}, :target => person, :requestor => profile) | 19 | + task = CustomFormsPlugin::MembershipSurvey.create!(:form_id => form.id, :submission => {field.id.to_s => 'Jack'}, :target => person, :requestor => profile) |
20 | 20 | ||
21 | assert_difference CustomFormsPlugin::Submission, :count, 1 do | 21 | assert_difference CustomFormsPlugin::Submission, :count, 1 do |
22 | task.finish | 22 | task.finish |
plugins/custom_forms/test/unit/custom_forms_plugin/select_field_test.rb
1 | require File.dirname(__FILE__) + '/../../../../../test/test_helper' | 1 | require File.dirname(__FILE__) + '/../../../../../test/test_helper' |
2 | 2 | ||
3 | class CustomFormsPlugin::SelectFieldTest < ActiveSupport::TestCase | 3 | class CustomFormsPlugin::SelectFieldTest < ActiveSupport::TestCase |
4 | - should 'validate presence of choices, multiple and list' do | ||
5 | - select = CustomFormsPlugin::SelectField.new | ||
6 | - select.valid? | ||
7 | - assert select.errors.invalid?(:choices) | 4 | + should 'validate type' do |
5 | + select = CustomFormsPlugin::SelectField.new(:name => 'select_field001' ) | ||
8 | 6 | ||
9 | - select.choices = {'label' => 'value'} | ||
10 | - select.valid? | ||
11 | - assert !select.errors.invalid?(:choices) | 7 | + select.update_attribute(:select_field_type, 'random') |
8 | + assert select.invalid? | ||
9 | + | ||
10 | + select.update_attribute(:select_field_type, 'radio') | ||
11 | + assert select.valid? | ||
12 | + select.update_attribute(:select_field_type, 'check_box') | ||
13 | + assert select.valid? | ||
14 | + select.update_attribute(:select_field_type, 'select') | ||
15 | + assert select.valid? | ||
16 | + select.update_attribute(:select_field_type, 'multiple_select') | ||
17 | + assert select.valid? | ||
12 | end | 18 | end |
13 | end | 19 | end |
plugins/custom_forms/views/custom_forms_plugin_myprofile/_edit_select.html.erb
1 | -<% elem_id = "edit-select-#{counter}" %> | ||
2 | -<div id=<%= elem_id %> class='edit-information'> | 1 | +<div class='edit-information edit-select'> |
3 | <h2><%= _('Options') %></h2> | 2 | <h2><%= _('Options') %></h2> |
4 | <table class='action-table' style='width: 420px'> | 3 | <table class='action-table' style='width: 420px'> |
5 | <tr> | 4 | <tr> |
6 | <th style='width: 40%'><%= _('Name') %></th> | 5 | <th style='width: 40%'><%= _('Name') %></th> |
7 | <th style='width: 40%'><%= _('Value') %></th> | 6 | <th style='width: 40%'><%= _('Value') %></th> |
8 | - <th style='width: 20%'><%= _('Actions') %></th> | 7 | + <th style='width: 20%'><%= _('Delete') %></th> |
9 | </tr> | 8 | </tr> |
10 | <% option_counter = 1 %> | 9 | <% option_counter = 1 %> |
11 | <% (field.choices || {}).each do |name, value| %> | 10 | <% (field.choices || {}).each do |name, value| %> |
plugins/custom_forms/views/custom_forms_plugin_myprofile/_edit_text.html.erb
@@ -1,10 +0,0 @@ | @@ -1,10 +0,0 @@ | ||
1 | -<% elem_id = "edit-text-#{counter}" %> | ||
2 | -<div id=<%= elem_id %> class='edit-information'> | ||
3 | - <h2><%= _('Default value') %></h2> | ||
4 | - <%= labelled_form_field _('Default value'), text_field("fields[#{counter}]", :default_value, :value => field.default_value) %> | ||
5 | - | ||
6 | - <% button_bar do %> | ||
7 | - <%= button :ok, _('Ok'), '#', :class => 'colorbox-ok-button', :div_id => elem_id %> | ||
8 | - <% end %> | ||
9 | -</div> | ||
10 | - |
plugins/custom_forms/views/custom_forms_plugin_myprofile/_field.html.erb
1 | -<tr id=<%= "field-#{counter}" %>> | ||
2 | - <td style="text-align: left"><%= text_field "fields[#{counter}]", :name, :value => field.name, :size => 25 %></td> | ||
3 | - <td><%= type_to_label(field.type) %></td> | ||
4 | - <%= hidden_field "fields[#{counter}]", :type, :value => type_for_options(field.class) %> | ||
5 | - <td><%= check_box "fields[#{counter}]", :mandatory, :checked => field.mandatory %></td> | ||
6 | - <%= hidden_field "fields[#{counter}]", :real_id, :value => field.id %> | ||
7 | - <%= hidden_field "fields[#{counter}]", :form_id, :value => @form.id %> | ||
8 | - <td class='actions'> | ||
9 | - <%= button_without_text :edit, _('Edit'), '#', :field_id => counter %> | ||
10 | - <%= button_without_text :remove, _('Remove'), '#', :class => 'remove-field', :field_id => counter, :confirm => _('Are you sure you want to remove this field?') %> | ||
11 | - </td> | ||
12 | -</tr> | 1 | +<fieldset class="field-box" <%='style="display:none"' if f.object._destroy %> > |
2 | + <legend><%= type_to_label(f.object.type) %></legend> | ||
3 | + <div> | ||
4 | + <%= f.label :name, _('Name:') %> | ||
5 | + <%= f.text_field :name, :size => 25 %> | ||
6 | + | ||
7 | + <%= f.hidden_field :type %> | ||
8 | + | ||
9 | + <%= f.check_box :mandatory %> | ||
10 | + <%= f.label :mandatory, _('Mandatory') %> | ||
11 | + | ||
12 | + <%= f.hidden_field :_destroy, :class => 'destroy-field' %> | ||
13 | + <%= button_to_function :delete, _('Remove field'), "customFormsPlugin.removeFieldBox(this, #{_('Are you sure you want to remove this field?').to_json})" %> | ||
14 | + <%= yield %> | ||
15 | +</div> | ||
16 | +</fieldset> |
plugins/custom_forms/views/custom_forms_plugin_myprofile/_form.html.erb
1 | <% self.extend(CustomFormsPlugin::Helper) %> | 1 | <% self.extend(CustomFormsPlugin::Helper) %> |
2 | 2 | ||
3 | -<%= error_messages_for :form %> | ||
4 | - | ||
5 | -<% form_for :form, @form do |f| %> | ||
6 | - <%= required labelled_form_field _('Name'), f.text_field(:name) %> | ||
7 | - <%= labelled_form_field(_('Period'), ( | ||
8 | - date_range_field('form[begining]', 'form[ending]', @form.begining, @form.ending, | ||
9 | - '%Y-%m-%d %H:%M', | ||
10 | - { :time => true, :change_month => true, :change_year => true, | ||
11 | - :date_format => 'yy-mm-dd', :time_format => 'hh:mm' }, | 3 | +<%= f.error_messages %> |
4 | +<%= required labelled_form_field _('Name'), f.text_field(:name) %> | ||
5 | +<%= labelled_form_field(_('Period'), ( | ||
6 | + date_range_field('form[begining]', 'form[ending]', @form.begining, @form.ending, | ||
7 | + '%Y-%m-%d %H:%M', | ||
8 | + { :time => true, :change_month => true, :change_year => true, | ||
9 | + :date_format => 'yy-mm-dd', :time_format => 'hh:mm' }, | ||
12 | { :size => 14 }) | 10 | { :size => 14 }) |
13 | - )) %> | ||
14 | - <%= labelled_form_field _('Access'), f.select(:access, access_options(profile))%> | ||
15 | - <% if profile.organization? %> | ||
16 | - <%= labelled_form_field _('Triggered on membership'), f.check_box(:on_membership) %> | ||
17 | - <% end %> | ||
18 | - <%= labelled_form_field _('Description'), f.text_area(:description, :style => 'width: 100%') %> | 11 | +)) %> |
12 | +<%= labelled_form_field _('Access'), f.select(:access, access_options(profile))%> | ||
13 | +<% if profile.organization? %> | ||
14 | + <%= labelled_form_field _('Triggered on membership'), f.check_box(:on_membership) %> | ||
15 | +<% end %> | ||
16 | +<%= labelled_form_field _('Description'), f.text_area(:description, :style => 'width: 100%') %> | ||
19 | 17 | ||
20 | - <h2><%= _('Fields') %></h2> | ||
21 | - <table class="action-table" id='fields-table'> | ||
22 | - <tr> | ||
23 | - <th style='width: 40%'><%= _('Name') %></th> | ||
24 | - <th style='width: 30%'><%= _('Type') %></th> | ||
25 | - <th style='width: 10%'><%= _('Mandatory') %></th> | ||
26 | - <th style='width: 20%'><%= _('Actions') %></th> | ||
27 | - </tr> | ||
28 | - <% counter = 1 %> | ||
29 | - <% @fields.each do |field| %> | ||
30 | - <%= render :partial => 'field', :locals => {:field => field, :counter => counter} %> | ||
31 | - <% counter += 1 %> | ||
32 | - <% end %> | ||
33 | - <%= render :partial => 'empty_field', :locals => {:field => @empty_field, :counter => counter} %> | ||
34 | - <tr class='new-item'> | ||
35 | - <td colspan='5'> | ||
36 | - <%= button(:add, _('Add a new field'), '#', :id => 'new-field')%> | ||
37 | - </td> | ||
38 | - </tr> | ||
39 | - </table> | 18 | +<h2><%= _('Fields') %></h2> |
40 | 19 | ||
41 | - <% counter = 1 %> | ||
42 | - <% @fields.each do |field| %> | ||
43 | - <%= render :partial => 'edit_text', :locals => {:field => field, :counter => counter} %> | ||
44 | - <%= render :partial => 'edit_select', :locals => {:field => field, :counter => counter} %> | ||
45 | - <% counter += 1 %> | ||
46 | - <% end %> | 20 | +<% f.fields_for :fields do |builder| %> |
21 | + <%= render partial_for_class(builder.object.class), :f => builder %> | ||
22 | +<% end %> | ||
47 | 23 | ||
48 | - <%= render :partial => 'edit_text', :locals => {:field => @empty_field, :counter => counter} %> | ||
49 | - <%= render :partial => 'edit_select', :locals => {:field => @empty_field, :counter => counter} %> | 24 | +<div class="addition-buttons"> |
25 | + <%= button(:add, _('Add a new text field'), '#', :onclick => "customFormsPlugin.addFields(this, 'fields', #{html_for_field(f, :fields, CustomFormsPlugin::TextField).to_json}); return false")%> | ||
26 | + <%= button(:add, _('Add a new select field'), '#', :onclick => "customFormsPlugin.addFields(this, 'fields', #{html_for_field(f, :fields, CustomFormsPlugin::SelectField).to_json}); return false")%> | ||
27 | +</div> | ||
50 | 28 | ||
51 | - <% button_bar do %> | ||
52 | - <%= submit_button :save, _('Save'), :cancel => {:action => 'index'}%> | ||
53 | - <% end %> | 29 | +<% button_bar do %> |
30 | + <%= submit_button :save, _('Save'), :cancel => {:action => 'index'}%> | ||
54 | <% end %> | 31 | <% end %> |
55 | 32 | ||
56 | <%= javascript_include_tag '../plugins/custom_forms/field' %> | 33 | <%= javascript_include_tag '../plugins/custom_forms/field' %> |
plugins/custom_forms/views/custom_forms_plugin_myprofile/_option.html.erb
@@ -1,7 +0,0 @@ | @@ -1,7 +0,0 @@ | ||
1 | -<tr id=<%= "field-#{counter}-option-#{option_counter}" %> style="display: auto;"> | ||
2 | - <td><%= text_field_tag("fields[#{counter}][choices][#{option_counter}][name]", name) %></td> | ||
3 | - <td><%= text_field_tag("fields[#{counter}][choices][#{option_counter}][value]", value) %></td> | ||
4 | - <td class='actions'> | ||
5 | - <%= button_without_text :remove, _('Remove'), '#', :class => 'remove-option', :field_id => counter, :option_id => option_counter, :confirm => _('Are you sure you want to remove this option?') %> | ||
6 | - </td> | ||
7 | -</tr> |
plugins/custom_forms/views/custom_forms_plugin_myprofile/create.html.erb
plugins/custom_forms/views/custom_forms_plugin_myprofile/custom_forms_plugin/_alternative.html.erb
0 → 100644
@@ -0,0 +1,10 @@ | @@ -0,0 +1,10 @@ | ||
1 | +<tr class="alternative"> | ||
2 | + <td> <%= f.text_field(:label) %> </td> | ||
3 | + | ||
4 | + <td> <%= f.check_box(:selected_by_default) %> </td> | ||
5 | + | ||
6 | + <td> | ||
7 | + <%= f.hidden_field :_destroy, :class => 'destroy-field' %> | ||
8 | + <%= 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') %> | ||
9 | + </td> | ||
10 | +</div> |
plugins/custom_forms/views/custom_forms_plugin_myprofile/custom_forms_plugin/_field.html.erb
0 → 100644
@@ -0,0 +1,9 @@ | @@ -0,0 +1,9 @@ | ||
1 | +<%-# Small hack necessary for fields_for when validation fails on #new %> | ||
2 | +<% case f.object.type | ||
3 | + when 'CustomFormsPlugin::SelectField' %> | ||
4 | + <%= render partial_for_class(CustomFormsPlugin::SelectField), :f => f %> | ||
5 | +<% when 'CustomFormsPlugin::TextField' %> | ||
6 | + <%= render partial_for_class(CustomFormsPlugin::TextField), :f => f %> | ||
7 | +<% else %> | ||
8 | + <% raise 'This field has no valid type' %> | ||
9 | +<% end %> |
plugins/custom_forms/views/custom_forms_plugin_myprofile/custom_forms_plugin/_select_field.html.erb
0 → 100644
@@ -0,0 +1,31 @@ | @@ -0,0 +1,31 @@ | ||
1 | +<% render :layout => 'field', :locals => { :f => f } do %> | ||
2 | + <div class="field-select-type"> | ||
3 | + <%= _('Type:') %> | ||
4 | + <%= f.radio_button(:select_field_type, 'radio') %> | ||
5 | + <%= f.label(:select_field_type, _('Radio'), :value => 'radio') %> | ||
6 | + <%= f.radio_button(:select_field_type, 'check_box') %> | ||
7 | + <%= f.label(:select_field_type, _('Checkbox'), :value => 'check_box') %> | ||
8 | + <%= f.radio_button(:select_field_type, 'select') %> | ||
9 | + <%= f.label(:select_field_type, _('Drop down'), :value => 'select') %> | ||
10 | + <%= f.radio_button(:select_field_type, 'multiple_select') %> | ||
11 | + <%= f.label(:select_field_type, _('Multiple Select'), :value => 'multiple_select') %> | ||
12 | + </div> | ||
13 | + | ||
14 | + <table> | ||
15 | + <tr <%='style="display:none"' if f.object.alternatives.empty? %>> | ||
16 | + <th><%= _('Alternative') %></th> | ||
17 | + <th><%= _('Preselected') %></th> | ||
18 | + <th><%= _('Remove') %></th> | ||
19 | + </tr> | ||
20 | + <% f.fields_for :alternatives do |builder| %> | ||
21 | + <%= render partial_for_class(builder.object.class), :f => builder %> | ||
22 | + <% end %> | ||
23 | + <tr class="addition-buttons"> | ||
24 | + <td colspan="3"> | ||
25 | + <%= button(:add, _('Add a new alternative'), '#', :onclick => "customFormsPlugin.addFields(this, 'alternatives', #{html_for_field(f, :alternatives, CustomFormsPlugin::Alternative).to_json}); return false") %> | ||
26 | + </td> | ||
27 | + </tr> | ||
28 | + </table> | ||
29 | + | ||
30 | + | ||
31 | +<% end %> |
plugins/custom_forms/views/custom_forms_plugin_myprofile/custom_forms_plugin/_text_field.html.erb
0 → 100644
plugins/custom_forms/views/custom_forms_plugin_myprofile/edit.html.erb
plugins/custom_forms/views/custom_forms_plugin_myprofile/index.html.erb
@@ -22,7 +22,7 @@ | @@ -22,7 +22,7 @@ | ||
22 | <% end %> | 22 | <% end %> |
23 | <tr id="new-item"> | 23 | <tr id="new-item"> |
24 | <td colspan='5'> | 24 | <td colspan='5'> |
25 | - <%= button(:add, _('Add a new form'), :action => 'create')%> | 25 | + <%= button(:add, _('Add a new form'), :action => 'new')%> |
26 | </td> | 26 | </td> |
27 | </tr> | 27 | </tr> |
28 | </table> | 28 | </table> |
plugins/custom_forms/views/custom_forms_plugin_myprofile/new.html.erb
0 → 100644
public/stylesheets/application.css
@@ -2471,11 +2471,11 @@ div#activation_enterprise label, div#activation_enterprise input, div#activation | @@ -2471,11 +2471,11 @@ div#activation_enterprise label, div#activation_enterprise input, div#activation | ||
2471 | } | 2471 | } |
2472 | /*** REQUIRED FIELDS ***/ | 2472 | /*** REQUIRED FIELDS ***/ |
2473 | 2473 | ||
2474 | -.required-field label { | 2474 | +.required-field label.formlabel { |
2475 | font-weight: bold; | 2475 | font-weight: bold; |
2476 | color: #c00; | 2476 | color: #c00; |
2477 | } | 2477 | } |
2478 | -.required-field label:after { | 2478 | +.required-field label.formlabel:after { |
2479 | content: ' (*)'; | 2479 | content: ' (*)'; |
2480 | } | 2480 | } |
2481 | .login-box { | 2481 | .login-box { |