Commit 84ca7256e30e2ac68264f248c8c15457cb134771
Exists in
master
and in
20 other branches
Merge branch 'customfields-rails4' into 'master'
Add custom field feature to core Custom fields can be added to any profile through the admin panel in the 'Fields' section. They have the same behavior as the current Noosfero's fields (active, signup, required and privacy). See merge request !730
Showing
52 changed files
with
806 additions
and
36 deletions
Show diff stats
app/controllers/admin/features_controller.rb
1 | 1 | class FeaturesController < AdminController |
2 | 2 | protect 'edit_environment_features', :environment |
3 | + helper CustomFieldsHelper | |
3 | 4 | |
4 | 5 | def index |
5 | 6 | @features = Environment.available_features.sort_by{|k,v|v} |
... | ... | @@ -51,6 +52,34 @@ class FeaturesController < AdminController |
51 | 52 | redirect_to :action => 'manage_fields' |
52 | 53 | end |
53 | 54 | |
55 | + def manage_custom_fields | |
56 | + custom_field_list = params[:custom_fields] || {} | |
57 | + | |
58 | + custom_fields_to_destroy = | |
59 | + params[:customized_type].constantize.custom_fields(environment).map(&:id) - custom_field_list.keys.map(&:to_i) | |
60 | + CustomField.destroy(custom_fields_to_destroy) | |
61 | + | |
62 | + custom_field_list.each_pair do |id, custom_field| | |
63 | + field = CustomField.find_by_id(id) | |
64 | + if not field.blank? | |
65 | + params_to_update = custom_field.except(:format, :extras, :customized_type,:environment) | |
66 | + field.update_attributes(params_to_update) | |
67 | + else | |
68 | + if !custom_field[:extras].nil? | |
69 | + tmp = [] | |
70 | + custom_field[:extras].each_pair do |k, v| | |
71 | + tmp << v | |
72 | + end | |
73 | + custom_field[:extras] = tmp | |
74 | + end | |
75 | + field = CustomField.new custom_field.except(:environment) | |
76 | + field.environment=environment | |
77 | + field.save if field.valid? | |
78 | + end | |
79 | + end | |
80 | + redirect_to :action => 'manage_fields' | |
81 | + end | |
82 | + | |
54 | 83 | def search_members |
55 | 84 | arg = params[:q].downcase |
56 | 85 | result = environment.people.where('LOWER(name) LIKE ? OR identifier LIKE ?', "%#{arg}%", "%#{arg}%") | ... | ... |
app/controllers/my_profile/memberships_controller.rb
app/controllers/my_profile/profile_editor_controller.rb
... | ... | @@ -8,6 +8,7 @@ class ProfileEditorController < MyProfileController |
8 | 8 | before_filter :forbid_destroy_profile, :only => [:destroy_profile] |
9 | 9 | before_filter :check_user_can_edit_header_footer, :only => [:header_footer] |
10 | 10 | helper_method :has_welcome_page |
11 | + helper CustomFieldsHelper | |
11 | 12 | |
12 | 13 | def index |
13 | 14 | @pending_tasks = Task.to(profile).pending.without_spam.select{|i| user.has_permission?(i.permission, profile)} | ... | ... |
app/controllers/public/account_controller.rb
... | ... | @@ -6,6 +6,7 @@ class AccountController < ApplicationController |
6 | 6 | before_filter :redirect_if_logged_in, :only => [:login, :signup] |
7 | 7 | before_filter :protect_from_bots, :only => :signup |
8 | 8 | |
9 | + helper CustomFieldsHelper | |
9 | 10 | # say something nice, you goof! something sweet. |
10 | 11 | def index |
11 | 12 | unless logged_in? | ... | ... |
app/controllers/public/profile_controller.rb
... | ... | @@ -0,0 +1,58 @@ |
1 | +module CustomFieldsHelper | |
2 | + | |
3 | + def format_name(format) | |
4 | + names = {} | |
5 | + names['string'] = _('String') | |
6 | + names['text'] = _('Text') | |
7 | + names['date'] = _('Date') | |
8 | + names['numeric'] = _('Numeric') | |
9 | + names['link'] = _('Link') | |
10 | + names['list'] = _('List') | |
11 | + names['checkbox'] = _('Checkbox') | |
12 | + names[format] | |
13 | + end | |
14 | + | |
15 | + def custom_field_forms(customized_type) | |
16 | + forms = [] | |
17 | + forms << [_('String'), form_for_format(customized_type,'string')] | |
18 | + forms << [_('Text'), form_for_format(customized_type,'text')] | |
19 | + forms << [_('Date'), form_for_format(customized_type,'date')] | |
20 | + forms << [_('Numeric'), form_for_format(customized_type,'numeric')] | |
21 | + forms << [_('Link'), form_for_format(customized_type,'link')] | |
22 | + forms << [_('List'), form_for_format(customized_type,'list')] | |
23 | + forms << [_('Checkbox'), form_for_format(customized_type,'checkbox')] | |
24 | + forms | |
25 | + end | |
26 | + | |
27 | + def render_extras_field(id, extra=nil, field=nil) | |
28 | + if extra.nil? | |
29 | + CGI::escapeHTML((render(:partial => 'features/custom_fields/extras_field', :locals => {:id => id, :extra => nil, :field => field}))) | |
30 | + else | |
31 | + render :partial => 'features/custom_fields/extras_field', :locals => {:id => id, :extra => extra, :field => field} | |
32 | + end | |
33 | + end | |
34 | + | |
35 | + def form_for_field(field, customized_type) | |
36 | + render :partial => 'features/custom_fields/form', :locals => {:field => field} | |
37 | + end | |
38 | + | |
39 | + def display_custom_field_value(custom_field_value) | |
40 | + value = profile.custom_value(custom_field_value.custom_field.name) | |
41 | + case custom_field_value.custom_field.format | |
42 | + when 'text', 'list', 'numeric', 'date', 'string' | |
43 | + value | |
44 | + when 'checkbox' | |
45 | + value == "1" ? _('Yes') : _('No') | |
46 | + when 'link' | |
47 | + url = value[/\Ahttps?:\/\//i] ? value : "http://#{value}" | |
48 | + link_to(value, url, :target => '_blank') | |
49 | + end | |
50 | + end | |
51 | + | |
52 | + private | |
53 | + | |
54 | + def form_for_format(customized_type, format) | |
55 | + field = CustomField.new(:format => format, :customized_type => customized_type, :environment => environment) | |
56 | + CGI::escapeHTML((render(:partial => 'features/custom_fields/form', :locals => {:field => field}))) | |
57 | + end | |
58 | +end | ... | ... |
app/helpers/forms_helper.rb
... | ... | @@ -186,6 +186,7 @@ module FormsHelper |
186 | 186 | element_id = html_options[:id] || 'datepicker-date' |
187 | 187 | value = value.strftime(format) if value.present? |
188 | 188 | method = datepicker_options[:time] ? 'datetimepicker' : 'datepicker' |
189 | + current_date_or_nil = value.present? ? "new Date('#{value}')" : "null" | |
189 | 190 | result = text_field_tag(name, value, html_options) |
190 | 191 | result += |
191 | 192 | " |
... | ... | @@ -236,7 +237,7 @@ module FormsHelper |
236 | 237 | weekHeader: #{datepicker_options[:week_header].to_json}, |
237 | 238 | yearRange: #{datepicker_options[:year_range].to_json}, |
238 | 239 | yearSuffix: #{datepicker_options[:year_suffix].to_json} |
239 | - }).datepicker('setDate', new Date('#{value}')) | |
240 | + }).datepicker('setDate', current_date_or_nil) | |
240 | 241 | </script> |
241 | 242 | ".html_safe |
242 | 243 | result | ... | ... |
app/models/community.rb
... | ... | @@ -29,7 +29,7 @@ class Community < Organization |
29 | 29 | # places that call this method are safe from mass-assignment by setting the |
30 | 30 | # environment key themselves. |
31 | 31 | def self.create_after_moderation(requestor, attributes = {}) |
32 | - environment = attributes.delete(:environment) | |
32 | + environment = attributes[:environment] | |
33 | 33 | community = Community.new(attributes) |
34 | 34 | community.environment = environment |
35 | 35 | if community.environment.enabled?('admin_must_approve_new_communities') | ... | ... |
... | ... | @@ -0,0 +1,34 @@ |
1 | +class CustomField < ActiveRecord::Base | |
2 | + attr_accessible :name, :default_value, :format, :extras, :customized_type, :active, :required, :signup, :environment | |
3 | + serialize :customized_type | |
4 | + serialize :extras | |
5 | + has_many :custom_field_values, :dependent => :delete_all | |
6 | + belongs_to :environment | |
7 | + | |
8 | + validates_presence_of :name, :format, :customized_type, :environment | |
9 | + validate :related_to_other? | |
10 | + validate :unique? | |
11 | + | |
12 | + def unique? | |
13 | + if environment.custom_fields.any?{|cf| cf.name==name && cf.environment == environment && cf.customized_type==customized_type && new_record?} | |
14 | + errors.add(:body, N_("There is a field with the same name for this type in this environment")) | |
15 | + return false | |
16 | + end | |
17 | + true | |
18 | + end | |
19 | + | |
20 | + def related_to_other? | |
21 | + environment.custom_fields.any? do |cf| | |
22 | + if cf.name == name && cf.customized_type != customized_type | |
23 | + ancestor = cf.customized_type.constantize < customized_type.constantize | |
24 | + descendant = cf.customized_type.constantize > customized_type.constantize | |
25 | + if ancestor || descendant | |
26 | + errors.add(:body, N_("New field related to existent one with same name")) | |
27 | + return false | |
28 | + end | |
29 | + end | |
30 | + end | |
31 | + true | |
32 | + end | |
33 | +end | |
34 | + | ... | ... |
... | ... | @@ -0,0 +1,14 @@ |
1 | +class CustomFieldValue < ActiveRecord::Base | |
2 | + belongs_to :custom_field | |
3 | + belongs_to :customized, :polymorphic => true | |
4 | + attr_accessible :value, :public, :customized, :custom_field, :customized_type | |
5 | + validate :can_save? | |
6 | + | |
7 | + def can_save? | |
8 | + if value.blank? && custom_field.required | |
9 | + errors.add(custom_field.name, _("can't be blank")) | |
10 | + return false | |
11 | + end | |
12 | + return true | |
13 | + end | |
14 | +end | ... | ... |
app/models/environment.rb
... | ... | @@ -24,6 +24,7 @@ class Environment < ActiveRecord::Base |
24 | 24 | |
25 | 25 | has_many :tasks, :dependent => :destroy, :as => 'target' |
26 | 26 | has_many :search_terms, :as => :context |
27 | + has_many :custom_fields, :dependent => :destroy | |
27 | 28 | |
28 | 29 | IDENTIFY_SCRIPTS = /(php[0-9s]?|[sp]htm[l]?|pl|py|cgi|rb)/ |
29 | 30 | ... | ... |
app/models/profile.rb
app/views/account/_signup_form.html.erb
... | ... | @@ -126,6 +126,7 @@ |
126 | 126 | </div> |
127 | 127 | |
128 | 128 | <%= recaptcha_tags :ajax => true, :display => {:theme => 'clean'} if @block_bot %> |
129 | +<%= render :partial => 'shared/custom_fields', :locals => {:f => f, :profile => @person, :signup => true} %> | |
129 | 130 | |
130 | 131 | <p style="text-align: center"> |
131 | 132 | <%= submit_button('save', _('Create my account')) %> | ... | ... |
... | ... | @@ -0,0 +1 @@ |
1 | +<%= labelled_check_box(field.name, name, 1, profile.custom_value(field.name) == '1' )%> | ... | ... |
... | ... | @@ -0,0 +1 @@ |
1 | +<%= labelled_form_field(field.name, date_field(name, profile.custom_value(field.name).to_date, '%Y-%m-%d', {:change_month => true, :change_year => true, :year_range => '-100:-5', :date_format => 'yy-mm-dd'}, {:id => field.name.parameterize.underscore}))%> | ... | ... |
... | ... | @@ -0,0 +1 @@ |
1 | +<%= render :partial => "custom_fields/string", :locals => {:field => field, :profile => profile, :name => name} %> | ... | ... |
... | ... | @@ -0,0 +1 @@ |
1 | +<%= labelled_form_field field.name, number_field_tag(name,profile.custom_value(field.name))%> | ... | ... |
... | ... | @@ -0,0 +1 @@ |
1 | +<%= labelled_form_field field.name, text_field_tag(name, profile.custom_value(field.name), :size => 30) %> | ... | ... |
... | ... | @@ -0,0 +1 @@ |
1 | +<%= labelled_form_field field.name, text_area_tag(name,profile.custom_value(field.name), :rows => 5, :cols => 40)%> | ... | ... |
app/views/features/_manage_community_fields.html.erb
... | ... | @@ -0,0 +1,29 @@ |
1 | +<h1><%= _("Custom Fields") %></h1><hr> | |
2 | + | |
3 | +<% form_id = "#{customized_type.to_s.downcase}-custom-fields-form" %> | |
4 | +<% fields_id = "#{customized_type.to_s.downcase}-custom-fields" %> | |
5 | +<% format_values_id = "#{customized_type.to_s.downcase}-formats" %> | |
6 | + | |
7 | +<%= form_tag({:action => 'manage_custom_fields'}, :id => "#{form_id}") do %> | |
8 | + | |
9 | +<%= hidden_field_tag 'customized_type', customized_type.to_s %> | |
10 | + | |
11 | +<div id="<%= fields_id %>"> | |
12 | + <% customized_type.custom_fields(environment).each do |field|%> | |
13 | + <%= form_for_field(field, customized_type.to_s) %> | |
14 | + <% end %> | |
15 | +</div> | |
16 | + | |
17 | +<div class="addition-buttons"> | |
18 | + <fieldset> | |
19 | + <legend><%= _('New field') %></legend> | |
20 | + <%= select_tag _('Type: '), options_for_select(custom_field_forms(customized_type.to_s)), {:id => "#{format_values_id}"} %> | |
21 | + <%= button(:add, _('Add'), 'javascript: void()', :onClick => "add_content('##{fields_id}',$('##{format_values_id} option:selected').val(), 'NEW_FIELD_ID');") %> | |
22 | + </fieldset> | |
23 | +</div> | |
24 | + | |
25 | +<% button_bar do %> | |
26 | + <%= button(:save, _('Save'), 'javascript: void()', :onClick => "submit_custom_field_form('##{format_values_id}', '##{form_id}');") %> | |
27 | +<% end %> | |
28 | + | |
29 | +<% end %> | ... | ... |
app/views/features/_manage_enterprise_fields.html.erb
app/views/features/_manage_person_fields.html.erb
... | ... | @@ -60,9 +60,7 @@ |
60 | 60 | <%= button :back, _('Back to admin panel'), :controller => 'admin_panel', :action => 'index' %> |
61 | 61 | <% end %> |
62 | 62 | </div> |
63 | - | |
63 | +<br> | |
64 | 64 | <% end %> |
65 | 65 | |
66 | - | |
67 | - | |
68 | - | |
66 | +<%= render :partial => "manage_custom_fields", :locals => {:customized_type => Person} %> | ... | ... |
... | ... | @@ -0,0 +1,15 @@ |
1 | +<% field_id = extra.nil? ? 'EXTRAS_ID' : "#{Time.now.usec}" %> | |
2 | +<% def_value = field.nil? ? '' : field.default_value%> | |
3 | +<tr id='<%= "extras_#{field_id}" %>' > | |
4 | + <td> | |
5 | + <%= text_field_tag "custom_fields[#{id}][extras][#{field_id}]", (extra.nil? ? '' : extra), :onkeyup => "update_default_value($(this).val(), '#custom_fields_#{id}_extras_#{field_id}_default')" %> | |
6 | + </td> | |
7 | + <td> | |
8 | + <%= check_box_tag "custom_fields[#{id}][default_value]", extra.blank? ? '' : extra, extra.blank? ? false : def_value == extra, :id => "custom_fields_#{id}_extras_#{field_id}_default", :onclick => "manage_default_option(this);" %> | |
9 | + </td> | |
10 | + <td> | |
11 | + <% if extra.nil? %> | |
12 | + <%= button_to_function_without_text :remove, _('Remove'), "remove_content('#extras_#{field_id}'); ", :class => 'remove-field', :title => 'Remove alternative' %> | |
13 | + <% end %> | |
14 | + </td> | |
15 | +</tr> | ... | ... |
... | ... | @@ -0,0 +1,43 @@ |
1 | +<% id = field.new_record? ? "NEW_FIELD_ID" : field.id %> | |
2 | + | |
3 | +<div id="<%= id %>" class="custom-field-item"> | |
4 | +<fieldset class="fieldbox"> | |
5 | + <legend><%= format_name(field.format) %></legend> | |
6 | + <%= required labelled_form_field _('Name'), text_field_tag("custom_fields[#{id}][name]", field.name, :size => 30) %> | |
7 | + <%= button_to_function :delete, _('Remove field'), "remove_content('##{id}');" %> | |
8 | + | |
9 | + <% if field.format != "list" %> | |
10 | + <%= labelled_form_field _('Default value'), text_field_tag("custom_fields[#{id}][default_value]", field.default_value, :size => 30) %> | |
11 | + <% end %> | |
12 | + <%= hidden_field_tag "custom_fields[#{id}][customized_type]", field.customized_type.to_s %> | |
13 | + <%= hidden_field_tag "custom_fields[#{id}][format]", field.format %> | |
14 | + | |
15 | + <div> | |
16 | + <%= labelled_check_box _('Active'), "custom_fields[#{id}][active]", 1, field.active, :id => "active_checkbox", :onclick => "active_action('custom_fields[#{id}][active]','custom_fields[#{id}][required]', 'custom_fields[#{id}][signup]')" %> | |
17 | + <%= labelled_check_box _('Required'), "custom_fields[#{id}][required]", 1, field.required, :id => "required_checkbox", :onclick => "required_action('custom_fields[#{id}][active]','custom_fields[#{id}][required]', 'custom_fields[#{id}][signup]')" %> | |
18 | + <%= labelled_check_box _('Display on creation?'), "custom_fields[#{id}][signup]", 1, field.signup, :id => "signup_checkbox",:onclick => "signup_action('custom_fields[#{id}][active]','custom_fields[#{id}][required]', 'custom_fields[#{id}][signup]')" %> | |
19 | + </div> | |
20 | + | |
21 | + <% if field.format == "list" %> | |
22 | + <table> | |
23 | + <thead> | |
24 | + <tr> | |
25 | + <th><%= _("Alternative") %></th> | |
26 | + <th><%= _("Default") %></th> | |
27 | + <th><%= _("Delete") %></th> | |
28 | + </tr> | |
29 | + </thead> | |
30 | + <tfoot> | |
31 | + <tr><td colspan=3><%= button(:add, _('Add option'), 'javascript: void()', :id => "btn_opt_#{id}", :onclick => "add_content('##{id} .custom-field-extras', $('#btn_opt_#{id}').attr('value'), 'EXTRAS_ID');", :value => "#{render_extras_field(id)}") %></td></tr> | |
32 | + </tfoot> | |
33 | + <tbody class="custom-field-extras"> | |
34 | + <% if !field.extras.blank?%> | |
35 | + <% field.extras.each do |extra|%> | |
36 | + <%= render_extras_field id, extra, field %> | |
37 | + <% end %> | |
38 | + <% end %> | |
39 | + </tbody> | |
40 | + </table> | |
41 | + <% end %> | |
42 | +</fieldset> | |
43 | +</div> | ... | ... |
... | ... | @@ -0,0 +1 @@ |
1 | +<%= render :partial => 'features/custom_fields/form' %> | ... | ... |
... | ... | @@ -0,0 +1 @@ |
1 | +<%= render :partial => 'features/custom_fields/form' %> | ... | ... |
app/views/memberships/new_community.html.erb
... | ... | @@ -13,7 +13,6 @@ |
13 | 13 | <%= labelled_form_for :community, :html => { :multipart => true } do |f| %> |
14 | 14 | |
15 | 15 | <%= required_fields_message %> |
16 | - | |
17 | 16 | <%= required f.text_field(:name) %> |
18 | 17 | |
19 | 18 | <% @plugins.dispatch(:new_community_hidden_fields).each do |field| %> |
... | ... | @@ -23,6 +22,7 @@ |
23 | 22 | <% end %> |
24 | 23 | |
25 | 24 | <%= render :partial => 'shared/organization_custom_fields', :locals => { :f => f, :object_name => 'community', :profile => @community } %> |
25 | + <%= render :partial => 'shared/custom_fields', :locals => { :f => f, :profile => @community, :signup => true } %> | |
26 | 26 | |
27 | 27 | <%= f.fields_for :image_builder, @community.image do |i| %> |
28 | 28 | <%= file_field_or_thumbnail(_('Image:'), @community.image, i) %> |
... | ... | @@ -56,7 +56,3 @@ |
56 | 56 | <% end %> |
57 | 57 | |
58 | 58 | </div> |
59 | - | |
60 | - | |
61 | - | |
62 | - | ... | ... |
... | ... | @@ -0,0 +1,11 @@ |
1 | +<% public_values = profile.public_values %> | |
2 | +<% if !public_values.blank?%> | |
3 | + <tr> <th colspan="2"><%= _('Others') %> </th></tr> | |
4 | + <% profile.public_values.each do |cv|%> | |
5 | + <tr> | |
6 | + <td class="field-name"><%= cv.custom_field.name %></td> | |
7 | + <td><%= display_custom_field_value(cv) %></td> | |
8 | + </tr> | |
9 | + <% end%> | |
10 | +<% end %> | |
11 | + | ... | ... |
app/views/profile/_organization_profile.html.erb
app/views/profile/_person_profile.html.erb
app/views/profile_editor/_organization.html.erb
... | ... | @@ -61,6 +61,7 @@ |
61 | 61 | <% end %> |
62 | 62 | |
63 | 63 | <%= render :partial => 'shared/organization_custom_fields', :locals => { :f => f, :object_name => 'profile_data', :profile => @profile } %> |
64 | +<%= render :partial => 'shared/custom_fields', :locals => {:f => f, :profile => @profile, :editing_profile => true} %> | |
64 | 65 | |
65 | 66 | <%= labelled_check_box(_('Enable "contact us"'), 'profile_data[enable_contact_us]', "1", @profile.enable_contact_us) if @profile.enterprise? %> |
66 | 67 | ... | ... |
app/views/profile_editor/_person.html.erb
... | ... | @@ -27,6 +27,7 @@ |
27 | 27 | <%= link_to("Reset token", {:controller => :profile_editor, :action => :reset_private_token, :id => @profile.id}, :class => "button with-text") %> |
28 | 28 | |
29 | 29 | <%= render :partial => 'person_form', :locals => {:f => f} %> |
30 | + <%= render :partial => 'shared/custom_fields', :locals => {:f => f, :profile => @profile, :editing_profile => true} %> | |
30 | 31 | |
31 | 32 | <h2><%= _('Notification options') %></h2> |
32 | 33 | <div> | ... | ... |
... | ... | @@ -0,0 +1,25 @@ |
1 | +<% if signup ||= false %> | |
2 | + <% fields = profile.class.signup_custom_fields environment%> | |
3 | +<% else %> | |
4 | + <% fields = profile.class.active_custom_fields environment%> | |
5 | +<% end %> | |
6 | +<% editing_profile ||= false %> | |
7 | +<% fields.each do |field| %> | |
8 | + <% rendered = render(:partial => "custom_fields/#{field.format}", :locals => {:field => field, :profile => profile, :name => "profile_data[custom_values[#{field.name}[value]]]"})%> | |
9 | + <div class="<%= 'field-with-privacy-selector' if editing_profile %>"> | |
10 | + | |
11 | + <% if field.required%> | |
12 | + <%= required rendered%> | |
13 | + <% else %> | |
14 | + <%= rendered %> | |
15 | + <% end %> | |
16 | + | |
17 | + <% if editing_profile %> | |
18 | + <div class="field-privacy-selector"> | |
19 | + <%= labelled_check_box(_('Public'),"profile_data[custom_values[#{field.name}[public]]]", "true", profile.is_public(field.name))%> | |
20 | + </div> | |
21 | + <% end %> | |
22 | + | |
23 | + </div> | |
24 | +<% end %> | |
25 | + | ... | ... |
app/views/shared/_organization_custom_fields.html.erb
... | ... | @@ -29,4 +29,7 @@ |
29 | 29 | <%= optional_field(profile, 'acronym', f.text_field(:acronym)) %> |
30 | 30 | <%= optional_field(profile, 'foundation_year', f.text_field(:foundation_year)) %> |
31 | 31 | <% end %> |
32 | + | |
33 | +<%= render :partial => 'shared/custom_fields', :locals => {:f => f, :profile => profile, :signup => true} %> | |
34 | + | |
32 | 35 | <%= javascript_include_tag('city_state_validation') %> | ... | ... |
config/initializers/dependencies.rb
... | ... | @@ -18,6 +18,7 @@ require 'acts_as_having_settings' |
18 | 18 | require 'acts_as_having_boxes' |
19 | 19 | require 'acts_as_having_image' |
20 | 20 | require 'acts_as_having_posts' |
21 | +require 'acts_as_customizable' | |
21 | 22 | require 'route_if' |
22 | 23 | require 'maybe_add_http' |
23 | 24 | require 'set_profile_region_from_city_state' | ... | ... |
... | ... | @@ -0,0 +1,31 @@ |
1 | +class CreateCustomFields < ActiveRecord::Migration | |
2 | + def change | |
3 | + create_table :custom_fields do |t| | |
4 | + t.string :name | |
5 | + t.string :format, :default => "" | |
6 | + t.text :default_value, :default => "" | |
7 | + t.string :customized_type | |
8 | + t.text :extras, :default => "" | |
9 | + t.boolean :active, :default => false | |
10 | + t.boolean :required, :default => false | |
11 | + t.boolean :signup, :default => false | |
12 | + t.integer :environment_id | |
13 | + t.timestamps | |
14 | + end | |
15 | + | |
16 | + create_table :custom_field_values do |t| | |
17 | + t.column "customized_type", :string, :default => "", :null => false | |
18 | + t.column "customized_id", :integer, :default => 0, :null => false | |
19 | + t.column "public", :boolean, :default => false, :null => false | |
20 | + t.column "custom_field_id", :integer, :default => 0, :null => false | |
21 | + t.column "value", :text, :default => "" | |
22 | + t.timestamps | |
23 | + end | |
24 | + | |
25 | + | |
26 | + add_index :custom_field_values, ["customized_type", "customized_id","custom_field_id"], :unique => true, :name => 'index_custom_field_values' | |
27 | + add_index :custom_fields, ["customized_type","name","environment_id"], :unique => true, :name => 'index_custom_field' | |
28 | + | |
29 | + end | |
30 | +end | |
31 | + | ... | ... |
... | ... | @@ -0,0 +1,125 @@ |
1 | +module Customizable | |
2 | + | |
3 | + def self.included(base) | |
4 | + base.attr_accessible :custom_values | |
5 | + base.extend ClassMethods | |
6 | + end | |
7 | + | |
8 | + module ClassMethods | |
9 | + def acts_as_customizable(options = {}) | |
10 | + attr_accessor :custom_values | |
11 | + has_many :custom_field_values, :dependent => :delete_all, :as => :customized | |
12 | + send :include, Customizable::InstanceMethods | |
13 | + after_save :save_custom_values | |
14 | + validate :valid_custom_values? | |
15 | + end | |
16 | + | |
17 | + def active_custom_fields environment | |
18 | + environment.custom_fields.select{|cf| customized_ancestors_list.include?(cf.customized_type) && cf.active} | |
19 | + end | |
20 | + | |
21 | + def required_custom_fields environment | |
22 | + environment.custom_fields.select{|cf| customized_ancestors_list.include?(cf.customized_type) && cf.required} | |
23 | + end | |
24 | + | |
25 | + def signup_custom_fields environment | |
26 | + environment.custom_fields.select{|cf| customized_ancestors_list.include?(cf.customized_type) && cf.signup} | |
27 | + end | |
28 | + | |
29 | + def custom_fields environment | |
30 | + environment.custom_fields.select{|cf| customized_ancestors_list.include?(cf.customized_type)} | |
31 | + end | |
32 | + | |
33 | + def customized_ancestors_list | |
34 | + current=self | |
35 | + result=[] | |
36 | + while current.instance_methods.include? :custom_value do | |
37 | + result << current.name | |
38 | + current=current.superclass | |
39 | + end | |
40 | + result | |
41 | + end | |
42 | + | |
43 | + end | |
44 | + | |
45 | + module InstanceMethods | |
46 | + | |
47 | + def valid_custom_values? | |
48 | + is_valid = true | |
49 | + parse_custom_values.each do |cv| | |
50 | + unless cv.valid? | |
51 | + name = cv.custom_field.name | |
52 | + errors.add(name, cv.errors.messages[name.to_sym].first) | |
53 | + is_valid = false | |
54 | + end | |
55 | + end | |
56 | + is_valid | |
57 | + end | |
58 | + | |
59 | + def customized_class | |
60 | + current=self.class | |
61 | + while current.instance_methods.include? :custom_fields do | |
62 | + result=current | |
63 | + current=current.superclass | |
64 | + end | |
65 | + result.name | |
66 | + end | |
67 | + | |
68 | + def is_public(field_name) | |
69 | + cv = self.custom_field_values.detect{|cv| cv.custom_field.name==field_name} | |
70 | + cv.nil? ? false : cv.public | |
71 | + end | |
72 | + | |
73 | + def public_values | |
74 | + self.custom_field_values.select{|cv| cv.public} | |
75 | + end | |
76 | + | |
77 | + def custom_value(field_name) | |
78 | + cv = self.custom_field_values.detect{|cv| cv.custom_field.name==field_name} | |
79 | + cv.nil? ? default_value_for(field_name) : cv.value | |
80 | + end | |
81 | + | |
82 | + def default_value_for(field_name) | |
83 | + field=self.class.custom_fields(environment).detect {|c| c.name == field_name} | |
84 | + field.nil? ? nil : field.default_value | |
85 | + end | |
86 | + | |
87 | + def parse_custom_values | |
88 | + return_list = [] | |
89 | + return return_list if custom_values.blank? | |
90 | + custom_values.each_pair do |key, value| | |
91 | + custom_field = environment.custom_fields.detect{|cf|cf.name==key} | |
92 | + next if custom_field.blank? | |
93 | + custom_field_value = self.custom_field_values.detect{|cv| cv.custom_field.name==key} | |
94 | + | |
95 | + if custom_field_value.nil? | |
96 | + custom_field_value = CustomFieldValue.new | |
97 | + custom_field_value.custom_field = custom_field | |
98 | + custom_field_value.customized = self | |
99 | + end | |
100 | + | |
101 | + if value.is_a?(Hash) | |
102 | + custom_field_value.value = value['value'].to_s | |
103 | + if value.has_key?('public') | |
104 | + is_public = value['public']=="true" || value['public']==true | |
105 | + custom_field_value.public = is_public | |
106 | + else | |
107 | + custom_field_value.public = false | |
108 | + end | |
109 | + else | |
110 | + custom_field_value.value = value.to_s | |
111 | + custom_field_value.public = false | |
112 | + end | |
113 | + return_list << custom_field_value | |
114 | + end | |
115 | + return_list | |
116 | + end | |
117 | + | |
118 | + def save_custom_values | |
119 | + parse_custom_values.each(&:save) | |
120 | + end | |
121 | + | |
122 | + end | |
123 | +end | |
124 | + | |
125 | +ActiveRecord::Base.send(:include, Customizable) | ... | ... |
lib/noosfero/api/entities.rb
... | ... | @@ -15,7 +15,7 @@ module Noosfero |
15 | 15 | } |
16 | 16 | |
17 | 17 | def self.can_display? profile, options, field, permission = :friend |
18 | - return true if profile.public_fields.include?(field) | |
18 | + return true if profile.public_fields.map{|f| f.to_sym}.include?(field.to_sym) | |
19 | 19 | current_person = options[:current_person] |
20 | 20 | |
21 | 21 | current_permission = if current_person.present? |
... | ... | @@ -31,7 +31,6 @@ module Noosfero |
31 | 31 | else |
32 | 32 | :anonymous |
33 | 33 | end |
34 | - | |
35 | 34 | PERMISSIONS[current_permission] <= PERMISSIONS[permission] |
36 | 35 | end |
37 | 36 | |
... | ... | @@ -84,6 +83,20 @@ module Noosfero |
84 | 83 | expose :identifier, :name, :id |
85 | 84 | expose :created_at, :format_with => :timestamp |
86 | 85 | expose :updated_at, :format_with => :timestamp |
86 | + expose :additional_data do |profile, options| | |
87 | + hash ={} | |
88 | + profile.public_values.each do |value| | |
89 | + hash[value.custom_field.name]=value.value | |
90 | + end | |
91 | + | |
92 | + private_values = profile.custom_field_values - profile.public_values | |
93 | + private_values.each do |value| | |
94 | + if Entities.can_display?(profile,options,:custom_field) | |
95 | + hash[value.custom_field.name]=value.value | |
96 | + end | |
97 | + end | |
98 | + hash | |
99 | + end | |
87 | 100 | expose :image, :using => Image |
88 | 101 | expose :region, :using => Region |
89 | 102 | end | ... | ... |
lib/noosfero/api/v1/comments.rb
... | ... | @@ -18,12 +18,12 @@ module Noosfero |
18 | 18 | article = find_article(environment.articles, params[:id]) |
19 | 19 | comments = select_filtered_collection_of(article, :comments, params) |
20 | 20 | |
21 | - present comments, :with => Entities::Comment | |
21 | + present comments, :with => Entities::Comment, :current_person => current_person | |
22 | 22 | end |
23 | 23 | |
24 | 24 | get ":id/comments/:comment_id" do |
25 | 25 | article = find_article(environment.articles, params[:id]) |
26 | - present article.comments.find(params[:comment_id]), :with => Entities::Comment | |
26 | + present article.comments.find(params[:comment_id]), :with => Entities::Comment, :current_person => current_person | |
27 | 27 | end |
28 | 28 | |
29 | 29 | # Example Request: |
... | ... | @@ -31,7 +31,7 @@ module Noosfero |
31 | 31 | post ":id/comments" do |
32 | 32 | article = find_article(environment.articles, params[:id]) |
33 | 33 | options = params.select { |key,v| !['id','private_token'].include?(key) }.merge(:author => current_person, :source => article) |
34 | - present Comment.create(options), :with => Entities::Comment | |
34 | + present Comment.create(options), :with => Entities::Comment, :current_person => current_person | |
35 | 35 | end |
36 | 36 | end |
37 | 37 | ... | ... |
lib/noosfero/api/v1/communities.rb
... | ... | @@ -20,14 +20,21 @@ module Noosfero |
20 | 20 | communities = select_filtered_collection_of(environment, 'communities', params) |
21 | 21 | communities = communities.visible_for_person(current_person) |
22 | 22 | communities = communities.by_location(params) # Must be the last. May return Exception obj. |
23 | - present communities, :with => Entities::Community | |
23 | + present communities, :with => Entities::Community, :current_person => current_person | |
24 | 24 | end |
25 | 25 | |
26 | 26 | |
27 | 27 | # Example Request: |
28 | 28 | # POST api/v1/communties?private_token=234298743290432&community[name]=some_name |
29 | + # for each custom field for community, add &community[field_name]=field_value to the request | |
29 | 30 | post do |
30 | 31 | params[:community] ||= {} |
32 | + | |
33 | + params[:community][:custom_values]={} | |
34 | + params[:community].keys.each do |key| | |
35 | + params[:community][:custom_values][key]=params[:community].delete(key) if Community.custom_fields(environment).any?{|cf| cf.name==key} | |
36 | + end | |
37 | + | |
31 | 38 | begin |
32 | 39 | community = Community.create_after_moderation(current_person, params[:community].merge({:environment => environment})) |
33 | 40 | rescue |
... | ... | @@ -38,12 +45,12 @@ module Noosfero |
38 | 45 | render_api_errors!(community.errors.full_messages) |
39 | 46 | end |
40 | 47 | |
41 | - present community, :with => Entities::Community | |
48 | + present community, :with => Entities::Community, :current_person => current_person | |
42 | 49 | end |
43 | 50 | |
44 | 51 | get ':id' do |
45 | 52 | community = environment.communities.visible_for_person(current_person).find_by_id(params[:id]) |
46 | - present community, :with => Entities::Community | |
53 | + present community, :with => Entities::Community, :current_person => current_person | |
47 | 54 | end |
48 | 55 | |
49 | 56 | end |
... | ... | @@ -58,7 +65,7 @@ module Noosfero |
58 | 65 | person = environment.people.find(params[:person_id]) |
59 | 66 | communities = select_filtered_collection_of(person, 'communities', params) |
60 | 67 | communities = communities.visible |
61 | - present communities, :with => Entities::Community | |
68 | + present communities, :with => Entities::Community, :current_person => current_person | |
62 | 69 | end |
63 | 70 | |
64 | 71 | end | ... | ... |
lib/noosfero/api/v1/enterprises.rb
... | ... | @@ -21,13 +21,13 @@ module Noosfero |
21 | 21 | enterprises = select_filtered_collection_of(environment, 'enterprises', params) |
22 | 22 | enterprises = enterprises.visible_for_person(current_person) |
23 | 23 | enterprises = enterprises.by_location(params) # Must be the last. May return Exception obj. |
24 | - present enterprises, :with => Entities::Enterprise | |
24 | + present enterprises, :with => Entities::Enterprise, :current_person => current_person | |
25 | 25 | end |
26 | 26 | |
27 | 27 | desc "Return one enterprise by id" |
28 | 28 | get ':id' do |
29 | 29 | enterprise = environment.enterprises.visible_for_person(current_person).find_by_id(params[:id]) |
30 | - present enterprise, :with => Entities::Enterprise | |
30 | + present enterprise, :with => Entities::Enterprise, :current_person => current_person | |
31 | 31 | end |
32 | 32 | |
33 | 33 | end |
... | ... | @@ -42,7 +42,7 @@ module Noosfero |
42 | 42 | person = environment.people.find(params[:person_id]) |
43 | 43 | enterprises = select_filtered_collection_of(person, 'enterprises', params) |
44 | 44 | enterprises = enterprises.visible.by_location(params) |
45 | - present enterprises, :with => Entities::Enterprise | |
45 | + present enterprises, :with => Entities::Enterprise, :current_person => current_person | |
46 | 46 | end |
47 | 47 | |
48 | 48 | end | ... | ... |
lib/noosfero/api/v1/people.rb
... | ... | @@ -33,30 +33,31 @@ module Noosfero |
33 | 33 | get do |
34 | 34 | people = select_filtered_collection_of(environment, 'people', params) |
35 | 35 | people = people.visible_for_person(current_person) |
36 | - present people, :with => Entities::Person | |
36 | + present people, :with => Entities::Person, :current_person => current_person | |
37 | 37 | end |
38 | 38 | |
39 | 39 | desc "Return the logged user information" |
40 | 40 | get "/me" do |
41 | - present current_person, :with => Entities::Person | |
41 | + present current_person, :with => Entities::Person, :current_person => current_person | |
42 | 42 | end |
43 | 43 | |
44 | 44 | desc "Return the person information" |
45 | 45 | get ':id' do |
46 | 46 | person = environment.people.visible_for_person(current_person).find_by_id(params[:id]) |
47 | 47 | return not_found! if person.blank? |
48 | - present person, :with => Entities::Person | |
48 | + present person, :with => Entities::Person, :current_person => current_person | |
49 | 49 | end |
50 | 50 | |
51 | 51 | desc "Update person information" |
52 | 52 | post ':id' do |
53 | 53 | return forbidden! if current_person.id.to_s != params[:id] |
54 | 54 | current_person.update_attributes!(params[:person]) |
55 | - present current_person, :with => Entities::Person | |
55 | + present current_person, :with => Entities::Person, :current_person => current_person | |
56 | 56 | end |
57 | 57 | |
58 | 58 | # Example Request: |
59 | 59 | # POST api/v1/people?person[login]=some_login&person[password]=some_password&person[name]=Jack |
60 | + # for each custom field for person, add &person[field_name]=field_value to the request | |
60 | 61 | desc "Create person" |
61 | 62 | post do |
62 | 63 | user_data = {} |
... | ... | @@ -64,14 +65,21 @@ module Noosfero |
64 | 65 | user_data[:email] = params[:person].delete(:email) |
65 | 66 | user_data[:password] = params[:person].delete(:password) |
66 | 67 | user_data[:password_confirmation] = params[:person].delete(:password_confirmation) |
68 | + | |
69 | + params[:person][:custom_values]={} | |
70 | + params[:person].keys.each do |key| | |
71 | + params[:person][:custom_values][key]=params[:person].delete(key) if Person.custom_fields(environment).any?{|cf| cf.name==key} | |
72 | + end | |
73 | + | |
67 | 74 | user = User.build(user_data, params[:person], environment) |
75 | + | |
68 | 76 | begin |
69 | 77 | user.signup! |
70 | 78 | rescue ActiveRecord::RecordInvalid |
71 | 79 | render_api_errors!(user.errors.full_messages) |
72 | 80 | end |
73 | 81 | |
74 | - present user.person, :with => Entities::Person | |
82 | + present user.person, :with => Entities::Person, :current_person => user.person | |
75 | 83 | end |
76 | 84 | |
77 | 85 | desc "Return the person friends" |
... | ... | @@ -79,7 +87,7 @@ module Noosfero |
79 | 87 | person = environment.people.visible_for_person(current_person).find_by_id(params[:id]) |
80 | 88 | return not_found! if person.blank? |
81 | 89 | friends = person.friends.visible |
82 | - present friends, :with => Entities::Person | |
90 | + present friends, :with => Entities::Person, :current_person => current_person | |
83 | 91 | end |
84 | 92 | |
85 | 93 | desc "Return the person permissions on other profiles" | ... | ... |
public/javascripts/manage-fields.js
... | ... | @@ -36,6 +36,34 @@ function signup_action(name_active, name_required, name_signup) { |
36 | 36 | update_active(name_active, name_required, name_signup) |
37 | 37 | } |
38 | 38 | |
39 | +function add_content(target_id, content, mask) { | |
40 | + var id = new Date().getTime(); | |
41 | + var regexp = new RegExp(mask, "g"); | |
42 | + content = content.replace(regexp, id); | |
43 | + $(target_id).append(content); | |
44 | + $('#' + id).hide().slideDown(); | |
45 | +} | |
46 | + | |
47 | +function remove_content(target) { | |
48 | + $(target).remove(); | |
49 | +} | |
50 | + | |
51 | +function submit_custom_field_form(selector_id, form_id, customized_type) { | |
52 | + $(selector_id).attr('disabled', true); | |
53 | + $(form_id).submit(); | |
54 | +} | |
55 | + | |
56 | +function manage_default_option(source) { | |
57 | + var th = $(source); | |
58 | + var name = th.prop('name'); | |
59 | + if(th.is(':checked')){ | |
60 | + $(':checkbox[name="' + name + '"]').not($(source)).prop('checked',false); | |
61 | + } | |
62 | +} | |
63 | + | |
64 | +function update_default_value(source, target) { | |
65 | + $(target).val(source); | |
66 | +} | |
39 | 67 | |
40 | 68 | jQuery(document).ready(function(){ |
41 | 69 | function check_fields(check, table_id, start) { | ... | ... |
public/stylesheets/manage-fields.scss
test/functional/features_controller_test.rb
... | ... | @@ -8,6 +8,7 @@ class FeaturesControllerTest < ActionController::TestCase |
8 | 8 | @controller = FeaturesController.new |
9 | 9 | @request = ActionController::TestRequest.new |
10 | 10 | @response = ActionController::TestResponse.new |
11 | + | |
11 | 12 | login_as(create_admin_user(Environment.find(2))) |
12 | 13 | end |
13 | 14 | |
... | ... | @@ -159,4 +160,51 @@ class FeaturesControllerTest < ActionController::TestCase |
159 | 160 | assert_includes json_response, {"id"=>person.id, "name"=>person.name} |
160 | 161 | end |
161 | 162 | |
163 | + should 'create custom field' do | |
164 | + uses_host 'anhetegua.net' | |
165 | + assert_nil Environment.find(2).custom_fields.find_by_name('foo') | |
166 | + post :manage_custom_fields, :customized_type => 'Person', :custom_fields => { | |
167 | + Time.now.to_i => { | |
168 | + :name => 'foo', | |
169 | + :default_value => 'foobar', | |
170 | + :format => 'string', | |
171 | + :customized_type => 'Person', | |
172 | + :active => true, | |
173 | + :required => true, | |
174 | + :signup => true | |
175 | + } | |
176 | + } | |
177 | + assert_redirected_to :action => 'manage_fields' | |
178 | + assert_not_nil Environment.find(2).custom_fields.find_by_name('foo') | |
179 | + end | |
180 | + | |
181 | + should 'update custom field' do | |
182 | + uses_host 'anhetegua.net' | |
183 | + | |
184 | + field = CustomField.create! :name => 'foo', :default_value => 'foobar', :format => 'string', :extras => '', :customized_type => 'Enterprise', :active => true, :required => true, :signup => true, :environment => Environment.find(2) | |
185 | + post :manage_custom_fields, :customized_type => 'Enterprise', :custom_fields => { | |
186 | + field.id => { | |
187 | + :name => 'foo bar', | |
188 | + :default_value => 'foobar', | |
189 | + :active => true, | |
190 | + :required => true, | |
191 | + :signup => true | |
192 | + } | |
193 | + } | |
194 | + field.reload | |
195 | + assert_redirected_to :action => 'manage_fields' | |
196 | + assert_equal 'foo bar', field.name | |
197 | + end | |
198 | + | |
199 | + should 'destroy custom field' do | |
200 | + uses_host 'anhetegua.net' | |
201 | + | |
202 | + field = CustomField.create! :name => 'foo', :default_value => 'foobar', :format => 'string', :extras => '', :customized_type => 'Enterprise', :active => true, :required => true, :signup => true, :environment => Environment.find(2) | |
203 | + | |
204 | + post :manage_custom_fields, :customized_type => 'Enterprise' | |
205 | + | |
206 | + assert_redirected_to :action => 'manage_fields' | |
207 | + assert_nil Environment.find(2).custom_fields.find_by_name('foo') | |
208 | + end | |
209 | + | |
162 | 210 | end | ... | ... |
... | ... | @@ -0,0 +1,23 @@ |
1 | +require_relative "../test_helper" | |
2 | + | |
3 | +class ActsAsCustomizableTest < ActiveSupport::TestCase | |
4 | + | |
5 | + should 'save custom field values for person' do | |
6 | + CustomField.create!(:name => "Blog", :format => "string", :customized_type => "Person", :active => true, :environment => Environment.default) | |
7 | + person = create_user('testinguser').person | |
8 | + assert_difference 'CustomFieldValue.count' do | |
9 | + person.custom_values = { "Blog" => { "value" => "www.blog.org", "public" => "0"} } | |
10 | + person.save! | |
11 | + assert_equal 'www.blog.org', CustomFieldValue.find(:last, :conditions => {:customized_id => person.id}).value | |
12 | + end | |
13 | + end | |
14 | + | |
15 | + should 'not be valid when required custom field not filled' do | |
16 | + CustomField.create!(:name => "Blog", :format => "string", :customized_type => "Person", :active => true, :environment => Environment.default, :required => true) | |
17 | + person = create_user('testinguser').person | |
18 | + | |
19 | + person.custom_values = { "Blog" => { "value" => "", "public" => "0"} } | |
20 | + refute person.valid? | |
21 | + end | |
22 | + | |
23 | +end | ... | ... |
test/unit/api/people_test.rb
... | ... | @@ -165,4 +165,44 @@ class PeopleTest < ActiveSupport::TestCase |
165 | 165 | assert_equal another_name, person.name |
166 | 166 | end |
167 | 167 | |
168 | + should 'display public custom fields' do | |
169 | + CustomField.create!(:name => "Custom Blog", :format => "string", :customized_type => "Person", :active => true, :environment => Environment.default) | |
170 | + some_person = create_user('some-person').person | |
171 | + some_person.custom_values = { "Custom Blog" => { "value" => "www.blog.org", "public" => "true"} } | |
172 | + some_person.save! | |
173 | + | |
174 | + get "/api/v1/people/#{some_person.id}?#{params.to_query}" | |
175 | + json = JSON.parse(last_response.body) | |
176 | + assert json['person']['additional_data'].has_key?('Custom Blog') | |
177 | + assert_equal "www.blog.org", json['person']['additional_data']['Custom Blog'] | |
178 | + end | |
179 | + | |
180 | + should 'not display non-public custom fields' do | |
181 | + CustomField.create!(:name => "Custom Blog", :format => "string", :customized_type => "Person", :active => true, :environment => Environment.default) | |
182 | + some_person = create_user('some-person').person | |
183 | + some_person.custom_values = { "Custom Blog" => { "value" => "www.blog.org", "public" => "0"} } | |
184 | + some_person.save! | |
185 | + | |
186 | + get "/api/v1/people/#{some_person.id}?#{params.to_query}" | |
187 | + json = JSON.parse(last_response.body) | |
188 | + assert_equal json['person']['additional_data'], {} | |
189 | + end | |
190 | + | |
191 | + should 'display non-public custom fields to friend' do | |
192 | + CustomField.create!(:name => "Custom Blog", :format => "string", :customized_type => "Person", :active => true, :environment => Environment.default) | |
193 | + some_person = create_user('some-person').person | |
194 | + some_person.custom_values = { "Custom Blog" => { "value" => "www.blog.org", "public" => "0"} } | |
195 | + some_person.save! | |
196 | + | |
197 | + f = Friendship.new | |
198 | + f.friend = some_person | |
199 | + f.person = person | |
200 | + f.save! | |
201 | + | |
202 | + get "/api/v1/people/#{some_person.id}?#{params.to_query}" | |
203 | + json = JSON.parse(last_response.body) | |
204 | + assert json['person']['additional_data'].has_key?("Custom Blog") | |
205 | + assert_equal "www.blog.org", json['person']['additional_data']['Custom Blog'] | |
206 | + end | |
207 | + | |
168 | 208 | end | ... | ... |
... | ... | @@ -0,0 +1,153 @@ |
1 | +require_relative "../test_helper" | |
2 | + | |
3 | +class CustomFieldTest < ActiveSupport::TestCase | |
4 | + | |
5 | + def setup | |
6 | + @person = create_user('test_user').person | |
7 | + | |
8 | + @e1 = Environment.default | |
9 | + @e2 = fast_create(Environment) | |
10 | + | |
11 | + @community = create(Community, :environment => @e1, :name => 'my new community') | |
12 | + | |
13 | + @community_custom_field = CustomField.create(:name => "community_field", :format=>"myFormat", :default_value => "value for community", :customized_type=>"Community", :active => true, :environment => @e1) | |
14 | + @person_custom_field = CustomField.create(:name => "person_field", :format=>"myFormat", :default_value => "value for person", :customized_type=>"Person", :active => true, :environment => @e1) | |
15 | + @profile_custom_field = CustomField.create(:name => "profile_field", :format=>"myFormat", :default_value => "value for any profile", :customized_type=>"Profile", :active => true, :environment => @e1) | |
16 | + | |
17 | + @e1.reload | |
18 | + end | |
19 | + | |
20 | + should 'not access another environments custom fields' do | |
21 | + @e2_custom_field = CustomField.create(:name => "another_field", :format=>"anoherFormat", :default_value => "default value for e2", :customized_type=>"Profile", :active => true, :environment => @e2) | |
22 | + @e2.reload | |
23 | + | |
24 | + assert_equal 1, Profile.custom_fields(@e1).size | |
25 | + assert_equal @profile_custom_field, Profile.custom_fields(@e1).first | |
26 | + | |
27 | + assert_equal 1, Profile.custom_fields(@e2).size | |
28 | + assert_equal @e2_custom_field, Profile.custom_fields(@e2).first | |
29 | + | |
30 | + end | |
31 | + | |
32 | + should 'no access to custom field on sibling' do | |
33 | + refute (Person.custom_fields(@e1).any?{|cf| cf.name == @community_custom_field.name}) | |
34 | + refute (Community.custom_fields(@e1).any?{|cf| cf.name == @person_custom_field.name}) | |
35 | + end | |
36 | + | |
37 | + should 'inheritance of custom_field' do | |
38 | + assert Community.custom_fields(@e1).any?{|cf| cf.name == @profile_custom_field.name} | |
39 | + assert Person.custom_fields(@e1).any?{|cf| cf.name == @profile_custom_field.name} | |
40 | + end | |
41 | + | |
42 | + should 'save custom_field_values' do | |
43 | + @community.custom_values = {"community_field" => "new_value!", "profile_field"=> "another_value!"} | |
44 | + @community.save | |
45 | + | |
46 | + assert CustomFieldValue.all.any?{|cv| cv.custom_field_id == @community_custom_field.id && cv.customized_id == @community.id && cv.value == "new_value!"} | |
47 | + assert CustomFieldValue.all.any?{|cv| cv.custom_field_id == @profile_custom_field.id && cv.customized_id == @community.id && cv.value = "another_value!"} | |
48 | + end | |
49 | + | |
50 | + should 'delete custom field and its values' do | |
51 | + @community.custom_values = {"community_field" => "new_value!", "profile_field"=> "another_value!"} | |
52 | + @community.save | |
53 | + | |
54 | + old_id = @community_custom_field.id | |
55 | + @community_custom_field.destroy | |
56 | + | |
57 | + @e1.reload | |
58 | + refute (@e1.custom_fields.any?{|cf| cf.id == old_id}) | |
59 | + refute (Community.custom_fields(@e1).any?{|cf| cf.name == "community_field"}) | |
60 | + refute (CustomFieldValue.all.any?{|cv| cv.custom_field_id == old_id}) | |
61 | + end | |
62 | + | |
63 | + should 'not save related custom field' do | |
64 | + another_field = CustomField.create(:name => "profile_field", :format=>"myFormat", :default_value => "value for any profile", :customized_type=>"Community", :environment => @e1) | |
65 | + assert another_field.id.nil? | |
66 | + end | |
67 | + | |
68 | + should 'not save same custom field twice in the same environment' do | |
69 | + field = CustomField.create(:name => "the new field", :format=>"myFormat", :customized_type=>"Community", :environment => @e1) | |
70 | + refute field.id.nil? | |
71 | + @e1.reload | |
72 | + another = CustomField.new(:name => "the new field", :format=>"myFormat", :customized_type=>"Community", :environment => @e1) | |
73 | + refute another.valid? | |
74 | + end | |
75 | + | |
76 | + should 'save same custom field in another environment' do | |
77 | + field = CustomField.create(:name => "the new field", :format=>"myFormat", :customized_type=>"Community", :environment => @e1) | |
78 | + refute field.id.nil? | |
79 | + another_field = CustomField.create(:name => "the new field", :format=>"myFormat", :customized_type=>"Community", :environment => @e2) | |
80 | + refute another_field.id.nil? | |
81 | + end | |
82 | + | |
83 | + should 'not return inactive fields' do | |
84 | + @community_custom_field.update_attributes(:active=>false) | |
85 | + @e1.reload | |
86 | + refute Community.active_custom_fields(@e1).any?{|cf| cf.name == @community_custom_field.name} | |
87 | + end | |
88 | + | |
89 | + should 'delete a model and its custom field values' do | |
90 | + @community.custom_values = {"community_field" => "new_value!", "profile_field"=> "another_value!"} | |
91 | + @community.save | |
92 | + | |
93 | + old_id = @community.id | |
94 | + @community.destroy | |
95 | + refute (Community.all.any?{|c| c.id == old_id}) | |
96 | + refute (CustomFieldValue.all.any?{|cv| cv.customized_id == old_id && cv.customized_type == "Community"}) | |
97 | + end | |
98 | + | |
99 | + should 'keep field value if the field is reactivated' do | |
100 | + | |
101 | + @community.custom_values = {"community_field" => "new_value!"} | |
102 | + @community.save | |
103 | + | |
104 | + @community_custom_field.update_attributes(:active=>false) | |
105 | + @e1.reload | |
106 | + refute Community.active_custom_fields(@e1).any?{|cf| cf.name == @community_custom_field.name} | |
107 | + | |
108 | + @community_custom_field.update_attributes(:active=>true) | |
109 | + | |
110 | + @e1.reload | |
111 | + @community.reload | |
112 | + assert Community.active_custom_fields(@e1).any?{|cf| cf.name == @community_custom_field.name} | |
113 | + assert_equal @community.custom_value("community_field"), "new_value!" | |
114 | + end | |
115 | + | |
116 | + should 'list of required fields' do | |
117 | + refute Community.required_custom_fields(@e1).any?{|cf| cf.name == @community_custom_field.name} | |
118 | + | |
119 | + @community_custom_field.update_attributes(:required=>true) | |
120 | + @community.reload | |
121 | + @e1.reload | |
122 | + assert Community.required_custom_fields(@e1).any?{|cf| cf.name == @community_custom_field.name} | |
123 | + end | |
124 | + | |
125 | + should 'list of signup fields' do | |
126 | + refute Community.signup_custom_fields(@e1).any?{|cf| cf.name == @community_custom_field.name} | |
127 | + | |
128 | + @community_custom_field.update_attributes(:signup=>true) | |
129 | + @community.reload | |
130 | + @e1.reload | |
131 | + assert Community.signup_custom_fields(@e1).any?{|cf| cf.name == @community_custom_field.name} | |
132 | + end | |
133 | + | |
134 | + should 'public values handling' do | |
135 | + refute @community.is_public("community_field") | |
136 | + @community.custom_values = {"community_field" => {"value" => "new_value!", "public"=>"true"}, "profile_field"=> "another_value!"} | |
137 | + @community.save | |
138 | + @community.reload | |
139 | + | |
140 | + assert @community.is_public("community_field") | |
141 | + refute @community.is_public("profile_field") | |
142 | + end | |
143 | + | |
144 | + should 'complete list of fields' do | |
145 | + assert Person.custom_fields(@e1).include? @profile_custom_field | |
146 | + assert Person.custom_fields(@e1).include? @person_custom_field | |
147 | + end | |
148 | + | |
149 | + should 'get correct customized ancestors list' do | |
150 | + assert (Person.customized_ancestors_list-["Person","Profile"]).blank? | |
151 | + end | |
152 | +end | |
153 | + | ... | ... |
... | ... | @@ -0,0 +1,12 @@ |
1 | +require_relative "../test_helper" | |
2 | + | |
3 | +class CustomFieldValuesTest < ActiveSupport::TestCase | |
4 | + | |
5 | + should 'custom field value not be valid' do | |
6 | + c = CustomField.create!(:name => "Blog", :format => "string", :customized_type => "Person", :active => true, :required => true, :environment => Environment.default) | |
7 | + person = create_user('testinguser').person | |
8 | + | |
9 | + cv=CustomFieldValue.new(:customized => person, :custom_field => c, :value => "") | |
10 | + refute cv.valid? | |
11 | + end | |
12 | +end | ... | ... |