diff options
author | Jean-Philippe Lang <jp_lang@yahoo.fr> | 2014-10-23 21:46:40 +0000 |
---|---|---|
committer | Jean-Philippe Lang <jp_lang@yahoo.fr> | 2014-10-23 21:46:40 +0000 |
commit | c2e73160daa7782d7a91f2b6a974a936c6f084da (patch) | |
tree | 62e174df69aba43cb5a84f2ddd278dc4562963f0 /app | |
parent | ca5946d82ebb96464a3d283be657bc24ce0c47f1 (diff) | |
download | redmine-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.rb | 18 | ||||
-rw-r--r-- | app/controllers/principal_memberships_controller.rb | 80 | ||||
-rw-r--r-- | app/controllers/users_controller.rb | 23 | ||||
-rw-r--r-- | app/helpers/application_helper.rb | 4 | ||||
-rw-r--r-- | app/helpers/principal_memberships_helper.rb | 56 | ||||
-rw-r--r-- | app/models/member.rb | 24 | ||||
-rw-r--r-- | app/models/principal.rb | 5 | ||||
-rw-r--r-- | app/models/user.rb | 5 | ||||
-rw-r--r-- | app/views/groups/_memberships.html.erb | 66 | ||||
-rw-r--r-- | app/views/principal_memberships/_index.html.erb | 52 | ||||
-rw-r--r-- | app/views/principal_memberships/_new_form.html.erb | 22 | ||||
-rw-r--r-- | app/views/principal_memberships/_new_modal.html.erb | 9 | ||||
-rw-r--r-- | app/views/principal_memberships/create.js.erb | 12 | ||||
-rw-r--r-- | app/views/principal_memberships/destroy.js.erb | 1 | ||||
-rw-r--r-- | app/views/principal_memberships/new.html.erb | 6 | ||||
-rw-r--r-- | app/views/principal_memberships/new.js.erb | 13 | ||||
-rw-r--r-- | app/views/principal_memberships/update.js.erb | 6 | ||||
-rw-r--r-- | app/views/users/_memberships.html.erb | 69 |
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 %> |