Index: test/functional/watchers_controller_test.rb =================================================================== --- test/functional/watchers_controller_test.rb (revision 9748) +++ test/functional/watchers_controller_test.rb (working copy) @@ -127,6 +127,7 @@ assert_select 'input[name=?][value=4]', 'issue[watcher_user_ids][]' assert_select 'input[name=?][value=7]', 'issue[watcher_user_ids][]' end + assert @response.body =~ /issue_new_setupDefaultWatchersEvents/ end end @@ -139,4 +140,24 @@ end assert !Issue.find(2).watched_by?(User.find(3)) end + + def test_show + watchable_type = 'Issue' + watchable_id = 2 + + @request.session[:user_id] = 2 + xhr :get, :show, :watchable_type => watchable_type.underscore, :watchable_id => watchable_id.to_s, :format => 'json' + assert_response :success + r = ActiveSupport::JSON.decode(@response.body) + assert r + assert_equal r.length, 2 + assert_equal watchable_type, r[0]['watchable_type'] + assert_equal watchable_type, r[1]['watchable_type'] + assert_equal watchable_id, r[0]['watchable_id'] + assert_equal watchable_id, r[1]['watchable_id'] + fixtures_user_ids = [ watchers(:watchers_001).user_id, + watchers(:watchers_002).user_id ].sort + r_user_ids = [r[0]['user_id'], r[1]['user_id']].sort + assert_equal fixtures_user_ids, r_user_ids + end end Index: test/functional/issue_categories_controller_test.rb =================================================================== --- test/functional/issue_categories_controller_test.rb (revision 9748) +++ test/functional/issue_categories_controller_test.rb (working copy) @@ -37,6 +37,8 @@ get :new, :project_id => '1' assert_response :success assert_template 'new' + assert_tag 'input', :attributes => {:name => 'issue_category[watcher_user_ids][]', :value => '2'} + assert_tag 'input', :attributes => {:name => 'issue_category[watcher_user_ids][]', :value => '3'} end def test_create @@ -50,6 +52,20 @@ assert_equal 1, category.project_id end + def test_create_with_watchers + @request.session[:user_id] = 2 # manager + assert_difference 'Watcher.count', 2 do + post :create, :project_id => '1', :issue_category => {:name => 'New category with watchers', :watcher_user_ids => ['2', '3']} + end + assert_redirected_to '/projects/ecookbook/settings/categories' + category = IssueCategory.find_by_name('New category with watchers') + assert_not_nil category + assert_equal 1, category.project_id + # Watchers added + assert_equal [2, 3], category.watcher_user_ids.sort + assert category.watched_by?(User.find(3)) + end + def test_create_failure @request.session[:user_id] = 2 post :create, :project_id => '1', :issue_category => {:name => ''} @@ -69,6 +85,7 @@ assert_select_rjs :replace, 'issue_category_id' do assert_select "option[value=#{category.id}][selected=selected]" end + assert @response.body =~ /issue_new_setupDefaultWatchersEvents/ end def test_create_from_issue_form_with_failure @@ -86,6 +103,8 @@ get :edit, :id => 2 assert_response :success assert_template 'edit' + assert_tag 'input', :attributes => {:name => 'issue_category[watcher_user_ids][]', :value => '2'} + assert_tag 'input', :attributes => {:name => 'issue_category[watcher_user_ids][]', :value => '3'} end def test_update @@ -96,6 +115,18 @@ assert_equal 'Testing', IssueCategory.find(2).name end + def test_update_with_watchers + assert_difference 'Watcher.count', 2 do + put :update, :id => 2, :issue_category => { :name => 'Testing', :watcher_user_ids => ['2', '3']} + end + assert_redirected_to '/projects/ecookbook/settings/categories' + category = IssueCategory.find(2) + assert_equal 'Testing', category.name + # Watchers added + assert_equal [2, 3], category.watcher_user_ids.sort + assert category.watched_by?(User.find(3)) + end + def test_update_failure put :update, :id => 2, :issue_category => { :name => '' } assert_response :success Index: test/integration/routing/watchers_test.rb =================================================================== --- test/integration/routing/watchers_test.rb (revision 9748) +++ test/integration/routing/watchers_test.rb (working copy) @@ -47,5 +47,9 @@ { :method => 'post', :path => "/watchers/unwatch" }, { :controller => 'watchers', :action => 'unwatch' } ) + assert_routing( + { :method => 'post', :path => "/watchers/show/issue_category/1.json" }, + { :controller => 'watchers', :action => 'show', :watchable_type => 'issue_category', :watchable_id => '1', :format => 'json' } + ) end end Index: app/helpers/issue_categories_helper.rb =================================================================== --- app/helpers/issue_categories_helper.rb (revision 9748) +++ app/helpers/issue_categories_helper.rb (working copy) @@ -18,4 +18,9 @@ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. module IssueCategoriesHelper + + def url_for_issue_category_watchers_json(watchable_id) + url_for :controller => 'watchers', :action => 'show', :watchable_type => 'issue_category', :watchable_id => watchable_id, :format => 'json' + end + end Index: app/helpers/watchers_helper.rb =================================================================== --- app/helpers/watchers_helper.rb (revision 9748) +++ app/helpers/watchers_helper.rb (working copy) @@ -64,11 +64,13 @@ (lis.empty? ? "" : "
<%= f.text_field :name, :size => 30, :required => true %>
<%= f.select :assigned_to_id, principals_options_for_select(@project.assignable_users, @category.assigned_to), :include_blank => true %>
++ + <%= watchers_checkboxes(@category, IssueCategory, @project.users) %> + + +<%= link_to_remote l(:label_search_for_watchers), + :url => {:controller => 'watchers', :action => 'new', :project_id => @project, :object_type => 'issue_category'}, + :method => 'get' %> + +
- <%= watchers_checkboxes(@issue, @available_watchers) %> + <%= watchers_checkboxes(@issue, Issue, @available_watchers) %> <%= link_to_remote l(:label_search_for_watchers), - :url => {:controller => 'watchers', :action => 'new', :project_id => @issue.project}, + :url => {:controller => 'watchers', :action => 'new', :project_id => @issue.project, :object_type => 'issue'}, :method => 'get' %> + <%= javascript_tag "issue_new_setupDefaultWatchersEvents('#{j(url_for_issue_category_watchers_json('WATCHABLE_ID'))}')" %>
<% end %> Index: config/locales/en.yml =================================================================== --- config/locales/en.yml (revision 9748) +++ config/locales/en.yml (working copy) @@ -502,6 +502,7 @@ label_issue_category: Issue category label_issue_category_plural: Issue categories label_issue_category_new: New category + label_issue_category_watchers: Default watchers label_custom_field: Custom field label_custom_field_plural: Custom fields label_custom_field_new: New custom field Index: config/locales/ja.yml =================================================================== --- config/locales/ja.yml (revision 9748) +++ config/locales/ja.yml (working copy) @@ -510,6 +510,7 @@ label_issue_category: チケットのカテゴリ label_issue_category_plural: チケットのカテゴリ label_issue_category_new: 新しいカテゴリ + label_issue_category_watchers: デフォルトウォッチャー label_custom_field: カスタムフィールド label_custom_field_plural: カスタムフィールド label_custom_field_new: 新しいカスタムフィールドを作成 Index: config/routes.rb =================================================================== --- config/routes.rb (revision 9748) +++ config/routes.rb (working copy) @@ -136,6 +136,8 @@ :conditions => {:method => :post} map.connect 'watchers/autocomplete_for_user', :controller=> 'watchers', :action => 'autocomplete_for_user', :conditions => {:method => :get} + map.connect 'watchers/show/:watchable_type/:watchable_id.:format', :controller => 'watchers', :action => 'show', + :conditions => {:method => :post} # TODO: port to be part of the resources route(s) map.with_options :conditions => {:method => :get} do |project_views| Index: public/javascripts/application.js =================================================================== --- public/javascripts/application.js (revision 9748) +++ public/javascripts/application.js (working copy) @@ -534,5 +534,53 @@ }); } +function issue_new_resetDefaultWatchersByCategory() { + $$('#watchers_inputs input').each(function(el){ + el.checked = false; + el.parentNode.removeClassName('watchers_default'); + }); +} + +function issue_new_setDefaultWatchersByCategory(url_for_issue_category_watchers_json) { + issue_category_id = $('issue_category_id'); + if (!issue_category_id) { + return; + } + if (0 < issue_category_id.value.length) { + url = url_for_issue_category_watchers_json.replace(/WATCHABLE_ID/, issue_category_id.value); + new Ajax.Request(url, { + onSuccess: function (request) { + eval("result="+ request.responseText); + issue_new_resetDefaultWatchersByCategory(); + $$('#watchers_inputs input').each(function(el){ + user_id = parseInt(el.value); + result.each(function(a){ + if (user_id === a.user_id) { + el.checked = true; + el.parentNode.addClassName('watchers_default'); + throw $break; + } + }); + }); + } + }); + } else { + issue_new_resetDefaultWatchersByCategory(); + } +} + +function issue_new_setupDefaultWatchersEvents(url_for_issue_category_watchers_json) { + issue_category_id = $('issue_category_id'); + if (!issue_category_id) { + return; + } + function f() { + issue_new_setDefaultWatchersByCategory( + url_for_issue_category_watchers_json); + } + Event.observe(issue_category_id, 'change', f); + f(); +} + Event.observe(window, 'load', hideOnLoad); Event.observe(window, 'load', addFormObserversForDoubleSubmit); Index: public/stylesheets/application.css =================================================================== --- public/stylesheets/application.css (revision 9748) +++ public/stylesheets/application.css (working copy) @@ -266,6 +266,7 @@ #watchers img.gravatar {margin: 0 4px 2px 0;} span#watchers_inputs {overflow:auto; display:block;} +span#watchers_inputs .watchers_default {color: #080; font-weight:bold;} 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%; }