[Git][noosfero/noosfero][master] 2 commits: Add custom field feature to core
Joenio Costa
gitlab at mg.gitlab.com
Wed Nov 18 22:53:49 BRST 2015
Joenio Costa pushed to branch master at Noosfero / noosfero
Commits:
7be7e7c6 by Marcos Ronaldo at 2015-11-18T16:36:42Z
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 behaviour as the current
Noosfero's fields (active, signup, required and privacy).
Signed-off-by: Fabio Teixeira <fabio1079 at gmail.com>
Signed-off-by: Gustavo Coelho <gust.rod.coelho at gmail.com>
Signed-off-by: Joenio Costa <joenio at colivre.coop.br>
Signed-off-by: Macartur de Sousa <macartur.sc at gmail.com>
Signed-off-by: Marcos Ramos <ms.ramos at outlook.com>
Signed-off-by: Marcos Ronaldo <marcos.rpj2 at gmail.com>
Signed-off-by: Pedro de Lyra <pedrodelyra at gmail.com>
Signed-off-by: Tallys Martins <tallysmartins at gmail.com>
- - - - -
84ca7256 by Joenio Costa at 2015-11-19T00:53:28Z
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
- - - - -
52 changed files:
- app/controllers/admin/features_controller.rb
- app/controllers/my_profile/memberships_controller.rb
- app/controllers/my_profile/profile_editor_controller.rb
- app/controllers/public/account_controller.rb
- app/controllers/public/profile_controller.rb
- + app/helpers/custom_fields_helper.rb
- app/helpers/forms_helper.rb
- app/models/community.rb
- + app/models/custom_field.rb
- + app/models/custom_field_value.rb
- app/models/environment.rb
- app/models/profile.rb
- app/views/account/_signup_form.html.erb
- + app/views/custom_fields/_checkbox.html.erb
- + app/views/custom_fields/_date.html.erb
- + app/views/custom_fields/_link.html.erb
- + app/views/custom_fields/_list.html.erb
- + app/views/custom_fields/_numeric.html.erb
- + app/views/custom_fields/_string.html.erb
- + app/views/custom_fields/_text.html.erb
- app/views/features/_manage_community_fields.html.erb
- + app/views/features/_manage_custom_fields.html.erb
- app/views/features/_manage_enterprise_fields.html.erb
- app/views/features/_manage_person_fields.html.erb
- + app/views/features/custom_fields/_extras_field.html.erb
- + app/views/features/custom_fields/_form.html.erb
- + app/views/features/custom_fields/_view.html.erb
- + app/views/features/custom_fields/edit.html.erb
- + app/views/features/custom_fields/new.html.erb
- app/views/memberships/new_community.html.erb
- + app/views/profile/_custom_fields.html.erb
- app/views/profile/_organization_profile.html.erb
- app/views/profile/_person_profile.html.erb
- app/views/profile_editor/_organization.html.erb
- app/views/profile_editor/_person.html.erb
- + app/views/shared/_custom_fields.html.erb
- app/views/shared/_organization_custom_fields.html.erb
- config/initializers/dependencies.rb
- + db/migrate/20150921140802_create_custom_fields.rb
- + lib/acts_as_customizable.rb
- lib/noosfero/api/entities.rb
- lib/noosfero/api/v1/comments.rb
- lib/noosfero/api/v1/communities.rb
- lib/noosfero/api/v1/enterprises.rb
- lib/noosfero/api/v1/people.rb
- public/javascripts/manage-fields.js
- public/stylesheets/manage-fields.scss
- test/functional/features_controller_test.rb
- + test/unit/acts_as_customizable_test.rb
- test/unit/api/people_test.rb
- + test/unit/custom_field_test.rb
- + test/unit/custom_field_values_test.rb
Changes:
=====================================
app/controllers/admin/features_controller.rb
=====================================
--- a/app/controllers/admin/features_controller.rb
+++ b/app/controllers/admin/features_controller.rb
@@ -1,5 +1,6 @@
class FeaturesController < AdminController
protect 'edit_environment_features', :environment
+ helper CustomFieldsHelper
def index
@features = Environment.available_features.sort_by{|k,v|v}
@@ -51,6 +52,34 @@ class FeaturesController < AdminController
redirect_to :action => 'manage_fields'
end
+ def manage_custom_fields
+ custom_field_list = params[:custom_fields] || {}
+
+ custom_fields_to_destroy =
+ params[:customized_type].constantize.custom_fields(environment).map(&:id) - custom_field_list.keys.map(&:to_i)
+ CustomField.destroy(custom_fields_to_destroy)
+
+ custom_field_list.each_pair do |id, custom_field|
+ field = CustomField.find_by_id(id)
+ if not field.blank?
+ params_to_update = custom_field.except(:format, :extras, :customized_type,:environment)
+ field.update_attributes(params_to_update)
+ else
+ if !custom_field[:extras].nil?
+ tmp = []
+ custom_field[:extras].each_pair do |k, v|
+ tmp << v
+ end
+ custom_field[:extras] = tmp
+ end
+ field = CustomField.new custom_field.except(:environment)
+ field.environment=environment
+ field.save if field.valid?
+ end
+ end
+ redirect_to :action => 'manage_fields'
+ end
+
def search_members
arg = params[:q].downcase
result = environment.people.where('LOWER(name) LIKE ? OR identifier LIKE ?', "%#{arg}%", "%#{arg}%")
=====================================
app/controllers/my_profile/memberships_controller.rb
=====================================
--- a/app/controllers/my_profile/memberships_controller.rb
+++ b/app/controllers/my_profile/memberships_controller.rb
@@ -1,6 +1,7 @@
class MembershipsController < MyProfileController
protect 'manage_memberships', :profile
+ helper CustomFieldsHelper
def index
@roles = environment.roles.select do |role|
=====================================
app/controllers/my_profile/profile_editor_controller.rb
=====================================
--- a/app/controllers/my_profile/profile_editor_controller.rb
+++ b/app/controllers/my_profile/profile_editor_controller.rb
@@ -8,6 +8,7 @@ class ProfileEditorController < MyProfileController
before_filter :forbid_destroy_profile, :only => [:destroy_profile]
before_filter :check_user_can_edit_header_footer, :only => [:header_footer]
helper_method :has_welcome_page
+ helper CustomFieldsHelper
def index
@pending_tasks = Task.to(profile).pending.without_spam.select{|i| user.has_permission?(i.permission, profile)}
=====================================
app/controllers/public/account_controller.rb
=====================================
--- a/app/controllers/public/account_controller.rb
+++ b/app/controllers/public/account_controller.rb
@@ -6,6 +6,7 @@ class AccountController < ApplicationController
before_filter :redirect_if_logged_in, :only => [:login, :signup]
before_filter :protect_from_bots, :only => :signup
+ helper CustomFieldsHelper
# say something nice, you goof! something sweet.
def index
unless logged_in?
=====================================
app/controllers/public/profile_controller.rb
=====================================
--- a/app/controllers/public/profile_controller.rb
+++ b/app/controllers/public/profile_controller.rb
@@ -7,6 +7,7 @@ class ProfileController < PublicController
helper TagsHelper
helper ActionTrackerHelper
+ helper CustomFieldsHelper
protect 'send_mail_to_members', :profile, :only => [:send_mail]
=====================================
app/helpers/custom_fields_helper.rb
=====================================
--- /dev/null
+++ b/app/helpers/custom_fields_helper.rb
@@ -0,0 +1,58 @@
+module CustomFieldsHelper
+
+ def format_name(format)
+ names = {}
+ names['string'] = _('String')
+ names['text'] = _('Text')
+ names['date'] = _('Date')
+ names['numeric'] = _('Numeric')
+ names['link'] = _('Link')
+ names['list'] = _('List')
+ names['checkbox'] = _('Checkbox')
+ names[format]
+ end
+
+ def custom_field_forms(customized_type)
+ forms = []
+ forms << [_('String'), form_for_format(customized_type,'string')]
+ forms << [_('Text'), form_for_format(customized_type,'text')]
+ forms << [_('Date'), form_for_format(customized_type,'date')]
+ forms << [_('Numeric'), form_for_format(customized_type,'numeric')]
+ forms << [_('Link'), form_for_format(customized_type,'link')]
+ forms << [_('List'), form_for_format(customized_type,'list')]
+ forms << [_('Checkbox'), form_for_format(customized_type,'checkbox')]
+ forms
+ end
+
+ def render_extras_field(id, extra=nil, field=nil)
+ if extra.nil?
+ CGI::escapeHTML((render(:partial => 'features/custom_fields/extras_field', :locals => {:id => id, :extra => nil, :field => field})))
+ else
+ render :partial => 'features/custom_fields/extras_field', :locals => {:id => id, :extra => extra, :field => field}
+ end
+ end
+
+ def form_for_field(field, customized_type)
+ render :partial => 'features/custom_fields/form', :locals => {:field => field}
+ end
+
+ def display_custom_field_value(custom_field_value)
+ value = profile.custom_value(custom_field_value.custom_field.name)
+ case custom_field_value.custom_field.format
+ when 'text', 'list', 'numeric', 'date', 'string'
+ value
+ when 'checkbox'
+ value == "1" ? _('Yes') : _('No')
+ when 'link'
+ url = value[/\Ahttps?:\/\//i] ? value : "http://#{value}"
+ link_to(value, url, :target => '_blank')
+ end
+ end
+
+ private
+
+ def form_for_format(customized_type, format)
+ field = CustomField.new(:format => format, :customized_type => customized_type, :environment => environment)
+ CGI::escapeHTML((render(:partial => 'features/custom_fields/form', :locals => {:field => field})))
+ end
+end
=====================================
app/helpers/forms_helper.rb
=====================================
--- a/app/helpers/forms_helper.rb
+++ b/app/helpers/forms_helper.rb
@@ -186,6 +186,7 @@ module FormsHelper
element_id = html_options[:id] || 'datepicker-date'
value = value.strftime(format) if value.present?
method = datepicker_options[:time] ? 'datetimepicker' : 'datepicker'
+ current_date_or_nil = value.present? ? "new Date('#{value}')" : "null"
result = text_field_tag(name, value, html_options)
result +=
"
@@ -236,7 +237,7 @@ module FormsHelper
weekHeader: #{datepicker_options[:week_header].to_json},
yearRange: #{datepicker_options[:year_range].to_json},
yearSuffix: #{datepicker_options[:year_suffix].to_json}
- }).datepicker('setDate', new Date('#{value}'))
+ }).datepicker('setDate', current_date_or_nil)
</script>
".html_safe
result
=====================================
app/models/community.rb
=====================================
--- a/app/models/community.rb
+++ b/app/models/community.rb
@@ -29,7 +29,7 @@ class Community < Organization
# places that call this method are safe from mass-assignment by setting the
# environment key themselves.
def self.create_after_moderation(requestor, attributes = {})
- environment = attributes.delete(:environment)
+ environment = attributes[:environment]
community = Community.new(attributes)
community.environment = environment
if community.environment.enabled?('admin_must_approve_new_communities')
=====================================
app/models/custom_field.rb
=====================================
--- /dev/null
+++ b/app/models/custom_field.rb
@@ -0,0 +1,34 @@
+class CustomField < ActiveRecord::Base
+ attr_accessible :name, :default_value, :format, :extras, :customized_type, :active, :required, :signup, :environment
+ serialize :customized_type
+ serialize :extras
+ has_many :custom_field_values, :dependent => :delete_all
+ belongs_to :environment
+
+ validates_presence_of :name, :format, :customized_type, :environment
+ validate :related_to_other?
+ validate :unique?
+
+ def unique?
+ if environment.custom_fields.any?{|cf| cf.name==name && cf.environment == environment && cf.customized_type==customized_type && new_record?}
+ errors.add(:body, N_("There is a field with the same name for this type in this environment"))
+ return false
+ end
+ true
+ end
+
+ def related_to_other?
+ environment.custom_fields.any? do |cf|
+ if cf.name == name && cf.customized_type != customized_type
+ ancestor = cf.customized_type.constantize < customized_type.constantize
+ descendant = cf.customized_type.constantize > customized_type.constantize
+ if ancestor || descendant
+ errors.add(:body, N_("New field related to existent one with same name"))
+ return false
+ end
+ end
+ end
+ true
+ end
+end
+
=====================================
app/models/custom_field_value.rb
=====================================
--- /dev/null
+++ b/app/models/custom_field_value.rb
@@ -0,0 +1,14 @@
+class CustomFieldValue < ActiveRecord::Base
+ belongs_to :custom_field
+ belongs_to :customized, :polymorphic => true
+ attr_accessible :value, :public, :customized, :custom_field, :customized_type
+ validate :can_save?
+
+ def can_save?
+ if value.blank? && custom_field.required
+ errors.add(custom_field.name, _("can't be blank"))
+ return false
+ end
+ return true
+ end
+end
=====================================
app/models/environment.rb
=====================================
--- a/app/models/environment.rb
+++ b/app/models/environment.rb
@@ -24,6 +24,7 @@ class Environment < ActiveRecord::Base
has_many :tasks, :dependent => :destroy, :as => 'target'
has_many :search_terms, :as => :context
+ has_many :custom_fields, :dependent => :destroy
IDENTIFY_SCRIPTS = /(php[0-9s]?|[sp]htm[l]?|pl|py|cgi|rb)/
=====================================
app/models/profile.rb
=====================================
--- a/app/models/profile.rb
+++ b/app/models/profile.rb
@@ -84,6 +84,7 @@ class Profile < ActiveRecord::Base
}
acts_as_accessible
+ acts_as_customizable
include Noosfero::Plugin::HotSpot
=====================================
app/views/account/_signup_form.html.erb
=====================================
--- a/app/views/account/_signup_form.html.erb
+++ b/app/views/account/_signup_form.html.erb
@@ -126,6 +126,7 @@
</div>
<%= recaptcha_tags :ajax => true, :display => {:theme => 'clean'} if @block_bot %>
+<%= render :partial => 'shared/custom_fields', :locals => {:f => f, :profile => @person, :signup => true} %>
<p style="text-align: center">
<%= submit_button('save', _('Create my account')) %>
=====================================
app/views/custom_fields/_checkbox.html.erb
=====================================
--- /dev/null
+++ b/app/views/custom_fields/_checkbox.html.erb
@@ -0,0 +1 @@
+<%= labelled_check_box(field.name, name, 1, profile.custom_value(field.name) == '1' )%>
=====================================
app/views/custom_fields/_date.html.erb
=====================================
--- /dev/null
+++ b/app/views/custom_fields/_date.html.erb
@@ -0,0 +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}))%>
=====================================
app/views/custom_fields/_link.html.erb
=====================================
--- /dev/null
+++ b/app/views/custom_fields/_link.html.erb
@@ -0,0 +1 @@
+<%= render :partial => "custom_fields/string", :locals => {:field => field, :profile => profile, :name => name} %>
=====================================
app/views/custom_fields/_list.html.erb
=====================================
--- /dev/null
+++ b/app/views/custom_fields/_list.html.erb
@@ -0,0 +1,2 @@
+<%= label_tag field.name, nil, class: 'formlabel'%>
+<%= select_tag name, options_for_select(field.extras.map{|v| [v,v]}, profile.custom_value(field.name)), {:prompt => _('[Select ...]') } %>
=====================================
app/views/custom_fields/_numeric.html.erb
=====================================
--- /dev/null
+++ b/app/views/custom_fields/_numeric.html.erb
@@ -0,0 +1 @@
+<%= labelled_form_field field.name, number_field_tag(name,profile.custom_value(field.name))%>
=====================================
app/views/custom_fields/_string.html.erb
=====================================
--- /dev/null
+++ b/app/views/custom_fields/_string.html.erb
@@ -0,0 +1 @@
+<%= labelled_form_field field.name, text_field_tag(name, profile.custom_value(field.name), :size => 30) %>
=====================================
app/views/custom_fields/_text.html.erb
=====================================
--- /dev/null
+++ b/app/views/custom_fields/_text.html.erb
@@ -0,0 +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
=====================================
--- a/app/views/features/_manage_community_fields.html.erb
+++ b/app/views/features/_manage_community_fields.html.erb
@@ -63,6 +63,4 @@
<% end %>
-
-
-
+<%= render :partial => "manage_custom_fields", :locals => {:customized_type => Community} %>
=====================================
app/views/features/_manage_custom_fields.html.erb
=====================================
--- /dev/null
+++ b/app/views/features/_manage_custom_fields.html.erb
@@ -0,0 +1,29 @@
+<h1><%= _("Custom Fields") %></h1><hr>
+
+<% form_id = "#{customized_type.to_s.downcase}-custom-fields-form" %>
+<% fields_id = "#{customized_type.to_s.downcase}-custom-fields" %>
+<% format_values_id = "#{customized_type.to_s.downcase}-formats" %>
+
+<%= form_tag({:action => 'manage_custom_fields'}, :id => "#{form_id}") do %>
+
+<%= hidden_field_tag 'customized_type', customized_type.to_s %>
+
+<div id="<%= fields_id %>">
+ <% customized_type.custom_fields(environment).each do |field|%>
+ <%= form_for_field(field, customized_type.to_s) %>
+ <% end %>
+</div>
+
+<div class="addition-buttons">
+ <fieldset>
+ <legend><%= _('New field') %></legend>
+ <%= select_tag _('Type: '), options_for_select(custom_field_forms(customized_type.to_s)), {:id => "#{format_values_id}"} %>
+ <%= button(:add, _('Add'), 'javascript: void()', :onClick => "add_content('##{fields_id}',$('##{format_values_id} option:selected').val(), 'NEW_FIELD_ID');") %>
+ </fieldset>
+</div>
+
+<% button_bar do %>
+ <%= button(:save, _('Save'), 'javascript: void()', :onClick => "submit_custom_field_form('##{format_values_id}', '##{form_id}');") %>
+<% end %>
+
+<% end %>
=====================================
app/views/features/_manage_enterprise_fields.html.erb
=====================================
--- a/app/views/features/_manage_enterprise_fields.html.erb
+++ b/app/views/features/_manage_enterprise_fields.html.erb
@@ -63,6 +63,4 @@
<% end %>
-
-
-
+<%= render :partial => "manage_custom_fields", :locals => {:customized_type => Enterprise} %>
=====================================
app/views/features/_manage_person_fields.html.erb
=====================================
--- a/app/views/features/_manage_person_fields.html.erb
+++ b/app/views/features/_manage_person_fields.html.erb
@@ -60,9 +60,7 @@
<%= button :back, _('Back to admin panel'), :controller => 'admin_panel', :action => 'index' %>
<% end %>
</div>
-
+<br>
<% end %>
-
-
-
+<%= render :partial => "manage_custom_fields", :locals => {:customized_type => Person} %>
=====================================
app/views/features/custom_fields/_extras_field.html.erb
=====================================
--- /dev/null
+++ b/app/views/features/custom_fields/_extras_field.html.erb
@@ -0,0 +1,15 @@
+<% field_id = extra.nil? ? 'EXTRAS_ID' : "#{Time.now.usec}" %>
+<% def_value = field.nil? ? '' : field.default_value%>
+<tr id='<%= "extras_#{field_id}" %>' >
+ <td>
+ <%= 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')" %>
+ </td>
+ <td>
+ <%= 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);" %>
+ </td>
+ <td>
+ <% if extra.nil? %>
+ <%= button_to_function_without_text :remove, _('Remove'), "remove_content('#extras_#{field_id}'); ", :class => 'remove-field', :title => 'Remove alternative' %>
+ <% end %>
+ </td>
+</tr>
=====================================
app/views/features/custom_fields/_form.html.erb
=====================================
--- /dev/null
+++ b/app/views/features/custom_fields/_form.html.erb
@@ -0,0 +1,43 @@
+<% id = field.new_record? ? "NEW_FIELD_ID" : field.id %>
+
+<div id="<%= id %>" class="custom-field-item">
+<fieldset class="fieldbox">
+ <legend><%= format_name(field.format) %></legend>
+ <%= required labelled_form_field _('Name'), text_field_tag("custom_fields[#{id}][name]", field.name, :size => 30) %>
+ <%= button_to_function :delete, _('Remove field'), "remove_content('##{id}');" %>
+
+ <% if field.format != "list" %>
+ <%= labelled_form_field _('Default value'), text_field_tag("custom_fields[#{id}][default_value]", field.default_value, :size => 30) %>
+ <% end %>
+ <%= hidden_field_tag "custom_fields[#{id}][customized_type]", field.customized_type.to_s %>
+ <%= hidden_field_tag "custom_fields[#{id}][format]", field.format %>
+
+ <div>
+ <%= 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]')" %>
+ <%= 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]')" %>
+ <%= 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]')" %>
+ </div>
+
+ <% if field.format == "list" %>
+ <table>
+ <thead>
+ <tr>
+ <th><%= _("Alternative") %></th>
+ <th><%= _("Default") %></th>
+ <th><%= _("Delete") %></th>
+ </tr>
+ </thead>
+ <tfoot>
+ <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>
+ </tfoot>
+ <tbody class="custom-field-extras">
+ <% if !field.extras.blank?%>
+ <% field.extras.each do |extra|%>
+ <%= render_extras_field id, extra, field %>
+ <% end %>
+ <% end %>
+ </tbody>
+ </table>
+ <% end %>
+</fieldset>
+</div>
=====================================
app/views/features/custom_fields/_view.html.erb
=====================================
--- /dev/null
+++ b/app/views/features/custom_fields/_view.html.erb
=====================================
app/views/features/custom_fields/edit.html.erb
=====================================
--- /dev/null
+++ b/app/views/features/custom_fields/edit.html.erb
@@ -0,0 +1 @@
+<%= render :partial => 'features/custom_fields/form' %>
=====================================
app/views/features/custom_fields/new.html.erb
=====================================
--- /dev/null
+++ b/app/views/features/custom_fields/new.html.erb
@@ -0,0 +1 @@
+<%= render :partial => 'features/custom_fields/form' %>
=====================================
app/views/memberships/new_community.html.erb
=====================================
--- a/app/views/memberships/new_community.html.erb
+++ b/app/views/memberships/new_community.html.erb
@@ -13,7 +13,6 @@
<%= labelled_form_for :community, :html => { :multipart => true } do |f| %>
<%= required_fields_message %>
-
<%= required f.text_field(:name) %>
<% @plugins.dispatch(:new_community_hidden_fields).each do |field| %>
@@ -23,6 +22,7 @@
<% end %>
<%= render :partial => 'shared/organization_custom_fields', :locals => { :f => f, :object_name => 'community', :profile => @community } %>
+ <%= render :partial => 'shared/custom_fields', :locals => { :f => f, :profile => @community, :signup => true } %>
<%= f.fields_for :image_builder, @community.image do |i| %>
<%= file_field_or_thumbnail(_('Image:'), @community.image, i) %>
@@ -56,7 +56,3 @@
<% end %>
</div>
-
-
-
-
=====================================
app/views/profile/_custom_fields.html.erb
=====================================
--- /dev/null
+++ b/app/views/profile/_custom_fields.html.erb
@@ -0,0 +1,11 @@
+<% public_values = profile.public_values %>
+<% if !public_values.blank?%>
+ <tr> <th colspan="2"><%= _('Others') %> </th></tr>
+ <% profile.public_values.each do |cv|%>
+ <tr>
+ <td class="field-name"><%= cv.custom_field.name %></td>
+ <td><%= display_custom_field_value(cv) %></td>
+ </tr>
+ <% end%>
+<% end %>
+
=====================================
app/views/profile/_organization_profile.html.erb
=====================================
--- a/app/views/profile/_organization_profile.html.erb
+++ b/app/views/profile/_organization_profile.html.erb
@@ -3,4 +3,5 @@
<%= display_contact %>
<%= display_economic %>
<%= render :partial => 'common' %>
+ <%= render :partial => 'custom_fields' %>
</table>
=====================================
app/views/profile/_person_profile.html.erb
=====================================
--- a/app/views/profile/_person_profile.html.erb
+++ b/app/views/profile/_person_profile.html.erb
@@ -10,5 +10,6 @@
<%= render :partial => 'common' %>
<% end %>
-</table>
+ <%= render :partial => 'custom_fields'%>
+</table>
=====================================
app/views/profile_editor/_organization.html.erb
=====================================
--- a/app/views/profile_editor/_organization.html.erb
+++ b/app/views/profile_editor/_organization.html.erb
@@ -61,6 +61,7 @@
<% end %>
<%= render :partial => 'shared/organization_custom_fields', :locals => { :f => f, :object_name => 'profile_data', :profile => @profile } %>
+<%= render :partial => 'shared/custom_fields', :locals => {:f => f, :profile => @profile, :editing_profile => true} %>
<%= labelled_check_box(_('Enable "contact us"'), 'profile_data[enable_contact_us]', "1", @profile.enable_contact_us) if @profile.enterprise? %>
=====================================
app/views/profile_editor/_person.html.erb
=====================================
--- a/app/views/profile_editor/_person.html.erb
+++ b/app/views/profile_editor/_person.html.erb
@@ -27,6 +27,7 @@
<%= link_to("Reset token", {:controller => :profile_editor, :action => :reset_private_token, :id => @profile.id}, :class => "button with-text") %>
<%= render :partial => 'person_form', :locals => {:f => f} %>
+ <%= render :partial => 'shared/custom_fields', :locals => {:f => f, :profile => @profile, :editing_profile => true} %>
<h2><%= _('Notification options') %></h2>
<div>
=====================================
app/views/shared/_custom_fields.html.erb
=====================================
--- /dev/null
+++ b/app/views/shared/_custom_fields.html.erb
@@ -0,0 +1,25 @@
+<% if signup ||= false %>
+ <% fields = profile.class.signup_custom_fields environment%>
+<% else %>
+ <% fields = profile.class.active_custom_fields environment%>
+<% end %>
+<% editing_profile ||= false %>
+<% fields.each do |field| %>
+ <% rendered = render(:partial => "custom_fields/#{field.format}", :locals => {:field => field, :profile => profile, :name => "profile_data[custom_values[#{field.name}[value]]]"})%>
+ <div class="<%= 'field-with-privacy-selector' if editing_profile %>">
+
+ <% if field.required%>
+ <%= required rendered%>
+ <% else %>
+ <%= rendered %>
+ <% end %>
+
+ <% if editing_profile %>
+ <div class="field-privacy-selector">
+ <%= labelled_check_box(_('Public'),"profile_data[custom_values[#{field.name}[public]]]", "true", profile.is_public(field.name))%>
+ </div>
+ <% end %>
+
+ </div>
+<% end %>
+
=====================================
app/views/shared/_organization_custom_fields.html.erb
=====================================
--- a/app/views/shared/_organization_custom_fields.html.erb
+++ b/app/views/shared/_organization_custom_fields.html.erb
@@ -29,4 +29,7 @@
<%= optional_field(profile, 'acronym', f.text_field(:acronym)) %>
<%= optional_field(profile, 'foundation_year', f.text_field(:foundation_year)) %>
<% end %>
+
+<%= render :partial => 'shared/custom_fields', :locals => {:f => f, :profile => profile, :signup => true} %>
+
<%= javascript_include_tag('city_state_validation') %>
=====================================
config/initializers/dependencies.rb
=====================================
--- a/config/initializers/dependencies.rb
+++ b/config/initializers/dependencies.rb
@@ -18,6 +18,7 @@ require 'acts_as_having_settings'
require 'acts_as_having_boxes'
require 'acts_as_having_image'
require 'acts_as_having_posts'
+require 'acts_as_customizable'
require 'route_if'
require 'maybe_add_http'
require 'set_profile_region_from_city_state'
=====================================
db/migrate/20150921140802_create_custom_fields.rb
=====================================
--- /dev/null
+++ b/db/migrate/20150921140802_create_custom_fields.rb
@@ -0,0 +1,31 @@
+class CreateCustomFields < ActiveRecord::Migration
+ def change
+ create_table :custom_fields do |t|
+ t.string :name
+ t.string :format, :default => ""
+ t.text :default_value, :default => ""
+ t.string :customized_type
+ t.text :extras, :default => ""
+ t.boolean :active, :default => false
+ t.boolean :required, :default => false
+ t.boolean :signup, :default => false
+ t.integer :environment_id
+ t.timestamps
+ end
+
+ create_table :custom_field_values do |t|
+ t.column "customized_type", :string, :default => "", :null => false
+ t.column "customized_id", :integer, :default => 0, :null => false
+ t.column "public", :boolean, :default => false, :null => false
+ t.column "custom_field_id", :integer, :default => 0, :null => false
+ t.column "value", :text, :default => ""
+ t.timestamps
+ end
+
+
+ add_index :custom_field_values, ["customized_type", "customized_id","custom_field_id"], :unique => true, :name => 'index_custom_field_values'
+ add_index :custom_fields, ["customized_type","name","environment_id"], :unique => true, :name => 'index_custom_field'
+
+ end
+end
+
=====================================
lib/acts_as_customizable.rb
=====================================
--- /dev/null
+++ b/lib/acts_as_customizable.rb
@@ -0,0 +1,125 @@
+module Customizable
+
+ def self.included(base)
+ base.attr_accessible :custom_values
+ base.extend ClassMethods
+ end
+
+ module ClassMethods
+ def acts_as_customizable(options = {})
+ attr_accessor :custom_values
+ has_many :custom_field_values, :dependent => :delete_all, :as => :customized
+ send :include, Customizable::InstanceMethods
+ after_save :save_custom_values
+ validate :valid_custom_values?
+ end
+
+ def active_custom_fields environment
+ environment.custom_fields.select{|cf| customized_ancestors_list.include?(cf.customized_type) && cf.active}
+ end
+
+ def required_custom_fields environment
+ environment.custom_fields.select{|cf| customized_ancestors_list.include?(cf.customized_type) && cf.required}
+ end
+
+ def signup_custom_fields environment
+ environment.custom_fields.select{|cf| customized_ancestors_list.include?(cf.customized_type) && cf.signup}
+ end
+
+ def custom_fields environment
+ environment.custom_fields.select{|cf| customized_ancestors_list.include?(cf.customized_type)}
+ end
+
+ def customized_ancestors_list
+ current=self
+ result=[]
+ while current.instance_methods.include? :custom_value do
+ result << current.name
+ current=current.superclass
+ end
+ result
+ end
+
+ end
+
+ module InstanceMethods
+
+ def valid_custom_values?
+ is_valid = true
+ parse_custom_values.each do |cv|
+ unless cv.valid?
+ name = cv.custom_field.name
+ errors.add(name, cv.errors.messages[name.to_sym].first)
+ is_valid = false
+ end
+ end
+ is_valid
+ end
+
+ def customized_class
+ current=self.class
+ while current.instance_methods.include? :custom_fields do
+ result=current
+ current=current.superclass
+ end
+ result.name
+ end
+
+ def is_public(field_name)
+ cv = self.custom_field_values.detect{|cv| cv.custom_field.name==field_name}
+ cv.nil? ? false : cv.public
+ end
+
+ def public_values
+ self.custom_field_values.select{|cv| cv.public}
+ end
+
+ def custom_value(field_name)
+ cv = self.custom_field_values.detect{|cv| cv.custom_field.name==field_name}
+ cv.nil? ? default_value_for(field_name) : cv.value
+ end
+
+ def default_value_for(field_name)
+ field=self.class.custom_fields(environment).detect {|c| c.name == field_name}
+ field.nil? ? nil : field.default_value
+ end
+
+ def parse_custom_values
+ return_list = []
+ return return_list if custom_values.blank?
+ custom_values.each_pair do |key, value|
+ custom_field = environment.custom_fields.detect{|cf|cf.name==key}
+ next if custom_field.blank?
+ custom_field_value = self.custom_field_values.detect{|cv| cv.custom_field.name==key}
+
+ if custom_field_value.nil?
+ custom_field_value = CustomFieldValue.new
+ custom_field_value.custom_field = custom_field
+ custom_field_value.customized = self
+ end
+
+ if value.is_a?(Hash)
+ custom_field_value.value = value['value'].to_s
+ if value.has_key?('public')
+ is_public = value['public']=="true" || value['public']==true
+ custom_field_value.public = is_public
+ else
+ custom_field_value.public = false
+ end
+ else
+ custom_field_value.value = value.to_s
+ custom_field_value.public = false
+ end
+ return_list << custom_field_value
+ end
+ return_list
+ end
+
+ def save_custom_values
+ parse_custom_values.each(&:save)
+ end
+
+ end
+end
+
+ActiveRecord::Base.send(:include, Customizable)
=====================================
lib/noosfero/api/entities.rb
=====================================
--- a/lib/noosfero/api/entities.rb
+++ b/lib/noosfero/api/entities.rb
@@ -15,7 +15,7 @@ module Noosfero
}
def self.can_display? profile, options, field, permission = :friend
- return true if profile.public_fields.include?(field)
+ return true if profile.public_fields.map{|f| f.to_sym}.include?(field.to_sym)
current_person = options[:current_person]
current_permission = if current_person.present?
@@ -31,7 +31,6 @@ module Noosfero
else
:anonymous
end
-
PERMISSIONS[current_permission] <= PERMISSIONS[permission]
end
@@ -84,6 +83,20 @@ module Noosfero
expose :identifier, :name, :id
expose :created_at, :format_with => :timestamp
expose :updated_at, :format_with => :timestamp
+ expose :additional_data do |profile, options|
+ hash ={}
+ profile.public_values.each do |value|
+ hash[value.custom_field.name]=value.value
+ end
+
+ private_values = profile.custom_field_values - profile.public_values
+ private_values.each do |value|
+ if Entities.can_display?(profile,options,:custom_field)
+ hash[value.custom_field.name]=value.value
+ end
+ end
+ hash
+ end
expose :image, :using => Image
expose :region, :using => Region
end
=====================================
lib/noosfero/api/v1/comments.rb
=====================================
--- a/lib/noosfero/api/v1/comments.rb
+++ b/lib/noosfero/api/v1/comments.rb
@@ -18,12 +18,12 @@ module Noosfero
article = find_article(environment.articles, params[:id])
comments = select_filtered_collection_of(article, :comments, params)
- present comments, :with => Entities::Comment
+ present comments, :with => Entities::Comment, :current_person => current_person
end
get ":id/comments/:comment_id" do
article = find_article(environment.articles, params[:id])
- present article.comments.find(params[:comment_id]), :with => Entities::Comment
+ present article.comments.find(params[:comment_id]), :with => Entities::Comment, :current_person => current_person
end
# Example Request:
@@ -31,7 +31,7 @@ module Noosfero
post ":id/comments" do
article = find_article(environment.articles, params[:id])
options = params.select { |key,v| !['id','private_token'].include?(key) }.merge(:author => current_person, :source => article)
- present Comment.create(options), :with => Entities::Comment
+ present Comment.create(options), :with => Entities::Comment, :current_person => current_person
end
end
=====================================
lib/noosfero/api/v1/communities.rb
=====================================
--- a/lib/noosfero/api/v1/communities.rb
+++ b/lib/noosfero/api/v1/communities.rb
@@ -20,14 +20,21 @@ module Noosfero
communities = select_filtered_collection_of(environment, 'communities', params)
communities = communities.visible_for_person(current_person)
communities = communities.by_location(params) # Must be the last. May return Exception obj.
- present communities, :with => Entities::Community
+ present communities, :with => Entities::Community, :current_person => current_person
end
# Example Request:
# POST api/v1/communties?private_token=234298743290432&community[name]=some_name
+ # for each custom field for community, add &community[field_name]=field_value to the request
post do
params[:community] ||= {}
+
+ params[:community][:custom_values]={}
+ params[:community].keys.each do |key|
+ params[:community][:custom_values][key]=params[:community].delete(key) if Community.custom_fields(environment).any?{|cf| cf.name==key}
+ end
+
begin
community = Community.create_after_moderation(current_person, params[:community].merge({:environment => environment}))
rescue
@@ -38,12 +45,12 @@ module Noosfero
render_api_errors!(community.errors.full_messages)
end
- present community, :with => Entities::Community
+ present community, :with => Entities::Community, :current_person => current_person
end
get ':id' do
community = environment.communities.visible_for_person(current_person).find_by_id(params[:id])
- present community, :with => Entities::Community
+ present community, :with => Entities::Community, :current_person => current_person
end
end
@@ -58,7 +65,7 @@ module Noosfero
person = environment.people.find(params[:person_id])
communities = select_filtered_collection_of(person, 'communities', params)
communities = communities.visible
- present communities, :with => Entities::Community
+ present communities, :with => Entities::Community, :current_person => current_person
end
end
=====================================
lib/noosfero/api/v1/enterprises.rb
=====================================
--- a/lib/noosfero/api/v1/enterprises.rb
+++ b/lib/noosfero/api/v1/enterprises.rb
@@ -21,13 +21,13 @@ module Noosfero
enterprises = select_filtered_collection_of(environment, 'enterprises', params)
enterprises = enterprises.visible_for_person(current_person)
enterprises = enterprises.by_location(params) # Must be the last. May return Exception obj.
- present enterprises, :with => Entities::Enterprise
+ present enterprises, :with => Entities::Enterprise, :current_person => current_person
end
desc "Return one enterprise by id"
get ':id' do
enterprise = environment.enterprises.visible_for_person(current_person).find_by_id(params[:id])
- present enterprise, :with => Entities::Enterprise
+ present enterprise, :with => Entities::Enterprise, :current_person => current_person
end
end
@@ -42,7 +42,7 @@ module Noosfero
person = environment.people.find(params[:person_id])
enterprises = select_filtered_collection_of(person, 'enterprises', params)
enterprises = enterprises.visible.by_location(params)
- present enterprises, :with => Entities::Enterprise
+ present enterprises, :with => Entities::Enterprise, :current_person => current_person
end
end
=====================================
lib/noosfero/api/v1/people.rb
=====================================
--- a/lib/noosfero/api/v1/people.rb
+++ b/lib/noosfero/api/v1/people.rb
@@ -33,30 +33,31 @@ module Noosfero
get do
people = select_filtered_collection_of(environment, 'people', params)
people = people.visible_for_person(current_person)
- present people, :with => Entities::Person
+ present people, :with => Entities::Person, :current_person => current_person
end
desc "Return the logged user information"
get "/me" do
- present current_person, :with => Entities::Person
+ present current_person, :with => Entities::Person, :current_person => current_person
end
desc "Return the person information"
get ':id' do
person = environment.people.visible_for_person(current_person).find_by_id(params[:id])
return not_found! if person.blank?
- present person, :with => Entities::Person
+ present person, :with => Entities::Person, :current_person => current_person
end
desc "Update person information"
post ':id' do
return forbidden! if current_person.id.to_s != params[:id]
current_person.update_attributes!(params[:person])
- present current_person, :with => Entities::Person
+ present current_person, :with => Entities::Person, :current_person => current_person
end
# Example Request:
# POST api/v1/people?person[login]=some_login&person[password]=some_password&person[name]=Jack
+ # for each custom field for person, add &person[field_name]=field_value to the request
desc "Create person"
post do
user_data = {}
@@ -64,14 +65,21 @@ module Noosfero
user_data[:email] = params[:person].delete(:email)
user_data[:password] = params[:person].delete(:password)
user_data[:password_confirmation] = params[:person].delete(:password_confirmation)
+
+ params[:person][:custom_values]={}
+ params[:person].keys.each do |key|
+ params[:person][:custom_values][key]=params[:person].delete(key) if Person.custom_fields(environment).any?{|cf| cf.name==key}
+ end
+
user = User.build(user_data, params[:person], environment)
+
begin
user.signup!
rescue ActiveRecord::RecordInvalid
render_api_errors!(user.errors.full_messages)
end
- present user.person, :with => Entities::Person
+ present user.person, :with => Entities::Person, :current_person => user.person
end
desc "Return the person friends"
@@ -79,7 +87,7 @@ module Noosfero
person = environment.people.visible_for_person(current_person).find_by_id(params[:id])
return not_found! if person.blank?
friends = person.friends.visible
- present friends, :with => Entities::Person
+ present friends, :with => Entities::Person, :current_person => current_person
end
desc "Return the person permissions on other profiles"
=====================================
public/javascripts/manage-fields.js
=====================================
--- a/public/javascripts/manage-fields.js
+++ b/public/javascripts/manage-fields.js
@@ -36,6 +36,34 @@ function signup_action(name_active, name_required, name_signup) {
update_active(name_active, name_required, name_signup)
}
+function add_content(target_id, content, mask) {
+ var id = new Date().getTime();
+ var regexp = new RegExp(mask, "g");
+ content = content.replace(regexp, id);
+ $(target_id).append(content);
+ $('#' + id).hide().slideDown();
+}
+
+function remove_content(target) {
+ $(target).remove();
+}
+
+function submit_custom_field_form(selector_id, form_id, customized_type) {
+ $(selector_id).attr('disabled', true);
+ $(form_id).submit();
+}
+
+function manage_default_option(source) {
+ var th = $(source);
+ var name = th.prop('name');
+ if(th.is(':checked')){
+ $(':checkbox[name="' + name + '"]').not($(source)).prop('checked',false);
+ }
+}
+
+function update_default_value(source, target) {
+ $(target).val(source);
+}
jQuery(document).ready(function(){
function check_fields(check, table_id, start) {
=====================================
public/stylesheets/manage-fields.scss
=====================================
--- a/public/stylesheets/manage-fields.scss
+++ b/public/stylesheets/manage-fields.scss
@@ -9,3 +9,11 @@
font-style: italic;
}
+.custom-field-item {
+ position: relative;
+ a.icon-delete {
+ position: absolute;
+ top: 20px;
+ right: 20px;
+ }
+}
=====================================
test/functional/features_controller_test.rb
=====================================
--- a/test/functional/features_controller_test.rb
+++ b/test/functional/features_controller_test.rb
@@ -8,6 +8,7 @@ class FeaturesControllerTest < ActionController::TestCase
@controller = FeaturesController.new
@request = ActionController::TestRequest.new
@response = ActionController::TestResponse.new
+
login_as(create_admin_user(Environment.find(2)))
end
@@ -159,4 +160,51 @@ class FeaturesControllerTest < ActionController::TestCase
assert_includes json_response, {"id"=>person.id, "name"=>person.name}
end
+ should 'create custom field' do
+ uses_host 'anhetegua.net'
+ assert_nil Environment.find(2).custom_fields.find_by_name('foo')
+ post :manage_custom_fields, :customized_type => 'Person', :custom_fields => {
+ Time.now.to_i => {
+ :name => 'foo',
+ :default_value => 'foobar',
+ :format => 'string',
+ :customized_type => 'Person',
+ :active => true,
+ :required => true,
+ :signup => true
+ }
+ }
+ assert_redirected_to :action => 'manage_fields'
+ assert_not_nil Environment.find(2).custom_fields.find_by_name('foo')
+ end
+
+ should 'update custom field' do
+ uses_host 'anhetegua.net'
+
+ field = CustomField.create! :name => 'foo', :default_value => 'foobar', :format => 'string', :extras => '', :customized_type => 'Enterprise', :active => true, :required => true, :signup => true, :environment => Environment.find(2)
+ post :manage_custom_fields, :customized_type => 'Enterprise', :custom_fields => {
+ field.id => {
+ :name => 'foo bar',
+ :default_value => 'foobar',
+ :active => true,
+ :required => true,
+ :signup => true
+ }
+ }
+ field.reload
+ assert_redirected_to :action => 'manage_fields'
+ assert_equal 'foo bar', field.name
+ end
+
+ should 'destroy custom field' do
+ uses_host 'anhetegua.net'
+
+ field = CustomField.create! :name => 'foo', :default_value => 'foobar', :format => 'string', :extras => '', :customized_type => 'Enterprise', :active => true, :required => true, :signup => true, :environment => Environment.find(2)
+
+ post :manage_custom_fields, :customized_type => 'Enterprise'
+
+ assert_redirected_to :action => 'manage_fields'
+ assert_nil Environment.find(2).custom_fields.find_by_name('foo')
+ end
+
end
=====================================
test/unit/acts_as_customizable_test.rb
=====================================
--- /dev/null
+++ b/test/unit/acts_as_customizable_test.rb
@@ -0,0 +1,23 @@
+require_relative "../test_helper"
+
+class ActsAsCustomizableTest < ActiveSupport::TestCase
+
+ should 'save custom field values for person' do
+ CustomField.create!(:name => "Blog", :format => "string", :customized_type => "Person", :active => true, :environment => Environment.default)
+ person = create_user('testinguser').person
+ assert_difference 'CustomFieldValue.count' do
+ person.custom_values = { "Blog" => { "value" => "www.blog.org", "public" => "0"} }
+ person.save!
+ assert_equal 'www.blog.org', CustomFieldValue.find(:last, :conditions => {:customized_id => person.id}).value
+ end
+ end
+
+ should 'not be valid when required custom field not filled' do
+ CustomField.create!(:name => "Blog", :format => "string", :customized_type => "Person", :active => true, :environment => Environment.default, :required => true)
+ person = create_user('testinguser').person
+
+ person.custom_values = { "Blog" => { "value" => "", "public" => "0"} }
+ refute person.valid?
+ end
+
+end
=====================================
test/unit/api/people_test.rb
=====================================
--- a/test/unit/api/people_test.rb
+++ b/test/unit/api/people_test.rb
@@ -165,4 +165,44 @@ class PeopleTest < ActiveSupport::TestCase
assert_equal another_name, person.name
end
+ should 'display public custom fields' do
+ CustomField.create!(:name => "Custom Blog", :format => "string", :customized_type => "Person", :active => true, :environment => Environment.default)
+ some_person = create_user('some-person').person
+ some_person.custom_values = { "Custom Blog" => { "value" => "www.blog.org", "public" => "true"} }
+ some_person.save!
+
+ get "/api/v1/people/#{some_person.id}?#{params.to_query}"
+ json = JSON.parse(last_response.body)
+ assert json['person']['additional_data'].has_key?('Custom Blog')
+ assert_equal "www.blog.org", json['person']['additional_data']['Custom Blog']
+ end
+
+ should 'not display non-public custom fields' do
+ CustomField.create!(:name => "Custom Blog", :format => "string", :customized_type => "Person", :active => true, :environment => Environment.default)
+ some_person = create_user('some-person').person
+ some_person.custom_values = { "Custom Blog" => { "value" => "www.blog.org", "public" => "0"} }
+ some_person.save!
+
+ get "/api/v1/people/#{some_person.id}?#{params.to_query}"
+ json = JSON.parse(last_response.body)
+ assert_equal json['person']['additional_data'], {}
+ end
+
+ should 'display non-public custom fields to friend' do
+ CustomField.create!(:name => "Custom Blog", :format => "string", :customized_type => "Person", :active => true, :environment => Environment.default)
+ some_person = create_user('some-person').person
+ some_person.custom_values = { "Custom Blog" => { "value" => "www.blog.org", "public" => "0"} }
+ some_person.save!
+
+ f = Friendship.new
+ f.friend = some_person
+ f.person = person
+ f.save!
+
+ get "/api/v1/people/#{some_person.id}?#{params.to_query}"
+ json = JSON.parse(last_response.body)
+ assert json['person']['additional_data'].has_key?("Custom Blog")
+ assert_equal "www.blog.org", json['person']['additional_data']['Custom Blog']
+ end
+
end
=====================================
test/unit/custom_field_test.rb
=====================================
--- /dev/null
+++ b/test/unit/custom_field_test.rb
@@ -0,0 +1,153 @@
+require_relative "../test_helper"
+
+class CustomFieldTest < ActiveSupport::TestCase
+
+ def setup
+ @person = create_user('test_user').person
+
+ @e1 = Environment.default
+ @e2 = fast_create(Environment)
+
+ @community = create(Community, :environment => @e1, :name => 'my new community')
+
+ @community_custom_field = CustomField.create(:name => "community_field", :format=>"myFormat", :default_value => "value for community", :customized_type=>"Community", :active => true, :environment => @e1)
+ @person_custom_field = CustomField.create(:name => "person_field", :format=>"myFormat", :default_value => "value for person", :customized_type=>"Person", :active => true, :environment => @e1)
+ @profile_custom_field = CustomField.create(:name => "profile_field", :format=>"myFormat", :default_value => "value for any profile", :customized_type=>"Profile", :active => true, :environment => @e1)
+
+ @e1.reload
+ end
+
+ should 'not access another environments custom fields' do
+ @e2_custom_field = CustomField.create(:name => "another_field", :format=>"anoherFormat", :default_value => "default value for e2", :customized_type=>"Profile", :active => true, :environment => @e2)
+ @e2.reload
+
+ assert_equal 1, Profile.custom_fields(@e1).size
+ assert_equal @profile_custom_field, Profile.custom_fields(@e1).first
+
+ assert_equal 1, Profile.custom_fields(@e2).size
+ assert_equal @e2_custom_field, Profile.custom_fields(@e2).first
+
+ end
+
+ should 'no access to custom field on sibling' do
+ refute (Person.custom_fields(@e1).any?{|cf| cf.name == @community_custom_field.name})
+ refute (Community.custom_fields(@e1).any?{|cf| cf.name == @person_custom_field.name})
+ end
+
+ should 'inheritance of custom_field' do
+ assert Community.custom_fields(@e1).any?{|cf| cf.name == @profile_custom_field.name}
+ assert Person.custom_fields(@e1).any?{|cf| cf.name == @profile_custom_field.name}
+ end
+
+ should 'save custom_field_values' do
+ @community.custom_values = {"community_field" => "new_value!", "profile_field"=> "another_value!"}
+ @community.save
+
+ assert CustomFieldValue.all.any?{|cv| cv.custom_field_id == @community_custom_field.id && cv.customized_id == @community.id && cv.value == "new_value!"}
+ assert CustomFieldValue.all.any?{|cv| cv.custom_field_id == @profile_custom_field.id && cv.customized_id == @community.id && cv.value = "another_value!"}
+ end
+
+ should 'delete custom field and its values' do
+ @community.custom_values = {"community_field" => "new_value!", "profile_field"=> "another_value!"}
+ @community.save
+
+ old_id = @community_custom_field.id
+ @community_custom_field.destroy
+
+ @e1.reload
+ refute (@e1.custom_fields.any?{|cf| cf.id == old_id})
+ refute (Community.custom_fields(@e1).any?{|cf| cf.name == "community_field"})
+ refute (CustomFieldValue.all.any?{|cv| cv.custom_field_id == old_id})
+ end
+
+ should 'not save related custom field' do
+ another_field = CustomField.create(:name => "profile_field", :format=>"myFormat", :default_value => "value for any profile", :customized_type=>"Community", :environment => @e1)
+ assert another_field.id.nil?
+ end
+
+ should 'not save same custom field twice in the same environment' do
+ field = CustomField.create(:name => "the new field", :format=>"myFormat", :customized_type=>"Community", :environment => @e1)
+ refute field.id.nil?
+ @e1.reload
+ another = CustomField.new(:name => "the new field", :format=>"myFormat", :customized_type=>"Community", :environment => @e1)
+ refute another.valid?
+ end
+
+ should 'save same custom field in another environment' do
+ field = CustomField.create(:name => "the new field", :format=>"myFormat", :customized_type=>"Community", :environment => @e1)
+ refute field.id.nil?
+ another_field = CustomField.create(:name => "the new field", :format=>"myFormat", :customized_type=>"Community", :environment => @e2)
+ refute another_field.id.nil?
+ end
+
+ should 'not return inactive fields' do
+ @community_custom_field.update_attributes(:active=>false)
+ @e1.reload
+ refute Community.active_custom_fields(@e1).any?{|cf| cf.name == @community_custom_field.name}
+ end
+
+ should 'delete a model and its custom field values' do
+ @community.custom_values = {"community_field" => "new_value!", "profile_field"=> "another_value!"}
+ @community.save
+
+ old_id = @community.id
+ @community.destroy
+ refute (Community.all.any?{|c| c.id == old_id})
+ refute (CustomFieldValue.all.any?{|cv| cv.customized_id == old_id && cv.customized_type == "Community"})
+ end
+
+ should 'keep field value if the field is reactivated' do
+
+ @community.custom_values = {"community_field" => "new_value!"}
+ @community.save
+
+ @community_custom_field.update_attributes(:active=>false)
+ @e1.reload
+ refute Community.active_custom_fields(@e1).any?{|cf| cf.name == @community_custom_field.name}
+
+ @community_custom_field.update_attributes(:active=>true)
+
+ @e1.reload
+ @community.reload
+ assert Community.active_custom_fields(@e1).any?{|cf| cf.name == @community_custom_field.name}
+ assert_equal @community.custom_value("community_field"), "new_value!"
+ end
+
+ should 'list of required fields' do
+ refute Community.required_custom_fields(@e1).any?{|cf| cf.name == @community_custom_field.name}
+
+ @community_custom_field.update_attributes(:required=>true)
+ @community.reload
+ @e1.reload
+ assert Community.required_custom_fields(@e1).any?{|cf| cf.name == @community_custom_field.name}
+ end
+
+ should 'list of signup fields' do
+ refute Community.signup_custom_fields(@e1).any?{|cf| cf.name == @community_custom_field.name}
+
+ @community_custom_field.update_attributes(:signup=>true)
+ @community.reload
+ @e1.reload
+ assert Community.signup_custom_fields(@e1).any?{|cf| cf.name == @community_custom_field.name}
+ end
+
+ should 'public values handling' do
+ refute @community.is_public("community_field")
+ @community.custom_values = {"community_field" => {"value" => "new_value!", "public"=>"true"}, "profile_field"=> "another_value!"}
+ @community.save
+ @community.reload
+
+ assert @community.is_public("community_field")
+ refute @community.is_public("profile_field")
+ end
+
+ should 'complete list of fields' do
+ assert Person.custom_fields(@e1).include? @profile_custom_field
+ assert Person.custom_fields(@e1).include? @person_custom_field
+ end
+
+ should 'get correct customized ancestors list' do
+ assert (Person.customized_ancestors_list-["Person","Profile"]).blank?
+ end
+end
+
=====================================
test/unit/custom_field_values_test.rb
=====================================
--- /dev/null
+++ b/test/unit/custom_field_values_test.rb
@@ -0,0 +1,12 @@
+require_relative "../test_helper"
+
+class CustomFieldValuesTest < ActiveSupport::TestCase
+
+ should 'custom field value not be valid' do
+ c = CustomField.create!(:name => "Blog", :format => "string", :customized_type => "Person", :active => true, :required => true, :environment => Environment.default)
+ person = create_user('testinguser').person
+
+ cv=CustomFieldValue.new(:customized => person, :custom_field => c, :value => "")
+ refute cv.valid?
+ end
+end
View it on GitLab: https://gitlab.com/noosfero/noosfero/compare/75f13387c60641e1863d67d7b154ee290486e7f2...84ca7256e30e2ac68264f248c8c15457cb134771
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://listas.softwarelivre.org/pipermail/noosfero-dev/attachments/20151119/ab1695e3/attachment-0001.html>
More information about the Noosfero-dev
mailing list