Commit b8ade54001d3480693016e52353b96a1bc79f9a2
1 parent
c0cb6076
Exists in
master
and in
29 other branches
Procedure after last admin leaves organization
* if he is also last member, the next user to join organization will become admin * if has other members, admin must choose some user to become admin * Generalized enterprise add_member interface. * Using json to manage action after join/leave/add/remove community/friend through ajax. * Person.members_of now returns unique profiles (ActionItem1400)
Showing
30 changed files
with
491 additions
and
134 deletions
Show diff stats
app/controllers/my_profile/profile_members_controller.rb
@@ -15,26 +15,29 @@ class ProfileMembersController < MyProfileController | @@ -15,26 +15,29 @@ class ProfileMembersController < MyProfileController | ||
15 | rescue ActiveRecord::RecordNotFound | 15 | rescue ActiveRecord::RecordNotFound |
16 | @person = nil | 16 | @person = nil |
17 | end | 17 | end |
18 | - if @person && @person.define_roles(@roles, profile) | ||
19 | - session[:notice] = _('Roles successfuly updated') | 18 | + if !params[:confirmation] && @person && @person.is_last_admin_leaving?(profile, @roles) |
19 | + redirect_to :action => :last_admin, :roles => params[:roles], :person => @person | ||
20 | else | 20 | else |
21 | - session[:notice] = _('Couldn\'t change the roles') | 21 | + if @person && @person.define_roles(@roles, profile) |
22 | + session[:notice] = _('Roles successfuly updated') | ||
23 | + else | ||
24 | + session[:notice] = _('Couldn\'t change the roles') | ||
25 | + end | ||
26 | + if params[:confirmation] | ||
27 | + redirect_to profile.url | ||
28 | + else | ||
29 | + redirect_to :action => :index | ||
30 | + end | ||
22 | end | 31 | end |
23 | - redirect_to :action => :index | ||
24 | end | 32 | end |
25 | 33 | ||
26 | - def change_role | ||
27 | - @roles = Profile::Roles.organization_member_roles(environment.id) | ||
28 | - begin | ||
29 | - @member = profile.members.find(params[:id]) | ||
30 | - rescue ActiveRecord::RecordNotFound | ||
31 | - @member = nil | ||
32 | - end | ||
33 | - if @member | ||
34 | - @associations = @member.find_roles(@profile) | ||
35 | - else | ||
36 | - redirect_to :action => :index | ||
37 | - end | 34 | + def last_admin |
35 | + @person = params[:person] | ||
36 | + @roles = params[:roles] || [] | ||
37 | + @members = profile.members.select {|member| !profile.admins.include?(member)} | ||
38 | + @title = _('Current admins') | ||
39 | + @collection = :profile_admins | ||
40 | + @remove_action = {:action => 'remove_admin'} | ||
38 | end | 41 | end |
39 | 42 | ||
40 | def add_role | 43 | def add_role |
@@ -59,14 +62,28 @@ class ProfileMembersController < MyProfileController | @@ -59,14 +62,28 @@ class ProfileMembersController < MyProfileController | ||
59 | render :layout => false | 62 | render :layout => false |
60 | end | 63 | end |
61 | 64 | ||
65 | + def change_role | ||
66 | + @roles = Profile::Roles.organization_member_roles(environment.id) | ||
67 | + begin | ||
68 | + @member = profile.members.find(params[:id]) | ||
69 | + rescue ActiveRecord::RecordNotFound | ||
70 | + @member = nil | ||
71 | + end | ||
72 | + if @member | ||
73 | + @associations = @member.find_roles(@profile) | ||
74 | + else | ||
75 | + redirect_to :action => :index | ||
76 | + end | ||
77 | + end | ||
78 | + | ||
62 | def unassociate | 79 | def unassociate |
63 | member = Person.find(params[:id]) | 80 | member = Person.find(params[:id]) |
64 | associations = member.find_roles(profile) | 81 | associations = member.find_roles(profile) |
65 | RoleAssignment.transaction do | 82 | RoleAssignment.transaction do |
66 | if associations.map(&:destroy) | 83 | if associations.map(&:destroy) |
67 | - session[:notice] = 'Member succefully unassociated' | 84 | + session[:notice] = _('Member succesfully unassociated') |
68 | else | 85 | else |
69 | - session[:notice] = 'Failed to unassociate member' | 86 | + session[:notice] = _('Failed to unassociate member') |
70 | end | 87 | end |
71 | end | 88 | end |
72 | render :layout => false | 89 | render :layout => false |
@@ -83,11 +100,39 @@ class ProfileMembersController < MyProfileController | @@ -83,11 +100,39 @@ class ProfileMembersController < MyProfileController | ||
83 | render :layout => false | 100 | render :layout => false |
84 | end | 101 | end |
85 | 102 | ||
103 | + def add_admin | ||
104 | + @title = _('Current admins') | ||
105 | + @collection = :profile_admins | ||
106 | + | ||
107 | + if profile.community? | ||
108 | + member = profile.members.find_by_identifier(params[:id]) | ||
109 | + profile.add_admin(member) | ||
110 | + end | ||
111 | + render :layout => false | ||
112 | + end | ||
113 | + | ||
114 | + def remove_admin | ||
115 | + @title = _('Current admins') | ||
116 | + @collection = :profile_admins | ||
117 | + | ||
118 | + if profile.community? | ||
119 | + member = profile.members.find_by_identifier(params[:id]) | ||
120 | + profile.remove_admin(member) | ||
121 | + end | ||
122 | + render :layout => false | ||
123 | + end | ||
124 | + | ||
86 | def find_users | 125 | def find_users |
87 | if !params[:query] || params[:query].length <= 2 | 126 | if !params[:query] || params[:query].length <= 2 |
88 | @users_found = [] | 127 | @users_found = [] |
89 | - else | ||
90 | - @users_found = Person.find_by_contents(params[:query] + '*') | 128 | + elsif params[:scope] == 'all_users' |
129 | + @users_found = Person.find_by_contents(params[:query] + '*').select {|user| !profile.members.include?(user)} | ||
130 | + @button_alt = _('Add member') | ||
131 | + @add_action = {:action => 'add_member'} | ||
132 | + elsif params[:scope] == 'new_admins' | ||
133 | + @users_found = Person.find_by_contents(params[:query] + '*').select {|user| profile.members.include?(user) && !profile.admins.include?(user)} | ||
134 | + @button_alt = _('Add member') | ||
135 | + @add_action = {:action => 'add_admin'} | ||
91 | end | 136 | end |
92 | render :layout => false | 137 | render :layout => false |
93 | end | 138 | end |
app/controllers/public/profile_controller.rb
@@ -82,13 +82,13 @@ class ProfileController < PublicController | @@ -82,13 +82,13 @@ class ProfileController < PublicController | ||
82 | def join | 82 | def join |
83 | if !user.memberships.include?(profile) | 83 | if !user.memberships.include?(profile) |
84 | profile.add_member(user) | 84 | profile.add_member(user) |
85 | - if profile.closed? | ||
86 | - render :text => _('%s administrator still needs to accept you as member.') % profile.name | 85 | + if !profile.members.include?(user) |
86 | + render :text => {:message => _('%s administrator still needs to accept you as member.') % profile.name}.to_json | ||
87 | else | 87 | else |
88 | - render :text => _('You just became a member of %s.') % profile.name | 88 | + render :text => {:message => _('You just became a member of %s.') % profile.name}.to_json |
89 | end | 89 | end |
90 | else | 90 | else |
91 | - render :text => _('You are already a member of %s.') % profile.name | 91 | + render :text => {:message => _('You are already a member of %s.') % profile.name}.to_json |
92 | end | 92 | end |
93 | end | 93 | end |
94 | 94 | ||
@@ -110,11 +110,14 @@ class ProfileController < PublicController | @@ -110,11 +110,14 @@ class ProfileController < PublicController | ||
110 | end | 110 | end |
111 | 111 | ||
112 | def leave | 112 | def leave |
113 | - if user.memberships.include?(profile) | ||
114 | - profile.remove_member(current_user.person) | ||
115 | - render :text => _('You just left %s.') % profile.name | 113 | + if current_person.memberships.include?(profile) |
114 | + if current_person.is_last_admin?(profile) | ||
115 | + render :text => {:redirect_to => url_for({:controller => 'profile_members', :action => 'last_admin', :person => current_person.id})}.to_json | ||
116 | + else | ||
117 | + render :text => current_person.leave(profile, params[:reload]) | ||
118 | + end | ||
116 | else | 119 | else |
117 | - render :text => _('You are already a member of %s.') % profile.name | 120 | + render :text => {:message => _('You are not a member of %s.') % profile.name}.to_json |
118 | end | 121 | end |
119 | end | 122 | end |
120 | 123 |
app/models/environment_mailing.rb
1 | class EnvironmentMailing < Mailing | 1 | class EnvironmentMailing < Mailing |
2 | 2 | ||
3 | def recipients(offset=0, limit=100) | 3 | def recipients(offset=0, limit=100) |
4 | - source.people.all(:order => :id, :offset => offset, :limit => limit, :joins => "LEFT OUTER JOIN mailing_sents m ON (m.mailing_id = #{id} AND m.person_id = profiles.id)", :order => :id, :conditions => { "m.person_id" => nil }) | 4 | + source.people.all(:order => :id, :offset => offset, :limit => limit, :joins => "LEFT OUTER JOIN mailing_sents m ON (m.mailing_id = #{id} AND m.person_id = profiles.id)", :conditions => { "m.person_id" => nil }) |
5 | end | 5 | end |
6 | 6 | ||
7 | def each_recipient | 7 | def each_recipient |
app/models/organization_mailing.rb
@@ -5,7 +5,7 @@ class OrganizationMailing < Mailing | @@ -5,7 +5,7 @@ class OrganizationMailing < Mailing | ||
5 | end | 5 | end |
6 | 6 | ||
7 | def recipients(offset=0, limit=100) | 7 | def recipients(offset=0, limit=100) |
8 | - source.members.all(:order => :id, :offset => offset, :limit => limit, :joins => "LEFT OUTER JOIN mailing_sents m ON (m.mailing_id = #{id} AND m.person_id = profiles.id)", :order => :id, :conditions => { "m.person_id" => nil }) | 8 | + source.members.all(:order => self.id, :offset => offset, :limit => limit, :joins => "LEFT OUTER JOIN mailing_sents m ON (m.mailing_id = #{id} AND m.person_id = profiles.id)", :conditions => { "m.person_id" => nil }) |
9 | end | 9 | end |
10 | 10 | ||
11 | def each_recipient | 11 | def each_recipient |
app/models/person.rb
@@ -4,7 +4,7 @@ class Person < Profile | @@ -4,7 +4,7 @@ class Person < Profile | ||
4 | acts_as_trackable :after_add => Proc.new {|p,t| notify_activity(t)} | 4 | acts_as_trackable :after_add => Proc.new {|p,t| notify_activity(t)} |
5 | acts_as_accessor | 5 | acts_as_accessor |
6 | 6 | ||
7 | - named_scope :members_of, lambda { |resource| { :select => 'DISTINCT profiles.*', :joins => :role_assignments, :conditions => ['role_assignments.resource_type = ? AND role_assignments.resource_id = ?', resource.class.base_class.name, resource.id ] } } | 7 | + named_scope :members_of, lambda { |resource| { :select => 'DISTINCT profiles.*', :include => :role_assignments, :group => 'profiles.id', :conditions => ['role_assignments.resource_type = ? AND role_assignments.resource_id = ?', resource.class.base_class.name, resource.id ] } } |
8 | 8 | ||
9 | def memberships | 9 | def memberships |
10 | Profile.memberships_of(self) | 10 | Profile.memberships_of(self) |
@@ -363,10 +363,26 @@ class Person < Profile | @@ -363,10 +363,26 @@ class Person < Profile | ||
363 | generate_url(:profile => identifier, :controller => 'profile', :action => 'index', :anchor => 'profile-wall') | 363 | generate_url(:profile => identifier, :controller => 'profile', :action => 'index', :anchor => 'profile-wall') |
364 | end | 364 | end |
365 | 365 | ||
366 | + def is_last_admin?(organization) | ||
367 | + organization.admins == [self] | ||
368 | + end | ||
369 | + | ||
370 | + def is_last_admin_leaving?(organization, roles) | ||
371 | + is_last_admin?(organization) && roles.select {|role| role.key == "profile_admin"}.blank? | ||
372 | + end | ||
373 | + | ||
374 | + def leave(profile, reload = false) | ||
375 | + leave_hash = {:message => _('You just left %s.') % profile.name} | ||
376 | + if reload | ||
377 | + leave_hash.merge!({:reload => true}) | ||
378 | + end | ||
379 | + profile.remove_member(self) | ||
380 | + leave_hash.to_json | ||
381 | + end | ||
382 | + | ||
366 | protected | 383 | protected |
367 | 384 | ||
368 | def followed_by?(profile) | 385 | def followed_by?(profile) |
369 | self == profile || self.is_a_friend?(profile) | 386 | self == profile || self.is_a_friend?(profile) |
370 | end | 387 | end |
371 | - | ||
372 | end | 388 | end |
app/models/profile.rb
@@ -424,8 +424,8 @@ class Profile < ActiveRecord::Base | @@ -424,8 +424,8 @@ class Profile < ActiveRecord::Base | ||
424 | { :profile => identifier, :controller => 'profile_editor', :action => 'index' } | 424 | { :profile => identifier, :controller => 'profile_editor', :action => 'index' } |
425 | end | 425 | end |
426 | 426 | ||
427 | - def leave_url | ||
428 | - { :profile => identifier, :controller => 'profile', :action => 'leave' } | 427 | + def leave_url(reload = false) |
428 | + { :profile => identifier, :controller => 'profile', :action => 'leave', :reload => reload } | ||
429 | end | 429 | end |
430 | 430 | ||
431 | def join_url | 431 | def join_url |
@@ -563,13 +563,16 @@ private :generate_url, :url_options | @@ -563,13 +563,16 @@ private :generate_url, :url_options | ||
563 | # Adds a person as member of this Profile. | 563 | # Adds a person as member of this Profile. |
564 | def add_member(person) | 564 | def add_member(person) |
565 | if self.has_members? | 565 | if self.has_members? |
566 | - if self.closed? | 566 | + if self.closed? && members.count > 0 |
567 | AddMember.create!(:person => person, :organization => self) unless self.already_request_membership?(person) | 567 | AddMember.create!(:person => person, :organization => self) unless self.already_request_membership?(person) |
568 | else | 568 | else |
569 | + if members.count == 0 | ||
570 | + self.affiliate(person, Profile::Roles.admin(environment.id)) | ||
571 | + end | ||
569 | self.affiliate(person, Profile::Roles.member(environment.id)) | 572 | self.affiliate(person, Profile::Roles.member(environment.id)) |
570 | end | 573 | end |
571 | else | 574 | else |
572 | - raise _("%s can't has members") % self.class.name | 575 | + raise _("%s can't have members") % self.class.name |
573 | end | 576 | end |
574 | end | 577 | end |
575 | 578 | ||
@@ -582,6 +585,10 @@ private :generate_url, :url_options | @@ -582,6 +585,10 @@ private :generate_url, :url_options | ||
582 | self.affiliate(person, Profile::Roles.admin(environment.id)) | 585 | self.affiliate(person, Profile::Roles.admin(environment.id)) |
583 | end | 586 | end |
584 | 587 | ||
588 | + def remove_admin(person) | ||
589 | + self.disaffiliate(person, Profile::Roles.admin(environment.id)) | ||
590 | + end | ||
591 | + | ||
585 | def add_moderator(person) | 592 | def add_moderator(person) |
586 | if self.has_members? | 593 | if self.has_members? |
587 | self.affiliate(person, Profile::Roles.moderator(environment.id)) | 594 | self.affiliate(person, Profile::Roles.moderator(environment.id)) |
app/views/memberships/index.rhtml
@@ -23,7 +23,7 @@ | @@ -23,7 +23,7 @@ | ||
23 | <%= _('Created at: %s') % show_date(membership.created_at) unless membership.enterprise? %> <br/> | 23 | <%= _('Created at: %s') % show_date(membership.created_at) unless membership.enterprise? %> <br/> |
24 | <% button_bar do %> | 24 | <% button_bar do %> |
25 | <%= button 'menu-ctrl-panel', _('Control panel of this group'), membership.admin_url %> | 25 | <%= button 'menu-ctrl-panel', _('Control panel of this group'), membership.admin_url %> |
26 | - <%= lightbox_button 'menu-logout', _('Leave'), membership.leave_url %> | 26 | + <%= button 'menu-logout', _('Leave'), membership.leave_url(true), :class => 'leave-community' %> |
27 | <% if (membership.community? && user.has_permission?(:destroy_profile, membership)) %> | 27 | <% if (membership.community? && user.has_permission?(:destroy_profile, membership)) %> |
28 | <%= button 'delete', _('Remove'), { :controller => 'profile_editor', :action => 'destroy_profile', :profile => membership.identifier } %> | 28 | <%= button 'delete', _('Remove'), { :controller => 'profile_editor', :action => 'destroy_profile', :profile => membership.identifier } %> |
29 | <% end %> | 29 | <% end %> |
@@ -0,0 +1,30 @@ | @@ -0,0 +1,30 @@ | ||
1 | +<h2><%= _('Add admins to %s') % profile.name %></h2> | ||
2 | + | ||
3 | +<% form_remote_tag :url => {:action => 'find_users', :profile => profile.identifier, :scope => 'new_admins'}, :update => 'users-list', :loading => '$("users-list").addClassName("loading")', :complete => '$("users-list").removeClassName("loading")' do %> | ||
4 | + <%= text_field_tag('query', '', :autocomplete => 'off') %> | ||
5 | + <%= submit_tag(_('Search')) %> | ||
6 | +<% end %> | ||
7 | + | ||
8 | +<%= observe_field('query', :url => {:action => 'find_users', :profile => profile.identifier, :scope => 'new_admins'}, :update => 'users-list', :frequency => 1, :with => 'query', :condition => '$("query").value.length > 2', :loading => '$("users-list").addClassName("loading")', :complete => '$("users-list").removeClassName("loading")') %> | ||
9 | +<%= observe_field('query', :frequency => 1, :condition => '$("query").value.length <= 2', :function => '$("users-list").update($("empty-query").innerHTML)') %> | ||
10 | + | ||
11 | +<div id="users-list"> | ||
12 | + <%= render :partial => 'find_users' %> | ||
13 | +</div> | ||
14 | + | ||
15 | +<div id='empty-query' style='display: none'> | ||
16 | + <%= render :partial => 'find_users' %> | ||
17 | +</div> | ||
18 | + | ||
19 | +<div id="members-list" class="add-members"> | ||
20 | + <%= render :partial => 'members_list' %> | ||
21 | +</div> | ||
22 | +<%= drop_receiving_element('members-list', | ||
23 | + :url => {:action => 'add_admin', :profile => profile.identifier, :leaving_admin => @person}, | ||
24 | + :before => '$("tr-" + element.id).hide()', | ||
25 | + :loading => '$("members-list").addClassName("loading")', | ||
26 | + :update => 'members-list', | ||
27 | + :success => '$("tr-" + element.id).hide(); $(element.id).show();', | ||
28 | + :complete => '$("members-list").removeClassName("loading")') %> | ||
29 | + | ||
30 | +<br style="clear:both" /> |
app/views/profile_members/_members_list.rhtml
1 | -<h3><%= _('Current Members') %></h3> | 1 | +<% collection = @collection == :profile_admins ? profile.admins : profile.members %> |
2 | +<% title = @title ? @title : "Current members" %> | ||
3 | +<% remove_action = @remove_action ? @remove_action : {:action => 'unassociate'} %> | ||
4 | + | ||
5 | +<h3><%= _(title) %></h3> | ||
2 | 6 | ||
3 | <table> | 7 | <table> |
4 | <tr> | 8 | <tr> |
5 | <th><%= _('Member') %></th> | 9 | <th><%= _('Member') %></th> |
6 | <th><%= _('Actions') %></th> | 10 | <th><%= _('Actions') %></th> |
7 | </tr> | 11 | </tr> |
8 | - <% profile.members.each do |m| %> | 12 | + <% collection.each do |m| %> |
9 | <tr> | 13 | <tr> |
10 | <td><%= link_to_profile m.short_name, m.identifier, :title => m.name %> </td> | 14 | <td><%= link_to_profile m.short_name, m.identifier, :title => m.name %> </td> |
11 | <td> | 15 | <td> |
@@ -16,8 +20,7 @@ | @@ -16,8 +20,7 @@ | ||
16 | :loading => '$("members-list").addClassName("loading")', | 20 | :loading => '$("members-list").addClassName("loading")', |
17 | :success => "$('tr-#{m.identifier}').show()", | 21 | :success => "$('tr-#{m.identifier}').show()", |
18 | :complete => '$("members-list").removeClassName("loading")', | 22 | :complete => '$("members-list").removeClassName("loading")', |
19 | - :confirm => _('Are you sure that you want to remove this member?'), | ||
20 | - :url => {:action => 'unassociate', :id => m}) if m != user %> | 23 | + :url => { :id => m }.merge(remove_action)) if m != user %> |
21 | </div> | 24 | </div> |
22 | </td> | 25 | </td> |
23 | </tr> | 26 | </tr> |
app/views/profile_members/add_members.rhtml
1 | <h2><%= _('Add members to %s') % profile.name %></h2> | 1 | <h2><%= _('Add members to %s') % profile.name %></h2> |
2 | 2 | ||
3 | -<% form_remote_tag :url => {:action => 'find_users', :profile => profile.identifier}, :update => 'users-list', :loading => '$("users-list").addClassName("loading")', :complete => '$("users-list").removeClassName("loading")' do %> | 3 | +<% form_remote_tag :url => {:action => 'find_users', :profile => profile.identifier, :scope => 'all_users'}, :update => 'users-list', :loading => '$("users-list").addClassName("loading")', :complete => '$("users-list").removeClassName("loading")' do %> |
4 | <%= text_field_tag('query', '', :autocomplete => 'off') %> | 4 | <%= text_field_tag('query', '', :autocomplete => 'off') %> |
5 | <%= submit_tag(_('Search')) %> | 5 | <%= submit_tag(_('Search')) %> |
6 | <% end %> | 6 | <% end %> |
7 | 7 | ||
8 | -<%= observe_field('query', :url => {:action => 'find_users', :profile => profile.identifier}, :update => 'users-list', :frequency => 1, :with => 'query', :condition => '$("query").value.length > 2', :loading => '$("users-list").addClassName("loading")', :complete => '$("users-list").removeClassName("loading")') %> | 8 | +<%= observe_field('query', :url => {:action => 'find_users', :profile => profile.identifier, :scope => 'all_users'}, :update => 'users-list', :frequency => 1, :with => 'query', :condition => '$("query").value.length > 2', :loading => '$("users-list").addClassName("loading")', :complete => '$("users-list").removeClassName("loading")') %> |
9 | <%= observe_field('query', :frequency => 1, :condition => '$("query").value.length <= 2', :function => '$("users-list").update($("empty-query").innerHTML)') %> | 9 | <%= observe_field('query', :frequency => 1, :condition => '$("query").value.length <= 2', :function => '$("users-list").update($("empty-query").innerHTML)') %> |
10 | 10 | ||
11 | <div id="users-list"> | 11 | <div id="users-list"> |
app/views/profile_members/find_users.rhtml
@@ -2,7 +2,7 @@ | @@ -2,7 +2,7 @@ | ||
2 | <table> | 2 | <table> |
3 | <tr><th><%= _('Name') %></th><th></th></tr> | 3 | <tr><th><%= _('Name') %></th><th></th></tr> |
4 | <% @users_found.each do |user| %> | 4 | <% @users_found.each do |user| %> |
5 | - <tr id="tr-<%= user.identifier %>"<%= profile.members.include?(user) ? 'style="display:none"' : '' %>> | 5 | + <tr id="tr-<%= user.identifier %>"> |
6 | <td> | 6 | <td> |
7 | <div id="<%= user.identifier %>" class="draggable-user"> | 7 | <div id="<%= user.identifier %>" class="draggable-user"> |
8 | <%= image_tag('/images/grip-clue.png') %> | 8 | <%= image_tag('/images/grip-clue.png') %> |
@@ -14,10 +14,10 @@ | @@ -14,10 +14,10 @@ | ||
14 | <%= draggable_element(user.identifier, :revert => true) %> | 14 | <%= draggable_element(user.identifier, :revert => true) %> |
15 | </td> | 15 | </td> |
16 | <td> | 16 | <td> |
17 | - <%= button_to_remote_without_text(:add, _('Add member'), | 17 | + <%= button_to_remote_without_text(:add, @button_alt, |
18 | { :loading => '$("members-list").addClassName("loading")', | 18 | { :loading => '$("members-list").addClassName("loading")', |
19 | :update => 'members-list', | 19 | :update => 'members-list', |
20 | - :url => {:action => 'add_member', :profile => profile.identifier, :id => user.id}, | 20 | + :url => {:id => user.id, :profile => profile.identifier}.merge(@add_action), |
21 | :success => "$('tr-#{user.identifier}').hide()", | 21 | :success => "$('tr-#{user.identifier}').hide()", |
22 | :complete => '$("members-list").removeClassName("loading")'}) %> | 22 | :complete => '$("members-list").removeClassName("loading")'}) %> |
23 | 23 |
@@ -0,0 +1,27 @@ | @@ -0,0 +1,27 @@ | ||
1 | +<h1><%= _('Last administrator leaving %s') % profile.name %></h1> | ||
2 | + | ||
3 | +<% if profile.members.count > 1 %> | ||
4 | + <div id='last-admin-message'> | ||
5 | + <%= _('Since you are the last administrator, you must choose at least one member to administer this community.') % profile.name %> | ||
6 | + </div> | ||
7 | + | ||
8 | + <%= render :partial => 'add_admins' %> | ||
9 | + | ||
10 | + <% form_tag :action => 'update_roles', :roles => @roles, :person => @person, :confirmation => profile.admins.count > 1 do %> | ||
11 | + <% button_bar do %> | ||
12 | + <%= submit_button(:save, _("Leave administration and save"), :cancel => {:action => 'index'}) %> | ||
13 | + <% end %> | ||
14 | + <% end %> | ||
15 | + | ||
16 | +<% else %> | ||
17 | + | ||
18 | + <div id='last-admin-message'> | ||
19 | + <%= _('Since you are the last administrator and there is no other member in this community, the next member to join this community will assume the administrator role.') % profile.name %> | ||
20 | + </div> | ||
21 | + | ||
22 | + <% form_tag :action => 'update_roles', :roles => @roles, :person => @person, :confirmation => true do %> | ||
23 | + <% button_bar do %> | ||
24 | + <%= submit_button(:ok, _("Ok, I want to leave"), :cancel => {:action => 'index'}) %> | ||
25 | + <% end %> | ||
26 | + <% end %> | ||
27 | +<% end %> |
features/delete_profile.feature
@@ -7,6 +7,11 @@ Feature: delete profile | @@ -7,6 +7,11 @@ Feature: delete profile | ||
7 | Given the following users | 7 | Given the following users |
8 | | login | name | | 8 | | login | name | |
9 | | joaosilva | Joao Silva | | 9 | | joaosilva | Joao Silva | |
10 | + | mariasilva | Maria Silva | | ||
11 | + And the following community | ||
12 | + | identifier | name | | ||
13 | + | sample-community | Sample Community | | ||
14 | + And "Maria Silva" is a member of "Sample Community" | ||
10 | 15 | ||
11 | Scenario: deleting profile | 16 | Scenario: deleting profile |
12 | Given I am logged in as "joaosilva" | 17 | Given I am logged in as "joaosilva" |
@@ -20,10 +25,7 @@ Feature: delete profile | @@ -20,10 +25,7 @@ Feature: delete profile | ||
20 | Then I should see "There is no such page" | 25 | Then I should see "There is no such page" |
21 | 26 | ||
22 | Scenario: deleting other profile | 27 | Scenario: deleting other profile |
23 | - Given the following users | ||
24 | - | login | name | | ||
25 | - | mariasilva | Maria Silva | | ||
26 | - And I am logged in as "mariasilva" | 28 | + Given I am logged in as "mariasilva" |
27 | And I go to /myprofile/joaosilva/profile_editor/destroy_profile | 29 | And I go to /myprofile/joaosilva/profile_editor/destroy_profile |
28 | Then I should see "Access denied" | 30 | Then I should see "Access denied" |
29 | 31 | ||
@@ -37,20 +39,14 @@ Feature: delete profile | @@ -37,20 +39,14 @@ Feature: delete profile | ||
37 | Then I should be on Joao Silva's profile | 39 | Then I should be on Joao Silva's profile |
38 | 40 | ||
39 | Scenario: community admin can see link to delete profile | 41 | Scenario: community admin can see link to delete profile |
40 | - Given the following community | ||
41 | - | identifier | name | | ||
42 | - | sample-community | Sample Community | | ||
43 | - And "Joao Silva" is admin of "Sample Community" | 42 | + Given "Joao Silva" is admin of "Sample Community" |
44 | And I am logged in as "joaosilva" | 43 | And I am logged in as "joaosilva" |
45 | And I am on Sample Community's control panel | 44 | And I am on Sample Community's control panel |
46 | When I follow "Community Info and settings" | 45 | When I follow "Community Info and settings" |
47 | Then I should see "Delete profile" | 46 | Then I should see "Delete profile" |
48 | 47 | ||
49 | Scenario: community admin deletes the community | 48 | Scenario: community admin deletes the community |
50 | - Given the following community | ||
51 | - | identifier | name | | ||
52 | - | sample-community | Sample Community | | ||
53 | - And "Joao Silva" is admin of "Sample Community" | 49 | + Given "Joao Silva" is admin of "Sample Community" |
54 | And I am logged in as "joaosilva" | 50 | And I am logged in as "joaosilva" |
55 | And I am on Sample Community's control panel | 51 | And I am on Sample Community's control panel |
56 | And I follow "Community Info and settings" | 52 | And I follow "Community Info and settings" |
@@ -62,10 +58,7 @@ Feature: delete profile | @@ -62,10 +58,7 @@ Feature: delete profile | ||
62 | Then I should see "There is no such page" | 58 | Then I should see "There is no such page" |
63 | 59 | ||
64 | Scenario: community regular member tries to delete the community | 60 | Scenario: community regular member tries to delete the community |
65 | - Given the following community | ||
66 | - | identifier | name | | ||
67 | - | sample-community | Sample Community | | ||
68 | - And "Joao Silva" is a member of "Sample Community" | 61 | + Given "Joao Silva" is a member of "Sample Community" |
69 | And I am logged in as "joaosilva" | 62 | And I am logged in as "joaosilva" |
70 | And I go to /myprofile/sample-community/profile_editor/destroy_profile | 63 | And I go to /myprofile/sample-community/profile_editor/destroy_profile |
71 | Then I should see "Access denied" | 64 | Then I should see "Access denied" |
@@ -96,19 +89,17 @@ Feature: delete profile | @@ -96,19 +89,17 @@ Feature: delete profile | ||
96 | Then I should see "There is no such page" | 89 | Then I should see "There is no such page" |
97 | 90 | ||
98 | Scenario: enterprise regular member tries to delete the enterprise | 91 | Scenario: enterprise regular member tries to delete the enterprise |
99 | - Given the following community | 92 | + Given the following enterprise |
100 | | identifier | name | | 93 | | identifier | name | |
101 | | sample-enterprise | Sample Enterprise | | 94 | | sample-enterprise | Sample Enterprise | |
95 | + And "Maria Silva" is a member of "Sample Enterprise" | ||
102 | And "Joao Silva" is a member of "Sample Enterprise" | 96 | And "Joao Silva" is a member of "Sample Enterprise" |
103 | And I am logged in as "joaosilva" | 97 | And I am logged in as "joaosilva" |
104 | And I go to /myprofile/sample-enterprise/profile_editor/destroy_profile | 98 | And I go to /myprofile/sample-enterprise/profile_editor/destroy_profile |
105 | Then I should see "Access denied" | 99 | Then I should see "Access denied" |
106 | 100 | ||
107 | Scenario: community regular member cannot see link to delete profile | 101 | Scenario: community regular member cannot see link to delete profile |
108 | - Given the following community | ||
109 | - | identifier | name | | ||
110 | - | sample-community | Sample Community | | ||
111 | - And "Joao Silva" is a member of "Sample Community" | 102 | + Given "Joao Silva" is a member of "Sample Community" |
112 | And I am logged in as "joaosilva" | 103 | And I am logged in as "joaosilva" |
113 | And I am on Sample Community's control panel | 104 | And I am on Sample Community's control panel |
114 | When I follow "Community Info and settings" | 105 | When I follow "Community Info and settings" |
@@ -0,0 +1,38 @@ | @@ -0,0 +1,38 @@ | ||
1 | +Feature: remove administrator role | ||
2 | + As an organization administrator | ||
3 | + I want to remove my administrator role | ||
4 | + In order to stop administrating the organization | ||
5 | + | ||
6 | + Background: | ||
7 | + Given the following users | ||
8 | + | login | name | | ||
9 | + | joaosilva | Joao Silva | | ||
10 | + | mariasouza | Maria Souza | | ||
11 | + And the following community | ||
12 | + | name | identifier | | ||
13 | + | Nice people | nice-people | | ||
14 | + And "Joao Silva" is admin of "Nice people" | ||
15 | + And I am logged in as "joaosilva" | ||
16 | + | ||
17 | + Scenario: the last administrator and member removes his administrator role and the next member to join becomes the new administrator | ||
18 | + Given I am on Nice people's members management | ||
19 | + And I follow "Edit" | ||
20 | + And I uncheck "Profile Administrator" | ||
21 | + When I press "Save changes" | ||
22 | + Then I should see "Since you are the last administrator and there is no other member in this community" | ||
23 | + And I press "Ok, I want to leave" | ||
24 | + And I am logged in as "mariasouza" | ||
25 | + When I go to Nice people's join page | ||
26 | + Then "Maria Souza" should be admin of "Nice people" | ||
27 | + | ||
28 | + Scenario: the last administrator and member removes his administrator role and the next member to join becomes the new administrator even if the organization is closed. | ||
29 | + Given the community "Nice people" is closed | ||
30 | + And I am on Nice people's members management | ||
31 | + And I follow "Edit" | ||
32 | + And I uncheck "Profile Administrator" | ||
33 | + When I press "Save changes" | ||
34 | + Then I should see "Since you are the last administrator and there is no other member in this community" | ||
35 | + And I press "Ok, I want to leave" | ||
36 | + And I am logged in as "mariasouza" | ||
37 | + When I go to Nice people's join page | ||
38 | + Then "Maria Souza" should be admin of "Nice people" |
features/register_enterprise.feature
@@ -93,7 +93,7 @@ Feature: register enterprise | @@ -93,7 +93,7 @@ Feature: register enterprise | ||
93 | Then I should see "Enterprise registration completed" | 93 | Then I should see "Enterprise registration completed" |
94 | And I am logged in as admin | 94 | And I am logged in as admin |
95 | And I go to the Control panel | 95 | And I go to the Control panel |
96 | - When I follow "Tasks" | 96 | + When I follow "Tasks" within ".control-panel" |
97 | Then I should see "Joao Silva wants to create enterprise My Enterprise." | 97 | Then I should see "Joao Silva wants to create enterprise My Enterprise." |
98 | And the first mail is to admin_user@example.com | 98 | And the first mail is to admin_user@example.com |
99 | And I choose "Accept" | 99 | And I choose "Accept" |
@@ -120,7 +120,7 @@ Feature: register enterprise | @@ -120,7 +120,7 @@ Feature: register enterprise | ||
120 | Then I should see "Enterprise registration completed" | 120 | Then I should see "Enterprise registration completed" |
121 | And I am logged in as admin | 121 | And I am logged in as admin |
122 | And I go to the Control panel | 122 | And I go to the Control panel |
123 | - When I follow "Tasks" | 123 | + When I follow "Tasks" within ".control-panel" |
124 | Then I should see "Joao Silva wants to create enterprise My Enterprise." | 124 | Then I should see "Joao Silva wants to create enterprise My Enterprise." |
125 | And the first mail is to admin_user@example.com | 125 | And the first mail is to admin_user@example.com |
126 | And I choose "Reject" | 126 | And I choose "Reject" |
features/step_definitions/noosfero_steps.rb
@@ -16,13 +16,13 @@ Given /^"(.+)" is (online|offline|busy) in chat$/ do |user, status| | @@ -16,13 +16,13 @@ Given /^"(.+)" is (online|offline|busy) in chat$/ do |user, status| | ||
16 | User.find_by_login(user).update_attributes(:chat_status => status, :chat_status_at => DateTime.now) | 16 | User.find_by_login(user).update_attributes(:chat_status => status, :chat_status_at => DateTime.now) |
17 | end | 17 | end |
18 | 18 | ||
19 | -Given /^the following (community|communities|enterprises?)$/ do |kind,table| | 19 | +Given /^the following (community|communities|enterprises?|organizations?)$/ do |kind,table| |
20 | klass = kind.singularize.camelize.constantize | 20 | klass = kind.singularize.camelize.constantize |
21 | table.hashes.each do |row| | 21 | table.hashes.each do |row| |
22 | owner = row.delete("owner") | 22 | owner = row.delete("owner") |
23 | - community = klass.create!(row) | 23 | + organization = klass.create!(row) |
24 | if owner | 24 | if owner |
25 | - community.add_admin(Profile[owner]) | 25 | + organization.add_admin(Profile[owner]) |
26 | end | 26 | end |
27 | end | 27 | end |
28 | end | 28 | end |
@@ -210,6 +210,12 @@ Given /^"(.+)" is admin of "(.+)"$/ do |person, organization| | @@ -210,6 +210,12 @@ Given /^"(.+)" is admin of "(.+)"$/ do |person, organization| | ||
210 | org.add_admin(user) | 210 | org.add_admin(user) |
211 | end | 211 | end |
212 | 212 | ||
213 | +Then /^"(.+)" should be admin of "(.+)"$/ do |person, organization| | ||
214 | + org = Organization.find_by_name(organization) | ||
215 | + user = Person.find_by_name(person) | ||
216 | + org.admins.should include(user) | ||
217 | +end | ||
218 | + | ||
213 | Given /^"([^\"]*)" has no articles$/ do |profile| | 219 | Given /^"([^\"]*)" has no articles$/ do |profile| |
214 | (Profile[profile] || Profile.find_by_name(profile)).articles.delete_all | 220 | (Profile[profile] || Profile.find_by_name(profile)).articles.delete_all |
215 | end | 221 | end |
@@ -317,3 +323,9 @@ Given /^the following comments?$/ do |table| | @@ -317,3 +323,9 @@ Given /^the following comments?$/ do |table| | ||
317 | comment.save! | 323 | comment.save! |
318 | end | 324 | end |
319 | end | 325 | end |
326 | + | ||
327 | +Given /^the community "(.+)" is closed$/ do |community| | ||
328 | + community = Community.find_by_name(community) | ||
329 | + community.closed = true | ||
330 | + community.save | ||
331 | +end |
features/support/paths.rb
@@ -36,6 +36,12 @@ module NavigationHelpers | @@ -36,6 +36,12 @@ module NavigationHelpers | ||
36 | when /^the profile$/ | 36 | when /^the profile$/ |
37 | '/profile/%s' % User.find_by_id(session[:user]).login | 37 | '/profile/%s' % User.find_by_id(session[:user]).login |
38 | 38 | ||
39 | + when /^(.*)'s join page/ | ||
40 | + '/profile/%s/join' % Profile.find_by_name($1).identifier | ||
41 | + | ||
42 | + when /^(.*)'s leave page/ | ||
43 | + '/profile/%s/leave' % Profile.find_by_name($1).identifier | ||
44 | + | ||
39 | when /^login page$/ | 45 | when /^login page$/ |
40 | '/account/login' | 46 | '/account/login' |
41 | 47 |
public/javascripts/add-and-join.js
@@ -23,8 +23,8 @@ jQuery(function($) { | @@ -23,8 +23,8 @@ jQuery(function($) { | ||
23 | }); | 23 | }); |
24 | clicked.css("cursor",""); | 24 | clicked.css("cursor",""); |
25 | $(".small-loading").remove(); | 25 | $(".small-loading").remove(); |
26 | - display_notice(data); | ||
27 | - }); | 26 | + display_notice(data.message); |
27 | + }, "json"); | ||
28 | return false; | 28 | return false; |
29 | }) | 29 | }) |
30 | 30 | ||
@@ -33,15 +33,24 @@ jQuery(function($) { | @@ -33,15 +33,24 @@ jQuery(function($) { | ||
33 | url = clicked.attr("href"); | 33 | url = clicked.attr("href"); |
34 | loading_for_button(this); | 34 | loading_for_button(this); |
35 | $.post(url, function(data){ | 35 | $.post(url, function(data){ |
36 | - clicked.fadeOut(function(){ | ||
37 | - clicked.css("display","none"); | ||
38 | - clicked.parent().parent().find(".join-community").fadeIn(); | ||
39 | - clicked.parent().parent().find(".join-community").css("display", ""); | ||
40 | - }); | ||
41 | - clicked.css("cursor",""); | ||
42 | - $(".small-loading").remove(); | ||
43 | - display_notice(data); | ||
44 | - }); | 36 | + if(data.redirect_to){ |
37 | + document.location.href = data.redirect_to; | ||
38 | + } | ||
39 | + else if(data.reload){ | ||
40 | + document.location.reload(true); | ||
41 | + } | ||
42 | + else{ | ||
43 | + clicked.fadeOut(function(){ | ||
44 | + clicked.css("display","none"); | ||
45 | + clicked.parent().parent().find(".join-community").fadeIn(); | ||
46 | + clicked.parent().parent().find(".join-community").css("display", ""); | ||
47 | + }); | ||
48 | + clicked.css("cursor",""); | ||
49 | + $(".small-loading").remove(); | ||
50 | + | ||
51 | + display_notice(data.message); | ||
52 | + } | ||
53 | + }, "json"); | ||
45 | return false; | 54 | return false; |
46 | }) | 55 | }) |
47 | 56 |
public/stylesheets/application.css
@@ -1566,7 +1566,7 @@ a.comment-picture { | @@ -1566,7 +1566,7 @@ a.comment-picture { | ||
1566 | a.button, a.button:visited, | 1566 | a.button, a.button:visited, |
1567 | body.noosfero a.button, body.noosfero a.button:visited, | 1567 | body.noosfero a.button, body.noosfero a.button:visited, |
1568 | input.button { | 1568 | input.button { |
1569 | - margin: 0px 2px; | 1569 | + margin: 0px 2px 0px 0px; |
1570 | background-repeat: no-repeat; | 1570 | background-repeat: no-repeat; |
1571 | background-position: 50% 50%; | 1571 | background-position: 50% 50%; |
1572 | padding: 3px 0px 3px 20px; | 1572 | padding: 3px 0px 3px 20px; |
@@ -4094,6 +4094,15 @@ h1#agenda-title { | @@ -4094,6 +4094,15 @@ h1#agenda-title { | ||
4094 | width: 100%; | 4094 | width: 100%; |
4095 | } | 4095 | } |
4096 | 4096 | ||
4097 | +#last-admin-message { | ||
4098 | + background-color: #CCC; | ||
4099 | + color: #000; | ||
4100 | + font-size: 14px; | ||
4101 | + padding: 20px 15px; | ||
4102 | + -moz-border-radius:10px; | ||
4103 | + -webkit-border-radius:10px; | ||
4104 | +} | ||
4105 | + | ||
4097 | /* ==> public/stylesheets/controller_search.css <== */ | 4106 | /* ==> public/stylesheets/controller_search.css <== */ |
4098 | /* @import url(pagination.css); ALREADY INCLUDED ABOVE */ | 4107 | /* @import url(pagination.css); ALREADY INCLUDED ABOVE */ |
4099 | 4108 |
test/functional/content_viewer_controller_test.rb
@@ -308,14 +308,16 @@ class ContentViewerControllerTest < Test::Unit::TestCase | @@ -308,14 +308,16 @@ class ContentViewerControllerTest < Test::Unit::TestCase | ||
308 | end | 308 | end |
309 | 309 | ||
310 | should 'not show private content to members' do | 310 | should 'not show private content to members' do |
311 | - community = Community.create!(:name => 'testcomm') | ||
312 | - Folder.create!(:name => 'test', :profile => community, :published => false) | ||
313 | - community.add_member(profile) | 311 | + community = fast_create(Community) |
312 | + admin = fast_create(Person) | ||
313 | + community.add_member(admin) | ||
314 | 314 | ||
315 | + folder = fast_create(Folder, :profile_id => community.id, :published => false) | ||
316 | + community.add_member(profile) | ||
315 | login_as(profile.identifier) | 317 | login_as(profile.identifier) |
316 | 318 | ||
317 | @request.stubs(:ssl?).returns(true) | 319 | @request.stubs(:ssl?).returns(true) |
318 | - get :view_page, :profile => community.identifier, :page => [ 'test' ] | 320 | + get :view_page, :profile => community.identifier, :page => [ folder.path ] |
319 | 321 | ||
320 | assert_template 'access_denied.rhtml' | 322 | assert_template 'access_denied.rhtml' |
321 | end | 323 | end |
test/functional/memberships_controller_test.rb
@@ -95,11 +95,11 @@ class MembershipsControllerTest < Test::Unit::TestCase | @@ -95,11 +95,11 @@ class MembershipsControllerTest < Test::Unit::TestCase | ||
95 | assert_no_tag :tag => 'li', :content => /Description:/ | 95 | assert_no_tag :tag => 'li', :content => /Description:/ |
96 | end | 96 | end |
97 | 97 | ||
98 | - should 'show link to leave from community' do | 98 | + should 'show link to leave from community with reload' do |
99 | community = Community.create!(:name => 'my test community', :description => 'description test') | 99 | community = Community.create!(:name => 'my test community', :description => 'description test') |
100 | community.add_member(profile) | 100 | community.add_member(profile) |
101 | get :index, :profile => profile.identifier | 101 | get :index, :profile => profile.identifier |
102 | - assert_tag :tag => 'a', :attributes => { :href => "/profile/#{community.identifier}/leave" }, :content => 'Leave' | 102 | + assert_tag :tag => 'a', :attributes => { :href => "/profile/#{community.identifier}/leave?reload=true" }, :content => 'Leave' |
103 | end | 103 | end |
104 | 104 | ||
105 | should 'current user is added as admin after create new community' do | 105 | should 'current user is added as admin after create new community' do |
@@ -127,7 +127,9 @@ class MembershipsControllerTest < Test::Unit::TestCase | @@ -127,7 +127,9 @@ class MembershipsControllerTest < Test::Unit::TestCase | ||
127 | end | 127 | end |
128 | 128 | ||
129 | should 'not display destroy link to normal members' do | 129 | should 'not display destroy link to normal members' do |
130 | - community = Community.create!(:name => 'A community to destroy') | 130 | + community = fast_create(Community) |
131 | + admin = fast_create(Person) | ||
132 | + community.add_member(admin) | ||
131 | 133 | ||
132 | person = Person['testuser'] | 134 | person = Person['testuser'] |
133 | community.add_member(person) | 135 | community.add_member(person) |
test/functional/profile_controller_test.rb
@@ -383,14 +383,28 @@ class ProfileControllerTest < Test::Unit::TestCase | @@ -383,14 +383,28 @@ class ProfileControllerTest < Test::Unit::TestCase | ||
383 | assert profile.memberships.include?(community), 'profile should be actually added to the community' | 383 | assert profile.memberships.include?(community), 'profile should be actually added to the community' |
384 | end | 384 | end |
385 | 385 | ||
386 | - should 'create task when join to closed organization' do | ||
387 | - community = Community.create!(:name => 'my test community', :closed => true) | ||
388 | - login_as @profile.identifier | 386 | + should 'create task when join to closed organization with members' do |
387 | + community = fast_create(Community) | ||
388 | + community.update_attribute(:closed, true) | ||
389 | + admin = fast_create(Person) | ||
390 | + community.add_member(admin) | ||
391 | + | ||
392 | + login_as profile.identifier | ||
389 | assert_difference AddMember, :count do | 393 | assert_difference AddMember, :count do |
390 | post :join, :profile => community.identifier | 394 | post :join, :profile => community.identifier |
391 | end | 395 | end |
392 | end | 396 | end |
393 | 397 | ||
398 | + should 'not create task when join to closed and empty organization' do | ||
399 | + community = fast_create(Community) | ||
400 | + community.update_attribute(:closed, true) | ||
401 | + | ||
402 | + login_as profile.identifier | ||
403 | + assert_no_difference AddMember, :count do | ||
404 | + post :join, :profile => community.identifier | ||
405 | + end | ||
406 | + end | ||
407 | + | ||
394 | should 'require login to join community' do | 408 | should 'require login to join community' do |
395 | community = Community.create!(:name => 'my test community', :closed => true) | 409 | community = Community.create!(:name => 'my test community', :closed => true) |
396 | get :join, :profile => community.identifier | 410 | get :join, :profile => community.identifier |
@@ -399,7 +413,10 @@ class ProfileControllerTest < Test::Unit::TestCase | @@ -399,7 +413,10 @@ class ProfileControllerTest < Test::Unit::TestCase | ||
399 | end | 413 | end |
400 | 414 | ||
401 | should 'actually leave profile' do | 415 | should 'actually leave profile' do |
402 | - community = Community.create!(:name => 'my test community') | 416 | + community = fast_create(Community) |
417 | + admin = fast_create(Person) | ||
418 | + community.add_member(admin) | ||
419 | + | ||
403 | community.add_member(profile) | 420 | community.add_member(profile) |
404 | assert_includes profile.memberships, community | 421 | assert_includes profile.memberships, community |
405 | 422 | ||
@@ -417,6 +434,21 @@ class ProfileControllerTest < Test::Unit::TestCase | @@ -417,6 +434,21 @@ class ProfileControllerTest < Test::Unit::TestCase | ||
417 | assert_redirected_to :controller => 'account', :action => 'login' | 434 | assert_redirected_to :controller => 'account', :action => 'login' |
418 | end | 435 | end |
419 | 436 | ||
437 | + should 'not leave if is last admin' do | ||
438 | + community = fast_create(Community) | ||
439 | + | ||
440 | + community.add_admin(profile) | ||
441 | + assert_includes profile.memberships, community | ||
442 | + | ||
443 | + login_as(profile.identifier) | ||
444 | + post :leave, :profile => community.identifier | ||
445 | + | ||
446 | + profile.reload | ||
447 | + assert_response :success | ||
448 | + assert_match(/last_admin/, @response.body) | ||
449 | + assert_includes profile.memberships, community | ||
450 | + end | ||
451 | + | ||
420 | should 'store location before login when request join via get not logged' do | 452 | should 'store location before login when request join via get not logged' do |
421 | community = Community.create!(:name => 'my test community') | 453 | community = Community.create!(:name => 'my test community') |
422 | 454 |
test/functional/profile_members_controller_test.rb
@@ -236,22 +236,42 @@ class ProfileMembersControllerTest < Test::Unit::TestCase | @@ -236,22 +236,42 @@ class ProfileMembersControllerTest < Test::Unit::TestCase | ||
236 | should 'find users' do | 236 | should 'find users' do |
237 | ent = fast_create(Enterprise, :name => 'Test Ent', :identifier => 'test_ent') | 237 | ent = fast_create(Enterprise, :name => 'Test Ent', :identifier => 'test_ent') |
238 | user = create_user_full('test_user').person | 238 | user = create_user_full('test_user').person |
239 | - u = create_user_with_permission('ent_user', 'manage_memberships', ent) | 239 | + person = create_user_with_permission('ent_user', 'manage_memberships', ent) |
240 | login_as :ent_user | 240 | login_as :ent_user |
241 | 241 | ||
242 | - get :find_users, :profile => ent.identifier, :query => 'test*' | 242 | + get :find_users, :profile => ent.identifier, :query => 'test*', :scope => 'all_users' |
243 | 243 | ||
244 | assert_includes assigns(:users_found), user | 244 | assert_includes assigns(:users_found), user |
245 | end | 245 | end |
246 | 246 | ||
247 | - should 'not appear add button for member in add members page' do | 247 | + should 'not display members when finding users in all_users scope' do |
248 | ent = fast_create(Enterprise, :name => 'Test Ent', :identifier => 'test_ent') | 248 | ent = fast_create(Enterprise, :name => 'Test Ent', :identifier => 'test_ent') |
249 | - p = create_user_with_permission('test_user', 'manage_memberships', ent) | ||
250 | - login_as :test_user | 249 | + user = create_user_full('test_user').person |
250 | + | ||
251 | + person = create_user_with_permission('ent_user', 'manage_memberships', ent) | ||
252 | + login_as :ent_user | ||
253 | + | ||
254 | + get :find_users, :profile => ent.identifier, :query => '*user', :scope => 'all_users' | ||
255 | + | ||
256 | + assert_tag :tag => 'a', :content => /#{user.name}/ | ||
257 | + assert_no_tag :tag => 'a', :content => /#{person.name}/ | ||
258 | + end | ||
251 | 259 | ||
252 | - get :find_users, :profile => ent.identifier, :query => 'test*' | 260 | + should 'not display admins when finding users in new_admins scope' do |
261 | + ent = fast_create(Enterprise, :name => 'Test Ent', :identifier => 'test_ent') | ||
262 | + | ||
263 | + person = create_user('admin_user').person | ||
264 | + ent.add_admin(person) | ||
265 | + | ||
266 | + user = create_user_full('test_user').person | ||
267 | + ent.add_member(user).finish | ||
253 | 268 | ||
254 | - assert_tag :tag => 'tr', :attributes => {:id => 'tr-test_user', :style => 'display:none'} | 269 | + login_as :admin_user |
270 | + | ||
271 | + get :find_users, :profile => ent.identifier, :query => '*user', :scope => 'new_admins' | ||
272 | + | ||
273 | + assert_tag :tag => 'a', :content => /#{user.name}/ | ||
274 | + assert_no_tag :tag => 'a', :content => /#{person.name}/ | ||
255 | end | 275 | end |
256 | 276 | ||
257 | should 'return users with <query> as a prefix' do | 277 | should 'return users with <query> as a prefix' do |
@@ -259,10 +279,10 @@ class ProfileMembersControllerTest < Test::Unit::TestCase | @@ -259,10 +279,10 @@ class ProfileMembersControllerTest < Test::Unit::TestCase | ||
259 | daniela = create_user_full('daniela').person | 279 | daniela = create_user_full('daniela').person |
260 | 280 | ||
261 | ent = fast_create(Enterprise, :name => 'Test Ent', :identifier => 'test_ent') | 281 | ent = fast_create(Enterprise, :name => 'Test Ent', :identifier => 'test_ent') |
262 | - p = create_user_with_permission('test_user', 'manage_memberships', ent) | 282 | + person = create_user_with_permission('test_user', 'manage_memberships', ent) |
263 | login_as :test_user | 283 | login_as :test_user |
264 | 284 | ||
265 | - get :find_users, :profile => ent.identifier, :query => 'daniel' | 285 | + get :find_users, :profile => ent.identifier, :query => 'daniel', :scope => 'all_users' |
266 | 286 | ||
267 | assert_includes assigns(:users_found), daniel | 287 | assert_includes assigns(:users_found), daniel |
268 | assert_includes assigns(:users_found), daniela | 288 | assert_includes assigns(:users_found), daniela |
@@ -307,4 +327,32 @@ class ProfileMembersControllerTest < Test::Unit::TestCase | @@ -307,4 +327,32 @@ class ProfileMembersControllerTest < Test::Unit::TestCase | ||
307 | assert_equal Profile['profile_admin_user'], assigns(:mailing).person | 327 | assert_equal Profile['profile_admin_user'], assigns(:mailing).person |
308 | end | 328 | end |
309 | 329 | ||
330 | + should 'set a community member as admin' do | ||
331 | + community = fast_create(Community) | ||
332 | + admin = create_user_with_permission('admin_user', 'manage_memberships', community) | ||
333 | + member = create_user('test_member').person | ||
334 | + community.add_member(member) | ||
335 | + | ||
336 | + assert_not_includes community.admins, member | ||
337 | + | ||
338 | + login_as :admin_user | ||
339 | + get :add_admin, :profile => community.identifier, :id => member.identifier | ||
340 | + | ||
341 | + assert_includes community.admins, member | ||
342 | + end | ||
343 | + | ||
344 | + should 'remove a community admin' do | ||
345 | + community = fast_create(Community) | ||
346 | + admin = create_user_with_permission('admin_user', 'manage_memberships', community) | ||
347 | + member = create_user('test_member').person | ||
348 | + community.add_admin(member) | ||
349 | + | ||
350 | + assert_includes community.admins, member | ||
351 | + | ||
352 | + login_as :admin_user | ||
353 | + get :remove_admin, :profile => community.identifier, :id => member.identifier | ||
354 | + | ||
355 | + assert_not_includes community.admins, member | ||
356 | + end | ||
357 | + | ||
310 | end | 358 | end |
test/unit/application_helper_test.rb
@@ -96,11 +96,20 @@ class ApplicationHelperTest < Test::Unit::TestCase | @@ -96,11 +96,20 @@ class ApplicationHelperTest < Test::Unit::TestCase | ||
96 | assert_equal 'black', role_color('none', Environment.default.id) | 96 | assert_equal 'black', role_color('none', Environment.default.id) |
97 | end | 97 | end |
98 | 98 | ||
99 | - should 'rolename for' do | 99 | + should 'rolename for first organization member' do |
100 | person = create_user('usertest').person | 100 | person = create_user('usertest').person |
101 | community = fast_create(Community, :name => 'new community', :identifier => 'new-community', :environment_id => Environment.default.id) | 101 | community = fast_create(Community, :name => 'new community', :identifier => 'new-community', :environment_id => Environment.default.id) |
102 | community.add_member(person) | 102 | community.add_member(person) |
103 | - assert_equal 'Profile Member', rolename_for(person, community) | 103 | + assert_equal 'Profile Administrator', rolename_for(person, community) |
104 | + end | ||
105 | + | ||
106 | + should 'rolename for a member' do | ||
107 | + member1 = create_user('usertest1').person | ||
108 | + member2 = create_user('usertest2').person | ||
109 | + community = fast_create(Community, :name => 'new community', :identifier => 'new-community', :environment_id => Environment.default.id) | ||
110 | + community.add_member(member1) | ||
111 | + community.add_member(member2) | ||
112 | + assert_equal 'Profile Member', rolename_for(member2, community) | ||
104 | end | 113 | end |
105 | 114 | ||
106 | should 'get theme from environment by default' do | 115 | should 'get theme from environment by default' do |
test/unit/community_test.rb
@@ -3,7 +3,7 @@ require File.dirname(__FILE__) + '/../test_helper' | @@ -3,7 +3,7 @@ require File.dirname(__FILE__) + '/../test_helper' | ||
3 | class CommunityTest < Test::Unit::TestCase | 3 | class CommunityTest < Test::Unit::TestCase |
4 | 4 | ||
5 | def setup | 5 | def setup |
6 | - @person = create_user('testuser').person | 6 | + @person = fast_create(Person) |
7 | end | 7 | end |
8 | 8 | ||
9 | attr_reader :person | 9 | attr_reader :person |
@@ -183,10 +183,33 @@ class CommunityTest < Test::Unit::TestCase | @@ -183,10 +183,33 @@ class CommunityTest < Test::Unit::TestCase | ||
183 | end | 183 | end |
184 | end | 184 | end |
185 | 185 | ||
186 | + should 'set as member without task if organization is closed and has no members' do | ||
187 | + community = fast_create(Community) | ||
188 | + community.closed = true | ||
189 | + community.save | ||
190 | + | ||
191 | + assert_no_difference AddMember, :count do | ||
192 | + community.add_member(person) | ||
193 | + end | ||
194 | + assert person.is_member_of?(community) | ||
195 | + end | ||
196 | + | ||
197 | + should 'set as member without task if organization is not closed and has no members' do | ||
198 | + community = fast_create(Community) | ||
199 | + | ||
200 | + assert_no_difference AddMember, :count do | ||
201 | + community.add_member(person) | ||
202 | + end | ||
203 | + assert person.is_member_of?(community) | ||
204 | + end | ||
205 | + | ||
186 | should 'not create new request membership if it already exists' do | 206 | should 'not create new request membership if it already exists' do |
187 | community = fast_create(Community) | 207 | community = fast_create(Community) |
188 | community.closed = true | 208 | community.closed = true |
189 | community.save | 209 | community.save |
210 | + | ||
211 | + community.add_member(fast_create(Person)) | ||
212 | + | ||
190 | assert_difference AddMember, :count do | 213 | assert_difference AddMember, :count do |
191 | community.add_member(person) | 214 | community.add_member(person) |
192 | end | 215 | end |
test/unit/enterprise_test.rb
@@ -102,14 +102,24 @@ class EnterpriseTest < Test::Unit::TestCase | @@ -102,14 +102,24 @@ class EnterpriseTest < Test::Unit::TestCase | ||
102 | assert_not_includes result, ent2 | 102 | assert_not_includes result, ent2 |
103 | end | 103 | end |
104 | 104 | ||
105 | + should 'allow to add new members if has no members' do | ||
106 | + enterprise = fast_create(Enterprise) | ||
107 | + | ||
108 | + person = fast_create(Person) | ||
109 | + enterprise.add_member(person) | ||
110 | + | ||
111 | + assert person.is_member_of?(enterprise) | ||
112 | + end | ||
113 | + | ||
105 | should 'not allow to add new members' do | 114 | should 'not allow to add new members' do |
106 | - o = fast_create(Enterprise, :name => 'my test profile', :identifier => 'mytestprofile') | ||
107 | - p = create_user('mytestuser').person | 115 | + enterprise = fast_create(Enterprise) |
116 | + member = fast_create(Person) | ||
117 | + enterprise.add_member(member) | ||
108 | 118 | ||
109 | - o.add_member(p) | ||
110 | - o.reload | 119 | + person = fast_create(Person) |
120 | + enterprise.add_member(person) | ||
111 | 121 | ||
112 | - assert_not_includes o.members, p | 122 | + assert_equal false, person.is_member_of?(enterprise) |
113 | end | 123 | end |
114 | 124 | ||
115 | should 'allow to remove members' do | 125 | should 'allow to remove members' do |
test/unit/person_test.rb
@@ -394,12 +394,16 @@ class PersonTest < Test::Unit::TestCase | @@ -394,12 +394,16 @@ class PersonTest < Test::Unit::TestCase | ||
394 | end | 394 | end |
395 | 395 | ||
396 | should 'not allow simple member to view group pending tasks' do | 396 | should 'not allow simple member to view group pending tasks' do |
397 | - c = fast_create(Community) | ||
398 | - c.tasks << Task.new | ||
399 | - p = create_user('user_without_tasks').person | ||
400 | - c.add_member(p) | 397 | + community = fast_create(Community) |
398 | + member = fast_create(Person) | ||
399 | + community.add_member(member) | ||
400 | + | ||
401 | + community.tasks << Task.new | ||
401 | 402 | ||
402 | - assert_not_includes Person.with_pending_tasks, p | 403 | + person = fast_create(Person) |
404 | + community.add_member(person) | ||
405 | + | ||
406 | + assert_not_includes Person.with_pending_tasks, person | ||
403 | end | 407 | end |
404 | 408 | ||
405 | should 'person has organization pending tasks' do | 409 | should 'person has organization pending tasks' do |
@@ -1116,4 +1120,29 @@ class PersonTest < Test::Unit::TestCase | @@ -1116,4 +1120,29 @@ class PersonTest < Test::Unit::TestCase | ||
1116 | assert person.receives_scrap_notification? | 1120 | assert person.receives_scrap_notification? |
1117 | end | 1121 | end |
1118 | 1122 | ||
1123 | + should 'check if person is the only admin' do | ||
1124 | + person = fast_create(Person) | ||
1125 | + organization = fast_create(Organization) | ||
1126 | + organization.add_admin(person) | ||
1127 | + | ||
1128 | + assert person.is_last_admin?(organization) | ||
1129 | + end | ||
1130 | + | ||
1131 | + should 'check if person is the last admin leaving the community' do | ||
1132 | + person = fast_create(Person) | ||
1133 | + organization = fast_create(Organization) | ||
1134 | + organization.add_admin(person) | ||
1135 | + | ||
1136 | + assert person.is_last_admin_leaving?(organization, []) | ||
1137 | + assert !person.is_last_admin_leaving?(organization, [Role.find_by_key('profile_admin')]) | ||
1138 | + end | ||
1139 | + | ||
1140 | + should 'return unique members of a community' do | ||
1141 | + person = fast_create(Person) | ||
1142 | + community = fast_create(Community) | ||
1143 | + community.add_member(person) | ||
1144 | + | ||
1145 | + assert_equal [person], Person.members_of(community) | ||
1146 | + assert_equal 1, Person.members_of(community).count | ||
1147 | + end | ||
1119 | end | 1148 | end |
test/unit/profile_test.rb
@@ -1406,7 +1406,12 @@ class ProfileTest < Test::Unit::TestCase | @@ -1406,7 +1406,12 @@ class ProfileTest < Test::Unit::TestCase | ||
1406 | 1406 | ||
1407 | should 'provide URL to leave' do | 1407 | should 'provide URL to leave' do |
1408 | profile = build(Profile, :identifier => 'testprofile') | 1408 | profile = build(Profile, :identifier => 'testprofile') |
1409 | - assert_equal({ :profile => 'testprofile', :controller => 'profile', :action => 'leave'}, profile.leave_url) | 1409 | + assert_equal({ :profile => 'testprofile', :controller => 'profile', :action => 'leave', :reload => false}, profile.leave_url) |
1410 | + end | ||
1411 | + | ||
1412 | + should 'provide URL to leave with reload' do | ||
1413 | + profile = build(Profile, :identifier => 'testprofile') | ||
1414 | + assert_equal({ :profile => 'testprofile', :controller => 'profile', :action => 'leave', :reload => true}, profile.leave_url(true)) | ||
1410 | end | 1415 | end |
1411 | 1416 | ||
1412 | should 'provide URL to join' do | 1417 | should 'provide URL to join' do |
@@ -1743,26 +1748,25 @@ class ProfileTest < Test::Unit::TestCase | @@ -1743,26 +1748,25 @@ class ProfileTest < Test::Unit::TestCase | ||
1743 | end | 1748 | end |
1744 | 1749 | ||
1745 | should "return one member on label if the profile has one member" do | 1750 | should "return one member on label if the profile has one member" do |
1746 | - p = fast_create(Person) | ||
1747 | - c = fast_create(Community) | ||
1748 | - c.add_member(p) | ||
1749 | - assert_equal 1, c.members.count | ||
1750 | - assert_equal "one member", c.more_popular_label | 1751 | + person = fast_create(Person) |
1752 | + community = fast_create(Community) | ||
1753 | + community.add_member(person) | ||
1754 | + | ||
1755 | + assert_equal "one member", community.more_popular_label | ||
1751 | end | 1756 | end |
1752 | 1757 | ||
1753 | should "return the number of members on label if the profile has more than one member" do | 1758 | should "return the number of members on label if the profile has more than one member" do |
1754 | - p1 = fast_create(Person) | ||
1755 | - p2 = fast_create(Person) | ||
1756 | - c = fast_create(Community) | ||
1757 | - c.add_member(p1) | ||
1758 | - c.add_member(p2) | ||
1759 | - assert_equal 2, c.members.count | ||
1760 | - assert_equal "2 members", c.more_popular_label | 1759 | + person1 = fast_create(Person) |
1760 | + person2 = fast_create(Person) | ||
1761 | + community = fast_create(Community) | ||
1761 | 1762 | ||
1762 | - p3 = fast_create(Person) | ||
1763 | - c.add_member(p3) | ||
1764 | - assert_equal 3, c.members.count | ||
1765 | - assert_equal "3 members", c.more_popular_label | 1763 | + community.add_member(person1) |
1764 | + community.add_member(person2) | ||
1765 | + assert_equal "2 members", community.more_popular_label | ||
1766 | + | ||
1767 | + person3 = fast_create(Person) | ||
1768 | + community.add_member(person3) | ||
1769 | + assert_equal "3 members", community.more_popular_label | ||
1766 | end | 1770 | end |
1767 | 1771 | ||
1768 | should 'provide list of galleries' do | 1772 | should 'provide list of galleries' do |