]> source.dussan.org Git - redmine.git/commitdiff
Ability to add multiple project members in a single action (#1556).
authorJean-Philippe Lang <jp_lang@yahoo.fr>
Fri, 27 Mar 2009 18:10:36 +0000 (18:10 +0000)
committerJean-Philippe Lang <jp_lang@yahoo.fr>
Fri, 27 Mar 2009 18:10:36 +0000 (18:10 +0000)
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@2635 e93f8b46-1217-0410-a6f0-8f06a7374b81

app/controllers/members_controller.rb
app/views/projects/settings/_members.rhtml
public/stylesheets/application.css
test/fixtures/users.yml
test/functional/members_controller_test.rb

index 130b56c8007090c859cf1abf5598b8cee70e5339..fcc65ba0f17f92e1daa9d83df14b505dc06d9938 100644 (file)
@@ -21,10 +21,26 @@ class MembersController < ApplicationController
   before_filter :authorize
 
   def new
-    @project.members << Member.new(params[:member]) if request.post?
+    members = []
+    if params[:member] && request.post?
+      attrs = params[:member].dup
+      if (user_ids = attrs.delete(:user_ids))
+        user_ids.each do |user_id|
+          members << Member.new(attrs.merge(:user_id => user_id))
+        end
+      else
+        members << Member.new(attrs)
+      end
+      @project.members << members
+    end
     respond_to do |format|
       format.html { redirect_to :controller => 'projects', :action => 'settings', :tab => 'members', :id => @project }
-      format.js { render(:update) {|page| page.replace_html "tab-content-members", :partial => 'projects/settings/members'} }
+      format.js { 
+        render(:update) {|page| 
+          page.replace_html "tab-content-members", :partial => 'projects/settings/members'
+          members.each {|member| page.visual_effect(:highlight, "member-#{member.id}") }
+        }
+      }
     end
   end
   
index 20806fe2d2839f5a1b32c09828c266de41af5aa6..79ddeded5d72cb3f3c721571b8a0c396bc94a938 100644 (file)
@@ -3,7 +3,8 @@
 <% users = User.active.find(:all).sort - @project.users %>
 <% # members sorted by role position
    members = @project.members.find(:all, :include => [:role, :user]).sort %>
-   
+
+<div class="splitcontentleft">
 <% if members.any? %>
 <table class="list">
        <thead>
@@ -15,7 +16,7 @@
        <tbody>
        <% members.each do |member| %>
        <% next if member.new_record? %>
-       <tr class="<%= cycle 'odd', 'even' %>">
+       <tr id="member-<%= member.id %>" class="<%= cycle 'odd', 'even' %>">
        <td><%= member.name %></td>
     <td align="center">
     <% if authorize_for('members', 'edit') %>
 <% else %>
 <p class="nodata"><%= l(:label_no_data) %></p>
 <% end %>
+</div>
 
-<% if authorize_for('members', 'new') && !users.empty? %>
+<div class="splitcontentright">
+<% if !users.empty? %>
   <% remote_form_for(:member, @member, :url => {:controller => 'members', :action => 'new', :id => @project}, :method => :post) do |f| %>
-    <p><label for="member_user_id"><%=l(:label_member_new)%></label><br />
-    <%= f.select :user_id, users.collect{|user| [user.name, user.id]} %>
-    <%= l(:label_role) %>: <%= f.select :role_id, roles.collect{|role| [role.name, role.id]}, :selected => nil %>
+    <fieldset><legend><%=l(:label_member_new)%></legend>
+               <div>
+               <% users.each do |user| -%>
+               <label><%= check_box_tag 'member[user_ids][]', user.id, false %> <%= user %></label>
+               <% end -%>
+               </div>
+    <p><%= l(:label_role) %>: <%= f.select :role_id, roles.collect{|role| [role.name, role.id]}, :selected => nil %>
     <%= submit_tag l(:button_add) %></p>
+               </fieldset>
   <% end %>
 <% end %>
+</div>
index 843860f442a484bd55241b77619661d7d4a5f9d9..f156b5fc4ed5b80c3d07bf2eb7fbe2d293a8e161 100644 (file)
@@ -324,6 +324,16 @@ p.other-formats { text-align: right; font-size:0.9em; color: #666; }
 
 a.atom { background: url(../images/feed.png) no-repeat 1px 50%; padding: 2px 0px 3px 16px; }
 
+/* Project members tab */
+div#tab-content-members .splitcontentleft { width: 64% }
+div#tab-content-members .splitcontentright { width: 34% }
+div#tab-content-members fieldset { margin-top: -8px; padding-top:0.6em; margin-bottom: 1em; }
+div#tab-content-members fieldset legend { font-weight: bold; }
+div#tab-content-members fieldset label { display: block; }
+div#tab-content-members fieldset div { max-height: 400px; overflow:auto; }
+
+* html div#tab-content-members fieldset div { height: 450px; }
+
 /***** Flash & error messages ****/
 #errorExplanation, div.flash, .nodata, .warning {
     padding: 4px 4px 4px 30px;
index 50c1dce29233875769ae4673ab3570b6c0fe4ab9..8be82284499d3d143fe032962a770a72019a6384 100644 (file)
@@ -112,5 +112,37 @@ users_007:
   mail_notification: false\r
   login: someone\r
   type: User\r
+users_008: \r
+  id: 8\r
+  created_on: 2006-07-19 19:33:19 +02:00\r
+  status: 1\r
+  last_login_on: \r
+  language: 'it'\r
+  hashed_password: 1\r
+  updated_on: 2006-07-19 19:33:19 +02:00\r
+  admin: false\r
+  mail: miscuser8@foo.bar\r
+  lastname: Misc\r
+  firstname: User\r
+  auth_source_id: \r
+  mail_notification: false\r
+  login: miscuser8\r
+  type: User\r
+users_009: \r
+  id: 9\r
+  created_on: 2006-07-19 19:33:19 +02:00\r
+  status: 1\r
+  last_login_on: \r
+  language: 'it'\r
+  hashed_password: 1\r
+  updated_on: 2006-07-19 19:33:19 +02:00\r
+  admin: false\r
+  mail: miscuser9@foo.bar\r
+  lastname: Misc\r
+  firstname: User\r
+  auth_source_id: \r
+  mail_notification: false\r
+  login: miscuser9\r
+  type: User\r
 \r
   
\ No newline at end of file
index c7868ae6345fff8bc59a1fdc7a46ccf3dd62a08a..be3e6d1cf4d686523235533136d3a28997a57069 100644 (file)
@@ -40,7 +40,7 @@ class MembersControllerTest < Test::Unit::TestCase
     )
   end
   
-  def test_new
+  def test_create
     assert_difference 'Member.count' do
       post :new, :id => 1, :member => {:role_id => 1, :user_id => 7}
     end
@@ -48,6 +48,14 @@ class MembersControllerTest < Test::Unit::TestCase
     assert User.find(7).member_of?(Project.find(1))
   end
   
+  def test_create_multiple
+    assert_difference 'Member.count', 3 do
+      post :new, :id => 1, :member => {:role_id => 1, :user_ids => [7, 8, 9]}
+    end
+    assert_redirected_to '/projects/ecookbook/settings/members'
+    assert User.find(7).member_of?(Project.find(1))
+  end
+  
   def test_edit
     assert_no_difference 'Member.count' do
       post :edit, :id => 2, :member => {:role_id => 1, :user_id => 3}