]> source.dussan.org Git - redmine.git/commitdiff
Ability to add non-member watchers on issue creation (#5159).
authorJean-Philippe Lang <jp_lang@yahoo.fr>
Sat, 24 Mar 2012 12:57:28 +0000 (12:57 +0000)
committerJean-Philippe Lang <jp_lang@yahoo.fr>
Sat, 24 Mar 2012 12:57:28 +0000 (12:57 +0000)
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@9254 e93f8b46-1217-0410-a6f0-8f06a7374b81

12 files changed:
app/controllers/issues_controller.rb
app/controllers/watchers_controller.rb
app/helpers/watchers_helper.rb
app/views/attachments/_form.html.erb
app/views/issues/new.html.erb
app/views/watchers/_new.html.erb
config/locales/en.yml
config/routes.rb
public/stylesheets/application.css
test/functional/issues_controller_test.rb
test/functional/watchers_controller_test.rb
test/integration/routing/watchers_test.rb

index 93a0873613a3581894d305e3f08dc55a1b6e4296..f8d982c12cc8c1cf4f552332589794e28386c875 100644 (file)
@@ -407,6 +407,7 @@ private
 
     @priorities = IssuePriority.active
     @allowed_statuses = @issue.new_statuses_allowed_to(User.current, true)
+    @available_watchers = (@issue.project.users.sort + @issue.watcher_users).uniq
   end
 
   def check_for_default_issue_status
index c51722b6ad3372c1bd3e2cb2684d77211c86487c..4c45ff7b2770d4ba2421a0c9efee2734249237d8 100644 (file)
@@ -64,6 +64,23 @@ class WatchersController < ApplicationController
     render :text => 'Watcher added.', :layout => true
   end
 
+  def append
+    if params[:watcher].is_a?(Hash)
+      user_ids = params[:watcher][:user_ids] || [params[:watcher][:user_id]]
+      users = User.active.find_all_by_id(user_ids)
+      respond_to do |format|
+        format.js do
+          render :update do |page|
+            users.each do |user|
+              page.select("#issue_watcher_user_ids_#{user.id}").each(&:hide)
+            end
+            page.insert_html :bottom, 'watchers_inputs', :text => watchers_checkboxes(nil, users, true)
+          end
+        end
+      end
+    end
+  end
+
   def destroy
     @watched.set_watcher(User.find(params[:user_id]), false) if request.post?
     respond_to do |format|
@@ -77,16 +94,23 @@ class WatchersController < ApplicationController
   end
 
   def autocomplete_for_user
-    @users = User.active.like(params[:q]).find(:all, :limit => 100) - @watched.watcher_users
+    @users = User.active.like(params[:q]).find(:all, :limit => 100)
+    if @watched
+      @user -= @watched.watcher_users
+    end
     render :layout => false
   end
 
 private
   def find_project
-    klass = Object.const_get(params[:object_type].camelcase)
-    return false unless klass.respond_to?('watched_by')
-    @watched = klass.find(params[:object_id])
-    @project = @watched.project
+    if params[:object_type] && params[:object_id]
+      klass = Object.const_get(params[:object_type].camelcase)
+      return false unless klass.respond_to?('watched_by')
+      @watched = klass.find(params[:object_id])
+      @project = @watched.project
+    elsif params[:project_id]
+      @project = Project.visible.find(params[:project_id])
+    end
   rescue
     render_404
   end
index 74bb0e1eccc791f110b560ee6ca70348b91b4958..fb77a90aebf5abc10a563715a701f181f0d4c1e6 100644 (file)
@@ -63,4 +63,12 @@ module WatchersHelper
     end
     (lis.empty? ? "" : "<ul>#{ lis.join("\n") }</ul>").html_safe
   end
+
+  def watchers_checkboxes(object, users, checked=nil)
+    users.map do |user|
+      c = checked.nil? ? object.watched_by?(user) : checked
+      tag = check_box_tag 'issue[watcher_user_ids][]', user.id, c, :id => nil
+      content_tag 'label', "#{tag} #{h(user)}", :id => "issue_watcher_user_ids_#{user.id}", :class => "floating"
+    end.join
+  end
 end
index 464d3a2d77f21be9148f6f8ab5e7503c98b24ce9..7eea17bb7118f964d8e55101e7fc427d49e235b8 100644 (file)
@@ -14,6 +14,5 @@
     <%= link_to_function(image_tag('delete.png'), 'removeFileField(this)', :title => (l(:button_delete))) %>
   </span>
 </span>
-<small><%= link_to l(:label_add_another_file), '#', :onclick => 'addFileField(); return false;' %>
-(<%= l(:label_max_size) %>: <%= number_to_human_size(Setting.attachment_max_size.to_i.kilobytes) %>)
-</small>
+<span class="add_attachment"><%= link_to l(:label_add_another_file), '#', :onclick => 'addFileField(); return false;', :class => 'add_attachment' %>
+(<%= l(:label_max_size) %>: <%= number_to_human_size(Setting.attachment_max_size.to_i.kilobytes) %>)</span>
index 11268214fa7977c9eb8979aa6eb94beb53722c48..c95daa1e48acf919511d3a291041de7746b41e11 100644 (file)
 
     <% if @issue.safe_attribute? 'watcher_user_ids' -%>
       <p id="watchers_form"><label><%= l(:label_issue_watchers) %></label>
-      <% @issue.project.users.sort.each do |user| -%>
-        <label class="floating"><%= check_box_tag 'issue[watcher_user_ids][]', user.id, @issue.watched_by?(user), :id => nil %> <%=h user %></label>
-      <% end -%>
-      </p>
+      <span id="watchers_inputs">
+        <%= watchers_checkboxes(@issue, @available_watchers) %>
+                       </span>
+                       <span class="search_for_watchers">
+      <%= link_to_remote l(:label_search_for_watchers),
+                   :url => {:controller => 'watchers', :action => 'new', :project_id => @issue.project},
+                   :method => 'get' %>
+                       </span>
+                       </p>
     <% end %>
   </div>
 
index 9b4227ad72cc051f3c4bbfa3b041d563f7b15556..c2c133ee7a55bc6652c6287153c48b6e4c05a2a6 100644 (file)
@@ -1,7 +1,7 @@
 <h3 class="title"><%= l(:permission_add_issue_watchers) %></h3>
 
 <% form_remote_tag :url => {:controller => 'watchers',
-                            :action => 'create',
+                            :action => (watched ? 'create' : 'append'),
                             :object_type => watched.class.name.underscore,
                             :object_id => watched},
                      :method => :post,
@@ -22,7 +22,7 @@
                :with => 'q') %>
 
   <div id="users_for_watcher">
-    <%= principals_check_box_tags 'watcher[user_ids][]', watched.addable_watcher_users %>
+    <%= principals_check_box_tags 'watcher[user_ids][]', (watched ? watched.addable_watcher_users : User.active.all(:limit => 100)) %>
   </div>
 
   <p class="buttons">
index 21e12ba17a3c195608c90d33b98532bdd488bccc..6180a860e06d956bb52db477af55c9a1e41c780b 100644 (file)
@@ -844,6 +844,7 @@ en:
   label_copy_attachments: Copy attachments
   label_item_position: "%{position} of %{count}"
   label_completed_versions: Completed versions
+  label_search_for_watchers: Search for watchers to add
 
   button_login: Login
   button_submit: Submit
index 3e98e9043f41e8f1be49b516b75aaba8889caa9c..25a7ca59bae893ea3697b5efd79d89f6a0c0e302 100644 (file)
@@ -124,6 +124,8 @@ ActionController::Routing::Routes.draw do |map|
               :conditions => {:method => :get}
   map.connect 'watchers', :controller=> 'watchers', :action => 'create',
               :conditions => {:method => :post}
+  map.connect 'watchers/append', :controller=> 'watchers', :action => 'append',
+              :conditions => {:method => :post}
   map.connect 'watchers/destroy', :controller=> 'watchers', :action => 'destroy',
               :conditions => {:method => :post}
   map.connect 'watchers/watch', :controller=> 'watchers', :action => 'watch',
index 937a69a831791dd0d266c1c6faec649afd754e50..72090235e6320f39a6ba8ee78b08c9a6677dc23d 100644 (file)
@@ -265,6 +265,12 @@ div.projects h3 { background: url(../images/projects.png) no-repeat 0% 50%; padd
 #watchers a.delete:hover {opacity: 1;}
 #watchers img.gravatar {margin: 0 4px 2px 0;}
 
+span#watchers_inputs {overflow:auto; display:block;}
+span.search_for_watchers {display:block;}
+span.search_for_watchers, span.add_attachment {font-size:80%; line-height:2.5em;}
+span.search_for_watchers a, span.add_attachment a {padding-left:16px; background: url(../images/bullet_add.png) no-repeat 0 50%; }
+
+
 .highlight { background-color: #FCFD8D;}
 .highlight.token-1 { background-color: #faa;}
 .highlight.token-2 { background-color: #afa;}
index 199e9317eb19e260b059dd49c50201ac410e57e7..e91acb20c58f7432f66c5bbad556f634a83918d6 100644 (file)
@@ -1680,6 +1680,21 @@ class IssuesControllerTest < ActionController::TestCase
                                         :value => 'Value for field 2'}
   end
 
+  def test_post_create_with_failure_should_preserve_watchers
+    assert !User.find(8).member_of?(Project.find(1))
+
+    @request.session[:user_id] = 2
+    post :create, :project_id => 1,
+         :issue => {:tracker_id => 1,
+                    :watcher_user_ids => ['3', '8']}
+    assert_response :success
+    assert_template 'new'
+
+    assert_tag 'input', :attributes => {:name => 'issue[watcher_user_ids][]', :value => '2', :checked => nil}
+    assert_tag 'input', :attributes => {:name => 'issue[watcher_user_ids][]', :value => '3', :checked => 'checked'}
+    assert_tag 'input', :attributes => {:name => 'issue[watcher_user_ids][]', :value => '8', :checked => 'checked'}
+  end
+
   def test_post_create_should_ignore_non_safe_attributes
     @request.session[:user_id] = 2
     assert_nothing_raised do
index bfd93fe0d66bf70dcf5702f69bf65df9a7ae11a9..03b1a977b7eeeffbc96e3151dccefba324f4d99c 100644 (file)
@@ -68,6 +68,13 @@ class WatchersControllerTest < ActionController::TestCase
     assert_select_rjs :replace_html, 'ajax-modal'
   end
 
+  def test_new_for_new_record
+    @request.session[:user_id] = 2
+    xhr :get, :new, :project_id => 1
+    assert_response :success
+    assert_select_rjs :replace_html, 'ajax-modal'
+  end
+
   def test_create
     @request.session[:user_id] = 2
     assert_difference('Watcher.count') do
@@ -91,6 +98,18 @@ class WatchersControllerTest < ActionController::TestCase
     assert Issue.find(2).watched_by?(User.find(7))
   end
 
+  def test_append
+    @request.session[:user_id] = 2
+    assert_no_difference 'Watcher.count' do
+      xhr :post, :append, :watcher => {:user_ids => ['4', '7']}
+      assert_response :success
+      assert_select_rjs :insert_html, 'watchers_inputs' do
+        assert_select 'input[name=?][value=4]', 'issue[watcher_user_ids][]'
+        assert_select 'input[name=?][value=7]', 'issue[watcher_user_ids][]'
+      end
+    end
+  end
+
   def test_remove_watcher
     @request.session[:user_id] = 2
     assert_difference('Watcher.count', -1) do
index 441d2533c3fc110e1876fc67c69cfe2f9f31ae42..00410289bf228ab26da8f7fe729bc2bdd821570a 100644 (file)
@@ -23,6 +23,10 @@ class RoutingWatchersTest < ActionController::IntegrationTest
         { :method => 'get', :path => "/watchers/new" },
         { :controller => 'watchers', :action => 'new' }
       )
+    assert_routing(
+        { :method => 'post', :path => "/watchers/append" },
+        { :controller => 'watchers', :action => 'append' }
+      )
     assert_routing(
         { :method => 'post', :path => "/watchers" },
         { :controller => 'watchers', :action => 'create' }