##// END OF EJS Templates
Add a second action menu to IssuesController#show. (#4331)...
Eric Davis -
r3005:e02da72947d2
parent child
Show More
@@ -0,0 +1,9
1 <div class="contextual">
2 <%= link_to_if_authorized(l(:button_update), {:controller => 'issues', :action => 'edit', :id => @issue }, :onclick => 'showAndScrollTo("update", "notes"); return false;', :class => 'icon icon-edit', :accesskey => accesskey(:edit)) %>
3 <%= link_to_if_authorized l(:button_log_time), {:controller => 'timelog', :action => 'edit', :issue_id => @issue}, :class => 'icon icon-time-add' %>
4 <% replace_watcher ||= 'watcher' %>
5 <%= watcher_tag(@issue, User.current, {:id => replace_watcher, :replace => ['watcher','watcher2']}) %>
6 <%= link_to_if_authorized l(:button_copy), {:controller => 'issues', :action => 'new', :project_id => @project, :copy_from => @issue }, :class => 'icon icon-copy' %>
7 <%= link_to_if_authorized l(:button_move), {:controller => 'issues', :action => 'move', :id => @issue }, :class => 'icon icon-move' %>
8 <%= link_to_if_authorized l(:button_delete), {:controller => 'issues', :action => 'destroy', :id => @issue}, :confirm => l(:text_are_you_sure), :method => :post, :class => 'icon icon-del' %>
9 </div>
@@ -1,82 +1,97
1 # redMine - project management software
1 # redMine - project management software
2 # Copyright (C) 2006-2007 Jean-Philippe Lang
2 # Copyright (C) 2006-2007 Jean-Philippe Lang
3 #
3 #
4 # This program is free software; you can redistribute it and/or
4 # This program is free software; you can redistribute it and/or
5 # modify it under the terms of the GNU General Public License
5 # modify it under the terms of the GNU General Public License
6 # as published by the Free Software Foundation; either version 2
6 # as published by the Free Software Foundation; either version 2
7 # of the License, or (at your option) any later version.
7 # of the License, or (at your option) any later version.
8 #
8 #
9 # This program is distributed in the hope that it will be useful,
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
12 # GNU General Public License for more details.
13 #
13 #
14 # You should have received a copy of the GNU General Public License
14 # You should have received a copy of the GNU General Public License
15 # along with this program; if not, write to the Free Software
15 # along with this program; if not, write to the Free Software
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17
17
18 class WatchersController < ApplicationController
18 class WatchersController < ApplicationController
19 before_filter :find_project
19 before_filter :find_project
20 before_filter :require_login, :check_project_privacy, :only => [:watch, :unwatch]
20 before_filter :require_login, :check_project_privacy, :only => [:watch, :unwatch]
21 before_filter :authorize, :only => [:new, :destroy]
21 before_filter :authorize, :only => [:new, :destroy]
22
22
23 verify :method => :post,
23 verify :method => :post,
24 :only => [ :watch, :unwatch ],
24 :only => [ :watch, :unwatch ],
25 :render => { :nothing => true, :status => :method_not_allowed }
25 :render => { :nothing => true, :status => :method_not_allowed }
26
26
27 def watch
27 def watch
28 set_watcher(User.current, true)
28 set_watcher(User.current, true)
29 end
29 end
30
30
31 def unwatch
31 def unwatch
32 set_watcher(User.current, false)
32 set_watcher(User.current, false)
33 end
33 end
34
34
35 def new
35 def new
36 @watcher = Watcher.new(params[:watcher])
36 @watcher = Watcher.new(params[:watcher])
37 @watcher.watchable = @watched
37 @watcher.watchable = @watched
38 @watcher.save if request.post?
38 @watcher.save if request.post?
39 respond_to do |format|
39 respond_to do |format|
40 format.html { redirect_to :back }
40 format.html { redirect_to :back }
41 format.js do
41 format.js do
42 render :update do |page|
42 render :update do |page|
43 page.replace_html 'watchers', :partial => 'watchers/watchers', :locals => {:watched => @watched}
43 page.replace_html 'watchers', :partial => 'watchers/watchers', :locals => {:watched => @watched}
44 end
44 end
45 end
45 end
46 end
46 end
47 rescue ::ActionController::RedirectBackError
47 rescue ::ActionController::RedirectBackError
48 render :text => 'Watcher added.', :layout => true
48 render :text => 'Watcher added.', :layout => true
49 end
49 end
50
50
51 def destroy
51 def destroy
52 @watched.set_watcher(User.find(params[:user_id]), false) if request.post?
52 @watched.set_watcher(User.find(params[:user_id]), false) if request.post?
53 respond_to do |format|
53 respond_to do |format|
54 format.html { redirect_to :back }
54 format.html { redirect_to :back }
55 format.js do
55 format.js do
56 render :update do |page|
56 render :update do |page|
57 page.replace_html 'watchers', :partial => 'watchers/watchers', :locals => {:watched => @watched}
57 page.replace_html 'watchers', :partial => 'watchers/watchers', :locals => {:watched => @watched}
58 end
58 end
59 end
59 end
60 end
60 end
61 end
61 end
62
62
63 private
63 private
64 def find_project
64 def find_project
65 klass = Object.const_get(params[:object_type].camelcase)
65 klass = Object.const_get(params[:object_type].camelcase)
66 return false unless klass.respond_to?('watched_by')
66 return false unless klass.respond_to?('watched_by')
67 @watched = klass.find(params[:object_id])
67 @watched = klass.find(params[:object_id])
68 @project = @watched.project
68 @project = @watched.project
69 rescue
69 rescue
70 render_404
70 render_404
71 end
71 end
72
72
73 def set_watcher(user, watching)
73 def set_watcher(user, watching)
74 @watched.set_watcher(user, watching)
74 @watched.set_watcher(user, watching)
75 if params[:replace].present?
76 if params[:replace].is_a? Array
77 replace_ids = params[:replace]
78 else
79 replace_ids = [params[:replace]]
80 end
81 else
82 replace_ids = 'watcher'
83 end
75 respond_to do |format|
84 respond_to do |format|
76 format.html { redirect_to :back }
85 format.html { redirect_to :back }
77 format.js { render(:update) {|page| page.replace_html 'watcher', watcher_link(@watched, user)} }
86 format.js do
87 render(:update) do |page|
88 replace_ids.each do |replace_id|
89 page.replace_html replace_id, watcher_link(@watched, user, :replace => replace_ids)
90 end
91 end
92 end
78 end
93 end
79 rescue ::ActionController::RedirectBackError
94 rescue ::ActionController::RedirectBackError
80 render :text => (watching ? 'Watcher added.' : 'Watcher removed.'), :layout => true
95 render :text => (watching ? 'Watcher added.' : 'Watcher removed.'), :layout => true
81 end
96 end
82 end
97 end
@@ -1,56 +1,67
1 # redMine - project management software
1 # redMine - project management software
2 # Copyright (C) 2006-2007 Jean-Philippe Lang
2 # Copyright (C) 2006-2007 Jean-Philippe Lang
3 #
3 #
4 # This program is free software; you can redistribute it and/or
4 # This program is free software; you can redistribute it and/or
5 # modify it under the terms of the GNU General Public License
5 # modify it under the terms of the GNU General Public License
6 # as published by the Free Software Foundation; either version 2
6 # as published by the Free Software Foundation; either version 2
7 # of the License, or (at your option) any later version.
7 # of the License, or (at your option) any later version.
8 #
8 #
9 # This program is distributed in the hope that it will be useful,
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
12 # GNU General Public License for more details.
13 #
13 #
14 # You should have received a copy of the GNU General Public License
14 # You should have received a copy of the GNU General Public License
15 # along with this program; if not, write to the Free Software
15 # along with this program; if not, write to the Free Software
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17
17
18 module WatchersHelper
18 module WatchersHelper
19 def watcher_tag(object, user)
19
20 content_tag("span", watcher_link(object, user), :id => 'watcher')
20 # Valid options
21 # * :id - the element id
22 # * :replace - a string or array of element ids that will be
23 # replaced
24 def watcher_tag(object, user, options={:replace => 'watcher'})
25 id = options[:id]
26 id ||= options[:replace] if options[:replace].is_a? String
27 content_tag("span", watcher_link(object, user, options), :id => id)
21 end
28 end
22
29
23 def watcher_link(object, user)
30 # Valid options
31 # * :replace - a string or array of element ids that will be
32 # replaced
33 def watcher_link(object, user, options={:replace => 'watcher'})
24 return '' unless user && user.logged? && object.respond_to?('watched_by?')
34 return '' unless user && user.logged? && object.respond_to?('watched_by?')
25 watched = object.watched_by?(user)
35 watched = object.watched_by?(user)
26 url = {:controller => 'watchers',
36 url = {:controller => 'watchers',
27 :action => (watched ? 'unwatch' : 'watch'),
37 :action => (watched ? 'unwatch' : 'watch'),
28 :object_type => object.class.to_s.underscore,
38 :object_type => object.class.to_s.underscore,
29 :object_id => object.id}
39 :object_id => object.id,
40 :replace => options[:replace]}
30 link_to_remote((watched ? l(:button_unwatch) : l(:button_watch)),
41 link_to_remote((watched ? l(:button_unwatch) : l(:button_watch)),
31 {:url => url},
42 {:url => url},
32 :href => url_for(url),
43 :href => url_for(url),
33 :class => (watched ? 'icon icon-fav' : 'icon icon-fav-off'))
44 :class => (watched ? 'icon icon-fav' : 'icon icon-fav-off'))
34
45
35 end
46 end
36
47
37 # Returns a comma separated list of users watching the given object
48 # Returns a comma separated list of users watching the given object
38 def watchers_list(object)
49 def watchers_list(object)
39 remove_allowed = User.current.allowed_to?("delete_#{object.class.name.underscore}_watchers".to_sym, object.project)
50 remove_allowed = User.current.allowed_to?("delete_#{object.class.name.underscore}_watchers".to_sym, object.project)
40 object.watcher_users.collect do |user|
51 object.watcher_users.collect do |user|
41 s = content_tag('span', link_to_user(user), :class => 'user')
52 s = content_tag('span', link_to_user(user), :class => 'user')
42 if remove_allowed
53 if remove_allowed
43 url = {:controller => 'watchers',
54 url = {:controller => 'watchers',
44 :action => 'destroy',
55 :action => 'destroy',
45 :object_type => object.class.to_s.underscore,
56 :object_type => object.class.to_s.underscore,
46 :object_id => object.id,
57 :object_id => object.id,
47 :user_id => user}
58 :user_id => user}
48 s += ' ' + link_to_remote(image_tag('delete.png'),
59 s += ' ' + link_to_remote(image_tag('delete.png'),
49 {:url => url},
60 {:url => url},
50 :href => url_for(url),
61 :href => url_for(url),
51 :style => "vertical-align: middle")
62 :style => "vertical-align: middle")
52 end
63 end
53 s
64 s
54 end.join(",\n")
65 end.join(",\n")
55 end
66 end
56 end
67 end
@@ -1,119 +1,115
1 <div class="contextual">
1 <%= render :partial => 'action_menu' %>
2 <%= link_to_if_authorized(l(:button_update), {:controller => 'issues', :action => 'edit', :id => @issue }, :onclick => 'showAndScrollTo("update", "notes"); return false;', :class => 'icon icon-edit', :accesskey => accesskey(:edit)) %>
3 <%= link_to_if_authorized l(:button_log_time), {:controller => 'timelog', :action => 'edit', :issue_id => @issue}, :class => 'icon icon-time-add' %>
4 <%= watcher_tag(@issue, User.current) %>
5 <%= link_to_if_authorized l(:button_copy), {:controller => 'issues', :action => 'new', :project_id => @project, :copy_from => @issue }, :class => 'icon icon-copy' %>
6 <%= link_to_if_authorized l(:button_move), {:controller => 'issues', :action => 'move', :id => @issue }, :class => 'icon icon-move' %>
7 <%= link_to_if_authorized l(:button_delete), {:controller => 'issues', :action => 'destroy', :id => @issue}, :confirm => l(:text_are_you_sure), :method => :post, :class => 'icon icon-del' %>
8 </div>
9
2
10 <h2><%= @issue.tracker.name %> #<%= @issue.id %></h2>
3 <h2><%= @issue.tracker.name %> #<%= @issue.id %></h2>
11
4
12 <div class="<%= @issue.css_classes %> details">
5 <div class="<%= @issue.css_classes %> details">
13 <%= avatar(@issue.author, :size => "64") %>
6 <%= avatar(@issue.author, :size => "64") %>
14 <h3><%=h @issue.subject %></h3>
7 <h3><%=h @issue.subject %></h3>
15 <p class="author">
8 <p class="author">
16 <%= authoring @issue.created_on, @issue.author %>.
9 <%= authoring @issue.created_on, @issue.author %>.
17 <% if @issue.created_on != @issue.updated_on %>
10 <% if @issue.created_on != @issue.updated_on %>
18 <%= l(:label_updated_time, time_tag(@issue.updated_on)) %>.
11 <%= l(:label_updated_time, time_tag(@issue.updated_on)) %>.
19 <% end %>
12 <% end %>
20 </p>
13 </p>
21
14
22 <table class="attributes">
15 <table class="attributes">
23 <tr>
16 <tr>
24 <th class="status"><%=l(:field_status)%>:</th><td class="status"><%= @issue.status.name %></td>
17 <th class="status"><%=l(:field_status)%>:</th><td class="status"><%= @issue.status.name %></td>
25 <th class="start-date"><%=l(:field_start_date)%>:</th><td class="start-date"><%= format_date(@issue.start_date) %></td>
18 <th class="start-date"><%=l(:field_start_date)%>:</th><td class="start-date"><%= format_date(@issue.start_date) %></td>
26 </tr>
19 </tr>
27 <tr>
20 <tr>
28 <th class="priority"><%=l(:field_priority)%>:</th><td class="priority"><%= @issue.priority.name %></td>
21 <th class="priority"><%=l(:field_priority)%>:</th><td class="priority"><%= @issue.priority.name %></td>
29 <th class="due-date"><%=l(:field_due_date)%>:</th><td class="due-date"><%= format_date(@issue.due_date) %></td>
22 <th class="due-date"><%=l(:field_due_date)%>:</th><td class="due-date"><%= format_date(@issue.due_date) %></td>
30 </tr>
23 </tr>
31 <tr>
24 <tr>
32 <th class="assigned-to"><%=l(:field_assigned_to)%>:</th><td class="assigned-to"><%= avatar(@issue.assigned_to, :size => "14") %><%= @issue.assigned_to ? link_to_user(@issue.assigned_to) : "-" %></td>
25 <th class="assigned-to"><%=l(:field_assigned_to)%>:</th><td class="assigned-to"><%= avatar(@issue.assigned_to, :size => "14") %><%= @issue.assigned_to ? link_to_user(@issue.assigned_to) : "-" %></td>
33 <th class="progress"><%=l(:field_done_ratio)%>:</th><td class="progress"><%= progress_bar @issue.done_ratio, :width => '80px', :legend => "#{@issue.done_ratio}%" %></td>
26 <th class="progress"><%=l(:field_done_ratio)%>:</th><td class="progress"><%= progress_bar @issue.done_ratio, :width => '80px', :legend => "#{@issue.done_ratio}%" %></td>
34 </tr>
27 </tr>
35 <tr>
28 <tr>
36 <th class="category"><%=l(:field_category)%>:</th><td class="category"><%=h @issue.category ? @issue.category.name : "-" %></td>
29 <th class="category"><%=l(:field_category)%>:</th><td class="category"><%=h @issue.category ? @issue.category.name : "-" %></td>
37 <% if User.current.allowed_to?(:view_time_entries, @project) %>
30 <% if User.current.allowed_to?(:view_time_entries, @project) %>
38 <th class="spent-time"><%=l(:label_spent_time)%>:</th>
31 <th class="spent-time"><%=l(:label_spent_time)%>:</th>
39 <td class="spent-time"><%= @issue.spent_hours > 0 ? (link_to l_hours(@issue.spent_hours), {:controller => 'timelog', :action => 'details', :project_id => @project, :issue_id => @issue}) : "-" %></td>
32 <td class="spent-time"><%= @issue.spent_hours > 0 ? (link_to l_hours(@issue.spent_hours), {:controller => 'timelog', :action => 'details', :project_id => @project, :issue_id => @issue}) : "-" %></td>
40 <% end %>
33 <% end %>
41 </tr>
34 </tr>
42 <tr>
35 <tr>
43 <th class="fixed-version"><%=l(:field_fixed_version)%>:</th><td class="fixed-version"><%= @issue.fixed_version ? link_to_version(@issue.fixed_version) : "-" %></td>
36 <th class="fixed-version"><%=l(:field_fixed_version)%>:</th><td class="fixed-version"><%= @issue.fixed_version ? link_to_version(@issue.fixed_version) : "-" %></td>
44 <% if @issue.estimated_hours %>
37 <% if @issue.estimated_hours %>
45 <th class="estimated-hours"><%=l(:field_estimated_hours)%>:</th><td class="estimated-hours"><%= l_hours(@issue.estimated_hours) %></td>
38 <th class="estimated-hours"><%=l(:field_estimated_hours)%>:</th><td class="estimated-hours"><%= l_hours(@issue.estimated_hours) %></td>
46 <% end %>
39 <% end %>
47 </tr>
40 </tr>
48 <%= render_custom_fields_rows(@issue) %>
41 <%= render_custom_fields_rows(@issue) %>
49 <%= call_hook(:view_issues_show_details_bottom, :issue => @issue) %>
42 <%= call_hook(:view_issues_show_details_bottom, :issue => @issue) %>
50 </table>
43 </table>
51 <hr />
44 <hr />
52
45
53 <div class="contextual">
46 <div class="contextual">
54 <%= link_to_remote_if_authorized(l(:button_quote), { :url => {:action => 'reply', :id => @issue} }, :class => 'icon icon-comment') unless @issue.description.blank? %>
47 <%= link_to_remote_if_authorized(l(:button_quote), { :url => {:action => 'reply', :id => @issue} }, :class => 'icon icon-comment') unless @issue.description.blank? %>
55 </div>
48 </div>
56
49
57 <p><strong><%=l(:field_description)%></strong></p>
50 <p><strong><%=l(:field_description)%></strong></p>
58 <div class="wiki">
51 <div class="wiki">
59 <%= textilizable @issue, :description, :attachments => @issue.attachments %>
52 <%= textilizable @issue, :description, :attachments => @issue.attachments %>
60 </div>
53 </div>
61
54
62 <%= link_to_attachments @issue %>
55 <%= link_to_attachments @issue %>
63
56
64 <%= call_hook(:view_issues_show_description_bottom, :issue => @issue) %>
57 <%= call_hook(:view_issues_show_description_bottom, :issue => @issue) %>
65
58
66 <% if authorize_for('issue_relations', 'new') || @issue.relations.any? %>
59 <% if authorize_for('issue_relations', 'new') || @issue.relations.any? %>
67 <hr />
60 <hr />
68 <div id="relations">
61 <div id="relations">
69 <%= render :partial => 'relations' %>
62 <%= render :partial => 'relations' %>
70 </div>
63 </div>
71 <% end %>
64 <% end %>
72
65
73 <% if User.current.allowed_to?(:add_issue_watchers, @project) ||
66 <% if User.current.allowed_to?(:add_issue_watchers, @project) ||
74 (@issue.watchers.any? && User.current.allowed_to?(:view_issue_watchers, @project)) %>
67 (@issue.watchers.any? && User.current.allowed_to?(:view_issue_watchers, @project)) %>
75 <hr />
68 <hr />
76 <div id="watchers">
69 <div id="watchers">
77 <%= render :partial => 'watchers/watchers', :locals => {:watched => @issue} %>
70 <%= render :partial => 'watchers/watchers', :locals => {:watched => @issue} %>
78 </div>
71 </div>
79 <% end %>
72 <% end %>
80
73
81 </div>
74 </div>
82
75
83 <% if @changesets.any? && User.current.allowed_to?(:view_changesets, @project) %>
76 <% if @changesets.any? && User.current.allowed_to?(:view_changesets, @project) %>
84 <div id="issue-changesets">
77 <div id="issue-changesets">
85 <h3><%=l(:label_associated_revisions)%></h3>
78 <h3><%=l(:label_associated_revisions)%></h3>
86 <%= render :partial => 'changesets', :locals => { :changesets => @changesets} %>
79 <%= render :partial => 'changesets', :locals => { :changesets => @changesets} %>
87 </div>
80 </div>
88 <% end %>
81 <% end %>
89
82
90 <% if @journals.any? %>
83 <% if @journals.any? %>
91 <div id="history">
84 <div id="history">
92 <h3><%=l(:label_history)%></h3>
85 <h3><%=l(:label_history)%></h3>
93 <%= render :partial => 'history', :locals => { :journals => @journals } %>
86 <%= render :partial => 'history', :locals => { :journals => @journals } %>
94 </div>
87 </div>
95 <% end %>
88 <% end %>
89
90 <%= render :partial => 'action_menu', :locals => {:replace_watcher => 'watcher2' } %>
91
96 <div style="clear: both;"></div>
92 <div style="clear: both;"></div>
97
93
98 <% if authorize_for('issues', 'edit') %>
94 <% if authorize_for('issues', 'edit') %>
99 <div id="update" style="display:none;">
95 <div id="update" style="display:none;">
100 <h3><%= l(:button_update) %></h3>
96 <h3><%= l(:button_update) %></h3>
101 <%= render :partial => 'edit' %>
97 <%= render :partial => 'edit' %>
102 </div>
98 </div>
103 <% end %>
99 <% end %>
104
100
105 <% other_formats_links do |f| %>
101 <% other_formats_links do |f| %>
106 <%= f.link_to 'Atom', :url => {:key => User.current.rss_key} %>
102 <%= f.link_to 'Atom', :url => {:key => User.current.rss_key} %>
107 <%= f.link_to 'PDF' %>
103 <%= f.link_to 'PDF' %>
108 <% end %>
104 <% end %>
109
105
110 <% html_title "#{@issue.tracker.name} ##{@issue.id}: #{@issue.subject}" %>
106 <% html_title "#{@issue.tracker.name} ##{@issue.id}: #{@issue.subject}" %>
111
107
112 <% content_for :sidebar do %>
108 <% content_for :sidebar do %>
113 <%= render :partial => 'issues/sidebar' %>
109 <%= render :partial => 'issues/sidebar' %>
114 <% end %>
110 <% end %>
115
111
116 <% content_for :header_tags do %>
112 <% content_for :header_tags do %>
117 <%= auto_discovery_link_tag(:atom, {:format => 'atom', :key => User.current.rss_key}, :title => "#{@issue.project} - #{@issue.tracker} ##{@issue.id}: #{@issue.subject}") %>
113 <%= auto_discovery_link_tag(:atom, {:format => 'atom', :key => User.current.rss_key}, :title => "#{@issue.project} - #{@issue.tracker} ##{@issue.id}: #{@issue.subject}") %>
118 <%= stylesheet_link_tag 'scm' %>
114 <%= stylesheet_link_tag 'scm' %>
119 <% end %>
115 <% end %>
@@ -1,80 +1,101
1 # Redmine - project management software
1 # Redmine - project management software
2 # Copyright (C) 2006-2008 Jean-Philippe Lang
2 # Copyright (C) 2006-2008 Jean-Philippe Lang
3 #
3 #
4 # This program is free software; you can redistribute it and/or
4 # This program is free software; you can redistribute it and/or
5 # modify it under the terms of the GNU General Public License
5 # modify it under the terms of the GNU General Public License
6 # as published by the Free Software Foundation; either version 2
6 # as published by the Free Software Foundation; either version 2
7 # of the License, or (at your option) any later version.
7 # of the License, or (at your option) any later version.
8 #
8 #
9 # This program is distributed in the hope that it will be useful,
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
12 # GNU General Public License for more details.
13 #
13 #
14 # You should have received a copy of the GNU General Public License
14 # You should have received a copy of the GNU General Public License
15 # along with this program; if not, write to the Free Software
15 # along with this program; if not, write to the Free Software
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17
17
18 require File.dirname(__FILE__) + '/../test_helper'
18 require File.dirname(__FILE__) + '/../test_helper'
19 require 'watchers_controller'
19 require 'watchers_controller'
20
20
21 # Re-raise errors caught by the controller.
21 # Re-raise errors caught by the controller.
22 class WatchersController; def rescue_action(e) raise e end; end
22 class WatchersController; def rescue_action(e) raise e end; end
23
23
24 class WatchersControllerTest < ActionController::TestCase
24 class WatchersControllerTest < ActionController::TestCase
25 fixtures :projects, :users, :roles, :members, :member_roles, :enabled_modules,
25 fixtures :projects, :users, :roles, :members, :member_roles, :enabled_modules,
26 :issues, :trackers, :projects_trackers, :issue_statuses, :enumerations, :watchers
26 :issues, :trackers, :projects_trackers, :issue_statuses, :enumerations, :watchers
27
27
28 def setup
28 def setup
29 @controller = WatchersController.new
29 @controller = WatchersController.new
30 @request = ActionController::TestRequest.new
30 @request = ActionController::TestRequest.new
31 @response = ActionController::TestResponse.new
31 @response = ActionController::TestResponse.new
32 User.current = nil
32 User.current = nil
33 end
33 end
34
34
35 def test_get_watch_should_be_invalid
35 def test_get_watch_should_be_invalid
36 @request.session[:user_id] = 3
36 @request.session[:user_id] = 3
37 get :watch, :object_type => 'issue', :object_id => '1'
37 get :watch, :object_type => 'issue', :object_id => '1'
38 assert_response 405
38 assert_response 405
39 end
39 end
40
40
41 def test_watch
41 def test_watch
42 @request.session[:user_id] = 3
42 @request.session[:user_id] = 3
43 assert_difference('Watcher.count') do
43 assert_difference('Watcher.count') do
44 xhr :post, :watch, :object_type => 'issue', :object_id => '1'
44 xhr :post, :watch, :object_type => 'issue', :object_id => '1'
45 assert_response :success
45 assert_response :success
46 assert_select_rjs :replace_html, 'watcher'
46 assert_select_rjs :replace_html, 'watcher'
47 end
47 end
48 assert Issue.find(1).watched_by?(User.find(3))
48 assert Issue.find(1).watched_by?(User.find(3))
49 end
49 end
50
51 def test_watch_with_multiple_replacements
52 @request.session[:user_id] = 3
53 assert_difference('Watcher.count') do
54 xhr :post, :watch, :object_type => 'issue', :object_id => '1', :replace => ['watch_item_1','watch_item_2']
55 assert_response :success
56 assert_select_rjs :replace_html, 'watch_item_1'
57 assert_select_rjs :replace_html, 'watch_item_2'
58 end
59 end
50
60
51 def test_unwatch
61 def test_unwatch
52 @request.session[:user_id] = 3
62 @request.session[:user_id] = 3
53 assert_difference('Watcher.count', -1) do
63 assert_difference('Watcher.count', -1) do
54 xhr :post, :unwatch, :object_type => 'issue', :object_id => '2'
64 xhr :post, :unwatch, :object_type => 'issue', :object_id => '2'
55 assert_response :success
65 assert_response :success
56 assert_select_rjs :replace_html, 'watcher'
66 assert_select_rjs :replace_html, 'watcher'
57 end
67 end
58 assert !Issue.find(1).watched_by?(User.find(3))
68 assert !Issue.find(1).watched_by?(User.find(3))
59 end
69 end
60
70
71 def test_unwatch_with_multiple_replacements
72 @request.session[:user_id] = 3
73 assert_difference('Watcher.count', -1) do
74 xhr :post, :unwatch, :object_type => 'issue', :object_id => '2', :replace => ['watch_item_1', 'watch_item_2']
75 assert_response :success
76 assert_select_rjs :replace_html, 'watch_item_1'
77 assert_select_rjs :replace_html, 'watch_item_2'
78 end
79 assert !Issue.find(1).watched_by?(User.find(3))
80 end
81
61 def test_new_watcher
82 def test_new_watcher
62 @request.session[:user_id] = 2
83 @request.session[:user_id] = 2
63 assert_difference('Watcher.count') do
84 assert_difference('Watcher.count') do
64 xhr :post, :new, :object_type => 'issue', :object_id => '2', :watcher => {:user_id => '4'}
85 xhr :post, :new, :object_type => 'issue', :object_id => '2', :watcher => {:user_id => '4'}
65 assert_response :success
86 assert_response :success
66 assert_select_rjs :replace_html, 'watchers'
87 assert_select_rjs :replace_html, 'watchers'
67 end
88 end
68 assert Issue.find(2).watched_by?(User.find(4))
89 assert Issue.find(2).watched_by?(User.find(4))
69 end
90 end
70
91
71 def test_remove_watcher
92 def test_remove_watcher
72 @request.session[:user_id] = 2
93 @request.session[:user_id] = 2
73 assert_difference('Watcher.count', -1) do
94 assert_difference('Watcher.count', -1) do
74 xhr :post, :destroy, :object_type => 'issue', :object_id => '2', :user_id => '3'
95 xhr :post, :destroy, :object_type => 'issue', :object_id => '2', :user_id => '3'
75 assert_response :success
96 assert_response :success
76 assert_select_rjs :replace_html, 'watchers'
97 assert_select_rjs :replace_html, 'watchers'
77 end
98 end
78 assert !Issue.find(2).watched_by?(User.find(3))
99 assert !Issue.find(2).watched_by?(User.find(3))
79 end
100 end
80 end
101 end
General Comments 0
You need to be logged in to leave comments. Login now