Commit 9e954d8c60e672519a5b4e93fec0520b6e0e3b79

Authored by Rodrigo Souto
2 parents 540c6070 45a88ecf

Merge branch 'master' into custom-forms

Conflicts:
	plugins/custom_forms/test/functional/custom_forms_plugin_myprofile_controller_test.rb
	plugins/custom_forms/views/custom_forms_plugin_myprofile/_form.html.erb
	plugins/custom_forms/views/custom_forms_plugin_profile/show.html.erb
	po/pt/noosfero.po
Showing 49 changed files with 1212 additions and 480 deletions   Show diff stats
plugins/custom_forms/controllers/custom_forms_plugin_myprofile_controller.rb
1   -class CustomFormsPluginMyprofileController < MyProfileController
  1 +require 'csv'
2 2  
  3 +class CustomFormsPluginMyprofileController < MyProfileController
3 4 protect 'post_content', :profile
  5 +
4 6 def index
5 7 @forms = CustomFormsPlugin::Form.from(profile)
6 8 end
7 9  
  10 + def new
  11 + @form = CustomFormsPlugin::Form.new
  12 +
  13 + respond_to do |format|
  14 + format.html
  15 + end
  16 + end
  17 +
8 18 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')
  19 + params[:form][:profile_id] = profile.id
  20 + @form = CustomFormsPlugin::Form.new(params[:form])
  21 +
  22 + normalize_positions(@form)
  23 +
  24 + respond_to do |format|
  25 + if @form.save
  26 + flash[:notice] = _("Custom form #{@form.name} was successfully created.")
  27 + format.html { redirect_to(:action=>'index') }
  28 + else
  29 + format.html { render :action => 'new' }
24 30 end
25 31 end
26 32 end
27 33  
28 34 def edit
29 35 @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)
  36 + end
  37 +
  38 + def update
  39 + @form = CustomFormsPlugin::Form.find(params[:id])
  40 + @form.attributes = params[:form]
  41 +
  42 + normalize_positions(@form)
  43 +
  44 + respond_to do |format|
  45 + if @form.save
  46 + flash[:notice] = _("Custom form #{@form.name} was successfully updated.")
  47 + format.html { redirect_to(:action=>'index') }
  48 + else
44 49 session['notice'] = _('Form could not be updated')
  50 + format.html { render :action => 'edit' }
45 51 end
46 52 end
47 53 end
... ... @@ -60,6 +66,26 @@ class CustomFormsPluginMyprofileController &lt; MyProfileController
60 66 def submissions
61 67 @form = CustomFormsPlugin::Form.find(params[:id])
62 68 @submissions = @form.submissions
  69 +
  70 + @sort_by = params[:sort_by]
  71 + @submissions = @submissions.sort_by { |s| s.profile.present? ? s.profile.name : s.author_name } if @sort_by == 'author'
  72 +
  73 + respond_to do |format|
  74 + format.html
  75 + format.csv do
  76 + # CSV contains form fields, timestamp, user name and user email
  77 + columns = @form.fields.count + 3
  78 + csv_content = CSV.generate_line(['Timestamp', 'Name', 'Email'] + @form.fields.map(&:name)) + "\n"
  79 + @submissions.each do |s|
  80 + fields = [s.updated_at.strftime('%Y/%m/%d %T %Z'), s.profile.present? ? s.profile.name : s.author_name, s.profile.present? ? s.profile.email : s.author_email]
  81 + @form.fields.each do |f|
  82 + fields << s.answers.select{|a| a.field == f}.map{|answer| answer.to_s}
  83 + end
  84 + CSV.generate_row(fields, columns, csv_content)
  85 + end
  86 + send_data csv_content, :type => 'text/csv', :filename => "#{@form.name}.csv"
  87 + end
  88 + end
63 89 end
64 90  
65 91 def show_submission
... ... @@ -67,82 +93,29 @@ class CustomFormsPluginMyprofileController &lt; MyProfileController
67 93 @form = @submission.form
68 94 end
69 95  
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
  96 + def pending
  97 + @form = CustomFormsPlugin::Form.find(params[:id])
  98 + @pendings = CustomFormsPlugin::AdmissionSurvey.from(@form.profile).pending.select {|task| task.form_id == @form.id}.map {|a| {:profile => a.target, :time => a.created_at} }
82 99  
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
  100 + @sort_by = params[:sort_by]
  101 + @pendings = @pendings.sort_by { |s| s[:profile].name } if @sort_by == 'user'
94 102 end
95 103  
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
  104 + private
103 105  
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
  106 + def normalize_positions(form)
  107 + counter = 0
  108 + form.fields.sort_by{ |f| f.position.to_i }.each do |field|
  109 + field.position = counter
  110 + counter += 1
122 111 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)
  112 + form.fields.each do |field|
  113 + counter = 0
  114 + field.alternatives.sort_by{ |alt| alt.position.to_i }.each do |alt|
  115 + alt.position = counter
  116 + counter += 1
132 117 end
133 118 end
134   - fields
135 119 end
136 120  
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 121 end
... ...
plugins/custom_forms/controllers/custom_forms_plugin_profile_controller.rb
1 1 class CustomFormsPluginProfileController < ProfileController
2   -
3 2 before_filter :has_access, :show
4 3  
5 4 def show
  5 + extend(CustomFormsPlugin::Helper)
  6 +
6 7 @form = CustomFormsPlugin::Form.find(params[:id])
7 8 if user
8 9 @submission ||= CustomFormsPlugin::Submission.find_by_form_id_and_profile_id(@form.id,user.id)
... ... @@ -10,22 +11,34 @@ class CustomFormsPluginProfileController &lt; ProfileController
10 11 else
11 12 @submission ||= CustomFormsPlugin::Submission.new(:form_id => @form.id)
12 13 end
  14 +
  15 + # build the answers
  16 + @submission.answers.push(*(answers = build_answers(params[:submission], @form))) if params[:submission]
  17 +
13 18 if request.post?
14 19 begin
15   - extend(CustomFormsPlugin::Helper)
16   - answers = build_answers(params[:submission], @form)
  20 + raise 'Submission already present!' if user.present? && CustomFormsPlugin::Submission.find_by_form_id_and_profile_id(@form.id,user.id)
  21 + raise 'Form expired!' if @form.expired?
  22 +
  23 + # @submission.answers for some reason has the same answer twice
17 24 failed_answers = answers.select {|answer| !answer.valid? }
  25 +
18 26 if failed_answers.empty?
19   - if !user
20   - @submission.author_name = params[:author_name]
21   - @submission.author_email = params[:author_email]
  27 + # Save the submission
  28 + ActiveRecord::Base.transaction do
  29 + if !user
  30 + @submission.author_name = params[:author_name]
  31 + @submission.author_email = params[:author_email]
  32 + end
  33 + @submission.save!
22 34 end
23   - @submission.save!
24   - answers.map {|answer| answer.submission = @submission; answer.save!}
25 35 else
26   - @submission.valid?
  36 + @submission.errors.clear
27 37 failed_answers.each do |answer|
28   - @submission.errors.add(answer.field.name.to_sym, answer.errors[answer.field.slug.to_sym])
  38 + answer.valid?
  39 + answer.errors.each do |attribute, msg|
  40 + @submission.errors.add(answer.field.id.to_s.to_sym, msg)
  41 + end
29 42 end
30 43 raise 'Submission failed: answers not valid'
31 44 end
... ...
plugins/custom_forms/db/migrate/20130823134700_create_custom_forms_plugin_alternatives.rb 0 → 100644
... ... @@ -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,32 @@
  1 +class AddSelectFieldTypeToCustomFormsPluginFields < ActiveRecord::Migration
  2 + def self.up
  3 + change_table :custom_forms_plugin_fields do |t|
  4 + t.string :select_field_type
  5 + end
  6 +
  7 + update("UPDATE custom_forms_plugin_fields SET select_field_type='radio' WHERE list IS FALSE AND multiple IS FALSE")
  8 + update("UPDATE custom_forms_plugin_fields SET select_field_type='check_box' WHERE list IS FALSE AND multiple IS TRUE")
  9 + update("UPDATE custom_forms_plugin_fields SET select_field_type='select' WHERE list IS TRUE AND multiple IS FALSE")
  10 + update("UPDATE custom_forms_plugin_fields SET select_field_type='multiple_select' WHERE list IS TRUE AND multiple IS TRUE")
  11 +
  12 + change_table :custom_forms_plugin_fields do |t|
  13 + t.remove :multiple, :list
  14 + end
  15 + end
  16 +
  17 + def self.down
  18 + change_table :custom_forms_plugin_fields do |t|
  19 + t.boolean :multiple
  20 + t.boolean :list
  21 + end
  22 +
  23 + update("UPDATE custom_forms_plugin_fields SET list=TRUE, multiple=FALSE WHERE select_field_type='radio'")
  24 + update("UPDATE custom_forms_plugin_fields SET list=FALSE, multiople=TRUE WHERE select_field_type='check_box'")
  25 + update("UPDATE custom_forms_plugin_fields SET list=TRUE, multiple=FALSE WHERE select_field_type='select'")
  26 + update("UPDATE custom_forms_plugin_fields SET list=TRUE, multiple=TRUE WHERE select_field_type='multiple_select'")
  27 +
  28 + change_table :custom_forms_plugin_fields do |t|
  29 + t.remove :select_fields_type
  30 + end
  31 + end
  32 +end
... ...
plugins/custom_forms/db/migrate/20130823151900_associate_fields_to_alternatives.rb 0 → 100644
... ... @@ -0,0 +1,37 @@
  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 + CustomFormsPlugin::Answer.find_each do |answer|
  18 + labels = []
  19 + answer.value.split(',').each do |value|
  20 + labels << answer.field.choices.invert[value]
  21 + end
  22 + labels.compact!
  23 + if labels.present?
  24 + answer.value = answer.field.alternatives.where('label IN (?)', labels).map(&:id).join(',')
  25 + answer.save!
  26 + end
  27 + end
  28 +
  29 + change_table :custom_forms_plugin_fields do |t|
  30 + t.remove :choices
  31 + end
  32 + end
  33 +
  34 + def self.down
  35 + raise ActiveRecord::IrreversibleMigration
  36 + end
  37 +end
... ...
plugins/custom_forms/db/migrate/20131002155900_update_select_field_type_in_custom_forms_plugin_fields.rb 0 → 100644
... ... @@ -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 @@
  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/db/migrate/20131107050913_add_position_to_field_and_alternatives.rb 0 → 100644
... ... @@ -0,0 +1,17 @@
  1 +class AddPositionToFieldAndAlternatives < ActiveRecord::Migration
  2 + def self.up
  3 + change_table :custom_forms_plugin_alternatives do |t|
  4 + t.integer :position, :default => 0
  5 + end
  6 +
  7 + update("UPDATE custom_forms_plugin_fields SET position=id")
  8 + update("UPDATE custom_forms_plugin_alternatives SET position=id")
  9 +
  10 + end
  11 +
  12 + def self.down
  13 + change_table :custom_forms_plugin_alternatives do |t|
  14 + t.remove :position
  15 + end
  16 + end
  17 +end
... ...
plugins/custom_forms/db/migrate/20131107125327_add_admission_to_form.rb 0 → 100644
... ... @@ -0,0 +1,18 @@
  1 +class AddAdmissionToForm < ActiveRecord::Migration
  2 + def self.up
  3 + change_table :custom_forms_plugin_forms do |t|
  4 + t.boolean :for_admission, :default => false
  5 + end
  6 +
  7 + CustomFormsPlugin::Form.find_each do |f|
  8 + f.for_admission = false
  9 + f.save!
  10 + end
  11 + end
  12 +
  13 + def self.down
  14 + change_table :custom_forms_plugin_forms do |t|
  15 + t.remove :for_admission
  16 + end
  17 + end
  18 +end
... ...
plugins/custom_forms/lib/custom_forms_plugin/admission_survey.rb 0 → 100644
... ... @@ -0,0 +1,24 @@
  1 +class CustomFormsPlugin::AdmissionSurvey < CustomFormsPlugin::MembershipSurvey
  2 +
  3 + def perform
  4 + super
  5 + requestor.add_member(target)
  6 + end
  7 +
  8 + def title
  9 + _("Admission survey")
  10 + end
  11 +
  12 + def information
  13 + {:message => _('%{requestor} wants you to fill in some information before joining.')}
  14 + end
  15 +
  16 + def target_notification_message
  17 + _('Before joining %{requestor}, the administrators of this organization
  18 + wants you to fill in some further information.') % {:requestor => requestor.name}
  19 + end
  20 +
  21 + def target_notification_description
  22 + _('%{requestor} wants you to fill in some further information.') % {:requestor => requestor.name}
  23 + end
  24 +end
... ...
plugins/custom_forms/lib/custom_forms_plugin/alternative.rb 0 → 100644
... ... @@ -0,0 +1,8 @@
  1 +class CustomFormsPlugin::Alternative < ActiveRecord::Base
  2 + set_table_name :custom_forms_plugin_alternatives
  3 +
  4 + validates_presence_of :label
  5 +
  6 + belongs_to :field, :class_name => 'CustomFormsPlugin::Field'
  7 +end
  8 +
... ...
plugins/custom_forms/lib/custom_forms_plugin/answer.rb
... ... @@ -7,8 +7,14 @@ class CustomFormsPlugin::Answer &lt; Noosfero::Plugin::ActiveRecord
7 7  
8 8 def value_mandatory
9 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 11 end
12 12 end
  13 +
  14 + def to_s
  15 + return value if value.blank? || field.alternatives.blank?
  16 + selected = value.split(',')
  17 + field.alternatives.select {|alt| selected.include? alt.id.to_s }.map(&:label).join(';')
  18 + end
13 19 end
14 20  
... ...
plugins/custom_forms/lib/custom_forms_plugin/field.rb
1 1 class CustomFormsPlugin::Field < ActiveRecord::Base
2 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 6 belongs_to :form, :class_name => 'CustomFormsPlugin::Form'
8 7 has_many :answers, :class_name => 'CustomFormsPlugin::Answer'
9 8  
10   - serialize :choices, Hash
  9 + has_many :alternatives, :order => 'position', :class_name => 'CustomFormsPlugin::Alternative'
  10 + accepts_nested_attributes_for :alternatives, :allow_destroy => true
  11 + #FIXME This validation should be in the subclass, but since we are using Single Table
  12 + # Inheritance we are instantiating a Field object with the type as a param. So the validation
  13 + # had to go here or rails would skip it.
  14 + validates_length_of :alternatives, :minimum => 1, :message => 'can\'t be empty', :if => Proc.new { |f| f.type == 'CustomFormsPlugin::SelectField' }
11 15  
12 16 before_validation do |field|
13 17 field.slug = field.name.to_slug if field.name.present?
14 18 end
15 19  
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
  20 + private
21 21  
22   - def position
23   - self[:position] || 0
  22 + def attributes_protected_by_default
  23 + super - [self.class.inheritance_column]
24 24 end
  25 +
25 26 end
26 27  
... ...
plugins/custom_forms/lib/custom_forms_plugin/form.rb
1 1 class CustomFormsPlugin::Form < Noosfero::Plugin::ActiveRecord
2 2 belongs_to :profile
3 3  
4   - has_many :fields, :class_name => 'CustomFormsPlugin::Field', :dependent => :destroy, :order => 'position'
  4 + has_many :fields, :order => 'position', :class_name => 'CustomFormsPlugin::Field', :dependent => :destroy
  5 + accepts_nested_attributes_for :fields, :allow_destroy => true
  6 +
5 7 has_many :submissions, :class_name => 'CustomFormsPlugin::Submission'
6 8  
7 9 serialize :access
8 10  
9 11 validates_presence_of :profile, :name
10 12 validates_uniqueness_of :slug, :scope => :profile_id
  13 + validate :period_range, :if => Proc.new { |f| f.begining.present? && f.ending.present? }
11 14 validate :access_format
12 15  
13 16 before_validation do |form|
... ... @@ -15,10 +18,16 @@ class CustomFormsPlugin::Form &lt; Noosfero::Plugin::ActiveRecord
15 18 form.access = nil if form.access.blank?
16 19 end
17 20  
  21 + after_destroy do |form|
  22 + tasks = CustomFormsPlugin::MembershipSurvey.from(form.profile).opened.select { |t| t.form_id == form.id }
  23 + tasks.each {|task| task.cancel}
  24 + end
  25 +
18 26 named_scope :from, lambda {|profile| {:conditions => {:profile_id => profile.id}}}
19   - named_scope :on_memberships, {:conditions => {:on_membership => true}}
  27 + named_scope :on_memberships, {:conditions => {:on_membership => true, :for_admission => false}}
  28 + named_scope :for_admissions, {:conditions => {:for_admission => true}}
20 29 =begin
21   - named_scope :accessible_to lambda do |profile|
  30 + named_scope :accessible_to lambda do |profile|
22 31 #TODO should verify is profile is associated with the form owner
23 32 profile_associated = ???
24 33 {:conditions => ["
... ... @@ -34,6 +43,10 @@ class CustomFormsPlugin::Form &lt; Noosfero::Plugin::ActiveRecord
34 43 (begining.present? && Time.now < begining) || (ending.present? && Time.now > ending)
35 44 end
36 45  
  46 + def will_open?
  47 + begining.present? && Time.now < begining
  48 + end
  49 +
37 50 def accessible_to(target)
38 51 return true if access.nil? || target == profile
39 52 return false if target.nil?
... ... @@ -58,7 +71,7 @@ class CustomFormsPlugin::Form &lt; Noosfero::Plugin::ActiveRecord
58 71 elsif access.kind_of?(Array)
59 72 access.each do |value|
60 73 if !value.kind_of?(Integer) || !Profile.exists?(value)
61   - errors.add(:access, _('There is no profile with the provided id.'))
  74 + errors.add(:access, _('There is no profile with the provided id.'))
62 75 break
63 76 end
64 77 end
... ... @@ -67,4 +80,8 @@ class CustomFormsPlugin::Form &lt; Noosfero::Plugin::ActiveRecord
67 80 end
68 81 end
69 82 end
  83 +
  84 + def period_range
  85 + errors.add(:base, _('The time range selected is invalid.')) if ending < begining
  86 + end
70 87 end
... ...
plugins/custom_forms/lib/custom_forms_plugin/helper.rb
1 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 9 def access_text(form)
3 10 return _('Public') if form.access.nil?
4 11 return _('Logged users') if form.access == 'logged'
5 12 if form.access == 'associated'
6   - return _('Members') if form.profile.organization?
  13 + return _('Members') if form.profile.organization?
7 14 return _('Friends') if form.profile.person?
8 15 end
9 16 return _('Custom')
... ... @@ -48,8 +55,8 @@ module CustomFormsPlugin::Helper
48 55  
49 56 def type_to_label(type)
50 57 map = {
51   - 'text_field' => _('Text'),
52   - 'select_field' => _('Select')
  58 + 'text_field' => _('Text field'),
  59 + 'select_field' => _('Select field')
53 60 }
54 61 map[type_for_options(type)]
55 62 end
... ... @@ -61,52 +68,61 @@ module CustomFormsPlugin::Helper
61 68 def display_custom_field(field, submission, form)
62 69 answer = submission.answers.select{|answer| answer.field == field}.first
63 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 72 required(labelled_form_field(field.name, field_tag))
66   - else
  73 + else
67 74 labelled_form_field(field.name, field_tag)
68 75 end
69 76 end
70 77  
  78 + def display_disabled?(field, answer)
  79 + (answer.present? && answer.id.present?) || field.form.expired?
  80 + end
  81 +
71 82 def display_text_field(field, answer, form)
72 83 value = answer.present? ? answer.value : field.default_value
73   - text_field(form, field.name.to_slug, :value => value, :disabled => answer.present?)
  84 + text_field(form, "#{field.id}", :value => value, :disabled => display_disabled?(field, answer))
  85 + end
  86 +
  87 + def default_selected(field, answer)
  88 + answer.present? ? answer.value.split(',') : field.alternatives.select {|a| a.selected_by_default}.map{|a| a.id.to_s}
74 89 end
75 90  
76 91 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?
  92 + case field.select_field_type
  93 + when 'select'
  94 + selected = default_selected(field, answer)
  95 + select_tag form.to_s + "[#{field.id}]", options_for_select([['','']] + field.alternatives.map {|a| [a.label, a.id.to_s]}, selected), :disabled => display_disabled?(field, answer)
  96 + when 'multiple_select'
  97 + selected = default_selected(field, answer)
  98 + select_tag form.to_s + "[#{field.id}]", options_for_select(field.alternatives.map{|a| [a.label, a.id.to_s]}, selected), :multiple => true, :title => _('Hold down Ctrl to select options'), :size => field.alternatives.size, :disabled => display_disabled?(field, answer)
  99 + when 'check_box'
  100 + field.alternatives.map do |alternative|
  101 + default = answer.present? ? answer.value.split(',').include?(alternative.id.to_s) : alternative.selected_by_default
  102 + labelled_check_box alternative.label, form.to_s + "[#{field.id}][#{alternative.id}]", '1', default, :disabled => display_disabled?(field, answer)
84 103 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?
  104 + when 'radio'
  105 + field.alternatives.map do |alternative|
  106 + default = answer.present? ? answer.value == alternative.id.to_s : alternative.selected_by_default
  107 + labelled_radio_button alternative.label, form.to_s + "[#{field.id}]", alternative.id, default, :disabled => display_disabled?(field, answer)
92 108 end.join("\n")
93 109 end
94 110 end
95 111  
96 112 def radio_button?(field)
97   - type_for_options(field.class) == 'select_field' && !field.list && !field.multiple
  113 + type_for_options(field.class) == 'select_field' && field.select_field_type == 'radio'
98 114 end
99 115  
100 116 def check_box?(field)
101   - type_for_options(field.class) == 'select_field' && !field.list && field.multiple
  117 + type_for_options(field.class) == 'select_field' && field.select_field_type == 'check_box'
102 118 end
103 119  
104 120 def build_answers(submission, form)
105 121 answers = []
106 122 form.fields.each do |field|
107 123 final_value = ''
108   - if submission.has_key?(field.slug)
109   - value = submission[field.slug]
  124 + if submission.has_key?(field.id.to_s)
  125 + value = submission[field.id.to_s]
110 126 if value.kind_of?(String)
111 127 final_value = value
112 128 elsif value.kind_of?(Array)
... ...
plugins/custom_forms/lib/custom_forms_plugin/membership_survey.rb
... ... @@ -5,11 +5,29 @@ class CustomFormsPlugin::MembershipSurvey &lt; Task
5 5  
6 6 include CustomFormsPlugin::Helper
7 7  
  8 + named_scope :from, lambda {|profile| {:conditions => {:requestor_id => profile.id}}}
  9 +
8 10 def perform
9 11 form = CustomFormsPlugin::Form.find(form_id)
  12 + raise 'Form expired' if form.expired?
  13 +
10 14 answers = build_answers(submission, form)
11 15 s = CustomFormsPlugin::Submission.create!(:form => form, :profile => target)
12   - answers.map {|answer| answer.submission = s; answer.save!}
  16 + s.answers.push(*answers)
  17 +
  18 + failed_answers = answers.select {|answer| !answer.valid? }
  19 + if failed_answers.empty?
  20 + s.save!
  21 + else
  22 + s.errors.clear
  23 + answers.each do |answer|
  24 + answer.valid?
  25 + answer.errors.each do |attribute, msg|
  26 + s.errors.add(answer.field.id.to_s.to_sym, msg)
  27 + end
  28 + end
  29 + raise ActiveRecord::RecordInvalid, s
  30 + end
13 31 end
14 32  
15 33 def title
... ...
plugins/custom_forms/lib/custom_forms_plugin/select_field.rb
1 1 class CustomFormsPlugin::SelectField < CustomFormsPlugin::Field
2 2 set_table_name :custom_forms_plugin_fields
3   - validates_presence_of :choices
  3 + validates_inclusion_of :select_field_type, :in => %w(radio check_box select multiple_select)
  4 + validates_length_of :alternatives, :minimum => 1, :message => 'can\'t be empty'
4 5 end
... ...
plugins/custom_forms/lib/custom_forms_plugin/submission.rb
... ... @@ -2,11 +2,20 @@ class CustomFormsPlugin::Submission &lt; Noosfero::Plugin::ActiveRecord
2 2 belongs_to :form, :class_name => 'CustomFormsPlugin::Form'
3 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 7 validates_presence_of :form
8 8 validates_presence_of :author_name, :author_email, :if => lambda {|submission| submission.profile.nil?}
9 9 validates_uniqueness_of :author_email, :scope => :form_id, :allow_nil => true
10 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 20 end
12 21  
... ...
plugins/custom_forms/lib/ext/role_assignment_trigger.rb
... ... @@ -13,7 +13,26 @@ module RoleAssignmentTrigger
13 13 end
14 14 end
15 15 end
16   -
  16 +
  17 + before_validation_on_create do |ra|
  18 + proceed_creation = true
  19 + if ra.resource.kind_of?(Profile)
  20 + profile = ra.resource
  21 + person = ra.accessor
  22 + ok = !profile.nil? && !person.nil? && profile.environment.present?
  23 + if ok && profile.environment.plugin_enabled?(CustomFormsPlugin) && !person.is_member_of?(profile)
  24 + CustomFormsPlugin::Form.from(profile).for_admissions.each do |form|
  25 + admission_task_pending = person.tasks.pending.select {|task| task.kind_of?(CustomFormsPlugin::AdmissionSurvey) && task.form_id == form.id }.present?
  26 + admission_task_finished = person.tasks.finished.select {|task| task.kind_of?(CustomFormsPlugin::AdmissionSurvey) && task.form_id == form.id }.present?
  27 +
  28 + CustomFormsPlugin::AdmissionSurvey.create!(:requestor => profile, :target => person, :form_id => form.id) unless admission_task_finished || admission_task_pending
  29 + proceed_creation = false unless admission_task_finished
  30 + end
  31 + end
  32 + end
  33 + proceed_creation
  34 + end
  35 +
17 36 after_destroy do |ra|
18 37 if ra.resource.kind_of?(Profile)
19 38 profile = ra.resource
... ... @@ -24,6 +43,10 @@ module RoleAssignmentTrigger
24 43 task = person.tasks.pending.select {|task| task.kind_of?(CustomFormsPlugin::MembershipSurvey) && task.form_id == form.id}.first
25 44 task.cancel if task
26 45 end
  46 + CustomFormsPlugin::Form.from(profile).for_admissions.each do |form|
  47 + task = person.tasks.pending.select {|task| task.kind_of?(CustomFormsPlugin::MembershipSurvey) && task.form_id == form.id}.first
  48 + task.cancel if task
  49 + end
27 50 end
28 51 end
29 52 end
... ...
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
12   - }
  1 +var fixHelperSortable = function(e, tr) {
  2 + tr.children().each(function() {
  3 + jQuery(this).width(jQuery(this).width());
13 4 });
14   - return false;
15   -});
  5 + return tr;
  6 +};
16 7  
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   -});
  8 +var updatePosition = function(e, ui) {
  9 + var tag = ui.item[0].tagName.toLowerCase();
  10 + var count = ui.item.prevAll(tag).eq(0).find('input').filter(function() {return /_position/.test(this.id); }).val();
  11 + count = count ? ++count : 0;
24 12  
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   -});
  13 + ui.item.find('input').filter(function() {return /_position/.test(this.id); }).eq(0).val(count);
35 14  
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));
  15 + for (i = 0; i < ui.item.nextAll(tag).length; i++) {
  16 + count++;
  17 + ui.item.nextAll(tag).eq(i).find('input').filter(function() {return /_position/.test(this.id); }).val(count);
  18 + }
45 19 }
46 20  
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   -}
  21 +jQuery('tbody.field-list').sortable({
  22 + helper: fixHelperSortable,
  23 + update: updatePosition
  24 +});
69 25  
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   -}
  26 +jQuery("ul.field-list").sortable({
  27 + placeholder: 'ui-state-highlight',
  28 + axis: 'y',
  29 + opacity: 0.8,
  30 + cursor: 'move',
  31 + tolerance: 'pointer',
  32 + forcePlaceholderSize: true,
  33 + update: updatePosition
  34 +});
92 35  
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);
  36 +jQuery("ul.field-list li").disableSelection();
100 37  
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');
  38 +var customFormsPlugin = {
  39 + removeFieldBox: function (button, confirmMsg) {
  40 + if (confirm(confirmMsg)) {
  41 + fb = jQuery(button).closest('.field-box');
  42 + jQuery('input.destroy-field', fb).val(1);
  43 + jQuery('> div', fb).slideUp({easing:'linear', complete:function(){fb.slideUp({easing:'linear', duration:250})}});
  44 + }
  45 + },
104 46  
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');
108   -}
  47 + removeAlternative: function (button, confirmMsg) {
  48 + if (confirm(confirmMsg)) {
  49 + alt = jQuery(button).closest('tr.alternative');
  50 + jQuery('input.destroy-field', alt).val(1);
  51 + alt.fadeOut(500, function() {
  52 + customFormsPlugin.checkHeaderDisplay(jQuery(button).closest('table'));
  53 + });
  54 + }
  55 + },
109 56  
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   -});
  57 + addFields: function (button, association, content) {
  58 + var new_id = new Date().getTime();
  59 + var regexp = new RegExp("new_" + association, "g");
  60 + content = content.replace(regexp, new_id);
123 61  
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   -});
  62 + if(association == 'alternatives') {
  63 + jQuery(content).appendTo(jQuery(button).closest('tfoot').next('tbody.field-list')).hide().slideDown();
  64 + jQuery(button).closest('table').find('tr:first').show();
  65 + jQuery(button).closest('tfoot').next('tbody.field-list').sortable({ helper: fixHelperSortable, update: updatePosition});
  66 + } else {
  67 + jQuery('<li>').append(jQuery(content)).appendTo(jQuery(button).parent().prev('ul.field-list')).hide().slideDown();
  68 + }
135 69  
136   -jQuery('.colorbox-ok-button').live('click', function(){
137   - jQuery('#'+jQuery(this).attr('div_id')).hide();
138   - jQuery.colorbox.close();
139   - return false
140   -});
  70 + jQuery('input').filter(function () { return new RegExp(new_id + "_position", "g").test(this.id); }).val(new_id);
  71 + },
  72 +
  73 + checkHeaderDisplay: function(table) {
  74 + trs =jQuery('tr:visible', table);
  75 + if (trs.length <= 2) {
  76 + trs[0].style.display = 'none';
  77 + } else {
  78 + trs[0].style.display = 'table-row';
  79 + }
  80 + }
  81 +}
... ...
plugins/custom_forms/public/style.css
... ... @@ -4,7 +4,7 @@
4 4 }
5 5  
6 6 .action-table {
7   - width: 100%;
  7 + width: 100%;
8 8 overflow: hidden;
9 9 }
10 10  
... ... @@ -13,12 +13,9 @@
13 13 text-align: center;
14 14 }
15 15  
16   -.action-table td{
17   - cursor: move;
18   -}
19   -
20 16 .action-table .actions{
21 17 white-space: nowrap;
  18 + text-align: left;
22 19 }
23 20  
24 21 .action-table .new-item{
... ... @@ -31,3 +28,62 @@
31 28 #colorbox .edit-information {
32 29 display: block;
33 30 }
  31 +
  32 +.field-box {
  33 + margin: 10px 0;
  34 +}
  35 +
  36 +.field-box > div {
  37 + overflow: hide;
  38 +}
  39 +
  40 +.field-box .button {
  41 + margin-left: 15px;
  42 +}
  43 +
  44 +.field-box .addition-buttons .button {
  45 + margin: 0px;
  46 +}
  47 +
  48 +.field-box .required-field label{
  49 + font-weight: bold;
  50 + color: #c00;
  51 +}
  52 +.field-box .required-field label:after {
  53 + content: ' (*)';
  54 +}
  55 +
  56 +.field-select-type {
  57 + margin: 10px 0;
  58 +}
  59 +
  60 +.field-text-default {
  61 + margin-top: 10px;
  62 +}
  63 +
  64 +.field-list {
  65 + list-style-type: none;
  66 + margin: 0px;
  67 + padding: 0px;
  68 + cursor: move;
  69 +}
  70 +
  71 +.field-list label, .field-list legend {
  72 + cursor: move;
  73 +}
  74 +
  75 +ul.field-list > li > fieldset:hover {
  76 + border: 2px dotted #BBB;
  77 +}
  78 +
  79 +tr.addition-buttons {
  80 + cursor: auto;
  81 +}
  82 +
  83 +#ui-datepicker-div {
  84 + border: 1px solid #CCC;
  85 +}
  86 +.ui-slider-horizontal {
  87 + border: 1px solid #BBB;
  88 + border-radius: 4px;
  89 +}
... ...
plugins/custom_forms/test/functional/custom_forms_plugin_myprofile_controller_test.rb
... ... @@ -48,21 +48,22 @@ class CustomFormsPluginMyprofileControllerTest &lt; ActionController::TestCase
48 48 :access => 'logged',
49 49 :begining => begining,
50 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 }
... ... @@ -75,32 +76,30 @@ class CustomFormsPluginMyprofileControllerTest &lt; ActionController::TestCase
75 76 assert_equal 'Cool form', form.description
76 77 assert_equal 2, form.fields.count
77 78  
78   - f1 = form.fields.first
79   - f2 = form.fields.last
  79 + f1 = form.fields[0]
  80 + f2 = form.fields[1]
80 81  
81 82 assert_equal 'Name', f1.name
82 83 assert_equal 'Jack', f1.default_value
83 84 assert f1.kind_of?(CustomFormsPlugin::TextField)
84 85  
85 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 89 assert f2.kind_of?(CustomFormsPlugin::SelectField)
91 90 end
92 91  
93   - should 'create fields in the order they are sent' do
  92 + should 'create fields in the order they are sent when no position defined' do
94 93 format = '%Y-%m-%d %H:%M'
95 94 num_fields = 10
96 95 begining = Time.now.strftime(format)
97 96 ending = (Time.now + 1.day).strftime(format)
98 97 fields = {}
99 98 num_fields.times do |i|
100   - fields[i.to_s] = {
101   - :name => i.to_s,
  99 + fields[i] = {
  100 + :name => (10-i).to_s,
102 101 :default_value => '',
103   - :type => 'text_field'
  102 + :type => 'CustomFormsPlugin::TextField'
104 103 }
105 104 end
106 105 assert_difference CustomFormsPlugin::Form, :count, 1 do
... ... @@ -110,29 +109,69 @@ class CustomFormsPluginMyprofileControllerTest &lt; ActionController::TestCase
110 109 :access => 'logged',
111 110 :begining => begining,
112 111 :ending => ending,
113   - :description => 'Cool form'},
114   - :fields => fields
  112 + :description => 'Cool form',
  113 + :fields_attributes => fields
  114 + }
115 115 end
116 116 form = CustomFormsPlugin::Form.find_by_name('My Form')
117 117 assert_equal num_fields, form.fields.count
118   - form.fields.find_each do |f|
119   - assert_equal f.position, f.name.to_i
  118 + lst = 10
  119 + form.fields.each do |f|
  120 + assert f.name.to_i == lst
  121 + lst = lst - 1
120 122 end
121 123 end
122 124  
  125 + should 'create fields in any position size' do
  126 + format = '%Y-%m-%d %H:%M'
  127 + begining = Time.now.strftime(format)
  128 + ending = (Time.now + 1.day).strftime(format)
  129 + fields = {}
  130 + fields['0'] = {
  131 + :name => '0',
  132 + :default_value => '',
  133 + :type => 'CustomFormsPlugin::TextField',
  134 + :position => '999999999999'
  135 + }
  136 + fields['1'] = {
  137 + :name => '1',
  138 + :default_value => '',
  139 + :type => 'CustomFormsPlugin::TextField',
  140 + :position => '1'
  141 + }
  142 + assert_difference CustomFormsPlugin::Form, :count, 1 do
  143 + post :create, :profile => profile.identifier,
  144 + :form => {
  145 + :name => 'My Form',
  146 + :access => 'logged',
  147 + :begining => begining,
  148 + :ending => ending,
  149 + :description => 'Cool form',
  150 + :fields_attributes => fields
  151 + }
  152 + end
  153 + form = CustomFormsPlugin::Form.find_by_name('My Form')
  154 + assert_equal 2, form.fields.count
  155 + assert form.fields.first.name == "1"
  156 + assert form.fields.last.name == "0"
  157 + end
  158 +
123 159 should 'edit a form' do
124 160 form = CustomFormsPlugin::Form.create!(:profile => profile, :name => 'Free Software')
125   - field = CustomFormsPlugin::TextField.create!(:form => form, :name => 'License')
126 161 format = '%Y-%m-%d %H:%M'
127 162 begining = Time.now.strftime(format)
128 163 ending = (Time.now + 1.day).strftime(format)
129 164  
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'}}
  165 + assert_equal form.fields.length, 0
  166 +
  167 + post :update, :profile => profile.identifier, :id => form.id,
  168 + :form => {:name => 'My Form', :access => 'logged', :begining => begining, :ending => ending, :description => 'Cool form',
  169 + :fields_attributes => {1 => {:name => 'Source'}}}
133 170  
134 171 form.reload
135   - field.reload
  172 + assert_equal form.fields.length, 1
  173 +
  174 + field = form.fields.last
136 175  
137 176 assert_equal 'logged', form.access
138 177 assert_equal begining, form.begining.strftime(format)
... ... @@ -149,5 +188,50 @@ class CustomFormsPluginMyprofileControllerTest &lt; ActionController::TestCase
149 188 assert_tag :tag => 'textarea', :attributes => { :id => 'form_description', :class => 'mceEditor' }
150 189 end
151 190  
152   -end
  191 + should 'export submissions as csv' do
  192 + form = CustomFormsPlugin::Form.create!(:profile => profile, :name => 'Free Software')
  193 + field = CustomFormsPlugin::TextField.create!(:name => "Title")
  194 + form.fields << field
153 195  
  196 + answer = CustomFormsPlugin::Answer.create!(:value => 'example', :field => field)
  197 +
  198 + sub1 = CustomFormsPlugin::Submission.create!(:author_name => "john", :author_email => 'john@example.com', :form => form)
  199 + sub1.answers << answer
  200 +
  201 + bob = create_user('bob').person
  202 + sub2 = CustomFormsPlugin::Submission.create!(:profile => bob, :form => form)
  203 +
  204 + get :submissions, :profile => profile.identifier, :id => form.id, :format => 'csv'
  205 + assert_equal @response.content_type, 'text/csv'
  206 + assert_equal @response.body.split("\n")[0], 'Timestamp,Name,Email,Title'
  207 + assert_equal @response.body.split("\n")[1], "#{sub1.updated_at.strftime('%Y/%m/%d %T %Z')},john,john@example.com,example"
  208 + assert_equal @response.body.split("\n")[2], "#{sub2.updated_at.strftime('%Y/%m/%d %T %Z')},bob,#{bob.email},\"\""
  209 + end
  210 +
  211 + should 'order submissions by name or time' do
  212 + form = CustomFormsPlugin::Form.create!(:profile => profile, :name => 'Free Software')
  213 + field = CustomFormsPlugin::TextField.create!(:name => "Title")
  214 + form.fields << field
  215 + sub1 = CustomFormsPlugin::Submission.create!(:author_name => "john", :author_email => 'john@example.com', :form => form)
  216 + bob = create_user('bob').person
  217 + sub2 = CustomFormsPlugin::Submission.create!(:profile => bob, :form => form)
  218 +
  219 + get :submissions, :profile => profile.identifier, :id => form.id, :sort_by => 'time'
  220 + assert_not_nil assigns(:sort_by)
  221 + assert_select 'table.action-table', /Author\W*Time\W*john[\W\dh]*bob[\W\dh]*/
  222 +
  223 + get :submissions, :profile => profile.identifier, :id => form.id, :sort_by => 'author'
  224 + assert_not_nil assigns(:sort_by)
  225 + assert_select 'table.action-table', /Author\W*Time\W*bob[\W\dh]*john[\W\dh]*/
  226 + end
  227 +
  228 + should 'list pending submissions for a form' do
  229 + person = fast_create(Person)
  230 + form = CustomFormsPlugin::Form.create!(:profile => profile, :name => 'Free Software', :for_admission => true)
  231 + task = CustomFormsPlugin::AdmissionSurvey.create!(:form_id => form.id, :target => person, :requestor => profile)
  232 +
  233 + get :pending, :profile => profile.identifier, :id => form.id
  234 +
  235 + assert_tag :td, :content => person.name
  236 + end
  237 +end
... ...
plugins/custom_forms/test/functional/custom_forms_plugin_profile_controller_test.rb
... ... @@ -23,9 +23,35 @@ class CustomFormsPluginProfileControllerTest &lt; ActionController::TestCase
23 23 field2 = CustomFormsPlugin::TextField.create(:name => 'License', :form => form)
24 24  
25 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 27 end
28 28 assert !session[:notice].include?('not saved')
29 29 assert_redirected_to :action => 'show'
30 30 end
  31 +
  32 + should 'disable fields if form expired' do
  33 + form = CustomFormsPlugin::Form.create!(:profile => profile, :name => 'Free Software', :begining => Time.now + 1.day)
  34 + form.fields << CustomFormsPlugin::TextField.create(:name => 'Field Name', :form => form, :default_value => "First Field")
  35 +
  36 + get :show, :profile => profile.identifier, :id => form.id
  37 +
  38 + assert_tag :tag => 'input', :attributes => {:disabled => 'disabled'}
  39 + end
  40 +
  41 + should 'show expired message' do
  42 + form = CustomFormsPlugin::Form.create!(:profile => profile, :name => 'Free Software', :begining => Time.now + 1.day)
  43 + form.fields << CustomFormsPlugin::TextField.create(:name => 'Field Name', :form => form, :default_value => "First Field")
  44 +
  45 + get :show, :profile => profile.identifier, :id => form.id
  46 +
  47 + assert_tag :tag => 'h2', :content => 'Sorry, you can\'t fill this form yet'
  48 +
  49 + form.begining = Time.now - 2.days
  50 + form.ending = Time.now - 1.days
  51 + form.save
  52 +
  53 + get :show, :profile => profile.identifier, :id => form.id
  54 +
  55 + assert_tag :tag => 'h2', :content => 'Sorry, you can\'t fill this form anymore'
  56 + end
31 57 end
... ...
plugins/custom_forms/test/unit/custom_forms_plugin/admission_survey_test.rb 0 → 100644
... ... @@ -0,0 +1,14 @@
  1 +require File.dirname(__FILE__) + '/../../../../../test/test_helper'
  2 +
  3 +class CustomFormsPlugin::AdmissionSurveyTest < ActiveSupport::TestCase
  4 + should 'add member to community on perform' do
  5 + profile = fast_create(Community)
  6 + person = fast_create(Person)
  7 + form = CustomFormsPlugin::Form.create!(:name => 'Simple Form', :profile => profile)
  8 + task = CustomFormsPlugin::AdmissionSurvey.create!(:form_id => form.id, :target => person, :requestor => profile)
  9 +
  10 + assert_difference person.memberships, :count, 1 do
  11 + task.finish
  12 + end
  13 + end
  14 +end
... ...
plugins/custom_forms/test/unit/custom_forms_plugin/answer_test.rb
... ... @@ -27,11 +27,24 @@ class CustomFormsPlugin::AnswerTest &lt; ActiveSupport::TestCase
27 27 field = CustomFormsPlugin::Field.create!(:name => 'License', :form => form, :mandatory => true)
28 28 answer = CustomFormsPlugin::Answer.new(:field => field)
29 29 answer.valid?
30   - assert answer.errors.invalid?(field.slug.to_sym)
  30 + assert answer.errors.invalid?(:value)
31 31  
32 32 answer.value = "GPL"
33 33 answer.valid?
34   - assert !answer.errors.invalid?(field.slug.to_sym)
  34 + assert !answer.errors.invalid?(:value)
  35 + end
  36 +
  37 + should 'make string representation show answers' do
  38 + form = CustomFormsPlugin::Form.create!(:name => 'Free Software', :profile => fast_create(Profile))
  39 + field = CustomFormsPlugin::Field.create!(:name => 'ProjectName', :form => form)
  40 + answer = CustomFormsPlugin::Answer.new(:field => field, :value => 'MyProject')
  41 +
  42 + field_select = CustomFormsPlugin::Field.create!(:name => 'License', :form => form)
  43 + alt = CustomFormsPlugin::Alternative.create!(:id => 1, :field => field_select, :label => 'GPL')
  44 + answer2 = CustomFormsPlugin::Answer.new(:field => field_select, :value => alt.id.to_s)
  45 +
  46 + assert_equal 'MyProject', answer.to_s
  47 + assert_equal 'GPL', answer2.to_s
35 48 end
36 49  
37 50 end
... ...
plugins/custom_forms/test/unit/custom_forms_plugin/field_test.rb
1 1 require File.dirname(__FILE__) + '/../../../../../test/test_helper'
2 2  
3 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 4 should 'set slug before validation based on name' do
19 5 field = CustomFormsPlugin::Field.new(:name => 'Name')
20 6 field.valid?
21 7 assert_equal field.name.to_slug, field.slug
22 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 10 should 'set mandatory field as false by default' do
39 11 field = CustomFormsPlugin::Field.new
40 12 assert !field.mandatory
... ... @@ -50,17 +22,6 @@ class CustomFormsPlugin::FieldTest &lt; ActiveSupport::TestCase
50 22 assert_includes field.answers, a2
51 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 25 should 'not destroy form after removing a field' do
65 26 form = CustomFormsPlugin::Form.create!(:name => 'Free Software', :profile => fast_create(Profile))
66 27 license_field = CustomFormsPlugin::Field.create!(:name => 'License', :form => form)
... ... @@ -72,26 +33,20 @@ class CustomFormsPlugin::FieldTest &lt; ActiveSupport::TestCase
72 33 assert_equal form.fields, [license_field]
73 34 end
74 35  
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
  36 + should 'have alternative if type is SelectField' do
  37 + select = CustomFormsPlugin::Field.new(:name => 'select_field001', :type => 'CustomFormsPlugin::SelectField')
  38 + assert !select.save
  39 +
  40 + select.alternatives << CustomFormsPlugin::Alternative.new(:label => 'option')
  41 + assert select.save
83 42 end
84 43  
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
  44 + should 'sort alternatives by position' do
  45 + field = CustomFormsPlugin::Field.create!(:name => 'field001')
  46 + second = CustomFormsPlugin::Alternative.create!(:label => 'second', :field => field, :position => 2)
  47 + first = CustomFormsPlugin::Alternative.create!(:label => 'first', :field => field, :position => 1)
90 48  
91   - assert_nothing_raised do
92   - field_1 = CustomFormsPlugin::Field.create!(:name => 'URL', :form => form)
93   - end
  49 + assert_equal field.alternatives, [first, second]
94 50 end
95   -
96 51 end
97 52  
... ...
plugins/custom_forms/test/unit/custom_forms_plugin/form_test.rb
... ... @@ -53,6 +53,20 @@ class CustomFormsPlugin::FormTest &lt; ActiveSupport::TestCase
53 53 assert !form.errors.invalid?(:slug)
54 54 end
55 55  
  56 + should 'validate the difference between ending and beginning is positive' do
  57 + profile = fast_create(Profile)
  58 + form = CustomFormsPlugin::Form.new(:profile => profile, :name => 'Free Software')
  59 +
  60 + form.begining = Time.now
  61 + form.ending = Time.now + 1.day
  62 + assert form.valid?
  63 + assert !form.errors.invalid?(:base)
  64 +
  65 + form.ending = Time.now - 2.day
  66 + assert !form.valid?
  67 + assert form.errors.invalid?(:base)
  68 + end
  69 +
56 70 should 'define form expiration' do
57 71 form = CustomFormsPlugin::Form.new
58 72 assert !form.expired?
... ... @@ -75,6 +89,22 @@ class CustomFormsPlugin::FormTest &lt; ActiveSupport::TestCase
75 89 assert !form.expired?
76 90 end
77 91  
  92 + should 'define if form will still open' do
  93 + form = CustomFormsPlugin::Form.new
  94 + assert !form.will_open?
  95 +
  96 + form.begining = Time.now + 1.day
  97 + assert form.will_open?
  98 +
  99 + form.begining = Time.now - 1.day
  100 + assert !form.will_open?
  101 +
  102 + form.begining = Time.now - 2.day
  103 + form.ending = Time.now - 1.day
  104 + assert form.expired?
  105 + assert !form.will_open?
  106 + end
  107 +
78 108 should 'validates format of access' do
79 109 form = CustomFormsPlugin::Form.new
80 110 form.valid?
... ... @@ -180,4 +210,54 @@ class CustomFormsPlugin::FormTest &lt; ActiveSupport::TestCase
180 210 end
181 211 end
182 212  
  213 + should 'sort fields by position' do
  214 + form = CustomFormsPlugin::Form.create!(:name => 'Free Software', :profile => fast_create(Profile))
  215 + license_field = CustomFormsPlugin::Field.create!(:name => 'License', :form => form, :position => 2)
  216 + url_field = CustomFormsPlugin::Field.create!(:name => 'URL', :form => form, :position => 0)
  217 +
  218 + assert_equal form.fields, [url_field, license_field]
  219 + end
  220 +
  221 + should 'have a named_scope that retrieves all forms required for membership' do
  222 + profile = fast_create(Profile)
  223 + f1 = CustomFormsPlugin::Form.create!(:name => 'For admission 1', :profile => profile, :for_admission => true)
  224 + f2 = CustomFormsPlugin::Form.create!(:name => 'For admission 2', :profile => profile, :for_admission => true)
  225 + f3 = CustomFormsPlugin::Form.create!(:name => 'Not for admission', :profile => profile, :for_admission => false)
  226 + scope = CustomFormsPlugin::Form.from(profile).for_admissions
  227 +
  228 + assert_equal ActiveRecord::NamedScope::Scope, scope.class
  229 + assert_includes scope, f1
  230 + assert_includes scope, f2
  231 + assert_not_includes scope, f3
  232 + end
  233 +
  234 + should 'not include admission membership in on membership named scope' do
  235 + profile = fast_create(Profile)
  236 + f1 = CustomFormsPlugin::Form.create!(:name => 'On membership', :profile => profile, :on_membership => true)
  237 + f2 = CustomFormsPlugin::Form.create!(:name => 'For admission', :profile => profile, :on_membership => true, :for_admission => true)
  238 + scope = CustomFormsPlugin::Form.from(profile).on_memberships
  239 +
  240 + assert_equal ActiveRecord::NamedScope::Scope, scope.class
  241 + assert_includes scope, f1
  242 + assert_not_includes scope, f2
  243 + end
  244 +
  245 + should 'cancel survey tasks after removing a form' do
  246 + profile = fast_create(Profile)
  247 + person = fast_create(Person)
  248 +
  249 + form1 = CustomFormsPlugin::Form.create!(:name => 'Free Software', :profile => profile)
  250 + form2 = CustomFormsPlugin::Form.create!(:name => 'Operation System', :profile => profile)
  251 +
  252 + task1 = CustomFormsPlugin::MembershipSurvey.create!(:form_id => form1.id, :target => person, :requestor => profile)
  253 + task2 = CustomFormsPlugin::MembershipSurvey.create!(:form_id => form2.id, :target => person, :requestor => profile)
  254 +
  255 + assert_includes Task.opened, task1
  256 + assert_includes Task.opened, task2
  257 + form1.destroy
  258 + assert_includes Task.canceled, task1
  259 + assert_includes Task.opened, task2
  260 + form2.destroy
  261 + assert_includes Task.canceled, task2
  262 + end
183 263 end
... ...
plugins/custom_forms/test/unit/custom_forms_plugin/membership_survey_test.rb
... ... @@ -16,16 +16,29 @@ class CustomFormsPlugin::MembershipSurveyTest &lt; ActiveSupport::TestCase
16 16 person = fast_create(Person)
17 17 form = CustomFormsPlugin::Form.create!(:name => 'Simple Form', :profile => profile)
18 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 21 assert_difference CustomFormsPlugin::Submission, :count, 1 do
22 22 task.finish
23 23 end
24 24  
25 25 submission = CustomFormsPlugin::Submission.last
26   - assert_equal submission.answers.count, 1
  26 + assert_equal submission.answers.count, 1
27 27  
28 28 answer = submission.answers.first
29 29 assert_equal answer.value, 'Jack'
30 30 end
  31 +
  32 + should 'have a named_scope that retrieves all tasks requested by profile' do
  33 + profile = fast_create(Profile)
  34 + person = fast_create(Person)
  35 + form = CustomFormsPlugin::Form.create!(:name => 'Simple Form', :profile => profile)
  36 + task1 = CustomFormsPlugin::MembershipSurvey.create!(:form_id => form.id, :target => person, :requestor => profile)
  37 + task2 = CustomFormsPlugin::MembershipSurvey.create!(:form_id => form.id, :target => person, :requestor => fast_create(Profile))
  38 + scope = CustomFormsPlugin::MembershipSurvey.from(profile)
  39 +
  40 + assert_equal ActiveRecord::NamedScope::Scope, scope.class
  41 + assert_includes scope, task1
  42 + assert_not_includes scope, task2
  43 + end
31 44 end
... ...
plugins/custom_forms/test/unit/custom_forms_plugin/select_field_test.rb
1 1 require File.dirname(__FILE__) + '/../../../../../test/test_helper'
2 2  
3 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)
8   -
9   - select.choices = {'label' => 'value'}
10   - select.valid?
11   - assert !select.errors.invalid?(:choices)
  4 + should 'have alternative' do
  5 + select = CustomFormsPlugin::SelectField.new(:name => 'select_field001' )
  6 + assert !select.save
  7 +
  8 + select.alternatives << CustomFormsPlugin::Alternative.new(:label => 'option')
  9 + assert select.save
  10 + end
  11 +
  12 + should 'validate type' do
  13 + select = CustomFormsPlugin::SelectField.new(:name => 'select_field001' )
  14 + select.alternatives << CustomFormsPlugin::Alternative.new(:label => 'option')
  15 +
  16 + select.update_attribute(:select_field_type, 'random')
  17 + assert select.invalid?
  18 +
  19 + select.update_attribute(:select_field_type, 'radio')
  20 + assert select.valid?
  21 + select.update_attribute(:select_field_type, 'check_box')
  22 + assert select.valid?
  23 + select.update_attribute(:select_field_type, 'select')
  24 + assert select.valid?
  25 + select.update_attribute(:select_field_type, 'multiple_select')
  26 + assert select.valid?
12 27 end
13 28 end
... ...
plugins/custom_forms/test/unit/ext/role_assingment_test.rb
... ... @@ -27,25 +27,46 @@ class RoleAssignmentsTest &lt; ActiveSupport::TestCase
27 27 end
28 28 end
29 29  
30   - should 'cancel membership_surveys if membership is undone and task is active' do
  30 + should 'cancel surveys if membership is undone and task is active' do
31 31 environment = Environment.default
32 32 environment.enable_plugin(CustomFormsPlugin)
33 33 organization = fast_create(Organization)
34 34 person = fast_create(Person)
35   - form = CustomFormsPlugin::Form.create!(:profile => organization, :name => 'Form', :on_membership => true)
  35 + form1 = CustomFormsPlugin::Form.create!(:profile => organization, :name => 'Form 1', :on_membership => true)
36 36 organization.add_member(person)
37 37  
38 38 assert_difference CustomFormsPlugin::MembershipSurvey.pending, :count, -1 do
39 39 organization.remove_member(person)
40 40 end
41 41  
  42 + form2 = CustomFormsPlugin::Form.create!(:profile => organization, :name => 'Form 2', :for_admission => true)
42 43 organization.add_member(person)
43   - task = CustomFormsPlugin::MembershipSurvey.last
44   - task.status = Task::Status::FINISHED
45   - task.save!
  44 +
  45 + assert_difference CustomFormsPlugin::AdmissionSurvey.pending, :count, -1 do
  46 + organization.remove_member(person)
  47 + end
  48 +
  49 + organization.add_member(person)
  50 + tasks = CustomFormsPlugin::MembershipSurvey.all.last(2)
  51 + tasks.each {|t| t.status = Task::Status::FINISHED }
  52 + tasks.each {|t| t.save! }
46 53 assert_no_difference CustomFormsPlugin::MembershipSurvey.finished, :count do
47 54 organization.remove_member(person)
48 55 end
49 56 end
50   -end
51 57  
  58 + should 'create admission survey when atempted membership' do
  59 + environment = Environment.default
  60 + environment.enable_plugin(CustomFormsPlugin)
  61 + organization = fast_create(Organization)
  62 + person = fast_create(Person)
  63 + f1 = CustomFormsPlugin::Form.create!(:profile => organization, :name => 'Form 1', :for_admission => true)
  64 + f2 = CustomFormsPlugin::Form.create!(:profile => organization, :name => 'Form 2', :for_admission => true)
  65 + f3 = CustomFormsPlugin::Form.create!(:profile => organization, :name => 'Form 3', :for_admission => false)
  66 +
  67 + assert_difference CustomFormsPlugin::AdmissionSurvey, :count, 2 do
  68 + organization.add_member(person)
  69 + end
  70 + assert !organization.members.include?(person)
  71 + end
  72 +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 2 <h2><%= _('Options') %></h2>
4 3 <table class='action-table' style='width: 420px'>
5 4 <tr>
6 5 <th style='width: 40%'><%= _('Name') %></th>
7 6 <th style='width: 40%'><%= _('Value') %></th>
8   - <th style='width: 20%'><%= _('Actions') %></th>
  7 + <th style='width: 20%'><%= _('Delete') %></th>
9 8 </tr>
10 9 <% option_counter = 1 %>
11 10 <% (field.choices || {}).each do |name, value| %>
... ...
plugins/custom_forms/views/custom_forms_plugin_myprofile/_edit_text.html.erb
... ... @@ -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 + <%= required f.label :name, _('Name:') %>
  5 + <%= f.text_field :name, :style => 'width: 14em' %>
  6 +
  7 + <%= f.hidden_field :type %>
  8 +
  9 + <%= f.check_box :mandatory %>
  10 + <%= f.label :mandatory, _('Mandatory') %>
  11 +
  12 + <%= f.hidden_field(:position) %>
  13 +
  14 + <%= f.hidden_field :_destroy, :class => 'destroy-field' %>
  15 + <%= button_to_function :delete, _('Remove field'), "customFormsPlugin.removeFieldBox(this, #{_('Are you sure you want to remove this field?').to_json})" %>
  16 + <%= yield %>
  17 +</div>
  18 +</fieldset>
... ...
plugins/custom_forms/views/custom_forms_plugin_myprofile/_form.html.erb
1 1 <% self.extend(CustomFormsPlugin::Helper) %>
2 2 <%= render :file => 'shared/tiny_mce', :locals => {:mode => 'simple'} %>
3 3  
4   -<%= error_messages_for :form %>
5   -
6   -<% form_for :form, @form do |f| %>
7   - <%= required labelled_form_field _('Name'), f.text_field(:name) %>
8   - <%= labelled_form_field(_('Period'), (
9   - date_range_field('form[begining]', 'form[ending]', @form.begining, @form.ending,
10   - '%Y-%m-%d %H:%M',
11   - { :time => true, :change_month => true, :change_year => true,
12   - :date_format => 'yy-mm-dd', :time_format => 'hh:mm' },
  4 +<%= f.error_messages %>
  5 +<%= required labelled_form_field _('Name'), f.text_field(:name) %>
  6 +<%= labelled_form_field(_('What is the time limit for this form to be filled?'), (
  7 + date_range_field('form[begining]', 'form[ending]', @form.begining, @form.ending,
  8 + '%Y-%m-%d %H:%M',
  9 + { :time => true, :change_month => true, :change_year => true,
  10 + :date_format => 'yy-mm-dd', :time_format => 'hh:mm' },
13 11 { :size => 14 })
14   - )) %>
15   - <%= labelled_form_field _('Access'), f.select(:access, access_options(profile))%>
16   - <% if profile.organization? %>
17   - <%= labelled_form_field _('Triggered on membership'), f.check_box(:on_membership) %>
18   - <% end %>
19   - <%= labelled_form_field _('Description'), f.text_area(:description, :style => 'width: 100%', :class => 'mceEditor') %>
  12 +)) %>
  13 +<%= labelled_form_field _('Access'), f.select(:access, access_options(profile))%>
  14 +<% if profile.organization? %>
  15 + <p>
  16 + <%= labelled_check_box _('Triggered on membership request as requirement for approval'), 'form[for_admission]', '1', @form.for_admission %>
  17 + <br/>
  18 + <%= labelled_check_box _('Triggered after membership'), 'form[on_membership]', '1', @form.on_membership %>
  19 + </p>
  20 +<% end %>
  21 +<%= labelled_form_field _('Description'), f.text_area(:description, :style => 'width: 100%', :class => 'mceEditor') %>
20 22  
21   - <h2><%= _('Fields') %></h2>
22   - <table class="action-table" id='fields-table'>
23   - <tr>
24   - <th style='width: 40%'><%= _('Name') %></th>
25   - <th style='width: 30%'><%= _('Type') %></th>
26   - <th style='width: 10%'><%= _('Mandatory') %></th>
27   - <th style='width: 20%'><%= _('Actions') %></th>
28   - </tr>
29   - <% counter = 1 %>
30   - <% @fields.each do |field| %>
31   - <%= render :partial => 'field', :locals => {:field => field, :counter => counter} %>
32   - <% counter += 1 %>
33   - <% end %>
34   - <%= render :partial => 'empty_field', :locals => {:field => @empty_field, :counter => counter} %>
35   - <tr class='new-item'>
36   - <td colspan='5'>
37   - <%= button(:add, _('Add a new field'), '#', :id => 'new-field')%>
38   - </td>
39   - </tr>
40   - </table>
  23 +<h2><%= _('Fields') %></h2>
41 24  
42   - <% counter = 1 %>
43   - <% @fields.each do |field| %>
44   - <%= render :partial => 'edit_text', :locals => {:field => field, :counter => counter} %>
45   - <%= render :partial => 'edit_select', :locals => {:field => field, :counter => counter} %>
46   - <% counter += 1 %>
  25 +<ul class='field-list'>
  26 + <% f.fields_for :fields do |builder| %>
  27 + <li>
  28 + <%= render partial_for_class(builder.object.class), :f => builder %>
  29 + </li>
47 30 <% end %>
  31 +</ul>
48 32  
49   - <%= render :partial => 'edit_text', :locals => {:field => @empty_field, :counter => counter} %>
50   - <%= render :partial => 'edit_select', :locals => {:field => @empty_field, :counter => counter} %>
  33 +<div class="addition-buttons">
  34 + <%= button(:add, _('Add a new text field'), '#', :onclick => "customFormsPlugin.addFields(this, 'fields', #{html_for_field(f, :fields, CustomFormsPlugin::TextField).to_json}); return false")%>
  35 + <%= button(:add, _('Add a new select field'), '#', :onclick => "customFormsPlugin.addFields(this, 'fields', #{html_for_field(f, :fields, CustomFormsPlugin::SelectField).to_json}); return false")%>
  36 +</div>
51 37  
52   - <% button_bar do %>
53   - <%= submit_button :save, _('Save'), :cancel => {:action => 'index'}%>
54   - <% end %>
  38 +<% button_bar do %>
  39 + <%= submit_button :save, _('Save'), :cancel => {:action => 'index'}%>
55 40 <% end %>
56 41  
57 42 <%= javascript_include_tag '../plugins/custom_forms/field' %>
... ...
plugins/custom_forms/views/custom_forms_plugin_myprofile/_option.html.erb
... ... @@ -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
... ... @@ -1,2 +0,0 @@
1   -<h1><%= _('New form') %></h1>
2   -<%= render :partial => 'form' %>
plugins/custom_forms/views/custom_forms_plugin_myprofile/custom_forms_plugin/_alternative.html.erb 0 → 100644
... ... @@ -0,0 +1,12 @@
  1 +<tr class="alternative">
  2 + <td> <%= f.text_field(:label) %> </td>
  3 +
  4 + <td> <%= f.check_box(:selected_by_default) %> </td>
  5 +
  6 + <%= f.hidden_field(:position) %>
  7 +
  8 + <td>
  9 + <%= f.hidden_field :_destroy, :class => 'destroy-field' %>
  10 + <%= 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') %>
  11 + </td>
  12 +</tr>
... ...
plugins/custom_forms/views/custom_forms_plugin_myprofile/custom_forms_plugin/_field.html.erb 0 → 100644
... ... @@ -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,36 @@
  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 + <thead>
  16 + <tr <%='style="display:none"' if f.object.alternatives.empty? %>>
  17 + <th><%= _('Alternative') %></th>
  18 + <th><%= _('Preselected') %></th>
  19 + <th><%= _('Remove') %></th>
  20 + </tr>
  21 + </thead>
  22 + <tfoot>
  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 + </tfoot>
  29 + <tbody class='field-list'>
  30 + <% f.fields_for :alternatives do |builder| %>
  31 + <%= render partial_for_class(builder.object.class), :f => builder %>
  32 + <% end %>
  33 + </tbody>
  34 + </table>
  35 +
  36 +<% end %>
... ...
plugins/custom_forms/views/custom_forms_plugin_myprofile/custom_forms_plugin/_text_field.html.erb 0 → 100644
... ... @@ -0,0 +1,6 @@
  1 +<% render :layout => 'field', :locals => { :f => f } do %>
  2 + <div class="field-text-default">
  3 + <%= f.label(:default_value, _('Default text:')) %>
  4 + <%= f.text_field(:default_value) %>
  5 + </div>
  6 +<% end %>
... ...
plugins/custom_forms/views/custom_forms_plugin_myprofile/edit.html.erb
1 1 <h1><%= _('Edit form') %></h1>
2   -<%= render :partial => 'form' %>
  2 +
  3 +<% form_for :form, @form, :url => { :action => 'update', :id => params[:id] } do |f| %>
  4 + <%= render :partial => 'form', :locals => {:f => f} %>
  5 +<% end %>
... ...
plugins/custom_forms/views/custom_forms_plugin_myprofile/index.html.erb
... ... @@ -17,12 +17,14 @@
17 17 <td><%= access_text(form) %></td>
18 18 <td class="actions">
19 19 <%= button_without_text :edit, _('Edit'), :action => 'edit', :id => form.id %>
20   - <%= button_without_text :remove, _('Remove'), {:action => 'remove', :id => form.id}, :confirm => _('Are you sure you want to remove this form?') %></td>
  20 + <%= button_without_text :search, _('Pending'), :action => 'pending', :id => form.id if form.for_admission %>
  21 + <%= button_without_text :remove, _('Remove'), {:action => 'remove', :id => form.id}, :confirm => _('Are you sure you want to remove this form?') %>
  22 + </td>
21 23 </tr>
22 24 <% end %>
23 25 <tr id="new-item">
24 26 <td colspan='5'>
25   - <%= button(:add, _('Add a new form'), :action => 'create')%>
  27 + <%= button(:add, _('Add a new form'), :action => 'new')%>
26 28 </td>
27 29 </tr>
28 30 </table>
... ...
plugins/custom_forms/views/custom_forms_plugin_myprofile/new.html.erb 0 → 100644
... ... @@ -0,0 +1,5 @@
  1 +<h1><%= _('New form') %></h1>
  2 +
  3 +<% form_for :form, @form, :url => { :action => 'create', :id => params[:id] } do |f| %>
  4 + <%= render :partial => 'form', :locals => {:f => f} %>
  5 +<% end %>
... ...
plugins/custom_forms/views/custom_forms_plugin_myprofile/pending.html.erb 0 → 100644
... ... @@ -0,0 +1,27 @@
  1 +<% self.extend CustomFormsPlugin::Helper %>
  2 +
  3 +<h1><%= _('Pending submissions for %s') % @form.name %></h1>
  4 +
  5 +<% if @pendings.empty? %>
  6 + <%= _('There are no pending submissions for this form.') %>
  7 +<% else %>
  8 + <p>
  9 + <%= labelled_select(_('Sort by')+': ', :sort_by, :first, :last, @sort_by, [['time', _('Time')], ['user', _('User')]], :onchange => 'document.location.href = "?sort_by="+this.value') %>
  10 + </p>
  11 + <table class="action-table">
  12 + <tr>
  13 + <th style='width: 50%'><%= _('User') %></th>
  14 + <th style='width: 50%'><%= _('Time') %></th>
  15 + </tr>
  16 + <% @pendings.each do |pending| %>
  17 + <tr>
  18 + <td><%= link_to(pending[:profile].name, {:controller => :profile, :profile => pending[:profile].identifier}) %></td>
  19 + <td><%= time_format(pending[:time]) %></td>
  20 + </tr>
  21 + <% end %>
  22 + </table>
  23 +<% end %>
  24 +
  25 +<% button_bar do %>
  26 + <%= button :back, _('Back to forms'), :action => 'index' %>
  27 +<% end %>
... ...
plugins/custom_forms/views/custom_forms_plugin_myprofile/submissions.html.erb
... ... @@ -5,6 +5,13 @@
5 5 <% if @form.submissions.empty? %>
6 6 <%= _('There are no submissions for this form.') %>
7 7 <% else %>
  8 + <p>
  9 + <%= _('Download all form responses as') %>:
  10 + <%= link_to '[CSV]', :format => 'csv' %>
  11 + </p>
  12 + <p>
  13 + <%= labelled_select(_('Sort by')+': ', :sort_by, :first, :last, @sort_by, [['time', _('Time')], ['author', _('Author')]], :onchange => 'document.location.href = "?sort_by="+this.value') %>
  14 + </p>
8 15 <table class="action-table">
9 16 <tr>
10 17 <th style='width: 50%'><%= _('Author') %></th>
... ...
plugins/custom_forms/views/custom_forms_plugin_profile/show.html.erb
... ... @@ -2,6 +2,14 @@
2 2 <p><%= @form.description %></p>
3 3  
4 4 <% if @submission.id.nil? %>
  5 + <% if @form.expired? %>
  6 + <% if @form.will_open? %>
  7 + <h2><%= _('Sorry, you can\'t fill this form yet') %></h2>
  8 + <% else %>
  9 + <h2><%= _('Sorry, you can\'t fill this form anymore') %></h2>
  10 + <% end %>
  11 + <% end %>
  12 +
5 13 <%= error_messages_for :submission %>
6 14  
7 15 <% form_for :submission, @submission do |f| %>
... ... @@ -13,8 +21,13 @@
13 21 <%= render :partial => 'shared/form_submission', :locals => {:f => f} %>
14 22  
15 23 <% button_bar do %>
16   - <%= submit_button :save, _('Save'), :cancel => {:controller=>:profile, :profile => profile.identifier} %>
  24 + <% if @form.expired? %>
  25 + <%= submit_button :save, _('Save'), :disabled => '', :class => 'disabled', :cancel => {:controller => :profile, :profile => profile.identifier} %>
  26 + <% else %>
  27 + <%= submit_button :save, _('Save'), :cancel => {:controller => :profile, :profile => profile.identifier} %>
  28 + <% end %>
17 29 <% end %>
  30 +
18 31 <% end %>
19 32 <% else %>
20 33 <% fields_for :submission, @submission do |f| %>
... ...
plugins/custom_forms/views/tasks/custom_forms_plugin/_membership_survey_accept_details.html.erb
... ... @@ -3,8 +3,14 @@
3 3  
4 4 <h2><%= @form.name %></h2>
5 5 <p><%= @form.description %></p>
  6 +<% if @form.expired? %>
  7 + <% if @form.will_open? %>
  8 + <h3><%= _('Sorry, you can\'t fill this form yet') %></h3>
  9 + <% else %>
  10 + <h3><%= _('Sorry, you can\'t fill this form anymore') %></h3>
  11 + <% end %>
  12 +<% end %>
6 13  
7 14 <% f.fields_for :submission do |fi| %>
8   - <%#= fi.error_messages_for :submission %>
9 15 <%= render :partial => 'shared/form_submission', :locals => {:f => fi} %>
10 16 <% end %>
... ...
po/pt/noosfero.po
... ... @@ -10441,6 +10441,18 @@ msgstr &quot;Bloco salvo com sucesso.&quot;
10441 10441 msgid "Sub-organizations updated"
10442 10442 msgstr "Sub-organizações atualizadas"
10443 10443  
  10444 +#: plugins/custom_forms/controllers/custom_forms_plugin_myprofile_controller.rb:26
  10445 +msgid "Custom form #{@form.name} was successfully created."
  10446 +msgstr "O formulário #{@form.name} foi criado com sucesso."
  10447 +
  10448 +#: plugins/custom_forms/controllers/custom_forms_plugin_myprofile_controller.rb:46
  10449 +msgid "Custom form #{@form.name} was successfully updated."
  10450 +msgstr "O formulário #{@form.name} foi atualizado com sucesso."
  10451 +
  10452 +#: plugins/tolerance_time/controllers/tolerance_time_plugin_myprofile_controller.rb:10
  10453 +msgid "Tolerance updated"
  10454 +msgstr "A tolerância foi atualizada"
  10455 +
10444 10456 #: plugins/sub_organizations/controllers/sub_organizations_plugin_myprofile_controller.rb:28
10445 10457 msgid "Sub-organizations could not be updated"
10446 10458 msgstr "As sub-organizações não puderam ser salvas"
... ... @@ -11087,6 +11099,15 @@ msgstr &quot;%s artigos encontrados&quot;
11087 11099 msgid "%s events found"
11088 11100 msgstr "%s eventos encontrados"
11089 11101  
  11102 +#: plugins/custom_forms/lib/custom_forms_plugin/helper.rb:87
  11103 +msgid "Hold down Ctrl to select options"
  11104 +msgstr "Segure Ctrl para selecionar as opções"
  11105 +
  11106 +#: plugins/custom_forms/lib/custom_forms_plugin/helper.rb:4
  11107 +#: plugins/custom_forms/lib/custom_forms_plugin/helper.rb:37
  11108 +msgid "Logged users"
  11109 +msgstr "Usuários logados"
  11110 +
11090 11111 #: plugins/solr/lib/solr_plugin/search_helper.rb:138
11091 11112 msgid "%s people found"
11092 11113 msgstr "%s pessoas encontradas"
... ... @@ -11119,6 +11140,47 @@ msgstr &quot;Um plugin que mostra grupos de comentários.&quot;
11119 11140 msgid "A plugin that add a container block."
11120 11141 msgstr "Um plugin que adiciona um bloco container."
11121 11142  
  11143 +#: plugins/custom_forms/lib/custom_forms_plugin/helper.rb:58
  11144 +msgid "Text field"
  11145 +msgstr "Campo de texto"
  11146 +
  11147 +#: plugins/custom_forms/lib/custom_forms_plugin/helper.rb:59
  11148 +msgid "Select field"
  11149 +msgstr "Campo de seleção"
  11150 +
  11151 +#: plugins/custom_forms/lib/custom_forms_plugin/membership_survey.rb:16
  11152 +msgid "Membership survey"
  11153 +msgstr "Pesquisa na associação de novos integrantes"
  11154 +
  11155 +#: plugins/custom_forms/lib/custom_forms_plugin/admission_survey.rb:9
  11156 +msgid "Admission survey"
  11157 +msgstr "Questionário para associação"
  11158 +
  11159 +#: plugins/custom_forms/lib/custom_forms_plugin/admission_survey.rb:13
  11160 +msgid "%{requestor} wants you to fill in some information before joining."
  11161 +msgstr "%{requestor} quer que você preencha algumas informações antes de se associar."
  11162 +
  11163 +#: plugins/custom_forms/lib/custom_forms_plugin/membership_survey.rb:28
  11164 +msgid "%{requestor} wants you to fill in some information."
  11165 +msgstr "%{requestor} quer que você preencha algumas informações."
  11166 +
  11167 +#: plugins/custom_forms/lib/custom_forms_plugin/admission_survey.rb:17
  11168 +msgid ""
  11169 +"Before joining %{requestor}, the administrators of this organization\n"
  11170 +" wants you to fill in some further information."
  11171 +msgstr ""
  11172 +"Antes de entrar em %{requestor}, os administradores dessa organização\n"
  11173 +" querem que você preencha algumas informações adicionais."
  11174 +
  11175 +#: plugins/custom_forms/lib/custom_forms_plugin/membership_survey.rb:40
  11176 +msgid ""
  11177 +"After joining %{requestor}, the administrators of this organization\n"
  11178 +" wants you to fill in some further information."
  11179 +msgstr ""
  11180 +"Após entrar em %{requestor}, os administradores dessa organização\n"
  11181 +" querem que você preencha algumas informações adicionais."
  11182 +>>>>>>> custom_forms
  11183 +
11122 11184 #: plugins/container_block/lib/container_block_plugin/container_block.rb:11
11123 11185 msgid "Container"
11124 11186 msgstr "Container"
... ... @@ -12106,6 +12168,39 @@ msgstr &quot;Horas&quot;
12106 12168 msgid "Content edition tolerance time"
12107 12169 msgstr "Tempo de tolerância para edição de conteúdo"
12108 12170  
  12171 +#: plugins/custom_forms/views/custom_forms_plugin_profile/show.html.erb:7
  12172 +msgid "Sorry, you can't fill this form yet"
  12173 +msgstr "Desculpe, você não pode preencher esse formulário ainda"
  12174 +
  12175 +#: plugins/custom_forms/views/custom_forms_plugin_profile/show.html.erb:9
  12176 +msgid "Sorry, you can't fill this form anymore"
  12177 +msgstr "Desculpe, você não pode mais preencher esse formulário"
  12178 +
  12179 +#: plugins/custom_forms/views/custom_forms_plugin_myprofile/_empty_field.html.erb:8
  12180 +#: plugins/custom_forms/views/custom_forms_plugin_myprofile/_field.html.erb:10
  12181 +msgid "Are you sure you want to remove this field?"
  12182 +msgstr "Tem certeza de que deseja remover este campo?"
  12183 +
  12184 +#: plugins/custom_forms/views/custom_forms_plugin_myprofile/_field.html.erb:3
  12185 +msgid "Remove field"
  12186 +msgstr "Remover campo"
  12187 +
  12188 +#: plugins/custom_forms/views/custom_forms_plugin_myprofile/index.html.erb:3
  12189 +msgid "Manage forms"
  12190 +msgstr "Gerenciar formulários"
  12191 +
  12192 +#: plugins/custom_forms/views/custom_forms_plugin_myprofile/index.html.erb:7
  12193 +msgid "Period"
  12194 +msgstr "Período"
  12195 +
  12196 +#: plugins/custom_forms/views/custom_forms_plugin_myprofile/_form.html.erb:7
  12197 +msgid "What is the time limit for this form to be filled?"
  12198 +msgstr "Qual o período limite em que esse formulário pode ser preenchido?"
  12199 +
  12200 +#: plugins/custom_forms/views/custom_forms_plugin_myprofile/index.html.erb:8
  12201 +msgid "Submissions"
  12202 +msgstr "Submissões"
  12203 +
12109 12204 #: plugins/tolerance_time/views/tolerance_time_plugin_myprofile/index.html.erb:14
12110 12205 msgid "Comment edition tolerance time"
12111 12206 msgstr "Tempo de tolerância para edição de comentários"
... ... @@ -12122,6 +12217,14 @@ msgstr &quot;Mostrando página %d de %d&quot;
12122 12217 msgid "No filter available"
12123 12218 msgstr "Nenhum filtro disponível"
12124 12219  
  12220 +#: plugins/custom_forms/views/custom_forms_plugin_myprofile/_form.html.erb:14
  12221 +msgid "Triggered on membership request as requirement for approval"
  12222 +msgstr "Disparado para novos integrantes como requisito de aprovação"
  12223 +
  12224 +#: plugins/custom_forms/views/custom_forms_plugin_myprofile/_form.html.erb:15
  12225 +msgid "Triggered after membership"
  12226 +msgstr "Disparado depois da aprovação de um novo integrante"
  12227 +
12125 12228 #: plugins/sub_organizations/views/sub_organizations_plugin_myprofile/index.html.erb:4
12126 12229 msgid "Sub-groups awaiting approval:"
12127 12230 msgstr "Sub-grupos aguardando aprovação:"
... ... @@ -12134,6 +12237,36 @@ msgstr &quot;Criar nova sub-comunidade&quot;
12134 12237 msgid "Register a new sub-enterprise"
12135 12238 msgstr "Registrar um novo sub-empreendimento"
12136 12239  
  12240 +#: plugins/custom_forms/views/custom_forms_plugin_myprofile/_form.html.erb:30
  12241 +msgid "Add a new text field"
  12242 +msgstr "Adicionar novo campo de texto"
  12243 +
  12244 +#: plugins/custom_forms/views/custom_forms_plugin_myprofile/_form.html.erb:31
  12245 +msgid "Add a new select field"
  12246 +msgstr "Adicionar novo campo de seleção"
  12247 +
  12248 +#: plugins/custom_forms/views/custom_forms_plugin_myprofile/_option.html.erb:5
  12249 +#: plugins/custom_forms/views/custom_forms_plugin_myprofile/_empty_option.html.erb:5
  12250 +msgid "Are you sure you want to remove this option?"
  12251 +msgstr "Tem certeza de que deseja remover esta opção?"
  12252 +
  12253 +#: plugins/custom_forms/views/custom_forms_plugin_myprofile/pending.html.erb:3
  12254 +msgid "Pending submissions for %s"
  12255 +msgstr "Submissões pendentes para %s"
  12256 +
  12257 +#: plugins/custom_forms/views/custom_forms_plugin_myprofile/pending.html.erb:6
  12258 +msgid "There are no pending submissions for this form."
  12259 +msgstr "Não há submissões pendentes para esse formulário"
  12260 +
  12261 +#: plugins/custom_forms/views/custom_forms_plugin_myprofile/pending.html.erb:13
  12262 +#: plugins/custom_forms/views/custom_forms_plugin_myprofile/pending.html.erb:9
  12263 +msgid "User"
  12264 +msgstr "Usuário"
  12265 +
  12266 +#: plugins/custom_forms/views/custom_forms_plugin_myprofile/show_submission.html.erb:9
  12267 +msgid "Back to submissions"
  12268 +msgstr "Voltar para submissões"
  12269 +
12137 12270 #: plugins/sub_organizations/views/sub_organizations_plugin_myprofile/index.html.erb:18
12138 12271 msgid ""
12139 12272 "Fill in the search field to find the groups that should be added as sub-"
... ... @@ -12158,6 +12291,14 @@ msgstr &quot;&quot;
12158 12291 "O fornecedor já recebeu o seu pedido de compra e deve te contactar para "
12159 12292 "confirmação."
12160 12293  
  12294 +#: plugins/custom_forms/views/custom_forms_plugin_myprofile/submissions.html.erb:9
  12295 +msgid "Download all form responses as"
  12296 +msgstr "Baixar todas as respostas como"
  12297 +
  12298 +#: plugins/custom_forms/views/custom_forms_plugin_myprofile/submissions.html.erb:11
  12299 +msgid "Time"
  12300 +msgstr "Tempo"
  12301 +
12161 12302 #: plugins/shopping_cart/views/shopping_cart_plugin/mailer/customer_notification.html.erb:12
12162 12303 msgid "If you have any doubts, contact us at: %s"
12163 12304 msgstr "Se você tem alguma dúvida, nos contacte em: %s"
... ... @@ -12218,6 +12359,34 @@ msgstr &quot;Esse é um pedido de compra feito por %s.&quot;
12218 12359 msgid "Below follows the customer informations:"
12219 12360 msgstr "Abaixo seguem as informações do consumidor:"
12220 12361  
  12362 +#: plugins/custom_forms/views/custom_forms_plugin_myprofile/custom_forms_plugin/_text_field.html.erb:25
  12363 +msgid "Default text:"
  12364 +msgstr "Texto padrão:"
  12365 +
  12366 +#: plugins/custom_forms/views/custom_forms_plugin_myprofile/custom_forms_plugin/_select_field.html.erb:17
  12367 +msgid "Alternative"
  12368 +msgstr "Alternativa"
  12369 +
  12370 +#: plugins/custom_forms/views/custom_forms_plugin_myprofile/custom_forms_plugin/_select_field.html.erb:18
  12371 +msgid "Preselected"
  12372 +msgstr "Pré-selecionado"
  12373 +
  12374 +#: plugins/custom_forms/views/custom_forms_plugin_myprofile/custom_forms_plugin/_select_field.html.erb:25
  12375 +msgid "Add a new alternative"
  12376 +msgstr "Adicionar nova alternativa"
  12377 +
  12378 +#: plugins/custom_forms/views/custom_forms_plugin_myprofile/custom_forms_plugin/_alternative.html.erb:10
  12379 +msgid "Remove alternative"
  12380 +msgstr "Remover alternativa"
  12381 +
  12382 +#: plugins/custom_forms/views/custom_forms_plugin_myprofile/custom_forms_plugin/_alternative.html.erb:10
  12383 +msgid "Are you sure you want to remove this alternative?"
  12384 +msgstr "Tem certeza que quer remover essa alternativa?"
  12385 +
  12386 +#: plugins/tolerance_time/views/tolerance_time_plugin_myprofile/index.html.erb:1
  12387 +msgid "Tolerance Adjustments"
  12388 +msgstr "Configurações de Tolerância"
  12389 +
12221 12390 #: plugins/shopping_cart/views/shopping_cart_plugin/mailer/supplier_notification.html.erb:45
12222 12391 msgid "And here are the items bought by this customer:"
12223 12392 msgstr "E aqui estão os itens pedidos por esse consumidor:"
... ...
public/stylesheets/application.css
... ... @@ -2533,11 +2533,11 @@ div#activation_enterprise label, div#activation_enterprise input, div#activation
2533 2533 }
2534 2534 /*** REQUIRED FIELDS ***/
2535 2535  
2536   -.required-field label {
  2536 +.required-field label.formlabel {
2537 2537 font-weight: bold;
2538 2538 color: #c00;
2539 2539 }
2540   -.required-field label:after {
  2540 +.required-field label.formlabel:after {
2541 2541 content: ' (*)';
2542 2542 }
2543 2543 .login-box {
... ...