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