##// END OF EJS Templates
Use a single query to retrieve issues on the roadmap....
Jean-Philippe Lang -
r8937:9c4014f446d8
parent child
Show More
@@ -1,205 +1,204
1 # Redmine - project management software
1 # Redmine - project management software
2 # Copyright (C) 2006-2011 Jean-Philippe Lang
2 # Copyright (C) 2006-2011 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 VersionsController < ApplicationController
18 class VersionsController < ApplicationController
19 menu_item :roadmap
19 menu_item :roadmap
20 model_object Version
20 model_object Version
21 before_filter :find_model_object, :except => [:index, :new, :create, :close_completed]
21 before_filter :find_model_object, :except => [:index, :new, :create, :close_completed]
22 before_filter :find_project_from_association, :except => [:index, :new, :create, :close_completed]
22 before_filter :find_project_from_association, :except => [:index, :new, :create, :close_completed]
23 before_filter :find_project, :only => [:index, :new, :create, :close_completed]
23 before_filter :find_project, :only => [:index, :new, :create, :close_completed]
24 before_filter :authorize
24 before_filter :authorize
25
25
26 accept_api_auth :index, :show, :create, :update, :destroy
26 accept_api_auth :index, :show, :create, :update, :destroy
27
27
28 helper :custom_fields
28 helper :custom_fields
29 helper :projects
29 helper :projects
30
30
31 def index
31 def index
32 respond_to do |format|
32 respond_to do |format|
33 format.html {
33 format.html {
34 @trackers = @project.trackers.find(:all, :order => 'position')
34 @trackers = @project.trackers.find(:all, :order => 'position')
35 retrieve_selected_tracker_ids(@trackers, @trackers.select {|t| t.is_in_roadmap?})
35 retrieve_selected_tracker_ids(@trackers, @trackers.select {|t| t.is_in_roadmap?})
36 @with_subprojects = params[:with_subprojects].nil? ? Setting.display_subprojects_issues? : (params[:with_subprojects] == '1')
36 @with_subprojects = params[:with_subprojects].nil? ? Setting.display_subprojects_issues? : (params[:with_subprojects] == '1')
37 project_ids = @with_subprojects ? @project.self_and_descendants.collect(&:id) : [@project.id]
37 project_ids = @with_subprojects ? @project.self_and_descendants.collect(&:id) : [@project.id]
38
38
39 @versions = @project.shared_versions || []
39 @versions = @project.shared_versions || []
40 @versions += @project.rolled_up_versions.visible if @with_subprojects
40 @versions += @project.rolled_up_versions.visible if @with_subprojects
41 @versions = @versions.uniq.sort
41 @versions = @versions.uniq.sort
42 unless params[:completed]
42 unless params[:completed]
43 @completed_versions = @versions.select {|version| version.closed? || version.completed? }
43 @completed_versions = @versions.select {|version| version.closed? || version.completed? }
44 @versions -= @completed_versions
44 @versions -= @completed_versions
45 end
45 end
46
46
47 @issues_by_version = {}
47 @issues_by_version = {}
48 unless @selected_tracker_ids.empty?
48 if @selected_tracker_ids.any? && @versions.any?
49 @versions.each do |version|
49 issues = Issue.visible.all(
50 issues = version.fixed_issues.visible.find(:all,
50 :include => [:project, :status, :tracker, :priority, :fixed_version],
51 :include => [:project, :status, :tracker, :priority],
51 :conditions => {:tracker_id => @selected_tracker_ids, :project_id => project_ids, :fixed_version_id => @versions.map(&:id)},
52 :conditions => {:tracker_id => @selected_tracker_ids, :project_id => project_ids},
52 :order => "#{Project.table_name}.lft, #{Tracker.table_name}.position, #{Issue.table_name}.id"
53 :order => "#{Project.table_name}.lft, #{Tracker.table_name}.position, #{Issue.table_name}.id")
53 )
54 @issues_by_version[version] = issues
54 @issues_by_version = issues.group_by(&:fixed_version)
55 end
56 end
55 end
57 @versions.reject! {|version| !project_ids.include?(version.project_id) && @issues_by_version[version].blank?}
56 @versions.reject! {|version| !project_ids.include?(version.project_id) && @issues_by_version[version].blank?}
58 }
57 }
59 format.api {
58 format.api {
60 @versions = @project.shared_versions.all
59 @versions = @project.shared_versions.all
61 }
60 }
62 end
61 end
63 end
62 end
64
63
65 def show
64 def show
66 respond_to do |format|
65 respond_to do |format|
67 format.html {
66 format.html {
68 @issues = @version.fixed_issues.visible.find(:all,
67 @issues = @version.fixed_issues.visible.find(:all,
69 :include => [:status, :tracker, :priority],
68 :include => [:status, :tracker, :priority],
70 :order => "#{Tracker.table_name}.position, #{Issue.table_name}.id")
69 :order => "#{Tracker.table_name}.position, #{Issue.table_name}.id")
71 }
70 }
72 format.api
71 format.api
73 end
72 end
74 end
73 end
75
74
76 def new
75 def new
77 @version = @project.versions.build(params[:version])
76 @version = @project.versions.build(params[:version])
78
77
79 respond_to do |format|
78 respond_to do |format|
80 format.html
79 format.html
81 format.js do
80 format.js do
82 render :update do |page|
81 render :update do |page|
83 page.replace_html 'ajax-modal', :partial => 'versions/new_modal'
82 page.replace_html 'ajax-modal', :partial => 'versions/new_modal'
84 page << "showModal('ajax-modal', '600px');"
83 page << "showModal('ajax-modal', '600px');"
85 page << "Form.Element.focus('version_name');"
84 page << "Form.Element.focus('version_name');"
86 end
85 end
87 end
86 end
88 end
87 end
89 end
88 end
90
89
91 def create
90 def create
92 @version = @project.versions.build
91 @version = @project.versions.build
93 if params[:version]
92 if params[:version]
94 attributes = params[:version].dup
93 attributes = params[:version].dup
95 attributes.delete('sharing') unless attributes.nil? || @version.allowed_sharings.include?(attributes['sharing'])
94 attributes.delete('sharing') unless attributes.nil? || @version.allowed_sharings.include?(attributes['sharing'])
96 @version.attributes = attributes
95 @version.attributes = attributes
97 end
96 end
98
97
99 if request.post?
98 if request.post?
100 if @version.save
99 if @version.save
101 respond_to do |format|
100 respond_to do |format|
102 format.html do
101 format.html do
103 flash[:notice] = l(:notice_successful_create)
102 flash[:notice] = l(:notice_successful_create)
104 redirect_back_or_default :controller => 'projects', :action => 'settings', :tab => 'versions', :id => @project
103 redirect_back_or_default :controller => 'projects', :action => 'settings', :tab => 'versions', :id => @project
105 end
104 end
106 format.js do
105 format.js do
107 render(:update) {|page|
106 render(:update) {|page|
108 page << 'hideModal();'
107 page << 'hideModal();'
109 # IE doesn't support the replace_html rjs method for select box options
108 # IE doesn't support the replace_html rjs method for select box options
110 page.replace "issue_fixed_version_id",
109 page.replace "issue_fixed_version_id",
111 content_tag('select', content_tag('option') + version_options_for_select(@project.shared_versions.open, @version), :id => 'issue_fixed_version_id', :name => 'issue[fixed_version_id]')
110 content_tag('select', content_tag('option') + version_options_for_select(@project.shared_versions.open, @version), :id => 'issue_fixed_version_id', :name => 'issue[fixed_version_id]')
112 }
111 }
113 end
112 end
114 format.api do
113 format.api do
115 render :action => 'show', :status => :created, :location => version_url(@version)
114 render :action => 'show', :status => :created, :location => version_url(@version)
116 end
115 end
117 end
116 end
118 else
117 else
119 respond_to do |format|
118 respond_to do |format|
120 format.html { render :action => 'new' }
119 format.html { render :action => 'new' }
121 format.js do
120 format.js do
122 render :update do |page|
121 render :update do |page|
123 page.replace_html 'ajax-modal', :partial => 'versions/new_modal'
122 page.replace_html 'ajax-modal', :partial => 'versions/new_modal'
124 page << "Form.Element.focus('version_name');"
123 page << "Form.Element.focus('version_name');"
125 end
124 end
126 end
125 end
127 format.api { render_validation_errors(@version) }
126 format.api { render_validation_errors(@version) }
128 end
127 end
129 end
128 end
130 end
129 end
131 end
130 end
132
131
133 def edit
132 def edit
134 end
133 end
135
134
136 def update
135 def update
137 if request.put? && params[:version]
136 if request.put? && params[:version]
138 attributes = params[:version].dup
137 attributes = params[:version].dup
139 attributes.delete('sharing') unless @version.allowed_sharings.include?(attributes['sharing'])
138 attributes.delete('sharing') unless @version.allowed_sharings.include?(attributes['sharing'])
140 if @version.update_attributes(attributes)
139 if @version.update_attributes(attributes)
141 respond_to do |format|
140 respond_to do |format|
142 format.html {
141 format.html {
143 flash[:notice] = l(:notice_successful_update)
142 flash[:notice] = l(:notice_successful_update)
144 redirect_back_or_default :controller => 'projects', :action => 'settings', :tab => 'versions', :id => @project
143 redirect_back_or_default :controller => 'projects', :action => 'settings', :tab => 'versions', :id => @project
145 }
144 }
146 format.api { head :ok }
145 format.api { head :ok }
147 end
146 end
148 else
147 else
149 respond_to do |format|
148 respond_to do |format|
150 format.html { render :action => 'edit' }
149 format.html { render :action => 'edit' }
151 format.api { render_validation_errors(@version) }
150 format.api { render_validation_errors(@version) }
152 end
151 end
153 end
152 end
154 end
153 end
155 end
154 end
156
155
157 def close_completed
156 def close_completed
158 if request.put?
157 if request.put?
159 @project.close_completed_versions
158 @project.close_completed_versions
160 end
159 end
161 redirect_to :controller => 'projects', :action => 'settings', :tab => 'versions', :id => @project
160 redirect_to :controller => 'projects', :action => 'settings', :tab => 'versions', :id => @project
162 end
161 end
163
162
164 verify :method => :delete, :only => :destroy, :render => {:nothing => true, :status => :method_not_allowed }
163 verify :method => :delete, :only => :destroy, :render => {:nothing => true, :status => :method_not_allowed }
165 def destroy
164 def destroy
166 if @version.fixed_issues.empty?
165 if @version.fixed_issues.empty?
167 @version.destroy
166 @version.destroy
168 respond_to do |format|
167 respond_to do |format|
169 format.html { redirect_back_or_default :controller => 'projects', :action => 'settings', :tab => 'versions', :id => @project }
168 format.html { redirect_back_or_default :controller => 'projects', :action => 'settings', :tab => 'versions', :id => @project }
170 format.api { head :ok }
169 format.api { head :ok }
171 end
170 end
172 else
171 else
173 respond_to do |format|
172 respond_to do |format|
174 format.html {
173 format.html {
175 flash[:error] = l(:notice_unable_delete_version)
174 flash[:error] = l(:notice_unable_delete_version)
176 redirect_to :controller => 'projects', :action => 'settings', :tab => 'versions', :id => @project
175 redirect_to :controller => 'projects', :action => 'settings', :tab => 'versions', :id => @project
177 }
176 }
178 format.api { head :unprocessable_entity }
177 format.api { head :unprocessable_entity }
179 end
178 end
180 end
179 end
181 end
180 end
182
181
183 def status_by
182 def status_by
184 respond_to do |format|
183 respond_to do |format|
185 format.html { render :action => 'show' }
184 format.html { render :action => 'show' }
186 format.js { render(:update) {|page| page.replace_html 'status_by', render_issue_status_by(@version, params[:status_by])} }
185 format.js { render(:update) {|page| page.replace_html 'status_by', render_issue_status_by(@version, params[:status_by])} }
187 end
186 end
188 end
187 end
189
188
190 private
189 private
191 def find_project
190 def find_project
192 @project = Project.find(params[:project_id])
191 @project = Project.find(params[:project_id])
193 rescue ActiveRecord::RecordNotFound
192 rescue ActiveRecord::RecordNotFound
194 render_404
193 render_404
195 end
194 end
196
195
197 def retrieve_selected_tracker_ids(selectable_trackers, default_trackers=nil)
196 def retrieve_selected_tracker_ids(selectable_trackers, default_trackers=nil)
198 if ids = params[:tracker_ids]
197 if ids = params[:tracker_ids]
199 @selected_tracker_ids = (ids.is_a? Array) ? ids.collect { |id| id.to_i.to_s } : ids.split('/').collect { |id| id.to_i.to_s }
198 @selected_tracker_ids = (ids.is_a? Array) ? ids.collect { |id| id.to_i.to_s } : ids.split('/').collect { |id| id.to_i.to_s }
200 else
199 else
201 @selected_tracker_ids = (default_trackers || selectable_trackers).collect {|t| t.id.to_s }
200 @selected_tracker_ids = (default_trackers || selectable_trackers).collect {|t| t.id.to_s }
202 end
201 end
203 end
202 end
204
203
205 end
204 end
General Comments 0
You need to be logged in to leave comments. Login now