summaryrefslogtreecommitdiffstats
path: root/app
diff options
context:
space:
mode:
authorJean-Philippe Lang <jp_lang@yahoo.fr>2014-10-23 21:46:40 +0000
committerJean-Philippe Lang <jp_lang@yahoo.fr>2014-10-23 21:46:40 +0000
commitc2e73160daa7782d7a91f2b6a974a936c6f084da (patch)
tree62e174df69aba43cb5a84f2ddd278dc4562963f0 /app
parentca5946d82ebb96464a3d283be657bc24ce0c47f1 (diff)
downloadredmine-c2e73160daa7782d7a91f2b6a974a936c6f084da.tar.gz
redmine-c2e73160daa7782d7a91f2b6a974a936c6f084da.zip
Adds a single controller for users and groups memberships and support for adding multiple projects at once (#11702).
git-svn-id: http://svn.redmine.org/redmine/trunk@13498 e93f8b46-1217-0410-a6f0-8f06a7374b81
Diffstat (limited to 'app')
-rw-r--r--app/controllers/groups_controller.rb18
-rw-r--r--app/controllers/principal_memberships_controller.rb80
-rw-r--r--app/controllers/users_controller.rb23
-rw-r--r--app/helpers/application_helper.rb4
-rw-r--r--app/helpers/principal_memberships_helper.rb56
-rw-r--r--app/models/member.rb24
-rw-r--r--app/models/principal.rb5
-rw-r--r--app/models/user.rb5
-rw-r--r--app/views/groups/_memberships.html.erb66
-rw-r--r--app/views/principal_memberships/_index.html.erb52
-rw-r--r--app/views/principal_memberships/_new_form.html.erb22
-rw-r--r--app/views/principal_memberships/_new_modal.html.erb9
-rw-r--r--app/views/principal_memberships/create.js.erb12
-rw-r--r--app/views/principal_memberships/destroy.js.erb1
-rw-r--r--app/views/principal_memberships/new.html.erb6
-rw-r--r--app/views/principal_memberships/new.js.erb13
-rw-r--r--app/views/principal_memberships/update.js.erb6
-rw-r--r--app/views/users/_memberships.html.erb69
18 files changed, 287 insertions, 184 deletions
diff --git a/app/controllers/groups_controller.rb b/app/controllers/groups_controller.rb
index 45ed4c4e1..d67f0382b 100644
--- a/app/controllers/groups_controller.rb
+++ b/app/controllers/groups_controller.rb
@@ -23,6 +23,7 @@ class GroupsController < ApplicationController
accept_api_auth :index, :show, :create, :update, :destroy, :add_users, :remove_user
helper :custom_fields
+ helper :principal_memberships
def index
respond_to do |format|
@@ -119,23 +120,6 @@ class GroupsController < ApplicationController
end
end
- def edit_membership
- @membership = Member.edit_membership(params[:membership_id], params[:membership], @group)
- @membership.save if request.post?
- respond_to do |format|
- format.html { redirect_to edit_group_path(@group, :tab => 'memberships') }
- format.js
- end
- end
-
- def destroy_membership
- Member.find(params[:membership_id]).destroy if request.post?
- respond_to do |format|
- format.html { redirect_to edit_group_path(@group, :tab => 'memberships') }
- format.js
- end
- end
-
private
def find_group
diff --git a/app/controllers/principal_memberships_controller.rb b/app/controllers/principal_memberships_controller.rb
new file mode 100644
index 000000000..5af897b6e
--- /dev/null
+++ b/app/controllers/principal_memberships_controller.rb
@@ -0,0 +1,80 @@
+# Redmine - project management software
+# Copyright (C) 2006-2014 Jean-Philippe Lang
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+class PrincipalMembershipsController < ApplicationController
+ layout 'admin'
+
+ before_filter :require_admin
+ before_filter :find_principal, :only => [:new, :create]
+ before_filter :find_membership, :only => [:update, :destroy]
+
+ def new
+ @projects = Project.active.all
+ @roles = Role.find_all_givable
+ respond_to do |format|
+ format.html
+ format.js
+ end
+ end
+
+ def create
+ @members = Member.create_principal_memberships(@principal, params[:membership])
+ respond_to do |format|
+ format.html { redirect_to_principal @principal }
+ format.js
+ end
+ end
+
+ def update
+ @membership.attributes = params[:membership]
+ @membership.save
+ respond_to do |format|
+ format.html { redirect_to_principal @principal }
+ format.js
+ end
+ end
+
+ def destroy
+ if @membership.deletable?
+ @membership.destroy
+ end
+ respond_to do |format|
+ format.html { redirect_to_principal @principal }
+ format.js
+ end
+ end
+
+ private
+
+ def find_principal
+ principal_id = params[:user_id] || params[:group_id]
+ @principal = Principal.find(principal_id)
+ rescue ActiveRecord::RecordNotFound
+ render_404
+ end
+
+ def find_membership
+ @membership = Member.find(params[:id])
+ @principal = @membership.principal
+ rescue ActiveRecord::RecordNotFound
+ render_404
+ end
+
+ def redirect_to_principal(principal)
+ redirect_to edit_polymorphic_path(principal, :tab => 'memberships')
+ end
+end
diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb
index bb56fb285..d14914af4 100644
--- a/app/controllers/users_controller.rb
+++ b/app/controllers/users_controller.rb
@@ -19,13 +19,14 @@ class UsersController < ApplicationController
layout 'admin'
before_filter :require_admin, :except => :show
- before_filter :find_user, :only => [:show, :edit, :update, :destroy, :edit_membership, :destroy_membership]
+ before_filter :find_user, :only => [:show, :edit, :update, :destroy]
accept_api_auth :index, :show, :create, :update, :destroy
helper :sort
include SortHelper
helper :custom_fields
include CustomFieldsHelper
+ helper :principal_memberships
def index
sort_init 'login', 'asc'
@@ -173,26 +174,6 @@ class UsersController < ApplicationController
end
end
- def edit_membership
- @membership = Member.edit_membership(params[:membership_id], params[:membership], @user)
- @membership.save
- respond_to do |format|
- format.html { redirect_to edit_user_path(@user, :tab => 'memberships') }
- format.js
- end
- end
-
- def destroy_membership
- @membership = Member.find(params[:membership_id])
- if @membership.deletable?
- @membership.destroy
- end
- respond_to do |format|
- format.html { redirect_to edit_user_path(@user, :tab => 'memberships') }
- format.js
- end
- end
-
private
def find_user
diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb
index 7e9cdce90..923dff581 100644
--- a/app/helpers/application_helper.rb
+++ b/app/helpers/application_helper.rb
@@ -252,7 +252,7 @@ module ApplicationHelper
# Renders a tree of projects as a nested set of unordered lists
# The given collection may be a subset of the whole project tree
# (eg. some intermediate nodes are private and can not be seen)
- def render_project_nested_lists(projects)
+ def render_project_nested_lists(projects, &block)
s = ''
if projects.any?
ancestors = []
@@ -272,7 +272,7 @@ module ApplicationHelper
end
classes = (ancestors.empty? ? 'root' : 'child')
s << "<li class='#{classes}'><div class='#{classes}'>"
- s << h(block_given? ? yield(project) : project.name)
+ s << h(block_given? ? capture(project, &block) : project.name)
s << "</div>\n"
ancestors << project
end
diff --git a/app/helpers/principal_memberships_helper.rb b/app/helpers/principal_memberships_helper.rb
new file mode 100644
index 000000000..e734f42c9
--- /dev/null
+++ b/app/helpers/principal_memberships_helper.rb
@@ -0,0 +1,56 @@
+# encoding: utf-8
+#
+# Redmine - project management software
+# Copyright (C) 2006-2014 Jean-Philippe Lang
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+module PrincipalMembershipsHelper
+ def render_principal_memberships(principal)
+ render :partial => 'principal_memberships/index', :locals => {:principal => principal}
+ end
+
+ def call_table_header_hook(principal)
+ if principal.is_a?(Group)
+ call_hook :view_groups_memberships_table_header, :group => principal
+ else
+ call_hook :view_users_memberships_table_header, :user => principal
+ end
+ end
+
+ def call_table_row_hook(principal, membership)
+ if principal.is_a?(Group)
+ call_hook :view_groups_memberships_table_row, :group => principal, :membership => membership
+ else
+ call_hook :view_users_memberships_table_row, :user => principal, :membership => membership
+ end
+ end
+
+ def new_principal_membership_path(principal, *args)
+ if principal.is_a?(Group)
+ new_group_membership_path(principal, *args)
+ else
+ new_user_membership_path(principal, *args)
+ end
+ end
+
+ def principal_membership_path(principal, membership, *args)
+ if principal.is_a?(Group)
+ group_membership_path(principal, membership, *args)
+ else
+ user_membership_path(principal, membership, *args)
+ end
+ end
+end
diff --git a/app/models/member.rb b/app/models/member.rb
index 8256d2e68..257178866 100644
--- a/app/models/member.rb
+++ b/app/models/member.rb
@@ -47,7 +47,7 @@ class Member < ActiveRecord::Base
new_role_ids = ids - role_ids
# Add new roles
- new_role_ids.each {|id| member_roles << MemberRole.new(:role_id => id) }
+ new_role_ids.each {|id| member_roles << MemberRole.new(:role_id => id, :member => self) }
# Remove roles (Rails' #role_ids= will not trigger MemberRole#on_destroy)
member_roles_to_destroy = member_roles.select {|mr| !ids.include?(mr.role_id)}
if member_roles_to_destroy.any?
@@ -102,11 +102,23 @@ class Member < ActiveRecord::Base
end
end
- # Find or initialize a Member with an id, attributes, and for a Principal
- def self.edit_membership(id, new_attributes, principal=nil)
- @membership = id.present? ? Member.find(id) : Member.new(:principal => principal)
- @membership.attributes = new_attributes
- @membership
+ # Creates memberships for principal with the attributes
+ # * project_ids : one or more project ids
+ # * role_ids : ids of the roles to give to each membership
+ #
+ # Example:
+ # Member.create_principal_memberships(user, :project_ids => [2, 5], :role_ids => [1, 3]
+ def self.create_principal_memberships(principal, attributes)
+ members = []
+ if attributes
+ project_ids = Array.wrap(attributes[:project_ids] || attributes[:project_id])
+ role_ids = attributes[:role_ids]
+ project_ids.each do |project_id|
+ members << Member.new(:principal => principal, :role_ids => role_ids, :project_id => project_id)
+ end
+ principal.members << members
+ end
+ members
end
# Finds or initilizes a Member for the given project and principal
diff --git a/app/models/principal.rb b/app/models/principal.rb
index d10241b3f..e6e6ea78e 100644
--- a/app/models/principal.rb
+++ b/app/models/principal.rb
@@ -84,6 +84,11 @@ class Principal < ActiveRecord::Base
to_s
end
+ # Return true if the principal is a member of project
+ def member_of?(project)
+ projects.to_a.include?(project)
+ end
+
def <=>(principal)
if principal.nil?
-1
diff --git a/app/models/user.rb b/app/models/user.rb
index d86627e85..3ac98620b 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -498,11 +498,6 @@ class User < Principal
end
end
- # Return true if the user is a member of project
- def member_of?(project)
- projects.to_a.include?(project)
- end
-
# Returns a hash of user's projects grouped by roles
def projects_by_role
return @projects_by_role if @projects_by_role
diff --git a/app/views/groups/_memberships.html.erb b/app/views/groups/_memberships.html.erb
index ec275c594..1242bf6e8 100644
--- a/app/views/groups/_memberships.html.erb
+++ b/app/views/groups/_memberships.html.erb
@@ -1,65 +1 @@
-<% roles = Role.find_all_givable %>
-<% projects = Project.active.to_a %>
-
-<div class="splitcontentleft">
-<% if @group.memberships.any? %>
-<table class="list memberships">
- <thead><tr>
- <th><%= l(:label_project) %></th>
- <th><%= l(:label_role_plural) %></th>
- <th style="width:15%"></th>
- </tr></thead>
- <tbody>
- <% @group.memberships.each do |membership| %>
- <% next if membership.new_record? %>
- <tr id="member-<%= membership.id %>" class="<%= cycle 'odd', 'even' %> class">
- <td class="project"><%= link_to_project membership.project %></td>
- <td class="roles">
- <span id="member-<%= membership.id %>-roles"><%=h membership.roles.sort.collect(&:to_s).join(', ') %></span>
- <%= form_for(:membership, :remote => true,
- :url => { :action => 'edit_membership', :id => @group, :membership_id => membership },
- :html => { :id => "member-#{membership.id}-roles-form", :style => 'display:none;'}) do %>
- <p><% roles.each do |role| %>
- <label><%= check_box_tag 'membership[role_ids][]', role.id, membership.roles.include?(role), :id => nil %> <%=h role %></label><br />
- <% end %></p>
- <p><%= submit_tag l(:button_change) %>
- <%= link_to_function(
- l(:button_cancel),
- "$('#member-#{membership.id}-roles').show(); $('#member-#{membership.id}-roles-form').hide(); return false;"
- ) %></p>
- <% end %>
- </td>
- <td class="buttons">
- <%= link_to_function(
- l(:button_edit),
- "$('#member-#{membership.id}-roles').hide(); $('#member-#{membership.id}-roles-form').show(); return false;",
- :class => 'icon icon-edit'
- ) %>
- <%= delete_link({:controller => 'groups', :action => 'destroy_membership', :id => @group, :membership_id => membership},
- :remote => true,
- :method => :post) %>
- </td>
- </tr>
-<% end; reset_cycle %>
- </tbody>
-</table>
-<% else %>
-<p class="nodata"><%= l(:label_no_data) %></p>
-<% end %>
-</div>
-
-<div class="splitcontentright">
-<% if projects.any? %>
-<fieldset><legend><%=l(:label_project_new)%></legend>
-<%= form_for(:membership, :remote => true, :url => { :action => 'edit_membership', :id => @group }) do %>
-<%= label_tag "membership_project_id", l(:description_choose_project), :class => "hidden-for-sighted" %>
-<%= select_tag 'membership[project_id]', options_for_membership_project_select(@group, projects) %>
-<p><%= l(:label_role_plural) %>:
-<% roles.each do |role| %>
- <label><%= check_box_tag 'membership[role_ids][]', role.id, false, :id => nil %> <%=h role %></label>
-<% end %></p>
-<p><%= submit_tag l(:button_add) %></p>
-<% end %>
-</fieldset>
-<% end %>
-</div>
+<%= render_principal_memberships @group %>
diff --git a/app/views/principal_memberships/_index.html.erb b/app/views/principal_memberships/_index.html.erb
new file mode 100644
index 000000000..8203999ad
--- /dev/null
+++ b/app/views/principal_memberships/_index.html.erb
@@ -0,0 +1,52 @@
+<% roles = Role.find_all_givable %>
+
+<p><%= link_to l(:label_add_projects), new_principal_membership_path(principal), :remote => true, :class => "icon icon-add" %></p>
+
+<% if principal.memberships.any? %>
+<table class="list memberships">
+ <thead><tr>
+ <th><%= l(:label_project) %></th>
+ <th><%= l(:label_role_plural) %></th>
+ <th style="width:15%"></th>
+ <%= call_table_header_hook principal %>
+ </tr></thead>
+ <tbody>
+ <% principal.memberships.preload(:member_roles => :role).each do |membership| %>
+ <% next if membership.new_record? %>
+ <tr id="member-<%= membership.id %>" class="<%= cycle 'odd', 'even' %> class">
+ <td class="project name">
+ <%= link_to_project membership.project %>
+ </td>
+ <td class="roles">
+ <span id="member-<%= membership.id %>-roles"><%=h membership.roles.sort.collect(&:to_s).join(', ') %></span>
+ <%= form_for(:membership, :remote => true,
+ :url => principal_membership_path(principal, membership), :method => :put,
+ :html => {:id => "member-#{membership.id}-roles-form",
+ :style => 'display:none;'}) do %>
+ <p><% roles.each do |role| %>
+ <label><%= check_box_tag 'membership[role_ids][]', role.id, membership.roles.include?(role),
+ :disabled => membership.member_roles.detect {|mr| mr.role_id == role.id && !mr.inherited_from.nil?},
+ :id => nil %> <%=h role %></label><br />
+ <% end %></p>
+ <%= hidden_field_tag 'membership[role_ids][]', '' %>
+ <p><%= submit_tag l(:button_change) %>
+ <%= link_to_function l(:button_cancel),
+ "$('#member-#{membership.id}-roles').show(); $('#member-#{membership.id}-roles-form').hide(); return false;"
+ %></p>
+ <% end %>
+ </td>
+ <td class="buttons">
+ <%= link_to_function l(:button_edit),
+ "$('#member-#{membership.id}-roles').hide(); $('#member-#{membership.id}-roles-form').show(); return false;",
+ :class => 'icon icon-edit'
+ %>
+ <%= delete_link principal_membership_path(principal, membership), :remote => true if membership.deletable? %>
+ </td>
+ <%= call_table_row_hook principal, membership %>
+ </tr>
+ <% end; reset_cycle %>
+ </tbody>
+</table>
+<% else %>
+<p class="nodata"><%= l(:label_no_data) %></p>
+<% end %>
diff --git a/app/views/principal_memberships/_new_form.html.erb b/app/views/principal_memberships/_new_form.html.erb
new file mode 100644
index 000000000..bdd7df64c
--- /dev/null
+++ b/app/views/principal_memberships/_new_form.html.erb
@@ -0,0 +1,22 @@
+<fieldset class="box">
+ <legend><%= l(:label_project_plural) %></legend>
+ <div style="max-height:300px; overflow:auto;">
+ <div class="projects-selection">
+ <%= render_project_nested_lists(@projects) do |p| %>
+ <label>
+ <%= check_box_tag('membership[project_ids][]', p.id, false, :id => nil, :disabled => @principal.member_of?(p)) %> <%= p %>
+ </label>
+ <% end %>
+ </div>
+ </div>
+</fieldset>
+
+<fieldset class="box">
+ <legend><%= l(:label_role_plural) %></legend>
+ <% @roles.each do |role| %>
+ <label class="inline">
+ <%= check_box_tag 'membership[role_ids][]', role.id, false, :id => nil %>
+ <%=h role %>
+ </label>
+ <% end %>
+</fieldset>
diff --git a/app/views/principal_memberships/_new_modal.html.erb b/app/views/principal_memberships/_new_modal.html.erb
new file mode 100644
index 000000000..175e09330
--- /dev/null
+++ b/app/views/principal_memberships/_new_modal.html.erb
@@ -0,0 +1,9 @@
+<h3 class="title"><%= l(:label_add_projects) %></h3>
+
+<%= form_for :membership, :remote => true, :url => user_memberships_path(@principal), :method => :post do |f| %>
+ <%= render :partial => 'new_form' %>
+ <p class="buttons">
+ <%= submit_tag l(:button_add), :name => nil %>
+ <%= submit_tag l(:button_cancel), :name => nil, :onclick => "hideModal(this);", :type => 'button' %>
+ </p>
+<% end %>
diff --git a/app/views/principal_memberships/create.js.erb b/app/views/principal_memberships/create.js.erb
new file mode 100644
index 000000000..17d7ee14d
--- /dev/null
+++ b/app/views/principal_memberships/create.js.erb
@@ -0,0 +1,12 @@
+$('#tab-content-memberships').html('<%= escape_javascript(render :partial => 'principal_memberships/index', :locals => {:principal => @principal}) %>');
+hideOnLoad();
+
+<% if @members.present? && @members.all? {|m| m.persisted? } %>
+ hideModal();
+ <% @members.each do |member| %>
+ $("#member-<%= member.id %>").effect("highlight");
+ <% end %>
+<% elsif @members.present? %>
+ <% errors = @members.collect {|m| m.errors.full_messages}.flatten.uniq.join(', ') %>
+ alert('<%= raw(escape_javascript(l(:notice_failed_to_save_members, :errors => errors))) %>');
+<% end %>
diff --git a/app/views/principal_memberships/destroy.js.erb b/app/views/principal_memberships/destroy.js.erb
new file mode 100644
index 000000000..c8564f459
--- /dev/null
+++ b/app/views/principal_memberships/destroy.js.erb
@@ -0,0 +1 @@
+$('#tab-content-memberships').html('<%= escape_javascript(render :partial => 'principal_memberships/index', :locals => {:principal => @principal}) %>');
diff --git a/app/views/principal_memberships/new.html.erb b/app/views/principal_memberships/new.html.erb
new file mode 100644
index 000000000..64d2ebe21
--- /dev/null
+++ b/app/views/principal_memberships/new.html.erb
@@ -0,0 +1,6 @@
+<h2><%= l(:label_add_projects) %></h2>
+
+<%= form_for :membership, :url => user_memberships_path(@principal), :method => :post do |f| %>
+ <%= render :partial => 'new_form' %>
+ <p><%= submit_tag l(:button_add), :name => nil %></p>
+<% end %>
diff --git a/app/views/principal_memberships/new.js.erb b/app/views/principal_memberships/new.js.erb
new file mode 100644
index 000000000..625eeaf68
--- /dev/null
+++ b/app/views/principal_memberships/new.js.erb
@@ -0,0 +1,13 @@
+$('#ajax-modal').html('<%= escape_javascript(render :partial => 'principal_memberships/new_modal') %>');
+showModal('ajax-modal', '700px');
+
+$('.projects-selection').on('click', 'input[type=checkbox]', function(e){
+ if (!$(this).is(':checked')) {
+ if ($(this).closest('li').find('ul input[type=checkbox]:not(:checked)').length > 0) {
+ $(this).closest('li').find('ul input[type=checkbox]:not(:checked)').attr('checked', 'checked');
+ e.preventDefault();
+ } else {
+ $(this).closest('li').find('ul input[type=checkbox]:checked').removeAttr('checked');
+ }
+ }
+});
diff --git a/app/views/principal_memberships/update.js.erb b/app/views/principal_memberships/update.js.erb
new file mode 100644
index 000000000..2986c4e55
--- /dev/null
+++ b/app/views/principal_memberships/update.js.erb
@@ -0,0 +1,6 @@
+<% if @membership.valid? %>
+ $('#tab-content-memberships').html('<%= escape_javascript(render :partial => 'principal_memberships/index', :locals => {:principal => @principal}) %>');
+ $("#member-<%= @membership.id %>").effect("highlight");
+<% else %>
+ alert('<%= raw(escape_javascript(l(:notice_failed_to_save_members, :errors => @membership.errors.full_messages.join(', ')))) %>');
+<% end %>
diff --git a/app/views/users/_memberships.html.erb b/app/views/users/_memberships.html.erb
index cd4201727..75871d63e 100644
--- a/app/views/users/_memberships.html.erb
+++ b/app/views/users/_memberships.html.erb
@@ -1,68 +1 @@
-<% roles = Role.find_all_givable %>
-<% projects = Project.active.to_a %>
-
-<div class="splitcontentleft">
-<% if @user.memberships.any? %>
-<table class="list memberships">
- <thead><tr>
- <th><%= l(:label_project) %></th>
- <th><%= l(:label_role_plural) %></th>
- <th style="width:15%"></th>
- <%= call_hook(:view_users_memberships_table_header, :user => @user )%>
- </tr></thead>
- <tbody>
- <% @user.memberships.each do |membership| %>
- <% next if membership.new_record? %>
- <tr id="member-<%= membership.id %>" class="<%= cycle 'odd', 'even' %> class">
- <td class="project">
- <%= link_to_project membership.project %>
- </td>
- <td class="roles">
- <span id="member-<%= membership.id %>-roles"><%=h membership.roles.sort.collect(&:to_s).join(', ') %></span>
- <%= form_for(:membership, :remote => true,
- :url => user_membership_path(@user, membership), :method => :put,
- :html => {:id => "member-#{membership.id}-roles-form",
- :style => 'display:none;'}) do %>
- <p><% roles.each do |role| %>
- <label><%= check_box_tag 'membership[role_ids][]', role.id, membership.roles.include?(role),
- :disabled => membership.member_roles.detect {|mr| mr.role_id == role.id && !mr.inherited_from.nil?},
- :id => nil %> <%=h role %></label><br />
- <% end %></p>
- <%= hidden_field_tag 'membership[role_ids][]', '' %>
- <p><%= submit_tag l(:button_change) %>
- <%= link_to_function l(:button_cancel),
- "$('#member-#{membership.id}-roles').show(); $('#member-#{membership.id}-roles-form').hide(); return false;"
- %></p>
- <% end %>
- </td>
- <td class="buttons">
- <%= link_to_function l(:button_edit),
- "$('#member-#{membership.id}-roles').hide(); $('#member-#{membership.id}-roles-form').show(); return false;",
- :class => 'icon icon-edit'
- %>
- <%= delete_link user_membership_path(@user, membership), :remote => true if membership.deletable? %>
- </td>
- <%= call_hook(:view_users_memberships_table_row, :user => @user, :membership => membership, :roles => roles, :projects => projects )%>
- </tr>
- <% end; reset_cycle %>
- </tbody>
-</table>
-<% else %>
-<p class="nodata"><%= l(:label_no_data) %></p>
-<% end %>
-</div>
-
-<div class="splitcontentright">
-<% if projects.any? %>
-<fieldset><legend><%=l(:label_project_new)%></legend>
-<%= form_for(:membership, :remote => true, :url => user_memberships_path(@user)) do %>
-<%= select_tag 'membership[project_id]', options_for_membership_project_select(@user, projects) %>
-<p><%= l(:label_role_plural) %>:
-<% roles.each do |role| %>
- <label><%= check_box_tag 'membership[role_ids][]', role.id, false, :id => nil %> <%=h role %></label>
-<% end %></p>
-<p><%= submit_tag l(:button_add) %></p>
-<% end %>
-</fieldset>
-<% end %>
-</div>
+<%= render_principal_memberships @user %>