Commit 9e954d8c60e672519a5b4e93fec0520b6e0e3b79
Exists in
master
and in
29 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 { | ... | ... |