Feature #465 » veersion_inheritance.patch
app/controllers/issues_controller.rb Sun Jun 15 14:27:25 2008 +0200 → app/controllers/issues_controller.rb Fri Jun 27 13:12:14 2008 +0200 | ||
---|---|---|
20 | 20 |
menu_item :new_issue, :only => :new |
21 | 21 |
|
22 | 22 |
before_filter :find_issue, :only => [:show, :edit, :destroy_attachment] |
23 |
before_filter :check_issue_perms, :only => [:show, :edit] |
|
23 | 24 |
before_filter :find_issues, :only => [:bulk_edit, :move, :destroy] |
24 | 25 |
before_filter :find_project, :only => [:new, :update_form, :preview] |
25 | 26 |
before_filter :authorize, :except => [:index, :changes, :preview, :update_form, :context_menu] |
... | ... | |
28 | 29 | |
29 | 30 |
helper :journals |
30 | 31 |
helper :projects |
31 |
include ProjectsHelper
|
|
32 |
include ProjectsHelper |
|
32 | 33 |
helper :custom_fields |
33 | 34 |
include CustomFieldsHelper |
34 | 35 |
helper :ifpdf |
... | ... | |
63 | 64 |
:conditions => @query.statement, |
64 | 65 |
:limit => limit, |
65 | 66 |
:offset => @issue_pages.current.offset |
67 |
@issues.map!{ |issue| issue_without_hidden_fields(issue) } # don't show forbidden fields |
|
66 | 68 |
respond_to do |format| |
67 | 69 |
format.html { render :template => 'issues/index.rhtml', :layout => !request.xhr? } |
68 | 70 |
format.atom { render_feed(@issues, :title => l(:label_issue_plural)) } |
... | ... | |
100 | 102 |
@journals.reverse! if User.current.wants_comments_in_reverse_order? |
101 | 103 |
@allowed_statuses = @issue.new_statuses_allowed_to(User.current) |
102 | 104 |
@edit_allowed = User.current.allowed_to?(:edit_issues, @project) |
105 |
@issue = issue_without_hidden_fields(@issue) |
|
106 |
@journals = journals_without_hidden_entries(@journals) |
|
103 | 107 |
@activities = Enumeration::get_values('ACTI') |
104 | 108 |
@priorities = Enumeration::get_values('IPRI') |
105 | 109 |
@time_entry = TimeEntry.new |
... | ... | |
388 | 392 |
render_404 |
389 | 393 |
end |
390 | 394 |
|
395 |
|
|
396 | ||
397 |
def issue_fixed_version_allowed?(issue) |
|
398 |
((not issue.fixed_version) || |
|
399 |
(User.current.allowed_to?(:view_issues, |
|
400 |
issue.fixed_version.project))) |
|
401 |
end |
|
402 | ||
403 |
def check_issue_perms |
|
404 |
@forbidden_fixed_version = (not issue_fixed_version_allowed?(@issue)) |
|
405 |
end |
|
406 | ||
407 |
## Filter journals to remove non allowed entries. This assumes there |
|
408 |
## is only 1 parent, so it won't work with more depth. We want here |
|
409 |
## to handle the _specific case_ of a user 'Joe' browsing 'Project |
|
410 |
## B' issues. 'Project B' is a subproject of 'Project A' and |
|
411 |
## inherits its versions. Joe can't see 'Project A, but issue |
|
412 |
## fixed_versions has been set at some point to a version belonging |
|
413 |
## to 'Project A', by an other member of 'Project B'. Joe should not |
|
414 |
## see this sensitive information. |
|
415 |
def journals_without_hidden_entries(journals) |
|
416 |
unless (journals.empty? || (not @project.parent_id) || |
|
417 |
(@project.parent_id && User.current.allowed_to?(:view_issues, @project.parent))) |
|
418 |
journals = journals.dup |
|
419 |
# we kill totally the journal entry when some of its elements are forbidden |
|
420 |
journals.delete_if do |j| |
|
421 |
j.details.map{ |d| (d.property == 'attr' && |
|
422 |
d.prop_key == 'fixed_version_id' && |
|
423 |
((d.old_value && |
|
424 |
(@project.parent_id == Version.find(d.old_value.to_i).project_id)) || |
|
425 |
(d.value && |
|
426 |
(@project.parent_id == Version.find(d.value.to_i).project_id))) |
|
427 |
) }.include?(true) |
|
428 |
end |
|
429 |
end |
|
430 |
journals |
|
431 |
end |
|
432 | ||
433 |
## Filter issue to remove non allowed fields. For more information, |
|
434 |
## see documentation of journals_without_hidden_entries |
|
435 |
def issue_without_hidden_fields(issue) |
|
436 |
unless issue_fixed_version_allowed?(issue) |
|
437 |
issue = issue.dup |
|
438 |
issue.fixed_version = nil |
|
439 |
end |
|
440 |
issue |
|
441 |
end |
|
442 | ||
391 | 443 |
# Retrieve query from session or build a new query |
392 | 444 |
def retrieve_query |
393 | 445 |
if !params[:query_id].blank? |
app/controllers/projects_controller.rb Sun Jun 15 14:27:25 2008 +0200 → app/controllers/projects_controller.rb Fri Jun 27 13:12:14 2008 +0200 | ||
---|---|---|
195 | 195 | |
196 | 196 |
def add_file |
197 | 197 |
if request.post? |
198 |
@version = @project.versions.find_by_id(params[:version_id]) |
|
198 |
@version = @project.related_versions.find_by_id(params[:version_id])
|
|
199 | 199 |
attachments = attach_files(@version, params[:attachments]) |
200 | 200 |
Mailer.deliver_attachments_added(attachments) if !attachments.empty? && Setting.notified_events.include?('file_added') |
201 | 201 |
redirect_to :controller => 'projects', :action => 'list_files', :id => @project |
202 | 202 |
end |
203 |
@versions = @project.versions.sort |
|
203 |
@versions = @project.related_versions.sort
|
|
204 | 204 |
end |
205 | 205 |
|
206 | 206 |
def list_files |
207 | 207 |
sort_init "#{Attachment.table_name}.filename", "asc" |
208 | 208 |
sort_update |
209 |
@versions = @project.versions.find(:all, :include => :attachments, :order => sort_clause).sort.reverse |
|
209 |
@versions = @project.related_versions.find(:all, :include => :attachments, :order => sort_clause).sort.reverse
|
|
210 | 210 |
render :layout => !request.xhr? |
211 | 211 |
end |
212 | 212 |
|
... | ... | |
214 | 214 |
def changelog |
215 | 215 |
@trackers = @project.trackers.find(:all, :conditions => ["is_in_chlog=?", true], :order => 'position') |
216 | 216 |
retrieve_selected_tracker_ids(@trackers) |
217 |
@versions = @project.versions.sort |
|
217 |
@versions = @project.related_versions.sort
|
|
218 | 218 |
end |
219 | 219 | |
220 | 220 |
def roadmap |
221 | 221 |
@trackers = @project.trackers.find(:all, :conditions => ["is_in_roadmap=?", true]) |
222 | 222 |
retrieve_selected_tracker_ids(@trackers) |
223 |
@versions = @project.versions.sort
|
|
224 |
@versions = @versions.select {|v| !v.completed? } unless params[:completed]
|
|
223 |
# retrieve_related_versions could be integrated right here.
|
|
224 |
@versions = retrieve_related_versions
|
|
225 | 225 |
end |
226 | 226 |
|
227 | 227 |
def activity |
... | ... | |
342 | 342 |
:conditions => ["((start_date BETWEEN ? AND ?) OR (due_date BETWEEN ? AND ?)) AND #{Issue.table_name}.tracker_id IN (#{@selected_tracker_ids.join(',')})", @calendar.startdt, @calendar.enddt, @calendar.startdt, @calendar.enddt] |
343 | 343 |
) unless @selected_tracker_ids.empty? |
344 | 344 |
events += Version.find(:all, :include => :project, |
345 |
:conditions => ["effective_date BETWEEN ? AND ?", @calendar.startdt, @calendar.enddt])
|
|
345 |
:conditions => { :effective_date => @calendar.startdt..@calendar.enddt})
|
|
346 | 346 |
end |
347 |
# add parent versions if relevant |
|
348 |
events += @project.related_versions.select{ |v| ((v.project_id == @project.parent_id) && |
|
349 |
v.effective_date) } |
|
350 |
|
|
347 | 351 |
@calendar.events = events |
348 | 352 |
|
349 | 353 |
render :layout => false if request.xhr? |
... | ... | |
390 | 394 |
@events += Version.find(:all, :include => :project, |
391 | 395 |
:conditions => ["effective_date BETWEEN ? AND ?", @date_from, @date_to]) |
392 | 396 |
end |
397 |
|
|
398 |
# add parent versions if relevant |
|
399 |
@events += @project.related_versions.select{ |v| ((v.project_id == @project.parent_id) && |
|
400 |
v.effective_date) } |
|
401 |
|
|
393 | 402 |
@events.sort! {|x,y| x.start_date <=> y.start_date } |
394 | 403 |
|
395 | 404 |
if params[:format]=='pdf' |
... | ... | |
423 | 432 |
render_404 |
424 | 433 |
end |
425 | 434 | |
435 |
def retrieve_related_versions |
|
436 |
related_versions=@project.related_versions |
|
437 |
# should this test be moved to projects_helper.rb : version_visible_issues ? |
|
438 |
params[:completed] ? related_versions : related_versions.select {|v| !v.completed? } |
|
439 |
end |
|
440 | ||
426 | 441 |
def retrieve_selected_tracker_ids(selectable_trackers) |
427 | 442 |
if ids = params[:tracker_ids] |
428 | 443 |
@selected_tracker_ids = (ids.is_a? Array) ? ids.collect { |id| id.to_i.to_s } : ids.split('/').collect { |id| id.to_i.to_s } |
app/controllers/reports_controller.rb Sun Jun 15 14:27:25 2008 +0200 → app/controllers/reports_controller.rb Fri Jun 27 13:12:14 2008 +0200 | ||
---|---|---|
32 | 32 |
render :template => "reports/issue_report_details" |
33 | 33 |
when "version" |
34 | 34 |
@field = "fixed_version_id" |
35 |
@rows = @project.versions.sort |
|
35 |
@rows = @project.related_versions.sort
|
|
36 | 36 |
@data = issues_by_version |
37 | 37 |
@report_title = l(:field_version) |
38 | 38 |
render :template => "reports/issue_report_details" |
... | ... | |
68 | 68 |
render :template => "reports/issue_report_details" |
69 | 69 |
else |
70 | 70 |
@trackers = @project.trackers |
71 |
@versions = @project.versions.sort |
|
71 |
@versions = @project.related_versions.sort
|
|
72 | 72 |
@priorities = Enumeration::get_values('IPRI') |
73 | 73 |
@categories = @project.issue_categories |
74 | 74 |
@assignees = @project.members.collect { |m| m.user } |
app/controllers/versions_controller.rb Sun Jun 15 14:27:25 2008 +0200 → app/controllers/versions_controller.rb Fri Jun 27 13:12:14 2008 +0200 | ||
---|---|---|
20 | 20 |
menu_item :roadmap |
21 | 21 |
before_filter :find_project, :authorize |
22 | 22 | |
23 |
helper :projects |
|
24 |
include ProjectsHelper |
|
25 | ||
23 | 26 |
def show |
27 |
@issues = version_visible_issues(@version,@project,@project.tracker_ids) |
|
24 | 28 |
end |
25 | 29 |
|
26 | 30 |
def edit |
app/helpers/projects_helper.rb Sun Jun 15 14:27:25 2008 +0200 → app/helpers/projects_helper.rb Fri Jun 27 13:12:14 2008 +0200 | ||
---|---|---|
46 | 46 |
tabs.select {|tab| User.current.allowed_to?(tab[:action], @project)} |
47 | 47 |
end |
48 | 48 |
|
49 |
## return an array of the issues attached to version that a user should see |
|
50 |
## As a convenience, allow limitation by trackers with Array of tracker_ids |
|
51 |
def version_visible_issues(version,project,tracker_ids=[],user=User.current) |
|
52 |
# Returns void when user can not see issues or if tracker_ids is void |
|
53 |
return [] if ((not user.allowed_to?(:view_issues, |
|
54 |
version.project)) or |
|
55 |
tracker_ids.empty?) |
|
56 |
# user can see project issues, carry on, retrieve them ... |
|
57 |
issues = version. |
|
58 |
fixed_issues.find(:all, |
|
59 |
:include => [:status, :tracker], |
|
60 |
:conditions => ["tracker_id in (#{tracker_ids.join(',')})"], |
|
61 |
:order => "#{Tracker.table_name}.position, #{Issue.table_name}.id") |
|
62 |
# Only keep issues from self, parent or children, |
|
63 |
related_projects=[project.id].concat(project.child_ids) # project and children |
|
64 |
related_projects.push project.parent.id if project.parent # parent if relevant |
|
65 |
related_projects = related_projects.select{|x| user.allowed_to?(:view_issues, Project.find(x))} |
|
66 |
# now only keep related issues. (issues from brother projects are discarded) |
|
67 |
issues.select {|x| related_projects.include?(x.project.id) } |
|
68 |
end |
|
69 | ||
49 | 70 |
# Generates a gantt image |
50 | 71 |
# Only defined if RMagick is avalaible |
51 | 72 |
def gantt_image(events, date_from, months, zoom) |
app/models/project.rb Sun Jun 15 14:27:25 2008 +0200 → app/models/project.rb Fri Jun 27 13:12:14 2008 +0200 | ||
---|---|---|
237 | 237 |
end |
238 | 238 |
end |
239 | 239 | |
240 |
## Return versions attached to self, and to parent if relevant. |
|
241 |
## Sorting is done in the SQL request to take advantage of cache |
|
242 |
def related_versions(user=User.current) |
|
243 |
Version.find(:all, |
|
244 |
:conditions => {:project_id => if self.parent && |
|
245 |
user.allowed_to?(:view_issues, |
|
246 |
self.parent) then |
|
247 |
[self.id, self.parent_id] |
|
248 |
else [self.id]; end}, |
|
249 |
:order => "effective_date ASC, name ASC ") |
|
250 |
end |
|
251 | ||
240 | 252 |
protected |
241 | 253 |
def validate |
242 | 254 |
errors.add(parent_id, " must be a root project") if parent and parent.parent |
app/models/query.rb Sun Jun 15 14:27:25 2008 +0200 → app/models/query.rb Fri Jun 27 13:12:14 2008 +0200 | ||
---|---|---|
168 | 168 |
if project |
169 | 169 |
# project specific filters |
170 | 170 |
@available_filters["category_id"] = { :type => :list_optional, :order => 6, :values => @project.issue_categories.collect{|s| [s.name, s.id.to_s] } } |
171 |
@available_filters["fixed_version_id"] = { :type => :list_optional, :order => 7, :values => @project.versions.sort.collect{|s| [s.name, s.id.to_s] } } |
|
171 |
@available_filters["fixed_version_id"] = { :type => :list_optional, :order => 7, :values => @project.related_versions.sort.collect{|s| [s.name, s.id.to_s] } }
|
|
172 | 172 |
unless @project.active_children.empty? |
173 | 173 |
@available_filters["subproject_id"] = { :type => :list_subprojects, :order => 13, :values => @project.active_children.collect{|s| [s.name, s.id.to_s] } } |
174 | 174 |
end |
app/views/issues/_form.rhtml Sun Jun 15 14:27:25 2008 +0200 → app/views/issues/_form.rhtml Fri Jun 27 13:12:14 2008 +0200 | ||
---|---|---|
29 | 29 |
l(:label_issue_category_new), 'category[name]', |
30 | 30 |
{:controller => 'projects', :action => 'add_issue_category', :id => @project}, |
31 | 31 |
:class => 'small', :tabindex => 199) if authorize_for('projects', 'add_issue_category') %></p> |
32 |
<%= content_tag('p', f.select(:fixed_version_id, |
|
33 |
(@project.versions.sort.collect {|v| [v.name, v.id]}), |
|
34 |
{ :include_blank => true })) unless @project.versions.empty? %> |
|
32 |
<%= unless (@project.related_versions.empty? || @forbidden_fixed_version) then |
|
33 |
content_tag('p', f.select(:fixed_version_id, |
|
34 |
(@project.related_versions.sort.collect {|v| [v.name, v.id]}), |
|
35 |
{ :include_blank => true })) |
|
36 |
end %> |
|
35 | 37 |
</div> |
36 | 38 | |
37 | 39 |
<div class="splitcontentright"> |
app/views/issues/_form_update.rhtml Sun Jun 15 14:27:25 2008 +0200 → app/views/issues/_form_update.rhtml Fri Jun 27 13:12:14 2008 +0200 | ||
---|---|---|
4 | 4 |
</div> |
5 | 5 |
<div class="splitcontentright"> |
6 | 6 |
<p><%= f.select :done_ratio, ((0..10).to_a.collect {|r| ["#{r*10} %", r*10] }) %></p> |
7 |
<%= content_tag('p', f.select(:fixed_version_id, |
|
8 |
(@project.versions.sort.collect {|v| [v.name, v.id]}), |
|
9 |
{ :include_blank => true })) unless @project.versions.empty? %> |
|
7 |
<%= unless (@issue.fixed_version && |
|
8 |
(not User.current.allowed_to?(:view_issues, |
|
9 |
@issue.fixed_version.project)) || |
|
10 |
@project.related_versions.empty?) then |
|
11 |
content_tag('p', f.select(:fixed_version_id, |
|
12 |
(@project.related_versions.sort.collect {|v| [v.name, v.id]}), |
|
13 |
{ :include_blank => true })) |
|
14 |
end %> |
|
10 | 15 |
</div> |
app/views/issues/_pdf.rfpdf Sun Jun 15 14:27:25 2008 +0200 → app/views/issues/_pdf.rfpdf Fri Jun 27 13:12:14 2008 +0200 | ||
---|---|---|
86 | 86 |
pdf.SetFontStyle('B',9) |
87 | 87 |
pdf.Cell(190,5, l(:label_history), "B") |
88 | 88 |
pdf.Ln |
89 |
for journal in issue.journals.find(:all, :include => [:user, :details], :order => "#{Journal.table_name}.created_on ASC")
|
|
89 |
for journal in @journals
|
|
90 | 90 |
pdf.SetFontStyle('B',8) |
91 | 91 |
pdf.Cell(190,5, format_time(journal.created_on) + " - " + journal.user.name) |
92 | 92 |
pdf.Ln |
app/views/issues/bulk_edit.rhtml Sun Jun 15 14:27:25 2008 +0200 → app/views/issues/bulk_edit.rhtml Fri Jun 27 13:12:14 2008 +0200 | ||
---|---|---|
27 | 27 |
<label><%= l(:field_fixed_version) %>: |
28 | 28 |
<%= select_tag('fixed_version_id', content_tag('option', l(:label_no_change_option), :value => '') + |
29 | 29 |
content_tag('option', l(:label_none), :value => 'none') + |
30 |
options_from_collection_for_select(@project.versions, :id, :name)) %></label> |
|
30 |
options_from_collection_for_select(@project.related_versions, :id, :name)) %></label>
|
|
31 | 31 |
</p> |
32 | 32 | |
33 | 33 |
<p> |
app/views/projects/roadmap.rhtml Sun Jun 15 14:27:25 2008 +0200 → app/views/projects/roadmap.rhtml Fri Jun 27 13:12:14 2008 +0200 | ||
---|---|---|
1 | 1 |
<h2><%=l(:label_roadmap)%></h2> |
2 | 2 | |
3 | 3 |
<% if @versions.empty? %> |
4 |
<p class="nodata"><%= l(:label_no_data) %></p> |
|
4 |
<p class="nodata"><%= l(:label_no_data) %></p>
|
|
5 | 5 |
<% else %> |
6 |
<div id="roadmap"> |
|
7 |
<% @versions.each do |version| %> |
|
8 |
<%= tag 'a', :name => version.name %> |
|
9 |
<h3 class="icon22 icon22-package"><%= link_to h(version.name), :controller => 'versions', :action => 'show', :id => version %></h3> |
|
10 |
<%= render :partial => 'versions/overview', :locals => {:version => version} %> |
|
11 |
<%= render(:partial => "wiki/content", :locals => {:content => version.wiki_page.content}) if version.wiki_page %> |
|
12 | ||
13 |
<% issues = version.fixed_issues.find(:all, |
|
14 |
:include => [:status, :tracker], |
|
15 |
:conditions => ["tracker_id in (#{@selected_tracker_ids.join(',')})"], |
|
16 |
:order => "#{Tracker.table_name}.position, #{Issue.table_name}.id") unless @selected_tracker_ids.empty? |
|
17 |
issues ||= [] |
|
18 |
%> |
|
19 |
<% if issues.size > 0 %> |
|
20 |
<fieldset class="related-issues"><legend><%= l(:label_related_issues) %></legend> |
|
21 |
<ul> |
|
22 |
<%- issues.each do |issue| -%> |
|
23 |
<li class="issue <%= 'closed' if issue.closed? %>"><%= link_to_issue(issue) %>: <%=h issue.subject %></li> |
|
24 |
<%- end -%> |
|
25 |
</ul> |
|
26 |
</fieldset> |
|
6 |
<div id="roadmap"> |
|
7 |
<% @versions.each do |version| %> |
|
8 |
<% issues = version_visible_issues(version,@project,@selected_tracker_ids) %> |
|
9 |
<% next if (version.project.id != @project.id && issues.empty?) %> |
|
10 |
<%= tag 'a', :name => version.name %> |
|
11 |
<h3 class="icon22 icon22-package"><%= link_to h(version.name), :controller => 'versions', :action => 'show', :id => version %></h3> |
|
12 |
<%= render :partial => 'versions/overview', :locals => {:version => version} %> |
|
13 |
<%= render(:partial => "wiki/content", :locals => {:content => version.wiki_page.content}) if version.wiki_page %> |
|
14 |
|
|
15 |
<% if issues.size > 0 %> |
|
16 |
<fieldset class="related-issues"><legend><%= l(:label_related_issues) %></legend> |
|
17 |
<ul> |
|
18 |
<%- issues.each do |issue| -%> |
|
19 |
<li class="issue <%= 'closed' if issue.closed? %>"> |
|
20 |
<%= link_to_issue(issue) %>: |
|
21 |
<%=h issue.subject %> |
|
22 |
<%= (" <em>(" + issue.project.name + ")</em>") unless issue.project.id == @project.id %> |
|
23 |
</li> |
|
24 |
<%- end -%> |
|
25 |
</ul> |
|
26 |
</fieldset> |
|
27 |
<% end %> |
|
28 |
<% end %> |
|
29 |
</div> |
|
30 |
<% end %> |
|
31 |
|
|
32 |
<% content_for :sidebar do %> |
|
33 |
<% form_tag do %> |
|
34 |
<h3><%= l(:label_roadmap) %></h3> |
|
35 |
<% @trackers.each do |tracker| %> |
|
36 |
<label><%= check_box_tag "tracker_ids[]", tracker.id, (@selected_tracker_ids.include? tracker.id.to_s), :id => nil %> |
|
37 |
<%= tracker.name %></label><br /> |
|
38 |
<% end %> |
|
39 |
<br /> |
|
40 |
<label for="completed"><%= check_box_tag "completed", 1, params[:completed] %> <%= l(:label_show_completed_versions) %></label> |
|
41 |
<p><%= submit_tag l(:button_apply), :class => 'button-small' %></p> |
|
27 | 42 |
<% end %> |
28 |
<% end %> |
|
29 |
</div> |
|
30 |
<% end %> |
|
31 | ||
32 |
<% content_for :sidebar do %> |
|
33 |
<% form_tag do %> |
|
34 |
<h3><%= l(:label_roadmap) %></h3> |
|
35 |
<% @trackers.each do |tracker| %> |
|
36 |
<label><%= check_box_tag "tracker_ids[]", tracker.id, (@selected_tracker_ids.include? tracker.id.to_s), :id => nil %> |
|
37 |
<%= tracker.name %></label><br /> |
|
38 |
<% end %> |
|
39 |
<br /> |
|
40 |
<label for="completed"><%= check_box_tag "completed", 1, params[:completed] %> <%= l(:label_show_completed_versions) %></label> |
|
41 |
<p><%= submit_tag l(:button_apply), :class => 'button-small' %></p> |
|
42 |
<% end %> |
|
43 | ||
44 |
<h3><%= l(:label_version_plural) %></h3> |
|
45 |
<% @versions.each do |version| %> |
|
46 |
<%= link_to version.name, "##{version.name}" %><br /> |
|
47 |
<% end %> |
|
48 |
<% end %> |
|
49 | ||
50 |
<% html_title(l(:label_roadmap)) %> |
|
43 |
|
|
44 |
<h3><%= l(:label_version_plural) %></h3> |
|
45 |
<% @versions.each do |version| %> |
|
46 |
<%= link_to version.name, "##{version.name}" %><br /> |
|
47 |
<% end %> |
|
48 |
<% end %> |
|
49 |
|
|
50 |
<% html_title(l(:label_roadmap)) %> |
app/views/versions/show.rhtml Sun Jun 15 14:27:25 2008 +0200 → app/views/versions/show.rhtml Fri Jun 27 13:12:14 2008 +0200 | ||
---|---|---|
31 | 31 |
<%= render :partial => 'versions/overview', :locals => {:version => @version} %> |
32 | 32 |
<%= render(:partial => "wiki/content", :locals => {:content => @version.wiki_page.content}) if @version.wiki_page %> |
33 | 33 | |
34 |
<% issues = @version.fixed_issues.find(:all, |
|
35 |
:include => [:status, :tracker], |
|
36 |
:order => "#{Tracker.table_name}.position, #{Issue.table_name}.id") %> |
|
37 |
<% if issues.size > 0 %> |
|
34 |
<% if @issues.size > 0 %> |
|
38 | 35 |
<fieldset class="related-issues"><legend><%= l(:label_related_issues) %></legend> |
39 | 36 |
<ul> |
40 |
<% issues.each do |issue| -%> |
|
41 |
<li class="issue <%= 'closed' if issue.closed? %>"><%= link_to_issue(issue) %>: <%=h issue.subject %></li> |
|
37 |
<% @issues.each do |issue| -%> |
|
38 |
<li class="issue <%= 'closed' if issue.closed? %>"> |
|
39 |
<%= link_to_issue(issue) %>: <%=h issue.subject %> |
|
40 |
<%= (" <em>(" + issue.project.name + ")</em>") unless issue.project.id == @project.id %> |
|
41 |
</li> |
|
42 | 42 |
<% end -%> |
43 | 43 |
</ul> |
44 | 44 |
</fieldset> |
lib/redmine.rb Sun Jun 15 14:27:25 2008 +0200 → lib/redmine.rb Fri Jun 27 13:12:14 2008 +0200 | ||
---|---|---|
116 | 116 |
menu.push :overview, { :controller => 'projects', :action => 'show' } |
117 | 117 |
menu.push :activity, { :controller => 'projects', :action => 'activity' } |
118 | 118 |
menu.push :roadmap, { :controller => 'projects', :action => 'roadmap' }, |
119 |
:if => Proc.new { |p| p.versions.any? } |
|
119 |
:if => Proc.new { |p| p.related_versions.any? }
|
|
120 | 120 |
menu.push :issues, { :controller => 'issues', :action => 'index' }, :param => :project_id, :caption => :label_issue_plural |
121 | 121 |
menu.push :new_issue, { :controller => 'issues', :action => 'new' }, :param => :project_id, :caption => :label_issue_new, |
122 | 122 |
:html => { :accesskey => Redmine::AccessKeys.key_for(:new_issue) } |