@@ -407,6 +407,7 private | |||
|
407 | 407 | |
|
408 | 408 | @priorities = IssuePriority.active |
|
409 | 409 | @allowed_statuses = @issue.new_statuses_allowed_to(User.current, true) |
|
410 | @available_watchers = (@issue.project.users.sort + @issue.watcher_users).uniq | |
|
410 | 411 | end |
|
411 | 412 | |
|
412 | 413 | def check_for_default_issue_status |
@@ -64,6 +64,23 class WatchersController < ApplicationController | |||
|
64 | 64 | render :text => 'Watcher added.', :layout => true |
|
65 | 65 | end |
|
66 | 66 | |
|
67 | def append | |
|
68 | if params[:watcher].is_a?(Hash) | |
|
69 | user_ids = params[:watcher][:user_ids] || [params[:watcher][:user_id]] | |
|
70 | users = User.active.find_all_by_id(user_ids) | |
|
71 | respond_to do |format| | |
|
72 | format.js do | |
|
73 | render :update do |page| | |
|
74 | users.each do |user| | |
|
75 | page.select("#issue_watcher_user_ids_#{user.id}").each(&:hide) | |
|
76 | end | |
|
77 | page.insert_html :bottom, 'watchers_inputs', :text => watchers_checkboxes(nil, users, true) | |
|
78 | end | |
|
79 | end | |
|
80 | end | |
|
81 | end | |
|
82 | end | |
|
83 | ||
|
67 | 84 | def destroy |
|
68 | 85 | @watched.set_watcher(User.find(params[:user_id]), false) if request.post? |
|
69 | 86 | respond_to do |format| |
@@ -77,16 +94,23 class WatchersController < ApplicationController | |||
|
77 | 94 | end |
|
78 | 95 | |
|
79 | 96 | def autocomplete_for_user |
|
80 |
@users = User.active.like(params[:q]).find(:all, :limit => 100) |
|
|
97 | @users = User.active.like(params[:q]).find(:all, :limit => 100) | |
|
98 | if @watched | |
|
99 | @user -= @watched.watcher_users | |
|
100 | end | |
|
81 | 101 | render :layout => false |
|
82 | 102 | end |
|
83 | 103 | |
|
84 | 104 | private |
|
85 | 105 | def find_project |
|
106 | if params[:object_type] && params[:object_id] | |
|
86 | 107 | klass = Object.const_get(params[:object_type].camelcase) |
|
87 | 108 | return false unless klass.respond_to?('watched_by') |
|
88 | 109 | @watched = klass.find(params[:object_id]) |
|
89 | 110 | @project = @watched.project |
|
111 | elsif params[:project_id] | |
|
112 | @project = Project.visible.find(params[:project_id]) | |
|
113 | end | |
|
90 | 114 | rescue |
|
91 | 115 | render_404 |
|
92 | 116 | end |
@@ -63,4 +63,12 module WatchersHelper | |||
|
63 | 63 | end |
|
64 | 64 | (lis.empty? ? "" : "<ul>#{ lis.join("\n") }</ul>").html_safe |
|
65 | 65 | end |
|
66 | ||
|
67 | def watchers_checkboxes(object, users, checked=nil) | |
|
68 | users.map do |user| | |
|
69 | c = checked.nil? ? object.watched_by?(user) : checked | |
|
70 | tag = check_box_tag 'issue[watcher_user_ids][]', user.id, c, :id => nil | |
|
71 | content_tag 'label', "#{tag} #{h(user)}", :id => "issue_watcher_user_ids_#{user.id}", :class => "floating" | |
|
72 | end.join | |
|
73 | end | |
|
66 | 74 | end |
@@ -14,6 +14,5 | |||
|
14 | 14 | <%= link_to_function(image_tag('delete.png'), 'removeFileField(this)', :title => (l(:button_delete))) %> |
|
15 | 15 | </span> |
|
16 | 16 | </span> |
|
17 |
<s |
|
|
18 | (<%= l(:label_max_size) %>: <%= number_to_human_size(Setting.attachment_max_size.to_i.kilobytes) %>) | |
|
19 | </small> | |
|
17 | <span class="add_attachment"><%= link_to l(:label_add_another_file), '#', :onclick => 'addFileField(); return false;', :class => 'add_attachment' %> | |
|
18 | (<%= l(:label_max_size) %>: <%= number_to_human_size(Setting.attachment_max_size.to_i.kilobytes) %>)</span> |
@@ -22,9 +22,14 | |||
|
22 | 22 | |
|
23 | 23 | <% if @issue.safe_attribute? 'watcher_user_ids' -%> |
|
24 | 24 | <p id="watchers_form"><label><%= l(:label_issue_watchers) %></label> |
|
25 | <% @issue.project.users.sort.each do |user| -%> | |
|
26 | <label class="floating"><%= check_box_tag 'issue[watcher_user_ids][]', user.id, @issue.watched_by?(user), :id => nil %> <%=h user %></label> | |
|
27 | <% end -%> | |
|
25 | <span id="watchers_inputs"> | |
|
26 | <%= watchers_checkboxes(@issue, @available_watchers) %> | |
|
27 | </span> | |
|
28 | <span class="search_for_watchers"> | |
|
29 | <%= link_to_remote l(:label_search_for_watchers), | |
|
30 | :url => {:controller => 'watchers', :action => 'new', :project_id => @issue.project}, | |
|
31 | :method => 'get' %> | |
|
32 | </span> | |
|
28 | 33 | </p> |
|
29 | 34 | <% end %> |
|
30 | 35 | </div> |
@@ -1,7 +1,7 | |||
|
1 | 1 | <h3 class="title"><%= l(:permission_add_issue_watchers) %></h3> |
|
2 | 2 | |
|
3 | 3 | <% form_remote_tag :url => {:controller => 'watchers', |
|
4 | :action => 'create', | |
|
4 | :action => (watched ? 'create' : 'append'), | |
|
5 | 5 | :object_type => watched.class.name.underscore, |
|
6 | 6 | :object_id => watched}, |
|
7 | 7 | :method => :post, |
@@ -22,7 +22,7 | |||
|
22 | 22 | :with => 'q') %> |
|
23 | 23 | |
|
24 | 24 | <div id="users_for_watcher"> |
|
25 | <%= principals_check_box_tags 'watcher[user_ids][]', watched.addable_watcher_users %> | |
|
25 | <%= principals_check_box_tags 'watcher[user_ids][]', (watched ? watched.addable_watcher_users : User.active.all(:limit => 100)) %> | |
|
26 | 26 | </div> |
|
27 | 27 | |
|
28 | 28 | <p class="buttons"> |
@@ -844,6 +844,7 en: | |||
|
844 | 844 | label_copy_attachments: Copy attachments |
|
845 | 845 | label_item_position: "%{position} of %{count}" |
|
846 | 846 | label_completed_versions: Completed versions |
|
847 | label_search_for_watchers: Search for watchers to add | |
|
847 | 848 | |
|
848 | 849 | button_login: Login |
|
849 | 850 | button_submit: Submit |
@@ -124,6 +124,8 ActionController::Routing::Routes.draw do |map| | |||
|
124 | 124 | :conditions => {:method => :get} |
|
125 | 125 | map.connect 'watchers', :controller=> 'watchers', :action => 'create', |
|
126 | 126 | :conditions => {:method => :post} |
|
127 | map.connect 'watchers/append', :controller=> 'watchers', :action => 'append', | |
|
128 | :conditions => {:method => :post} | |
|
127 | 129 | map.connect 'watchers/destroy', :controller=> 'watchers', :action => 'destroy', |
|
128 | 130 | :conditions => {:method => :post} |
|
129 | 131 | map.connect 'watchers/watch', :controller=> 'watchers', :action => 'watch', |
@@ -265,6 +265,12 div.projects h3 { background: url(../images/projects.png) no-repeat 0% 50%; padd | |||
|
265 | 265 | #watchers a.delete:hover {opacity: 1;} |
|
266 | 266 | #watchers img.gravatar {margin: 0 4px 2px 0;} |
|
267 | 267 | |
|
268 | span#watchers_inputs {overflow:auto; display:block;} | |
|
269 | span.search_for_watchers {display:block;} | |
|
270 | span.search_for_watchers, span.add_attachment {font-size:80%; line-height:2.5em;} | |
|
271 | span.search_for_watchers a, span.add_attachment a {padding-left:16px; background: url(../images/bullet_add.png) no-repeat 0 50%; } | |
|
272 | ||
|
273 | ||
|
268 | 274 | .highlight { background-color: #FCFD8D;} |
|
269 | 275 | .highlight.token-1 { background-color: #faa;} |
|
270 | 276 | .highlight.token-2 { background-color: #afa;} |
@@ -1680,6 +1680,21 class IssuesControllerTest < ActionController::TestCase | |||
|
1680 | 1680 | :value => 'Value for field 2'} |
|
1681 | 1681 | end |
|
1682 | 1682 | |
|
1683 | def test_post_create_with_failure_should_preserve_watchers | |
|
1684 | assert !User.find(8).member_of?(Project.find(1)) | |
|
1685 | ||
|
1686 | @request.session[:user_id] = 2 | |
|
1687 | post :create, :project_id => 1, | |
|
1688 | :issue => {:tracker_id => 1, | |
|
1689 | :watcher_user_ids => ['3', '8']} | |
|
1690 | assert_response :success | |
|
1691 | assert_template 'new' | |
|
1692 | ||
|
1693 | assert_tag 'input', :attributes => {:name => 'issue[watcher_user_ids][]', :value => '2', :checked => nil} | |
|
1694 | assert_tag 'input', :attributes => {:name => 'issue[watcher_user_ids][]', :value => '3', :checked => 'checked'} | |
|
1695 | assert_tag 'input', :attributes => {:name => 'issue[watcher_user_ids][]', :value => '8', :checked => 'checked'} | |
|
1696 | end | |
|
1697 | ||
|
1683 | 1698 | def test_post_create_should_ignore_non_safe_attributes |
|
1684 | 1699 | @request.session[:user_id] = 2 |
|
1685 | 1700 | assert_nothing_raised do |
@@ -68,6 +68,13 class WatchersControllerTest < ActionController::TestCase | |||
|
68 | 68 | assert_select_rjs :replace_html, 'ajax-modal' |
|
69 | 69 | end |
|
70 | 70 | |
|
71 | def test_new_for_new_record | |
|
72 | @request.session[:user_id] = 2 | |
|
73 | xhr :get, :new, :project_id => 1 | |
|
74 | assert_response :success | |
|
75 | assert_select_rjs :replace_html, 'ajax-modal' | |
|
76 | end | |
|
77 | ||
|
71 | 78 | def test_create |
|
72 | 79 | @request.session[:user_id] = 2 |
|
73 | 80 | assert_difference('Watcher.count') do |
@@ -91,6 +98,18 class WatchersControllerTest < ActionController::TestCase | |||
|
91 | 98 | assert Issue.find(2).watched_by?(User.find(7)) |
|
92 | 99 | end |
|
93 | 100 | |
|
101 | def test_append | |
|
102 | @request.session[:user_id] = 2 | |
|
103 | assert_no_difference 'Watcher.count' do | |
|
104 | xhr :post, :append, :watcher => {:user_ids => ['4', '7']} | |
|
105 | assert_response :success | |
|
106 | assert_select_rjs :insert_html, 'watchers_inputs' do | |
|
107 | assert_select 'input[name=?][value=4]', 'issue[watcher_user_ids][]' | |
|
108 | assert_select 'input[name=?][value=7]', 'issue[watcher_user_ids][]' | |
|
109 | end | |
|
110 | end | |
|
111 | end | |
|
112 | ||
|
94 | 113 | def test_remove_watcher |
|
95 | 114 | @request.session[:user_id] = 2 |
|
96 | 115 | assert_difference('Watcher.count', -1) do |
@@ -24,6 +24,10 class RoutingWatchersTest < ActionController::IntegrationTest | |||
|
24 | 24 | { :controller => 'watchers', :action => 'new' } |
|
25 | 25 | ) |
|
26 | 26 | assert_routing( |
|
27 | { :method => 'post', :path => "/watchers/append" }, | |
|
28 | { :controller => 'watchers', :action => 'append' } | |
|
29 | ) | |
|
30 | assert_routing( | |
|
27 | 31 | { :method => 'post', :path => "/watchers" }, |
|
28 | 32 | { :controller => 'watchers', :action => 'create' } |
|
29 | 33 | ) |
General Comments 0
You need to be logged in to leave comments.
Login now