]> source.dussan.org Git - redmine.git/commitdiff
Adds permissions for viewing the watcher list and adding new watchers on the issue...
authorJean-Philippe Lang <jp_lang@yahoo.fr>
Sun, 3 Aug 2008 09:14:43 +0000 (09:14 +0000)
committerJean-Philippe Lang <jp_lang@yahoo.fr>
Sun, 3 Aug 2008 09:14:43 +0000 (09:14 +0000)
git-svn-id: http://redmine.rubyforge.org/svn/trunk@1712 e93f8b46-1217-0410-a6f0-8f06a7374b81

38 files changed:
app/controllers/watchers_controller.rb
app/helpers/watchers_helper.rb
app/models/watcher.rb
app/views/issues/show.rhtml
app/views/watchers/_watchers.rhtml [new file with mode: 0644]
lang/bg.yml
lang/cs.yml
lang/da.yml
lang/de.yml
lang/en.yml
lang/es.yml
lang/fi.yml
lang/fr.yml
lang/he.yml
lang/hu.yml
lang/it.yml
lang/ja.yml
lang/ko.yml
lang/lt.yml
lang/nl.yml
lang/no.yml
lang/pl.yml
lang/pt-br.yml
lang/pt.yml
lang/ro.yml
lang/ru.yml
lang/sr.yml
lang/sv.yml
lang/th.yml
lang/uk.yml
lang/zh-tw.yml
lang/zh.yml
lib/redmine.rb
test/fixtures/roles.yml
test/fixtures/watchers.yml [new file with mode: 0644]
test/functional/watchers_controller_test.rb [new file with mode: 0644]
vendor/plugins/acts_as_watchable/lib/acts_as_watchable.rb
vendor/plugins/gloc-1.1.0/lib/gloc-rails-text.rb

index 014779b7ff7ba296953065fdaa6a8a80092eba2f..a44686d3fd8c8ebd76654c173d5d9238a596b886 100644 (file)
 
 class WatchersController < ApplicationController
   layout 'base'
-  before_filter :require_login, :find_project, :check_project_privacy
+  before_filter :find_project
+  before_filter :require_login, :check_project_privacy, :only => [:watch, :unwatch]
+  before_filter :authorize, :only => :new
   
-  def add
-    user = User.current
-    @watched.add_watcher(user)
-    respond_to do |format|
-      format.html { redirect_to :back }
-      format.js { render(:update) {|page| page.replace_html 'watcher', watcher_link(@watched, user)} }
-    end
-  rescue RedirectBackError
-    render :text => 'Watcher added.', :layout => true
+  verify :method => :post,
+         :only => [ :watch, :unwatch ],
+         :render => { :nothing => true, :status => :method_not_allowed }
+  
+  def watch
+    set_watcher(User.current, true)
+  end
+  
+  def unwatch
+    set_watcher(User.current, false)
   end
   
-  def remove
-    user = User.current
-    @watched.remove_watcher(user)
+  def new
+    @watcher = Watcher.new(params[:watcher])
+    @watcher.watchable = @watched
+    @watcher.save if request.post?
     respond_to do |format|
       format.html { redirect_to :back }
-      format.js { render(:update) {|page| page.replace_html 'watcher', watcher_link(@watched, user)} }
+      format.js do
+        render :update do |page|
+          page.replace_html 'watchers', :partial => 'watchers/watchers', :locals => {:watched => @watched}
+        end
+      end
     end
-  rescue RedirectBackError
-    render :text => 'Watcher removed.', :layout => true
+  rescue ::ActionController::RedirectBackError
+    render :text => 'Watcher added.', :layout => true
   end
-
+  
 private
   def find_project
     klass = Object.const_get(params[:object_type].camelcase)
@@ -50,4 +58,14 @@ private
   rescue
     render_404
   end
+  
+  def set_watcher(user, watching)
+    @watched.set_watcher(user, watching)
+    respond_to do |format|
+      format.html { redirect_to :back }
+      format.js { render(:update) {|page| page.replace_html 'watcher', watcher_link(@watched, user)} }
+    end
+  rescue ::ActionController::RedirectBackError
+    render :text => (watching ? 'Watcher added.' : 'Watcher removed.'), :layout => true
+  end
 end
index c83c785fc701d6adc57cb7ad1d8fff5dfd43fefd..f4767ebed2d82eb8d0232c75f24fce3294fd7b03 100644 (file)
@@ -24,7 +24,7 @@ module WatchersHelper
     return '' unless user && user.logged? && object.respond_to?('watched_by?')
     watched = object.watched_by?(user)
     url = {:controller => 'watchers',
-           :action => (watched ? 'remove' : 'add'),
+           :action => (watched ? 'unwatch' : 'watch'),
            :object_type => object.class.to_s.underscore,
            :object_id => object.id}           
     link_to_remote((watched ? l(:button_unwatch) : l(:button_watch)),
@@ -33,4 +33,9 @@ module WatchersHelper
                    :class => (watched ? 'icon icon-fav' : 'icon icon-fav-off'))
   
   end
+  
+  # Returns a comma separated list of users watching the given object
+  def watchers_list(object)
+    object.watcher_users.collect {|u| content_tag('span', link_to_user(u), :class => 'user') }.join(",\n")
+  end
 end
index cb6ff52eaaaabc870b7932c5aff155bca7cd4528..38110c584bc56d3f647331adc111aa440bb166d3 100644 (file)
@@ -19,5 +19,12 @@ class Watcher < ActiveRecord::Base
   belongs_to :watchable, :polymorphic => true
   belongs_to :user
   
+  validates_presence_of :user
   validates_uniqueness_of :user_id, :scope => [:watchable_type, :watchable_id]
+  
+  protected
+  
+  def validate
+    errors.add :user_id, :activerecord_error_invalid unless user.nil? || user.active?
+  end
 end
index b71a02ee72a7ca03134c8ddd8c3189b75d6d0e0e..df8fc372aedc4036c5e03e54b22711290df86dea 100644 (file)
@@ -78,6 +78,14 @@ end %>
 </div>
 <% end %>
 
+<% if User.current.allowed_to?(:add_issue_watchers, @project) ||
+        (@issue.watchers.any? && User.current.allowed_to?(:view_issue_watchers, @project)) %>
+<hr />
+<div id="watchers">
+<%= render :partial => 'watchers/watchers', :locals => {:watched => @issue} %>
+</div>
+<% end %>
+
 </div>
 
 <% if @issue.changesets.any? && User.current.allowed_to?(:view_changesets, @project) %>
diff --git a/app/views/watchers/_watchers.rhtml b/app/views/watchers/_watchers.rhtml
new file mode 100644 (file)
index 0000000..14bb5fc
--- /dev/null
@@ -0,0 +1,25 @@
+<div class="contextual">
+<%= link_to_remote l(:button_add), 
+                   :url => {:controller => 'watchers',
+                            :action => 'new',
+                            :object_type => watched.class.name.underscore,
+                            :object_id => watched} if User.current.allowed_to?(:add_issue_watchers, @project) %>
+</div>
+
+<p><strong><%= l(:label_issue_watchers) %></strong></p>
+<%= watchers_list(watched) %>
+
+<% unless @watcher.nil? %>
+<% remote_form_for(:watcher, @watcher, 
+                   :url => {:controller => 'watchers',
+                            :action => 'new',
+                            :object_type => watched.class.name.underscore,
+                            :object_id => watched},
+                   :method => :post,
+                   :html => {:id => 'new-watcher-form'}) do |f| %>
+<p><%= f.select :user_id, (watched.addable_watcher_users.collect {|m| [m.name, m.id]}), :prompt => true %>
+
+<%= submit_tag l(:button_add) %>
+<%= toggle_link l(:button_cancel), 'new-watcher-form'%></p>
+<% end %>
+<% end %>
index e8191dc20e8bbd05a54c22636268916a804a4d66..6a9676119ef3c2fe3338b78f77a15052aaeeeec8 100644 (file)
@@ -633,3 +633,4 @@ setting_mail_handler_api_enabled: Enable WS for incoming emails
 setting_mail_handler_api_key: API key
 text_email_delivery_not_configured: "Email delivery is not configured, and notifications are disabled.\nConfigure your SMTP server in config/email.yml and restart the application to enable them."
 field_parent_title: Parent page
+label_issue_watchers: Watchers
index 68273191ab3c42819dcd6a34cec3c188b3cee335..cc5847ee4e9638b414588984353dad81f6db93a2 100644 (file)
@@ -638,3 +638,4 @@ setting_mail_handler_api_enabled: Enable WS for incoming emails
 setting_mail_handler_api_key: API key
 text_email_delivery_not_configured: "Email delivery is not configured, and notifications are disabled.\nConfigure your SMTP server in config/email.yml and restart the application to enable them."
 field_parent_title: Parent page
+label_issue_watchers: Watchers
index 1b5aba69ced1ca7b1d01c051ebfcceb09840aff8..1cb55cc486cff655f26a1168818ead5cc13cbe18 100644 (file)
@@ -635,3 +635,4 @@ setting_mail_handler_api_enabled: Enable WS for incoming emails
 setting_mail_handler_api_key: API key
 text_email_delivery_not_configured: "Email delivery is not configured, and notifications are disabled.\nConfigure your SMTP server in config/email.yml and restart the application to enable them."
 field_parent_title: Parent page
+label_issue_watchers: Watchers
index dc2960c9cce55489821f26f07c7e3afb74ae2532..f0be844906e4cc9bf361244be5bd79f9fb8fe5e1 100644 (file)
@@ -634,3 +634,4 @@ setting_mail_handler_api_enabled: Enable WS for incoming emails
 setting_mail_handler_api_key: API key
 text_email_delivery_not_configured: "Email delivery is not configured, and notifications are disabled.\nConfigure your SMTP server in config/email.yml and restart the application to enable them."
 field_parent_title: Parent page
+label_issue_watchers: Watchers
index 3cc788b8c37546190caf2d13a0e2e85db2b588bd..2307b159153515833b23dd17fb76337824dbe966 100644 (file)
@@ -521,6 +521,7 @@ label_reverse_chronological_order: In reverse chronological order
 label_planning: Planning
 label_incoming_emails: Incoming emails
 label_generate_key: Generate a key
+label_issue_watchers: Watchers
 
 button_login: Login
 button_submit: Submit
index c753f367f0475ee8f0a2c435f34290e65261380d..7f27d53e578a7dd3caed569480cd46215e7578aa 100644 (file)
@@ -636,3 +636,4 @@ setting_mail_handler_api_enabled: Enable WS for incoming emails
 setting_mail_handler_api_key: API key
 text_email_delivery_not_configured: "Email delivery is not configured, and notifications are disabled.\nConfigure your SMTP server in config/email.yml and restart the application to enable them."
 field_parent_title: Parent page
+label_issue_watchers: Watchers
index b48d8a319355316c834f98f9bb272c53d1645dbd..031d59d63ce8a1936d370ac6aece1f496b3b0a31 100644 (file)
@@ -633,3 +633,4 @@ setting_mail_handler_api_enabled: Enable WS for incoming emails
 setting_mail_handler_api_key: API key
 text_email_delivery_not_configured: "Email delivery is not configured, and notifications are disabled.\nConfigure your SMTP server in config/email.yml and restart the application to enable them."
 field_parent_title: Parent page
+label_issue_watchers: Watchers
index b9d542da61b0f5c0252c11357d6083eb91274722..0372520675c6d694df97e5c44ba389fcd4ac0223 100644 (file)
@@ -521,6 +521,7 @@ label_reverse_chronological_order: Dans l'ordre chronologique inverse
 label_planning: Planning
 label_incoming_emails: Emails entrants
 label_generate_key: Générer une clé
+label_issue_watchers: Utilisateurs surveillant cette demande
 
 button_login: Connexion
 button_submit: Soumettre
index 63aa2bb6438ca82cdedccd2e905990aa118f4b31..9c8fbae7e8922814a6a1b00119bd3e6a254e5ba8 100644 (file)
@@ -633,3 +633,4 @@ setting_mail_handler_api_enabled: Enable WS for incoming emails
 setting_mail_handler_api_key: API key
 text_email_delivery_not_configured: "Email delivery is not configured, and notifications are disabled.\nConfigure your SMTP server in config/email.yml and restart the application to enable them."
 field_parent_title: Parent page
+label_issue_watchers: Watchers
index 9becbb3499495d72225b2c071b241a9974a3c752..a5d208cb66ceaca0e1894720c72be1760105f24e 100644 (file)
@@ -634,3 +634,4 @@ setting_mail_handler_api_enabled: Web Service engedélyezése a beérkezett leve
 setting_mail_handler_api_key: API kulcs
 text_email_delivery_not_configured: "Az E-mail küldés nincs konfigurálva, és az értesítések ki vannak kapcsolva.\nÁllítsd be az SMTP szervert a config/email.yml fájlban és indítsd újra az alkalmazást, hogy érvénybe lépjen."
 field_parent_title: Parent page
+label_issue_watchers: Watchers
index e7a8772cc0e6901060cd27c02fffbb1aac6544fe..5d62e3255558e2540600a346da6ddb32116b2378 100644 (file)
@@ -633,3 +633,4 @@ setting_mail_handler_api_enabled: Abilita WS per le e-mail in arrivo
 setting_mail_handler_api_key: chiave API
 text_email_delivery_not_configured: "La consegna via e-mail non è configurata e le notifiche sono disabilitate.\nConfigura il tuo server SMTP in config/email.yml e riavvia l'applicazione per abilitarle."
 field_parent_title: Parent page
+label_issue_watchers: Watchers
index f78fcdba47dee572cb099819676accf05e146292..f3ade750dd91d0909c7dac78877627f6f92aa73b 100644 (file)
@@ -634,3 +634,4 @@ setting_mail_handler_api_enabled: Enable WS for incoming emails
 setting_mail_handler_api_key: API key
 text_email_delivery_not_configured: "Email delivery is not configured, and notifications are disabled.\nConfigure your SMTP server in config/email.yml and restart the application to enable them."
 field_parent_title: Parent page
+label_issue_watchers: Watchers
index 77672c60171fa5021417b66582ff0ba0a4c916e4..961255e016685beb0d4491647429c886f09894fd 100644 (file)
@@ -633,3 +633,4 @@ setting_mail_handler_api_enabled: Enable WS for incoming emails
 setting_mail_handler_api_key: API key
 text_email_delivery_not_configured: "Email delivery is not configured, and notifications are disabled.\nConfigure your SMTP server in config/email.yml and restart the application to enable them."
 field_parent_title: Parent page
+label_issue_watchers: Watchers
index 706133bfe0d9a10b5f90fc71dba70f30f468286a..58f79850606e3c88d7045d46d3e5c388b13d9996 100644 (file)
@@ -636,3 +636,4 @@ setting_mail_handler_api_key: API raktas
 
 text_email_delivery_not_configured: "Email delivery is not configured, and notifications are disabled.\nConfigure your SMTP server in config/email.yml and restart the application to enable them."
 field_parent_title: Parent page
+label_issue_watchers: Watchers
index 3cfb0aa193e09a0aae8f55d1c821ab5197b06872..08e300143de0dc09e1c84b1329305561484c89a8 100644 (file)
@@ -634,3 +634,4 @@ setting_mail_handler_api_enabled: Enable WS for incoming emails
 setting_mail_handler_api_key: API key
 text_email_delivery_not_configured: "Email delivery is not configured, and notifications are disabled.\nConfigure your SMTP server in config/email.yml and restart the application to enable them."
 field_parent_title: Parent page
+label_issue_watchers: Watchers
index 0836bd48fa2b55191e6c323a3d882c209ea93892..7af029db9fe6ba9e12a9e049cb817d626ec1b467 100644 (file)
@@ -634,3 +634,4 @@ setting_mail_handler_api_enabled: Enable WS for incoming emails
 setting_mail_handler_api_key: API key
 text_email_delivery_not_configured: "Email delivery is not configured, and notifications are disabled.\nConfigure your SMTP server in config/email.yml and restart the application to enable them."
 field_parent_title: Parent page
+label_issue_watchers: Watchers
index 278d56a88de4bdd2a9a1e635e2d70eaa5de7b903..0a29b7c473e7b5bf868b8bff61b3890673bb1117 100644 (file)
@@ -633,3 +633,4 @@ setting_mail_handler_api_enabled: Enable WS for incoming emails
 setting_mail_handler_api_key: API key
 text_email_delivery_not_configured: "Email delivery is not configured, and notifications are disabled.\nConfigure your SMTP server in config/email.yml and restart the application to enable them."
 field_parent_title: Parent page
+label_issue_watchers: Watchers
index 9276d768e0351f70c042246c3239d23b048a83ca..3ab24aeb04fa18290036260d269478640ee1c0c0 100644 (file)
@@ -633,3 +633,4 @@ setting_mail_handler_api_enabled: Enable WS for incoming emails
 setting_mail_handler_api_key: API key\r
 text_email_delivery_not_configured: "Email delivery is not configured, and notifications are disabled.\nConfigure your SMTP server in config/email.yml and restart the application to enable them."\r
 field_parent_title: Parent page\r
+label_issue_watchers: Watchers\r
index a7647e31f125bc873a127e37eb429277c3a30c9b..bd32cd1404741314914c6228509c23a0711a10bb 100644 (file)
@@ -633,3 +633,4 @@ setting_mail_handler_api_enabled: Enable WS for incoming emails
 setting_mail_handler_api_key: API key
 text_email_delivery_not_configured: "Email delivery is not configured, and notifications are disabled.\nConfigure your SMTP server in config/email.yml and restart the application to enable them."
 field_parent_title: Parent page
+label_issue_watchers: Watchers
index c3640d7e10eca4b313b7a5fc7e0573f169263aeb..2e562e2378ecb84610009a11df7ecf472b530bd3 100644 (file)
@@ -633,3 +633,4 @@ setting_mail_handler_api_enabled: Enable WS for incoming emails
 setting_mail_handler_api_key: API key
 text_email_delivery_not_configured: "Email delivery is not configured, and notifications are disabled.\nConfigure your SMTP server in config/email.yml and restart the application to enable them."
 field_parent_title: Parent page
+label_issue_watchers: Watchers
index e8bda05b72b8593145baa883b9f94168510b769e..61e71369473d3de0ceac538525a20d434c15dfff 100644 (file)
@@ -637,3 +637,4 @@ setting_mail_handler_api_enabled: Включить веб-сервис для в
 setting_mail_handler_api_key: API ключ
 text_email_delivery_not_configured: "Параметры работы с почтовым сервером не настроены и функция уведомления по email не активна.\nНастроить параметры для вашего SMTP сервера вы можете в файле config/email.yml. Для применения изменений перезапустите приложение."
 field_parent_title: Parent page
+label_issue_watchers: Watchers
index 688fa8ede2c5c4a63b9aa6b36f4146edbbaf2aeb..ba79d4ef2bfc4de5354bb8626deb16e355da4140 100644 (file)
@@ -634,3 +634,4 @@ setting_mail_handler_api_enabled: Enable WS for incoming emails
 setting_mail_handler_api_key: API key
 text_email_delivery_not_configured: "Email delivery is not configured, and notifications are disabled.\nConfigure your SMTP server in config/email.yml and restart the application to enable them."
 field_parent_title: Parent page
+label_issue_watchers: Watchers
index 58507a0b706eb9e9668b24f8a351b73f5b78c197..9505759c82e34d4003447cc8f212a09f4aae73f2 100644 (file)
@@ -634,3 +634,4 @@ setting_mail_handler_api_enabled: Enable WS for incoming emails
 setting_mail_handler_api_key: API key
 text_email_delivery_not_configured: "Email delivery is not configured, and notifications are disabled.\nConfigure your SMTP server in config/email.yml and restart the application to enable them."
 field_parent_title: Parent page
+label_issue_watchers: Watchers
index a7f949c96e14c3fe241711e569d2642cad84baa1..6c4ce30d63082d0ab0f67305391528c3f85e10a6 100644 (file)
@@ -636,3 +636,4 @@ setting_mail_handler_api_enabled: Enable WS for incoming emails
 setting_mail_handler_api_key: API key
 text_email_delivery_not_configured: "Email delivery is not configured, and notifications are disabled.\nConfigure your SMTP server in config/email.yml and restart the application to enable them."
 field_parent_title: Parent page
+label_issue_watchers: Watchers
index 766ddaaab4104d10518e56a51c9204a0abb5a9a3..4fa27f7d307045a6d462c978ea2df26c90845d15 100644 (file)
@@ -635,3 +635,4 @@ setting_mail_handler_api_enabled: Enable WS for incoming emails
 setting_mail_handler_api_key: API key
 text_email_delivery_not_configured: "Email delivery is not configured, and notifications are disabled.\nConfigure your SMTP server in config/email.yml and restart the application to enable them."
 field_parent_title: Parent page
+label_issue_watchers: Watchers
index 82f26ab8683b85250d5e9381f281cc63dc99c5d6..1e6483631a99bd8435d22f876a7c68d672b9e213 100644 (file)
@@ -634,3 +634,4 @@ enumeration_issue_priorities: 項目優先權
 enumeration_doc_categories: 文件分類
 enumeration_activities: 活動 (時間追蹤)
 field_parent_title: Parent page
+label_issue_watchers: Watchers
index b4ae89ba7ea62f3b3c43227ba5b883c8871316bc..7158a7f83b364fab583500de76dddcc24eb19fff 100644 (file)
@@ -634,3 +634,4 @@ enumeration_doc_categories: 文档类别
 enumeration_activities: 活动(时间跟踪)
 text_email_delivery_not_configured: "Email delivery is not configured, and notifications are disabled.\nConfigure your SMTP server in config/email.yml and restart the application to enable them."
 field_parent_title: Parent page
+label_issue_watchers: Watchers
index bd413c96c62f64c73ffa63c2915986cf9eed2645..9890ab06f4ac62d23407eef300f109db3610c1a6 100644 (file)
@@ -46,6 +46,9 @@ Redmine::AccessControl.map do |map|
     # Gantt & calendar
     map.permission :view_gantt, :projects => :gantt
     map.permission :view_calendar, :projects => :calendar
+    # Watchers
+    map.permission :view_issue_watchers, {}
+    map.permission :add_issue_watchers, {:watchers => :new}
   end
   
   map.project_module :time_tracking do |map|
index e7b1422684b714ad6e0ade048fdd18ec6a9807c8..234e971c4e94e2b48c82156b3fd06417107502c7 100644 (file)
@@ -15,6 +15,8 @@ roles_001:
     - :add_issue_notes\r
     - :move_issues\r
     - :delete_issues\r
+    - :view_issue_watchers\r
+    - :add_issue_watchers\r
     - :manage_public_queries\r
     - :save_queries\r
     - :view_gantt\r
@@ -58,6 +60,7 @@ roles_002:
     - :add_issue_notes\r
     - :move_issues\r
     - :delete_issues\r
+    - :view_issue_watchers\r
     - :save_queries\r
     - :view_gantt\r
     - :view_calendar\r
@@ -95,6 +98,7 @@ roles_003:
     - :manage_issue_relations\r
     - :add_issue_notes\r
     - :move_issues\r
+    - :view_issue_watchers\r
     - :save_queries\r
     - :view_gantt\r
     - :view_calendar\r
diff --git a/test/fixtures/watchers.yml b/test/fixtures/watchers.yml
new file mode 100644 (file)
index 0000000..a8c4829
--- /dev/null
@@ -0,0 +1,6 @@
+--- 
+watchers_001: 
+  watchable_type: Issue
+  watchable_id: 2
+  user_id: 3
+  
\ No newline at end of file
diff --git a/test/functional/watchers_controller_test.rb b/test/functional/watchers_controller_test.rb
new file mode 100644 (file)
index 0000000..cd65394
--- /dev/null
@@ -0,0 +1,70 @@
+# Redmine - project management software
+# Copyright (C) 2006-2008  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.
+
+require File.dirname(__FILE__) + '/../test_helper'
+require 'watchers_controller'
+
+# Re-raise errors caught by the controller.
+class WatchersController; def rescue_action(e) raise e end; end
+
+class WatchersControllerTest < Test::Unit::TestCase
+  fixtures :projects, :users, :roles, :members, :enabled_modules,
+           :issues, :trackers, :projects_trackers, :issue_statuses, :enumerations, :watchers
+  
+  def setup
+    @controller = WatchersController.new
+    @request    = ActionController::TestRequest.new
+    @response   = ActionController::TestResponse.new
+    User.current = nil
+  end
+  
+  def test_get_watch_should_be_invalid
+    @request.session[:user_id] = 3
+    get :watch, :object_type => 'issue', :object_id => '1'
+    assert_response 405
+  end
+  
+  def test_watch
+    @request.session[:user_id] = 3
+    assert_difference('Watcher.count') do
+      xhr :post, :watch, :object_type => 'issue', :object_id => '1'
+      assert_response :success
+      assert_select_rjs :replace_html, 'watcher'
+    end
+    assert Issue.find(1).watched_by?(User.find(3))
+  end
+  
+  def test_unwatch
+    @request.session[:user_id] = 3
+    assert_difference('Watcher.count', -1) do
+      xhr :post, :unwatch, :object_type => 'issue', :object_id => '2'
+      assert_response :success
+      assert_select_rjs :replace_html, 'watcher'
+    end
+    assert !Issue.find(1).watched_by?(User.find(3))
+  end
+  
+  def test_new_watcher
+    @request.session[:user_id] = 2
+    assert_difference('Watcher.count') do
+      xhr :post, :new, :object_type => 'issue', :object_id => '2', :watcher => {:user_id => '4'}
+      assert_response :success
+      assert_select_rjs :replace_html, 'watchers'
+    end
+    assert Issue.find(2).watched_by?(User.find(4))
+  end
+end
index 53e4455cffd52ff0f0f15a44ad324de4037c1e0e..2cb122795997e2b35feff8116a2a5b2b4265ac2c 100644 (file)
@@ -13,6 +13,7 @@ module Redmine
           
           class_eval do
             has_many :watchers, :as => :watchable, :dependent => :delete_all
+            has_many :watcher_users, :through => :watchers, :source => :user
           end
         end
       end
@@ -22,25 +23,40 @@ module Redmine
           base.extend ClassMethods
         end
         
+        # Returns an array of users that are proposed as watchers
+        def addable_watcher_users
+          self.project.users.sort - self.watcher_users
+        end
+        
+        # Adds user as a watcher
         def add_watcher(user)
           self.watchers << Watcher.new(:user => user)
         end
         
+        # Removes user from the watchers list
         def remove_watcher(user)
           return nil unless user && user.is_a?(User)
           Watcher.delete_all "watchable_type = '#{self.class}' AND watchable_id = #{self.id} AND user_id = #{user.id}"
         end
         
+        # Adds/removes watcher
+        def set_watcher(user, watching=true)
+          watching ? add_watcher(user) : remove_watcher(user)
+        end
+        
+        # Returns if object is watched by user
         def watched_by?(user)
           !self.watchers.find(:first,
                               :conditions => ["#{Watcher.table_name}.user_id = ?", user.id]).nil?
         end
         
+        # Returns an array of watchers' email addresses
         def watcher_recipients
           self.watchers.collect { |w| w.user.mail if w.user.active? }.compact
         end
 
         module ClassMethods
+          # Returns the objects that are watched by user
           def watched_by(user)
             find(:all, 
                  :include => :watchers,
@@ -50,4 +66,4 @@ module Redmine
       end
     end
   end
-end 
\ No newline at end of file
+end
index f437410dc6f7b4cc6f2fbe7ce699d32dbcdfbf52..51c02483892aefbb5317a8cb3fe217e280afab6c 100644 (file)
@@ -138,8 +138,8 @@ module ActionView #:nodoc:
       def add_options(option_tags, options, value = nil)\r
         option_tags = "<option value=\"\"></option>\n" + option_tags if options[:include_blank]\r
         \r
-        if value.blank? && options[:prompt]\r
-          ("<option value=\"\">#{options[:prompt].kind_of?(String) ? options[:prompt] : l(:actionview_instancetag_blank_option)}</option>\n") + option_tags\r
+        if options[:prompt]\r
+          ("<option value=\"\">--- #{options[:prompt].kind_of?(String) ? options[:prompt] : l(:actionview_instancetag_blank_option)} ---</option>\n") + option_tags\r
          else\r
           option_tags\r
         end\r