Commit 810b5519a12915d9753bb6e0cf72c694a49c91b3
Committed by
Rodrigo Souto
1 parent
3ac7b587
Exists in
master
and in
12 other branches
Added new community member highlight.
* Mark new members with a label on top of image profile. Signed-off-by: Lucas Kanashiro <kanashiro.duarte@gmail.com> Signed-off-by: Rodrigo Siqueira <siqueira@kuniri.org>
Showing
13 changed files
with
141 additions
and
23 deletions
Show diff stats
app/helpers/application_helper.rb
| @@ -554,14 +554,25 @@ module ApplicationHelper | @@ -554,14 +554,25 @@ module ApplicationHelper | ||
| 554 | trigger_class = 'enterprise-trigger' | 554 | trigger_class = 'enterprise-trigger' |
| 555 | end | 555 | end |
| 556 | end | 556 | end |
| 557 | - extra_info = extra_info.nil? ? '' : content_tag( 'span', extra_info, :class => 'extra_info' ) | 557 | + |
| 558 | + extra_info_tag = '' | ||
| 559 | + img_class = 'profile-image' | ||
| 560 | + | ||
| 561 | + if extra_info.is_a? Hash | ||
| 562 | + extra_info_tag = content_tag( 'span', extra_info[:value], :class => 'extra_info '+extra_info[:class]) | ||
| 563 | + img_class +=' '+extra_info[:class] | ||
| 564 | + else | ||
| 565 | + extra_info_tag = content_tag( 'span', extra_info, :class => 'extra_info' ) | ||
| 566 | + end | ||
| 567 | + | ||
| 558 | links = links_for_balloon(profile) | 568 | links = links_for_balloon(profile) |
| 559 | content_tag('div', content_tag(tag, | 569 | content_tag('div', content_tag(tag, |
| 560 | - (environment.enabled?(:show_balloon_with_profile_links_when_clicked) ? popover_menu(_('Profile links'),profile.short_name,links,{:class => trigger_class, :url => url}) : "") + | 570 | + (environment.enabled?(:show_balloon_with_profile_links_when_clicked) ? |
| 571 | + popover_menu(_('Profile links'),profile.short_name,links,{:class => trigger_class, :url => url}) : "") + | ||
| 561 | link_to( | 572 | link_to( |
| 562 | - content_tag( 'span', profile_image( profile, size ), :class => 'profile-image' ) + | 573 | + content_tag( 'span', profile_image( profile, size ), :class => img_class ) + |
| 563 | content_tag( 'span', h(name), :class => ( profile.class == Person ? 'fn' : 'org' ) ) + | 574 | content_tag( 'span', h(name), :class => ( profile.class == Person ? 'fn' : 'org' ) ) + |
| 564 | - extra_info + profile_sex_icon( profile ), | 575 | + extra_info_tag + profile_sex_icon( profile ), |
| 565 | profile.url, | 576 | profile.url, |
| 566 | :class => 'profile_link url', | 577 | :class => 'profile_link url', |
| 567 | :help => _('Click on this icon to go to the <b>%s</b>\'s home page') % profile.name, | 578 | :help => _('Click on this icon to go to the <b>%s</b>\'s home page') % profile.name, |
| @@ -709,7 +720,7 @@ module ApplicationHelper | @@ -709,7 +720,7 @@ module ApplicationHelper | ||
| 709 | class NoosferoFormBuilder < ActionView::Helpers::FormBuilder | 720 | class NoosferoFormBuilder < ActionView::Helpers::FormBuilder |
| 710 | extend ActionView::Helpers::TagHelper | 721 | extend ActionView::Helpers::TagHelper |
| 711 | 722 | ||
| 712 | - def self.output_field(text, field_html, field_id = nil, options = {}) | 723 | + def self.output_field(text, field_html, field_id = nil) |
| 713 | # try to guess an id if none given | 724 | # try to guess an id if none given |
| 714 | if field_id.nil? | 725 | if field_id.nil? |
| 715 | field_html =~ /id=['"]([^'"]*)['"]/ | 726 | field_html =~ /id=['"]([^'"]*)['"]/ |
app/models/profile.rb
| @@ -738,13 +738,13 @@ private :generate_url, :url_options | @@ -738,13 +738,13 @@ private :generate_url, :url_options | ||
| 738 | end | 738 | end |
| 739 | 739 | ||
| 740 | # Adds a person as member of this Profile. | 740 | # Adds a person as member of this Profile. |
| 741 | - def add_member(person) | 741 | + def add_member(person, attributes={}) |
| 742 | if self.has_members? | 742 | if self.has_members? |
| 743 | if self.closed? && members.count > 0 | 743 | if self.closed? && members.count > 0 |
| 744 | AddMember.create!(:person => person, :organization => self) unless self.already_request_membership?(person) | 744 | AddMember.create!(:person => person, :organization => self) unless self.already_request_membership?(person) |
| 745 | else | 745 | else |
| 746 | - self.affiliate(person, Profile::Roles.admin(environment.id)) if members.count == 0 | ||
| 747 | - self.affiliate(person, Profile::Roles.member(environment.id)) | 746 | + self.affiliate(person, Profile::Roles.admin(environment.id), attributes) if members.count == 0 |
| 747 | + self.affiliate(person, Profile::Roles.member(environment.id), attributes) | ||
| 748 | end | 748 | end |
| 749 | person.tasks.pending.of("InviteMember").select { |t| t.data[:community_id] == self.id }.each { |invite| invite.cancel } | 749 | person.tasks.pending.of("InviteMember").select { |t| t.data[:community_id] == self.id }.each { |invite| invite.cancel } |
| 750 | remove_from_suggestion_list person | 750 | remove_from_suggestion_list person |
app/views/profile/_profile_members_list.html.erb
| @@ -9,7 +9,8 @@ | @@ -9,7 +9,8 @@ | ||
| 9 | </div> | 9 | </div> |
| 10 | <ul class="profile-list-<%= role %>" > | 10 | <ul class="profile-list-<%= role %>" > |
| 11 | <% users.each do |u| %> | 11 | <% users.each do |u| %> |
| 12 | - <%= profile_image_link(u, :thumb) %> | 12 | + <% extra_info = u.member_since_date(profile) == Date.today ? {:value =>_('New'), :class => 'new-profile'}:'' %> |
| 13 | + <%= profile_image_link(u, :thumb, 'li', extra_info) %> | ||
| 13 | <% end %> | 14 | <% end %> |
| 14 | </ul> | 15 | </ul> |
| 15 | 16 |
app/views/profile/members.html.erb
| @@ -19,7 +19,6 @@ | @@ -19,7 +19,6 @@ | ||
| 19 | :id => "members-tab", | 19 | :id => "members-tab", |
| 20 | :content => div_members | 20 | :content => div_members |
| 21 | } %> | 21 | } %> |
| 22 | - | ||
| 23 | <% div_admins = content_tag :div, :class => "profile-admins" do | 22 | <% div_admins = content_tag :div, :class => "profile-admins" do |
| 24 | render :partial => 'profile_members_list', | 23 | render :partial => 'profile_members_list', |
| 25 | :locals => { | 24 | :locals => { |
db/migrate/20160202142247_add_timestamps_to_role_assignments.rb
0 → 100644
db/schema.rb
| @@ -11,7 +11,7 @@ | @@ -11,7 +11,7 @@ | ||
| 11 | # | 11 | # |
| 12 | # It's strongly recommended that you check this file into your version control system. | 12 | # It's strongly recommended that you check this file into your version control system. |
| 13 | 13 | ||
| 14 | -ActiveRecord::Schema.define(version: 20150921140802) do | 14 | +ActiveRecord::Schema.define(version: 20160202142247) do |
| 15 | 15 | ||
| 16 | # These are extensions that must be enabled in order to support this database | 16 | # These are extensions that must be enabled in order to support this database |
| 17 | enable_extension "plpgsql" | 17 | enable_extension "plpgsql" |
| @@ -639,12 +639,14 @@ ActiveRecord::Schema.define(version: 20150921140802) do | @@ -639,12 +639,14 @@ ActiveRecord::Schema.define(version: 20150921140802) do | ||
| 639 | end | 639 | end |
| 640 | 640 | ||
| 641 | create_table "role_assignments", force: :cascade do |t| | 641 | create_table "role_assignments", force: :cascade do |t| |
| 642 | - t.integer "accessor_id", null: false | ||
| 643 | - t.string "accessor_type" | ||
| 644 | - t.integer "resource_id" | ||
| 645 | - t.string "resource_type" | ||
| 646 | - t.integer "role_id", null: false | ||
| 647 | - t.boolean "is_global" | 642 | + t.integer "accessor_id", null: false |
| 643 | + t.string "accessor_type" | ||
| 644 | + t.integer "resource_id" | ||
| 645 | + t.string "resource_type" | ||
| 646 | + t.integer "role_id", null: false | ||
| 647 | + t.boolean "is_global" | ||
| 648 | + t.datetime "created_at" | ||
| 649 | + t.datetime "updated_at" | ||
| 648 | end | 650 | end |
| 649 | 651 | ||
| 650 | create_table "roles", force: :cascade do |t| | 652 | create_table "roles", force: :cascade do |t| |
public/stylesheets/profile-list.scss
| @@ -207,3 +207,23 @@ | @@ -207,3 +207,23 @@ | ||
| 207 | height: auto; | 207 | height: auto; |
| 208 | font-size: 12px; | 208 | font-size: 12px; |
| 209 | } | 209 | } |
| 210 | +.action-profile-members .profile_link{ | ||
| 211 | + position: relative; | ||
| 212 | +} | ||
| 213 | +.action-profile-members .profile_link span.new-profile:last-child{ | ||
| 214 | + position: absolute; | ||
| 215 | + top: 3px; | ||
| 216 | + right: 2px; | ||
| 217 | + text-transform: uppercase; | ||
| 218 | + color: #FFF; | ||
| 219 | + font-size: 9px; | ||
| 220 | + background: #66CC33; | ||
| 221 | + padding: 2px; | ||
| 222 | + display: block; | ||
| 223 | + width: 35px; | ||
| 224 | + font-weight: 700; | ||
| 225 | +} | ||
| 226 | +.action-profile-members .profile_link .fn{ | ||
| 227 | + font-style: normal; | ||
| 228 | + color: #000; | ||
| 229 | +} |
| @@ -0,0 +1,34 @@ | @@ -0,0 +1,34 @@ | ||
| 1 | + | ||
| 2 | +require_relative "../test_helper" | ||
| 3 | + | ||
| 4 | +class AccessControlTest < ActiveSupport::TestCase | ||
| 5 | + | ||
| 6 | + include ActsAsAccessor | ||
| 7 | + | ||
| 8 | + should 'raise exception if parameter is not a profile' do | ||
| 9 | + assert_raises(TypeError) { member_relation_of(nil) } | ||
| 10 | + end | ||
| 11 | + | ||
| 12 | + should 'Verify relation among member and community' do | ||
| 13 | + person = fast_create(Person) | ||
| 14 | + community = fast_create(Community) | ||
| 15 | + assert_difference 'person.member_relation_of(community).count', 2 do | ||
| 16 | + community.add_member(person) | ||
| 17 | + end | ||
| 18 | + end | ||
| 19 | + | ||
| 20 | + should 'Member does not belong to community' do | ||
| 21 | + person = fast_create(Person) | ||
| 22 | + community = fast_create(Community) | ||
| 23 | + assert_nil person.member_since_date(community) | ||
| 24 | + end | ||
| 25 | + | ||
| 26 | + should 'Verify if enter date of member in community is available' do | ||
| 27 | + person = fast_create(Person) | ||
| 28 | + community = fast_create(Community) | ||
| 29 | + community.add_member(person) | ||
| 30 | + | ||
| 31 | + assert_instance_of Date, person.member_since_date(community) | ||
| 32 | + end | ||
| 33 | + | ||
| 34 | +end |
test/unit/application_helper_test.rb
| @@ -1043,6 +1043,31 @@ class ApplicationHelperTest < ActionView::TestCase | @@ -1043,6 +1043,31 @@ class ApplicationHelperTest < ActionView::TestCase | ||
| 1043 | assert_equal c.top_url, top_url | 1043 | assert_equal c.top_url, top_url |
| 1044 | end | 1044 | end |
| 1045 | 1045 | ||
| 1046 | + should "Extra info with hash" do | ||
| 1047 | + @plugins = mock | ||
| 1048 | + @plugins.stubs(:dispatch_first).returns(false) | ||
| 1049 | + env = Environment.default | ||
| 1050 | + stubs(:environment).returns(env) | ||
| 1051 | + stubs(:profile).returns(profile) | ||
| 1052 | + profile = fast_create(Person, :environment_id => env.id) | ||
| 1053 | + info = {:value =>_('New'), :class => 'new-profile'} | ||
| 1054 | + html = profile_image_link(profile, size=:portrait, tag='li', extra_info = info) | ||
| 1055 | + assert_tag_in_string html, :tag => 'span', :attributes => { :class => 'profile-image new-profile' } | ||
| 1056 | + assert_tag_in_string html, :tag => 'span', :attributes => { :class => 'extra_info new-profile' }, :content => 'New' | ||
| 1057 | + end | ||
| 1058 | + | ||
| 1059 | + should "Extra info without hash" do | ||
| 1060 | + @plugins = mock | ||
| 1061 | + @plugins.stubs(:dispatch_first).returns(false) | ||
| 1062 | + env = Environment.default | ||
| 1063 | + stubs(:environment).returns(env) | ||
| 1064 | + stubs(:profile).returns(profile) | ||
| 1065 | + profile = fast_create(Person, :environment_id => env.id) | ||
| 1066 | + info = 'new' | ||
| 1067 | + html = profile_image_link(profile, size=:portrait, tag='li', extra_info = info) | ||
| 1068 | + assert_tag_in_string html, :tag => 'span', :attributes => { :class => 'extra_info' }, :content => 'new' | ||
| 1069 | + end | ||
| 1070 | + | ||
| 1046 | protected | 1071 | protected |
| 1047 | include NoosferoTestHelper | 1072 | include NoosferoTestHelper |
| 1048 | 1073 |
test/unit/person_test.rb
| @@ -1925,5 +1925,13 @@ class PersonTest < ActiveSupport::TestCase | @@ -1925,5 +1925,13 @@ class PersonTest < ActiveSupport::TestCase | ||
| 1925 | assert_equal 2, Person.with_role(Profile::Roles.moderator(c1.environment.id).id).count | 1925 | assert_equal 2, Person.with_role(Profile::Roles.moderator(c1.environment.id).id).count |
| 1926 | end | 1926 | end |
| 1927 | 1927 | ||
| 1928 | + should 'check if a person is added like a member of a community today' do | ||
| 1929 | + person = create_user('person').person | ||
| 1930 | + community = fast_create(Community) | ||
| 1928 | 1931 | ||
| 1932 | + community.add_member person | ||
| 1933 | + | ||
| 1934 | + assert !person.member_relation_of(community).empty?, "Person '#{person.identifier}' is not a member of Community '#{community.identifier}'" | ||
| 1935 | + assert person.member_since_date(community) == Date.today,"Person '#{person.identifier}' is not added like a member of Community '#{community.identifier}' today" | ||
| 1936 | + end | ||
| 1929 | end | 1937 | end |
vendor/plugins/access_control/lib/acts_as_accessible.rb
| @@ -19,9 +19,9 @@ module ActsAsAccessible | @@ -19,9 +19,9 @@ module ActsAsAccessible | ||
| 19 | nil | 19 | nil |
| 20 | end | 20 | end |
| 21 | 21 | ||
| 22 | - def affiliate(accessor, roles) | 22 | + def affiliate(accessor, roles, attributes = {}) |
| 23 | roles = Array(roles) | 23 | roles = Array(roles) |
| 24 | - roles.map {|role| accessor.add_role(role, self)}.any? | 24 | + roles.map {|role| accessor.add_role(role, self, attributes)}.any? |
| 25 | end | 25 | end |
| 26 | 26 | ||
| 27 | def disaffiliate(accessor, roles) | 27 | def disaffiliate(accessor, roles) |
vendor/plugins/access_control/lib/acts_as_accessor.rb
| @@ -21,9 +21,9 @@ module ActsAsAccessor | @@ -21,9 +21,9 @@ module ActsAsAccessor | ||
| 21 | (actual_roles - roles).each {|r| remove_role(r, resource)} | 21 | (actual_roles - roles).each {|r| remove_role(r, resource)} |
| 22 | end | 22 | end |
| 23 | 23 | ||
| 24 | - def add_role(role, resource) | ||
| 25 | - attributes = role_attributes(role, resource) | ||
| 26 | - if RoleAssignment.where(attributes).empty? | 24 | + def add_role(role, resource, attributes = {}) |
| 25 | + attributes = role_attributes(role, resource).merge attributes | ||
| 26 | + if RoleAssignment.find(:all, :conditions => attributes).empty? | ||
| 27 | ra = RoleAssignment.new(attributes) | 27 | ra = RoleAssignment.new(attributes) |
| 28 | role_assignments << ra | 28 | role_assignments << ra |
| 29 | resource.role_assignments << ra | 29 | resource.role_assignments << ra |
| @@ -44,6 +44,19 @@ module ActsAsAccessor | @@ -44,6 +44,19 @@ module ActsAsAccessor | ||
| 44 | RoleAssignment.where(role_attributes nil, res) | 44 | RoleAssignment.where(role_attributes nil, res) |
| 45 | end | 45 | end |
| 46 | 46 | ||
| 47 | + def member_relation_of(profile) | ||
| 48 | + raise TypeError, "Expected instance of 'Profile' class, but '#{profile.class.name}' was founded" unless profile.is_a? Profile | ||
| 49 | + | ||
| 50 | + role_assignments.where(resource_id: profile.id) | ||
| 51 | + end | ||
| 52 | + | ||
| 53 | + def member_since_date(profile) | ||
| 54 | + result = member_relation_of(profile).to_a | ||
| 55 | + unless result.empty? | ||
| 56 | + result.last.created_at ? result.last.created_at.to_date : Date.yesterday | ||
| 57 | + end | ||
| 58 | + end | ||
| 59 | + | ||
| 47 | protected | 60 | protected |
| 48 | def role_attributes(role, resource) | 61 | def role_attributes(role, resource) |
| 49 | attributes = {:accessor_id => self.id, :accessor_type => self.class.base_class.name} | 62 | attributes = {:accessor_id => self.id, :accessor_type => self.class.base_class.name} |
vendor/plugins/access_control/lib/role_assignment.rb
| 1 | class RoleAssignment < ActiveRecord::Base | 1 | class RoleAssignment < ActiveRecord::Base |
| 2 | 2 | ||
| 3 | - attr_accessible :accessor_id, :accessor_type, :role_id, :resource_id, :resource_type | 3 | + attr_accessible :accessor_id, :accessor_type, :role_id, :resource_id, :resource_type, :created_at |
| 4 | 4 | ||
| 5 | belongs_to :role | 5 | belongs_to :role |
| 6 | belongs_to :accessor, :polymorphic => true | 6 | belongs_to :accessor, :polymorphic => true |