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 protect 'post_content', :profile 4 protect 'post_content', :profile
  5 +
4 def index 6 def index
5 @forms = CustomFormsPlugin::Form.from(profile) 7 @forms = CustomFormsPlugin::Form.from(profile)
6 end 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 def create 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 end 30 end
25 end 31 end
26 end 32 end
27 33
28 def edit 34 def edit
29 @form = CustomFormsPlugin::Form.find(params[:id]) 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 session['notice'] = _('Form could not be updated') 49 session['notice'] = _('Form could not be updated')
  50 + format.html { render :action => 'edit' }
45 end 51 end
46 end 52 end
47 end 53 end
@@ -60,6 +66,26 @@ class CustomFormsPluginMyprofileController &lt; MyProfileController @@ -60,6 +66,26 @@ class CustomFormsPluginMyprofileController &lt; MyProfileController
60 def submissions 66 def submissions
61 @form = CustomFormsPlugin::Form.find(params[:id]) 67 @form = CustomFormsPlugin::Form.find(params[:id])
62 @submissions = @form.submissions 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 end 89 end
64 90
65 def show_submission 91 def show_submission
@@ -67,82 +93,29 @@ class CustomFormsPluginMyprofileController &lt; MyProfileController @@ -67,82 +93,29 @@ class CustomFormsPluginMyprofileController &lt; MyProfileController
67 @form = @submission.form 93 @form = @submission.form
68 end 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 end 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 end 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 end 117 end
133 end 118 end
134 - fields  
135 end 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 end 121 end
plugins/custom_forms/controllers/custom_forms_plugin_profile_controller.rb
1 class CustomFormsPluginProfileController < ProfileController 1 class CustomFormsPluginProfileController < ProfileController
2 -  
3 before_filter :has_access, :show 2 before_filter :has_access, :show
4 3
5 def show 4 def show
  5 + extend(CustomFormsPlugin::Helper)
  6 +
6 @form = CustomFormsPlugin::Form.find(params[:id]) 7 @form = CustomFormsPlugin::Form.find(params[:id])
7 if user 8 if user
8 @submission ||= CustomFormsPlugin::Submission.find_by_form_id_and_profile_id(@form.id,user.id) 9 @submission ||= CustomFormsPlugin::Submission.find_by_form_id_and_profile_id(@form.id,user.id)
@@ -10,22 +11,34 @@ class CustomFormsPluginProfileController &lt; ProfileController @@ -10,22 +11,34 @@ class CustomFormsPluginProfileController &lt; ProfileController
10 else 11 else
11 @submission ||= CustomFormsPlugin::Submission.new(:form_id => @form.id) 12 @submission ||= CustomFormsPlugin::Submission.new(:form_id => @form.id)
12 end 13 end
  14 +
  15 + # build the answers
  16 + @submission.answers.push(*(answers = build_answers(params[:submission], @form))) if params[:submission]
  17 +
13 if request.post? 18 if request.post?
14 begin 19 begin
15 - extend(CustomFormsPlugin::Helper)  
16 - answers = build_answers(params[:submission], @form) 20 + raise 'Submission already present!' if 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 failed_answers = answers.select {|answer| !answer.valid? } 24 failed_answers = answers.select {|answer| !answer.valid? }
  25 +
18 if failed_answers.empty? 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 end 34 end
23 - @submission.save!  
24 - answers.map {|answer| answer.submission = @submission; answer.save!}  
25 else 35 else
26 - @submission.valid? 36 + @submission.errors.clear
27 failed_answers.each do |answer| 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 end 42 end
30 raise 'Submission failed: answers not valid' 43 raise 'Submission failed: answers not valid'
31 end 44 end
plugins/custom_forms/db/migrate/20130823134700_create_custom_forms_plugin_alternatives.rb 0 → 100644
@@ -0,0 +1,12 @@ @@ -0,0 +1,12 @@
  1 +class CreateCustomFormsPluginAlternatives < ActiveRecord::Migration
  2 + def self.up
  3 + create_table :custom_forms_plugin_alternatives do |t|
  4 + t.string :label
  5 + t.references :field
  6 + end
  7 + end
  8 +
  9 + def self.down
  10 + drop_table :custom_forms_plugin_alternatives
  11 + end
  12 +end
plugins/custom_forms/db/migrate/20130823135600_add_select_field_type_to_custom_forms_plugin_fields.rb 0 → 100644
@@ -0,0 +1,32 @@ @@ -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 @@ @@ -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 @@ @@ -0,0 +1,9 @@
  1 +class UpdateSelectFieldTypeInCustomFormsPluginFields < ActiveRecord::Migration
  2 + def self.up
  3 + change_column :custom_forms_plugin_fields, :select_field_type, :string, :null => false, :default => 'radio'
  4 + end
  5 +
  6 + def self.down
  7 + raise ActiveRecord::IrreversibleMigration
  8 + end
  9 +end
plugins/custom_forms/db/migrate/20131007120600_add_selected_by_default_to_custom_forms_plugin_alternatives.rb 0 → 100644
@@ -0,0 +1,14 @@ @@ -0,0 +1,14 @@
  1 +class AddSelectedByDefaultToCustomFormsPluginAlternatives < ActiveRecord::Migration
  2 + def self.up
  3 + add_column :custom_forms_plugin_alternatives, :selected_by_default, :boolean, :null => false, :default => false
  4 + CustomFormsPlugin::Field.find_each do |f|
  5 + f.alternatives.each do |a|
  6 + a.update_attribute(:selected_by_default, true) if a.label == f.default_value
  7 + end
  8 + end
  9 + end
  10 +
  11 + def self.down
  12 + raise ActiveRecord::IrreversibleMigration
  13 + end
  14 +end
plugins/custom_forms/db/migrate/20131107050913_add_position_to_field_and_alternatives.rb 0 → 100644
@@ -0,0 +1,17 @@ @@ -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 @@ @@ -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 @@ @@ -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 @@ @@ -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,8 +7,14 @@ class CustomFormsPlugin::Answer &lt; Noosfero::Plugin::ActiveRecord
7 7
8 def value_mandatory 8 def value_mandatory
9 if field.mandatory && value.blank? 9 if field.mandatory && value.blank?
10 - errors.add(field.slug.to_sym, _("is mandatory.").fix_i18n) 10 + errors.add(:value, _("is mandatory.").fix_i18n)
11 end 11 end
12 end 12 end
  13 +
  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 end 19 end
14 20
plugins/custom_forms/lib/custom_forms_plugin/field.rb
1 class CustomFormsPlugin::Field < ActiveRecord::Base 1 class CustomFormsPlugin::Field < ActiveRecord::Base
2 set_table_name :custom_forms_plugin_fields 2 set_table_name :custom_forms_plugin_fields
3 3
4 - validates_presence_of :form, :name  
5 - validates_uniqueness_of :slug, :scope => :form_id 4 + validates_presence_of :name
6 5
7 belongs_to :form, :class_name => 'CustomFormsPlugin::Form' 6 belongs_to :form, :class_name => 'CustomFormsPlugin::Form'
8 has_many :answers, :class_name => 'CustomFormsPlugin::Answer' 7 has_many :answers, :class_name => 'CustomFormsPlugin::Answer'
9 8
10 - serialize :choices, Hash 9 + has_many :alternatives, :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 before_validation do |field| 16 before_validation do |field|
13 field.slug = field.name.to_slug if field.name.present? 17 field.slug = field.name.to_slug if field.name.present?
14 end 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 end 24 end
  25 +
25 end 26 end
26 27
plugins/custom_forms/lib/custom_forms_plugin/form.rb
1 class CustomFormsPlugin::Form < Noosfero::Plugin::ActiveRecord 1 class CustomFormsPlugin::Form < Noosfero::Plugin::ActiveRecord
2 belongs_to :profile 2 belongs_to :profile
3 3
4 - has_many :fields, :class_name => 'CustomFormsPlugin::Field', :dependent => :destroy, :order => 'position' 4 + has_many :fields, :order => 'position', :class_name => 'CustomFormsPlugin::Field', :dependent => :destroy
  5 + accepts_nested_attributes_for :fields, :allow_destroy => true
  6 +
5 has_many :submissions, :class_name => 'CustomFormsPlugin::Submission' 7 has_many :submissions, :class_name => 'CustomFormsPlugin::Submission'
6 8
7 serialize :access 9 serialize :access
8 10
9 validates_presence_of :profile, :name 11 validates_presence_of :profile, :name
10 validates_uniqueness_of :slug, :scope => :profile_id 12 validates_uniqueness_of :slug, :scope => :profile_id
  13 + validate :period_range, :if => Proc.new { |f| f.begining.present? && f.ending.present? }
11 validate :access_format 14 validate :access_format
12 15
13 before_validation do |form| 16 before_validation do |form|
@@ -15,10 +18,16 @@ class CustomFormsPlugin::Form &lt; Noosfero::Plugin::ActiveRecord @@ -15,10 +18,16 @@ class CustomFormsPlugin::Form &lt; Noosfero::Plugin::ActiveRecord
15 form.access = nil if form.access.blank? 18 form.access = nil if form.access.blank?
16 end 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 named_scope :from, lambda {|profile| {:conditions => {:profile_id => profile.id}}} 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 =begin 29 =begin
21 - named_scope :accessible_to lambda do |profile| 30 + named_scope :accessible_to lambda do |profile|
22 #TODO should verify is profile is associated with the form owner 31 #TODO should verify is profile is associated with the form owner
23 profile_associated = ??? 32 profile_associated = ???
24 {:conditions => [" 33 {:conditions => ["
@@ -34,6 +43,10 @@ class CustomFormsPlugin::Form &lt; Noosfero::Plugin::ActiveRecord @@ -34,6 +43,10 @@ class CustomFormsPlugin::Form &lt; Noosfero::Plugin::ActiveRecord
34 (begining.present? && Time.now < begining) || (ending.present? && Time.now > ending) 43 (begining.present? && Time.now < begining) || (ending.present? && Time.now > ending)
35 end 44 end
36 45
  46 + def will_open?
  47 + begining.present? && Time.now < begining
  48 + end
  49 +
37 def accessible_to(target) 50 def accessible_to(target)
38 return true if access.nil? || target == profile 51 return true if access.nil? || target == profile
39 return false if target.nil? 52 return false if target.nil?
@@ -58,7 +71,7 @@ class CustomFormsPlugin::Form &lt; Noosfero::Plugin::ActiveRecord @@ -58,7 +71,7 @@ class CustomFormsPlugin::Form &lt; Noosfero::Plugin::ActiveRecord
58 elsif access.kind_of?(Array) 71 elsif access.kind_of?(Array)
59 access.each do |value| 72 access.each do |value|
60 if !value.kind_of?(Integer) || !Profile.exists?(value) 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 break 75 break
63 end 76 end
64 end 77 end
@@ -67,4 +80,8 @@ class CustomFormsPlugin::Form &lt; Noosfero::Plugin::ActiveRecord @@ -67,4 +80,8 @@ class CustomFormsPlugin::Form &lt; Noosfero::Plugin::ActiveRecord
67 end 80 end
68 end 81 end
69 end 82 end
  83 +
  84 + def period_range
  85 + errors.add(:base, _('The time range selected is invalid.')) if ending < begining
  86 + end
70 end 87 end
plugins/custom_forms/lib/custom_forms_plugin/helper.rb
1 module CustomFormsPlugin::Helper 1 module CustomFormsPlugin::Helper
  2 + def html_for_field(builder, association, klass)
  3 + new_object = klass.new
  4 + builder.fields_for(association, new_object, :child_index => "new_#{association}") do |f|
  5 + render(partial_for_class(klass), :f => f)
  6 + end
  7 + end
  8 +
2 def access_text(form) 9 def access_text(form)
3 return _('Public') if form.access.nil? 10 return _('Public') if form.access.nil?
4 return _('Logged users') if form.access == 'logged' 11 return _('Logged users') if form.access == 'logged'
5 if form.access == 'associated' 12 if form.access == 'associated'
6 - return _('Members') if form.profile.organization? 13 + return _('Members') if form.profile.organization?
7 return _('Friends') if form.profile.person? 14 return _('Friends') if form.profile.person?
8 end 15 end
9 return _('Custom') 16 return _('Custom')
@@ -48,8 +55,8 @@ module CustomFormsPlugin::Helper @@ -48,8 +55,8 @@ module CustomFormsPlugin::Helper
48 55
49 def type_to_label(type) 56 def type_to_label(type)
50 map = { 57 map = {
51 - 'text_field' => _('Text'),  
52 - 'select_field' => _('Select') 58 + 'text_field' => _('Text field'),
  59 + 'select_field' => _('Select field')
53 } 60 }
54 map[type_for_options(type)] 61 map[type_for_options(type)]
55 end 62 end
@@ -61,52 +68,61 @@ module CustomFormsPlugin::Helper @@ -61,52 +68,61 @@ module CustomFormsPlugin::Helper
61 def display_custom_field(field, submission, form) 68 def display_custom_field(field, submission, form)
62 answer = submission.answers.select{|answer| answer.field == field}.first 69 answer = submission.answers.select{|answer| answer.field == field}.first
63 field_tag = send("display_#{type_for_options(field.class)}",field, answer, form) 70 field_tag = send("display_#{type_for_options(field.class)}",field, answer, form)
64 - if field.mandatory? && !radio_button?(field) && !check_box?(field) && submission.id.nil? 71 + if field.mandatory? && submission.id.nil?
65 required(labelled_form_field(field.name, field_tag)) 72 required(labelled_form_field(field.name, field_tag))
66 - else 73 + else
67 labelled_form_field(field.name, field_tag) 74 labelled_form_field(field.name, field_tag)
68 end 75 end
69 end 76 end
70 77
  78 + def display_disabled?(field, answer)
  79 + (answer.present? && answer.id.present?) || field.form.expired?
  80 + end
  81 +
71 def display_text_field(field, answer, form) 82 def display_text_field(field, answer, form)
72 value = answer.present? ? answer.value : field.default_value 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 end 89 end
75 90
76 def display_select_field(field, answer, form) 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 end.join("\n") 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 end.join("\n") 108 end.join("\n")
93 end 109 end
94 end 110 end
95 111
96 def radio_button?(field) 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 end 114 end
99 115
100 def check_box?(field) 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 end 118 end
103 119
104 def build_answers(submission, form) 120 def build_answers(submission, form)
105 answers = [] 121 answers = []
106 form.fields.each do |field| 122 form.fields.each do |field|
107 final_value = '' 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 if value.kind_of?(String) 126 if value.kind_of?(String)
111 final_value = value 127 final_value = value
112 elsif value.kind_of?(Array) 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,11 +5,29 @@ class CustomFormsPlugin::MembershipSurvey &lt; Task
5 5
6 include CustomFormsPlugin::Helper 6 include CustomFormsPlugin::Helper
7 7
  8 + named_scope :from, lambda {|profile| {:conditions => {:requestor_id => profile.id}}}
  9 +
8 def perform 10 def perform
9 form = CustomFormsPlugin::Form.find(form_id) 11 form = CustomFormsPlugin::Form.find(form_id)
  12 + raise 'Form expired' if form.expired?
  13 +
10 answers = build_answers(submission, form) 14 answers = build_answers(submission, form)
11 s = CustomFormsPlugin::Submission.create!(:form => form, :profile => target) 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 end 31 end
14 32
15 def title 33 def title
plugins/custom_forms/lib/custom_forms_plugin/select_field.rb
1 class CustomFormsPlugin::SelectField < CustomFormsPlugin::Field 1 class CustomFormsPlugin::SelectField < CustomFormsPlugin::Field
2 set_table_name :custom_forms_plugin_fields 2 set_table_name :custom_forms_plugin_fields
3 - validates_presence_of :choices 3 + 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 end 5 end
plugins/custom_forms/lib/custom_forms_plugin/submission.rb
@@ -2,11 +2,20 @@ class CustomFormsPlugin::Submission &lt; Noosfero::Plugin::ActiveRecord @@ -2,11 +2,20 @@ class CustomFormsPlugin::Submission &lt; Noosfero::Plugin::ActiveRecord
2 belongs_to :form, :class_name => 'CustomFormsPlugin::Form' 2 belongs_to :form, :class_name => 'CustomFormsPlugin::Form'
3 belongs_to :profile 3 belongs_to :profile
4 4
5 - has_many :answers, :class_name => 'CustomFormsPlugin::Answer' 5 + has_many :answers, :class_name => 'CustomFormsPlugin::Answer', :dependent => :destroy
6 6
7 validates_presence_of :form 7 validates_presence_of :form
8 validates_presence_of :author_name, :author_email, :if => lambda {|submission| submission.profile.nil?} 8 validates_presence_of :author_name, :author_email, :if => lambda {|submission| submission.profile.nil?}
9 validates_uniqueness_of :author_email, :scope => :form_id, :allow_nil => true 9 validates_uniqueness_of :author_email, :scope => :form_id, :allow_nil => true
10 validates_format_of :author_email, :with => Noosfero::Constants::EMAIL_FORMAT, :if => (lambda {|submission| !submission.author_email.blank?}) 10 validates_format_of :author_email, :with => Noosfero::Constants::EMAIL_FORMAT, :if => (lambda {|submission| !submission.author_email.blank?})
  11 +
  12 + def self.human_attribute_name(attrib)
  13 + if /\d+/ =~ attrib and (f = CustomFormsPlugin::Field.find_by_id(attrib.to_i))
  14 + f.name
  15 + else
  16 + attrib
  17 + end
  18 + end
  19 +
11 end 20 end
12 21
plugins/custom_forms/lib/ext/role_assignment_trigger.rb
@@ -13,7 +13,26 @@ module RoleAssignmentTrigger @@ -13,7 +13,26 @@ module RoleAssignmentTrigger
13 end 13 end
14 end 14 end
15 end 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 after_destroy do |ra| 36 after_destroy do |ra|
18 if ra.resource.kind_of?(Profile) 37 if ra.resource.kind_of?(Profile)
19 profile = ra.resource 38 profile = ra.resource
@@ -24,6 +43,10 @@ module RoleAssignmentTrigger @@ -24,6 +43,10 @@ module RoleAssignmentTrigger
24 task = person.tasks.pending.select {|task| task.kind_of?(CustomFormsPlugin::MembershipSurvey) && task.form_id == form.id}.first 43 task = person.tasks.pending.select {|task| task.kind_of?(CustomFormsPlugin::MembershipSurvey) && task.form_id == form.id}.first
25 task.cancel if task 44 task.cancel if task
26 end 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 end 50 end
28 end 51 end
29 end 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,7 +4,7 @@
4 } 4 }
5 5
6 .action-table { 6 .action-table {
7 - width: 100%; 7 + width: 100%;
8 overflow: hidden; 8 overflow: hidden;
9 } 9 }
10 10
@@ -13,12 +13,9 @@ @@ -13,12 +13,9 @@
13 text-align: center; 13 text-align: center;
14 } 14 }
15 15
16 -.action-table td{  
17 - cursor: move;  
18 -}  
19 -  
20 .action-table .actions{ 16 .action-table .actions{
21 white-space: nowrap; 17 white-space: nowrap;
  18 + text-align: left;
22 } 19 }
23 20
24 .action-table .new-item{ 21 .action-table .new-item{
@@ -31,3 +28,62 @@ @@ -31,3 +28,62 @@
31 #colorbox .edit-information { 28 #colorbox .edit-information {
32 display: block; 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,21 +48,22 @@ class CustomFormsPluginMyprofileControllerTest &lt; ActionController::TestCase
48 :access => 'logged', 48 :access => 'logged',
49 :begining => begining, 49 :begining => begining,
50 :ending => ending, 50 :ending => ending,
51 - :description => 'Cool form'},  
52 - :fields => {  
53 - 1 => {  
54 - :name => 'Name',  
55 - :default_value => 'Jack',  
56 - :type => 'text_field'  
57 - },  
58 - 2 => {  
59 - :name => 'Color',  
60 - :list => '1',  
61 - :type => 'select_field',  
62 - :choices => {  
63 - 1 => {:name => 'Red', :value => 'red'},  
64 - 2 => {:name => 'Blue', :value => 'blue'},  
65 - 3 => {:name => 'Black', :value => 'black'} 51 + :description => 'Cool form',
  52 + :fields_attributes => {
  53 + 1 => {
  54 + :name => 'Name',
  55 + :default_value => 'Jack',
  56 + :type => 'CustomFormsPlugin::TextField'
  57 + },
  58 + 2 => {
  59 + :name => 'Color',
  60 + :select_field_type => 'radio',
  61 + :type => 'CustomFormsPlugin::SelectField',
  62 + :alternatives_attributes => {
  63 + 1 => {:label => 'Red'},
  64 + 2 => {:label => 'Blue'},
  65 + 3 => {:label => 'Black'}
  66 + }
66 } 67 }
67 } 68 }
68 } 69 }
@@ -75,32 +76,30 @@ class CustomFormsPluginMyprofileControllerTest &lt; ActionController::TestCase @@ -75,32 +76,30 @@ class CustomFormsPluginMyprofileControllerTest &lt; ActionController::TestCase
75 assert_equal 'Cool form', form.description 76 assert_equal 'Cool form', form.description
76 assert_equal 2, form.fields.count 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 assert_equal 'Name', f1.name 82 assert_equal 'Name', f1.name
82 assert_equal 'Jack', f1.default_value 83 assert_equal 'Jack', f1.default_value
83 assert f1.kind_of?(CustomFormsPlugin::TextField) 84 assert f1.kind_of?(CustomFormsPlugin::TextField)
84 85
85 assert_equal 'Color', f2.name 86 assert_equal 'Color', f2.name
86 - assert_equal 'red', f2.choices['Red']  
87 - assert_equal 'blue', f2.choices['Blue']  
88 - assert_equal 'black', f2.choices['Black']  
89 - assert f2.list 87 + assert_equal f2.alternatives.map(&:label).sort, ['Red', 'Blue', 'Black'].sort
  88 + assert_equal f2.select_field_type, 'radio'
90 assert f2.kind_of?(CustomFormsPlugin::SelectField) 89 assert f2.kind_of?(CustomFormsPlugin::SelectField)
91 end 90 end
92 91
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 format = '%Y-%m-%d %H:%M' 93 format = '%Y-%m-%d %H:%M'
95 num_fields = 10 94 num_fields = 10
96 begining = Time.now.strftime(format) 95 begining = Time.now.strftime(format)
97 ending = (Time.now + 1.day).strftime(format) 96 ending = (Time.now + 1.day).strftime(format)
98 fields = {} 97 fields = {}
99 num_fields.times do |i| 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 :default_value => '', 101 :default_value => '',
103 - :type => 'text_field' 102 + :type => 'CustomFormsPlugin::TextField'
104 } 103 }
105 end 104 end
106 assert_difference CustomFormsPlugin::Form, :count, 1 do 105 assert_difference CustomFormsPlugin::Form, :count, 1 do
@@ -110,29 +109,69 @@ class CustomFormsPluginMyprofileControllerTest &lt; ActionController::TestCase @@ -110,29 +109,69 @@ class CustomFormsPluginMyprofileControllerTest &lt; ActionController::TestCase
110 :access => 'logged', 109 :access => 'logged',
111 :begining => begining, 110 :begining => begining,
112 :ending => ending, 111 :ending => ending,
113 - :description => 'Cool form'},  
114 - :fields => fields 112 + :description => 'Cool form',
  113 + :fields_attributes => fields
  114 + }
115 end 115 end
116 form = CustomFormsPlugin::Form.find_by_name('My Form') 116 form = CustomFormsPlugin::Form.find_by_name('My Form')
117 assert_equal num_fields, form.fields.count 117 assert_equal num_fields, form.fields.count
118 - 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 end 122 end
121 end 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 should 'edit a form' do 159 should 'edit a form' do
124 form = CustomFormsPlugin::Form.create!(:profile => profile, :name => 'Free Software') 160 form = CustomFormsPlugin::Form.create!(:profile => profile, :name => 'Free Software')
125 - field = CustomFormsPlugin::TextField.create!(:form => form, :name => 'License')  
126 format = '%Y-%m-%d %H:%M' 161 format = '%Y-%m-%d %H:%M'
127 begining = Time.now.strftime(format) 162 begining = Time.now.strftime(format)
128 ending = (Time.now + 1.day).strftime(format) 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 form.reload 171 form.reload
135 - field.reload 172 + assert_equal form.fields.length, 1
  173 +
  174 + field = form.fields.last
136 175
137 assert_equal 'logged', form.access 176 assert_equal 'logged', form.access
138 assert_equal begining, form.begining.strftime(format) 177 assert_equal begining, form.begining.strftime(format)
@@ -149,5 +188,50 @@ class CustomFormsPluginMyprofileControllerTest &lt; ActionController::TestCase @@ -149,5 +188,50 @@ class CustomFormsPluginMyprofileControllerTest &lt; ActionController::TestCase
149 assert_tag :tag => 'textarea', :attributes => { :id => 'form_description', :class => 'mceEditor' } 188 assert_tag :tag => 'textarea', :attributes => { :id => 'form_description', :class => 'mceEditor' }
150 end 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,9 +23,35 @@ class CustomFormsPluginProfileControllerTest &lt; ActionController::TestCase
23 field2 = CustomFormsPlugin::TextField.create(:name => 'License', :form => form) 23 field2 = CustomFormsPlugin::TextField.create(:name => 'License', :form => form)
24 24
25 assert_difference CustomFormsPlugin::Submission, :count, 1 do 25 assert_difference CustomFormsPlugin::Submission, :count, 1 do
26 - post :show, :profile => profile.identifier, :id => form.id, :submission => {field1.name.to_slug => 'Noosfero', field2.name.to_slug => 'GPL'} 26 + post :show, :profile => profile.identifier, :id => form.id, :submission => {field1.id.to_s => 'Noosfero', field2.id.to_s => 'GPL'}
27 end 27 end
28 assert !session[:notice].include?('not saved') 28 assert !session[:notice].include?('not saved')
29 assert_redirected_to :action => 'show' 29 assert_redirected_to :action => 'show'
30 end 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 end 57 end
plugins/custom_forms/test/unit/custom_forms_plugin/admission_survey_test.rb 0 → 100644
@@ -0,0 +1,14 @@ @@ -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,11 +27,24 @@ class CustomFormsPlugin::AnswerTest &lt; ActiveSupport::TestCase
27 field = CustomFormsPlugin::Field.create!(:name => 'License', :form => form, :mandatory => true) 27 field = CustomFormsPlugin::Field.create!(:name => 'License', :form => form, :mandatory => true)
28 answer = CustomFormsPlugin::Answer.new(:field => field) 28 answer = CustomFormsPlugin::Answer.new(:field => field)
29 answer.valid? 29 answer.valid?
30 - assert answer.errors.invalid?(field.slug.to_sym) 30 + assert answer.errors.invalid?(:value)
31 31
32 answer.value = "GPL" 32 answer.value = "GPL"
33 answer.valid? 33 answer.valid?
34 - assert !answer.errors.invalid?(field.slug.to_sym) 34 + assert !answer.errors.invalid?(:value)
  35 + end
  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 end 48 end
36 49
37 end 50 end
plugins/custom_forms/test/unit/custom_forms_plugin/field_test.rb
1 require File.dirname(__FILE__) + '/../../../../../test/test_helper' 1 require File.dirname(__FILE__) + '/../../../../../test/test_helper'
2 2
3 class CustomFormsPlugin::FieldTest < ActiveSupport::TestCase 3 class CustomFormsPlugin::FieldTest < ActiveSupport::TestCase
4 - should 'validate presence of form' do  
5 - field = CustomFormsPlugin::Field.new  
6 - field.valid?  
7 - assert field.errors.invalid?(:form)  
8 - assert field.errors.invalid?(:name)  
9 -  
10 - form = CustomFormsPlugin::Form.create!(:name => 'Free Software', :profile => fast_create(Profile))  
11 - field.form = form  
12 - field.name = 'License'  
13 - field.valid?  
14 - assert !field.errors.invalid?(:form)  
15 - assert !field.errors.invalid?(:name)  
16 - end  
17 -  
18 should 'set slug before validation based on name' do 4 should 'set slug before validation based on name' do
19 field = CustomFormsPlugin::Field.new(:name => 'Name') 5 field = CustomFormsPlugin::Field.new(:name => 'Name')
20 field.valid? 6 field.valid?
21 assert_equal field.name.to_slug, field.slug 7 assert_equal field.name.to_slug, field.slug
22 end 8 end
23 9
24 - should 'validate uniqueness of slug scoped on the form' do  
25 - form1 = CustomFormsPlugin::Form.create!(:name => 'Free Software', :profile => fast_create(Profile))  
26 - form2 = CustomFormsPlugin::Form.create!(:name => 'Open Source', :profile => fast_create(Profile))  
27 - f1 = CustomFormsPlugin::Field.create!(:name => 'License', :form => form1)  
28 - f2 = CustomFormsPlugin::Field.new(:name => 'License', :form => form1)  
29 - f3 = CustomFormsPlugin::Field.new(:name => 'License', :form => form2)  
30 -  
31 - f2.valid?  
32 - f3.valid?  
33 -  
34 - assert f2.errors.invalid?(:slug)  
35 - assert !f3.errors.invalid?(:slug)  
36 - end  
37 -  
38 should 'set mandatory field as false by default' do 10 should 'set mandatory field as false by default' do
39 field = CustomFormsPlugin::Field.new 11 field = CustomFormsPlugin::Field.new
40 assert !field.mandatory 12 assert !field.mandatory
@@ -50,17 +22,6 @@ class CustomFormsPlugin::FieldTest &lt; ActiveSupport::TestCase @@ -50,17 +22,6 @@ class CustomFormsPlugin::FieldTest &lt; ActiveSupport::TestCase
50 assert_includes field.answers, a2 22 assert_includes field.answers, a2
51 end 23 end
52 24
53 - should 'serialize choices into a hash' do  
54 - form = CustomFormsPlugin::Form.create!(:name => 'Free Software', :profile => fast_create(Profile))  
55 - field = CustomFormsPlugin::Field.create!(:name => 'License', :form => form)  
56 - field.choices = {'First' => 1, 'Second' => 2, 'Third' => 3}  
57 - field.save!  
58 -  
59 - assert_equal 1, field.choices['First']  
60 - assert_equal 2, field.choices['Second']  
61 - assert_equal 3, field.choices['Third']  
62 - end  
63 -  
64 should 'not destroy form after removing a field' do 25 should 'not destroy form after removing a field' do
65 form = CustomFormsPlugin::Form.create!(:name => 'Free Software', :profile => fast_create(Profile)) 26 form = CustomFormsPlugin::Form.create!(:name => 'Free Software', :profile => fast_create(Profile))
66 license_field = CustomFormsPlugin::Field.create!(:name => 'License', :form => form) 27 license_field = CustomFormsPlugin::Field.create!(:name => 'License', :form => form)
@@ -72,26 +33,20 @@ class CustomFormsPlugin::FieldTest &lt; ActiveSupport::TestCase @@ -72,26 +33,20 @@ class CustomFormsPlugin::FieldTest &lt; ActiveSupport::TestCase
72 assert_equal form.fields, [license_field] 33 assert_equal form.fields, [license_field]
73 end 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 end 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 end 50 end
95 -  
96 end 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,6 +53,20 @@ class CustomFormsPlugin::FormTest &lt; ActiveSupport::TestCase
53 assert !form.errors.invalid?(:slug) 53 assert !form.errors.invalid?(:slug)
54 end 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 should 'define form expiration' do 70 should 'define form expiration' do
57 form = CustomFormsPlugin::Form.new 71 form = CustomFormsPlugin::Form.new
58 assert !form.expired? 72 assert !form.expired?
@@ -75,6 +89,22 @@ class CustomFormsPlugin::FormTest &lt; ActiveSupport::TestCase @@ -75,6 +89,22 @@ class CustomFormsPlugin::FormTest &lt; ActiveSupport::TestCase
75 assert !form.expired? 89 assert !form.expired?
76 end 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 should 'validates format of access' do 108 should 'validates format of access' do
79 form = CustomFormsPlugin::Form.new 109 form = CustomFormsPlugin::Form.new
80 form.valid? 110 form.valid?
@@ -180,4 +210,54 @@ class CustomFormsPlugin::FormTest &lt; ActiveSupport::TestCase @@ -180,4 +210,54 @@ class CustomFormsPlugin::FormTest &lt; ActiveSupport::TestCase
180 end 210 end
181 end 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 end 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 +16,29 @@ class CustomFormsPlugin::MembershipSurveyTest &lt; ActiveSupport::TestCase
16 person = fast_create(Person) 16 person = fast_create(Person)
17 form = CustomFormsPlugin::Form.create!(:name => 'Simple Form', :profile => profile) 17 form = CustomFormsPlugin::Form.create!(:name => 'Simple Form', :profile => profile)
18 field = CustomFormsPlugin::Field.create!(:name => 'Name', :form => form) 18 field = CustomFormsPlugin::Field.create!(:name => 'Name', :form => form)
19 - task = CustomFormsPlugin::MembershipSurvey.create!(:form_id => form.id, :submission => {'name' => 'Jack'}, :target => person, :requestor => profile) 19 + task = CustomFormsPlugin::MembershipSurvey.create!(:form_id => form.id, :submission => {field.id.to_s => 'Jack'}, :target => person, :requestor => profile)
20 20
21 assert_difference CustomFormsPlugin::Submission, :count, 1 do 21 assert_difference CustomFormsPlugin::Submission, :count, 1 do
22 task.finish 22 task.finish
23 end 23 end
24 24
25 submission = CustomFormsPlugin::Submission.last 25 submission = CustomFormsPlugin::Submission.last
26 - assert_equal submission.answers.count, 1 26 + assert_equal submission.answers.count, 1
27 27
28 answer = submission.answers.first 28 answer = submission.answers.first
29 assert_equal answer.value, 'Jack' 29 assert_equal answer.value, 'Jack'
30 end 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 end 44 end
plugins/custom_forms/test/unit/custom_forms_plugin/select_field_test.rb
1 require File.dirname(__FILE__) + '/../../../../../test/test_helper' 1 require File.dirname(__FILE__) + '/../../../../../test/test_helper'
2 2
3 class CustomFormsPlugin::SelectFieldTest < ActiveSupport::TestCase 3 class CustomFormsPlugin::SelectFieldTest < ActiveSupport::TestCase
4 - should 'validate presence of choices, multiple and list' do  
5 - select = CustomFormsPlugin::SelectField.new  
6 - select.valid?  
7 - assert select.errors.invalid?(:choices)  
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 end 27 end
13 end 28 end
plugins/custom_forms/test/unit/ext/role_assingment_test.rb
@@ -27,25 +27,46 @@ class RoleAssignmentsTest &lt; ActiveSupport::TestCase @@ -27,25 +27,46 @@ class RoleAssignmentsTest &lt; ActiveSupport::TestCase
27 end 27 end
28 end 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 environment = Environment.default 31 environment = Environment.default
32 environment.enable_plugin(CustomFormsPlugin) 32 environment.enable_plugin(CustomFormsPlugin)
33 organization = fast_create(Organization) 33 organization = fast_create(Organization)
34 person = fast_create(Person) 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 organization.add_member(person) 36 organization.add_member(person)
37 37
38 assert_difference CustomFormsPlugin::MembershipSurvey.pending, :count, -1 do 38 assert_difference CustomFormsPlugin::MembershipSurvey.pending, :count, -1 do
39 organization.remove_member(person) 39 organization.remove_member(person)
40 end 40 end
41 41
  42 + form2 = CustomFormsPlugin::Form.create!(:profile => organization, :name => 'Form 2', :for_admission => true)
42 organization.add_member(person) 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 assert_no_difference CustomFormsPlugin::MembershipSurvey.finished, :count do 53 assert_no_difference CustomFormsPlugin::MembershipSurvey.finished, :count do
47 organization.remove_member(person) 54 organization.remove_member(person)
48 end 55 end
49 end 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 <h2><%= _('Options') %></h2> 2 <h2><%= _('Options') %></h2>
4 <table class='action-table' style='width: 420px'> 3 <table class='action-table' style='width: 420px'>
5 <tr> 4 <tr>
6 <th style='width: 40%'><%= _('Name') %></th> 5 <th style='width: 40%'><%= _('Name') %></th>
7 <th style='width: 40%'><%= _('Value') %></th> 6 <th style='width: 40%'><%= _('Value') %></th>
8 - <th style='width: 20%'><%= _('Actions') %></th> 7 + <th style='width: 20%'><%= _('Delete') %></th>
9 </tr> 8 </tr>
10 <% option_counter = 1 %> 9 <% option_counter = 1 %>
11 <% (field.choices || {}).each do |name, value| %> 10 <% (field.choices || {}).each do |name, value| %>
plugins/custom_forms/views/custom_forms_plugin_myprofile/_edit_text.html.erb
@@ -1,10 +0,0 @@ @@ -1,10 +0,0 @@
1 -<% elem_id = "edit-text-#{counter}" %>  
2 -<div id=<%= elem_id %> class='edit-information'>  
3 - <h2><%= _('Default value') %></h2>  
4 - <%= labelled_form_field _('Default value'), text_field("fields[#{counter}]", :default_value, :value => field.default_value) %>  
5 -  
6 - <% button_bar do %>  
7 - <%= button :ok, _('Ok'), '#', :class => 'colorbox-ok-button', :div_id => elem_id %>  
8 - <% end %>  
9 -</div>  
10 -  
plugins/custom_forms/views/custom_forms_plugin_myprofile/_field.html.erb
1 -<tr id=<%= "field-#{counter}" %>>  
2 - <td style="text-align: left"><%= text_field "fields[#{counter}]", :name, :value => field.name, :size => 25 %></td>  
3 - <td><%= type_to_label(field.type) %></td>  
4 - <%= hidden_field "fields[#{counter}]", :type, :value => type_for_options(field.class) %>  
5 - <td><%= check_box "fields[#{counter}]", :mandatory, :checked => field.mandatory %></td>  
6 - <%= hidden_field "fields[#{counter}]", :real_id, :value => field.id %>  
7 - <%= hidden_field "fields[#{counter}]", :form_id, :value => @form.id %>  
8 - <td class='actions'>  
9 - <%= button_without_text :edit, _('Edit'), '#', :field_id => counter %>  
10 - <%= button_without_text :remove, _('Remove'), '#', :class => 'remove-field', :field_id => counter, :confirm => _('Are you sure you want to remove this field?') %>  
11 - </td>  
12 -</tr> 1 +<fieldset class="field-box" <%='style="display:none"' if f.object._destroy %> >
  2 + <legend><%= type_to_label(f.object.type) %></legend>
  3 + <div>
  4 + <%= 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 <% self.extend(CustomFormsPlugin::Helper) %> 1 <% self.extend(CustomFormsPlugin::Helper) %>
2 <%= render :file => 'shared/tiny_mce', :locals => {:mode => 'simple'} %> 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 { :size => 14 }) 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 <% end %> 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 <% end %> 40 <% end %>
56 41
57 <%= javascript_include_tag '../plugins/custom_forms/field' %> 42 <%= javascript_include_tag '../plugins/custom_forms/field' %>
plugins/custom_forms/views/custom_forms_plugin_myprofile/_option.html.erb
@@ -1,7 +0,0 @@ @@ -1,7 +0,0 @@
1 -<tr id=<%= "field-#{counter}-option-#{option_counter}" %> style="display: auto;">  
2 - <td><%= text_field_tag("fields[#{counter}][choices][#{option_counter}][name]", name) %></td>  
3 - <td><%= text_field_tag("fields[#{counter}][choices][#{option_counter}][value]", value) %></td>  
4 - <td class='actions'>  
5 - <%= button_without_text :remove, _('Remove'), '#', :class => 'remove-option', :field_id => counter, :option_id => option_counter, :confirm => _('Are you sure you want to remove this option?') %>  
6 - </td>  
7 -</tr>  
plugins/custom_forms/views/custom_forms_plugin_myprofile/create.html.erb
@@ -1,2 +0,0 @@ @@ -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 @@ @@ -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 @@ @@ -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 @@ @@ -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 @@ @@ -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 <h1><%= _('Edit form') %></h1> 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,12 +17,14 @@
17 <td><%= access_text(form) %></td> 17 <td><%= access_text(form) %></td>
18 <td class="actions"> 18 <td class="actions">
19 <%= button_without_text :edit, _('Edit'), :action => 'edit', :id => form.id %> 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 </tr> 23 </tr>
22 <% end %> 24 <% end %>
23 <tr id="new-item"> 25 <tr id="new-item">
24 <td colspan='5'> 26 <td colspan='5'>
25 - <%= button(:add, _('Add a new form'), :action => 'create')%> 27 + <%= button(:add, _('Add a new form'), :action => 'new')%>
26 </td> 28 </td>
27 </tr> 29 </tr>
28 </table> 30 </table>
plugins/custom_forms/views/custom_forms_plugin_myprofile/new.html.erb 0 → 100644
@@ -0,0 +1,5 @@ @@ -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 @@ @@ -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,6 +5,13 @@
5 <% if @form.submissions.empty? %> 5 <% if @form.submissions.empty? %>
6 <%= _('There are no submissions for this form.') %> 6 <%= _('There are no submissions for this form.') %>
7 <% else %> 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 <table class="action-table"> 15 <table class="action-table">
9 <tr> 16 <tr>
10 <th style='width: 50%'><%= _('Author') %></th> 17 <th style='width: 50%'><%= _('Author') %></th>
plugins/custom_forms/views/custom_forms_plugin_profile/show.html.erb
@@ -2,6 +2,14 @@ @@ -2,6 +2,14 @@
2 <p><%= @form.description %></p> 2 <p><%= @form.description %></p>
3 3
4 <% if @submission.id.nil? %> 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 <%= error_messages_for :submission %> 13 <%= error_messages_for :submission %>
6 14
7 <% form_for :submission, @submission do |f| %> 15 <% form_for :submission, @submission do |f| %>
@@ -13,8 +21,13 @@ @@ -13,8 +21,13 @@
13 <%= render :partial => 'shared/form_submission', :locals => {:f => f} %> 21 <%= render :partial => 'shared/form_submission', :locals => {:f => f} %>
14 22
15 <% button_bar do %> 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 <% end %> 29 <% end %>
  30 +
18 <% end %> 31 <% end %>
19 <% else %> 32 <% else %>
20 <% fields_for :submission, @submission do |f| %> 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,8 +3,14 @@
3 3
4 <h2><%= @form.name %></h2> 4 <h2><%= @form.name %></h2>
5 <p><%= @form.description %></p> 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 <% f.fields_for :submission do |fi| %> 14 <% f.fields_for :submission do |fi| %>
8 - <%#= fi.error_messages_for :submission %>  
9 <%= render :partial => 'shared/form_submission', :locals => {:f => fi} %> 15 <%= render :partial => 'shared/form_submission', :locals => {:f => fi} %>
10 <% end %> 16 <% end %>
po/pt/noosfero.po
@@ -10441,6 +10441,18 @@ msgstr &quot;Bloco salvo com sucesso.&quot; @@ -10441,6 +10441,18 @@ msgstr &quot;Bloco salvo com sucesso.&quot;
10441 msgid "Sub-organizations updated" 10441 msgid "Sub-organizations updated"
10442 msgstr "Sub-organizações atualizadas" 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 #: plugins/sub_organizations/controllers/sub_organizations_plugin_myprofile_controller.rb:28 10456 #: plugins/sub_organizations/controllers/sub_organizations_plugin_myprofile_controller.rb:28
10445 msgid "Sub-organizations could not be updated" 10457 msgid "Sub-organizations could not be updated"
10446 msgstr "As sub-organizações não puderam ser salvas" 10458 msgstr "As sub-organizações não puderam ser salvas"
@@ -11087,6 +11099,15 @@ msgstr &quot;%s artigos encontrados&quot; @@ -11087,6 +11099,15 @@ msgstr &quot;%s artigos encontrados&quot;
11087 msgid "%s events found" 11099 msgid "%s events found"
11088 msgstr "%s eventos encontrados" 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 #: plugins/solr/lib/solr_plugin/search_helper.rb:138 11111 #: plugins/solr/lib/solr_plugin/search_helper.rb:138
11091 msgid "%s people found" 11112 msgid "%s people found"
11092 msgstr "%s pessoas encontradas" 11113 msgstr "%s pessoas encontradas"
@@ -11119,6 +11140,47 @@ msgstr &quot;Um plugin que mostra grupos de comentários.&quot; @@ -11119,6 +11140,47 @@ msgstr &quot;Um plugin que mostra grupos de comentários.&quot;
11119 msgid "A plugin that add a container block." 11140 msgid "A plugin that add a container block."
11120 msgstr "Um plugin que adiciona um bloco container." 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 #: plugins/container_block/lib/container_block_plugin/container_block.rb:11 11184 #: plugins/container_block/lib/container_block_plugin/container_block.rb:11
11123 msgid "Container" 11185 msgid "Container"
11124 msgstr "Container" 11186 msgstr "Container"
@@ -12106,6 +12168,39 @@ msgstr &quot;Horas&quot; @@ -12106,6 +12168,39 @@ msgstr &quot;Horas&quot;
12106 msgid "Content edition tolerance time" 12168 msgid "Content edition tolerance time"
12107 msgstr "Tempo de tolerância para edição de conteúdo" 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 #: plugins/tolerance_time/views/tolerance_time_plugin_myprofile/index.html.erb:14 12204 #: plugins/tolerance_time/views/tolerance_time_plugin_myprofile/index.html.erb:14
12110 msgid "Comment edition tolerance time" 12205 msgid "Comment edition tolerance time"
12111 msgstr "Tempo de tolerância para edição de comentários" 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,6 +12217,14 @@ msgstr &quot;Mostrando página %d de %d&quot;
12122 msgid "No filter available" 12217 msgid "No filter available"
12123 msgstr "Nenhum filtro disponível" 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 #: plugins/sub_organizations/views/sub_organizations_plugin_myprofile/index.html.erb:4 12228 #: plugins/sub_organizations/views/sub_organizations_plugin_myprofile/index.html.erb:4
12126 msgid "Sub-groups awaiting approval:" 12229 msgid "Sub-groups awaiting approval:"
12127 msgstr "Sub-grupos aguardando aprovação:" 12230 msgstr "Sub-grupos aguardando aprovação:"
@@ -12134,6 +12237,36 @@ msgstr &quot;Criar nova sub-comunidade&quot; @@ -12134,6 +12237,36 @@ msgstr &quot;Criar nova sub-comunidade&quot;
12134 msgid "Register a new sub-enterprise" 12237 msgid "Register a new sub-enterprise"
12135 msgstr "Registrar um novo sub-empreendimento" 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 #: plugins/sub_organizations/views/sub_organizations_plugin_myprofile/index.html.erb:18 12270 #: plugins/sub_organizations/views/sub_organizations_plugin_myprofile/index.html.erb:18
12138 msgid "" 12271 msgid ""
12139 "Fill in the search field to find the groups that should be added as sub-" 12272 "Fill in the search field to find the groups that should be added as sub-"
@@ -12158,6 +12291,14 @@ msgstr &quot;&quot; @@ -12158,6 +12291,14 @@ msgstr &quot;&quot;
12158 "O fornecedor já recebeu o seu pedido de compra e deve te contactar para " 12291 "O fornecedor já recebeu o seu pedido de compra e deve te contactar para "
12159 "confirmação." 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 #: plugins/shopping_cart/views/shopping_cart_plugin/mailer/customer_notification.html.erb:12 12302 #: plugins/shopping_cart/views/shopping_cart_plugin/mailer/customer_notification.html.erb:12
12162 msgid "If you have any doubts, contact us at: %s" 12303 msgid "If you have any doubts, contact us at: %s"
12163 msgstr "Se você tem alguma dúvida, nos contacte em: %s" 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,6 +12359,34 @@ msgstr &quot;Esse é um pedido de compra feito por %s.&quot;
12218 msgid "Below follows the customer informations:" 12359 msgid "Below follows the customer informations:"
12219 msgstr "Abaixo seguem as informações do consumidor:" 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 #: plugins/shopping_cart/views/shopping_cart_plugin/mailer/supplier_notification.html.erb:45 12390 #: plugins/shopping_cart/views/shopping_cart_plugin/mailer/supplier_notification.html.erb:45
12222 msgid "And here are the items bought by this customer:" 12391 msgid "And here are the items bought by this customer:"
12223 msgstr "E aqui estão os itens pedidos por esse consumidor:" 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,11 +2533,11 @@ div#activation_enterprise label, div#activation_enterprise input, div#activation
2533 } 2533 }
2534 /*** REQUIRED FIELDS ***/ 2534 /*** REQUIRED FIELDS ***/
2535 2535
2536 -.required-field label { 2536 +.required-field label.formlabel {
2537 font-weight: bold; 2537 font-weight: bold;
2538 color: #c00; 2538 color: #c00;
2539 } 2539 }
2540 -.required-field label:after { 2540 +.required-field label.formlabel:after {
2541 content: ' (*)'; 2541 content: ' (*)';
2542 } 2542 }
2543 .login-box { 2543 .login-box {