##// END OF EJS Templates
Added version details view accessible from the roadmap....
Jean-Philippe Lang -
r942:3c44aac1f50c
parent child
Show More
@@ -0,0 +1,35
1 <form id="status_by_form">
2 <fieldset>
3 <legend>
4 <%= l(:label_issues_by,
5 select_tag('status_by',
6 status_by_options_for_select(criteria),
7 :id => 'status_by_select',
8 :onchange => remote_function(:url => { :action => :status_by, :id => version },
9 :with => "Form.serialize('status_by_form')"))) %>
10 </legend>
11 <% if counts.empty? %>
12 <p><em><%= l(:label_no_data) %></em></p>
13 <% else %>
14 <table>
15 <% counts.each do |count| %>
16 <tr>
17 <td width="130px" align="right" >
18 <%= link_to count[:group], {:controller => 'issues',
19 :action => 'index',
20 :project_id => version.project,
21 :set_filter => 1,
22 :fixed_version_id => version,
23 "#{criteria}_id" => count[:group]} %>
24 </td>
25 <td width="240px">
26 <%= progress_bar((count[:closed].to_f / count[:total])*100,
27 :legend => "#{count[:closed]}/#{count[:total]}",
28 :width => "#{(count[:total].to_f / max * 200).floor}px;") %>
29 </td>
30 </tr>
31 <% end %>
32 </table>
33 <% end %>
34 </fieldset>
35 </form>
@@ -0,0 +1,24
1 <% if version.completed? %>
2 <p><%= format_date(version.effective_date) %></p>
3 <% elsif version.overdue? %>
4 <p><strong><%= l(:label_roadmap_overdue, distance_of_time_in_words(Time.now, version.effective_date)) %> (<%= format_date(version.effective_date) %>)</strong></p>
5 <% elsif version.effective_date %>
6 <p><strong><%=l(:label_roadmap_due_in)%> <%= distance_of_time_in_words Time.now, version.effective_date %> (<%= format_date(version.effective_date) %>)</strong></p>
7 <% end %>
8
9 <p><%=h version.description %></p>
10
11 <% if version.fixed_issues.count > 0 %>
12 <%= progress_bar([version.closed_pourcent, version.completed_pourcent], :width => '40em', :legend => ('%0.0f%' % version.completed_pourcent)) %>
13 <p class="progress-info">
14 <%= link_to(version.closed_issues_count, :controller => 'issues', :action => 'index', :project_id => version.project, :status_id => 'c', :fixed_version_id => version, :set_filter => 1) %>
15 <%= lwr(:label_closed_issues, version.closed_issues_count) %>
16 (<%= '%0.0f' % (version.closed_issues_count.to_f / version.fixed_issues.count * 100) %>%)
17 &#160;
18 <%= link_to(version.open_issues_count, :controller => 'issues', :action => 'index', :project_id => version.project, :status_id => 'o', :fixed_version_id => version, :set_filter => 1) %>
19 <%= lwr(:label_open_issues, version.open_issues_count)%>
20 (<%= '%0.0f' % (version.open_issues_count.to_f / version.fixed_issues.count * 100) %>%)
21 </p>
22 <% else %>
23 <p><em><%= l(:label_roadmap_no_issues) %></em></p>
24 <% end %>
@@ -0,0 +1,14
1 <div class="contextual">
2 <%= link_to_if_authorized l(:button_edit), {:controller => 'versions', :action => 'edit', :id => @version}, :class => 'icon icon-edit' %>
3 </div>
4
5 <h2><%= h(@version.name) %></h2>
6
7 <div id="status_by" style="float:right;">
8 <%= render_issue_status_by(@version, params[:status_by]) if @version.fixed_issues.count > 0 %>
9 </div>
10
11 <%= render :partial => 'versions/overview', :locals => {:version => @version} %>
12 <%= render(:partial => "wiki/content", :locals => {:content => @version.wiki_page.content}) if @version.wiki_page %>
13
14 <% set_html_title h(@version.name) %>
@@ -0,0 +1,42
1 # redMine - project management software
2 # Copyright (C) 2006-2007 Jean-Philippe Lang
3 #
4 # This program is free software; you can redistribute it and/or
5 # modify it under the terms of the GNU General Public License
6 # as published by the Free Software Foundation; either version 2
7 # of the License, or (at your option) any later version.
8 #
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
13 #
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
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17
18 require File.dirname(__FILE__) + '/../test_helper'
19 require 'versions_controller'
20
21 # Re-raise errors caught by the controller.
22 class VersionsController; def rescue_action(e) raise e end; end
23
24 class VersionsControllerTest < Test::Unit::TestCase
25 fixtures :projects, :versions, :users, :roles, :members, :enabled_modules
26
27 def setup
28 @controller = VersionsController.new
29 @request = ActionController::TestRequest.new
30 @response = ActionController::TestResponse.new
31 User.current = nil
32 end
33
34 def test_show
35 get :show, :id => 2
36 assert_response :success
37 assert_template 'show'
38 assert_not_nil assigns(:version)
39
40 assert_tag :tag => 'h2', :content => /1.0/
41 end
42 end
@@ -21,6 +21,9 class VersionsController < ApplicationController
21
21
22 cache_sweeper :version_sweeper, :only => [ :edit, :destroy ]
22 cache_sweeper :version_sweeper, :only => [ :edit, :destroy ]
23
23
24 def show
25 end
26
24 def edit
27 def edit
25 if request.post? and @version.update_attributes(params[:version])
28 if request.post? and @version.update_attributes(params[:version])
26 flash[:notice] = l(:notice_successful_update)
29 flash[:notice] = l(:notice_successful_update)
@@ -49,6 +52,13 class VersionsController < ApplicationController
49 flash[:notice] = l(:notice_successful_delete)
52 flash[:notice] = l(:notice_successful_delete)
50 redirect_to :controller => 'projects', :action => 'list_files', :id => @project
53 redirect_to :controller => 'projects', :action => 'list_files', :id => @project
51 end
54 end
55
56 def status_by
57 respond_to do |format|
58 format.html { render :action => 'show' }
59 format.js { render(:update) {|page| page.replace_html 'status_by', render_issue_status_by(@version, params[:status_by])} }
60 end
61 end
52
62
53 private
63 private
54 def find_project
64 def find_project
@@ -16,4 +16,32
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 VersionsHelper
18 module VersionsHelper
19
20 STATUS_BY_CRITERIAS = %w(category tracker priority author assigned_to)
21
22 def render_issue_status_by(version, criteria)
23 criteria ||= 'category'
24 raise 'Unknown criteria' unless STATUS_BY_CRITERIAS.include?(criteria)
25
26 h = Hash.new {|k,v| k[v] = [0, 0]}
27 begin
28 # Total issue count
29 Issue.count(:group => criteria,
30 :conditions => ["#{Issue.table_name}.fixed_version_id = ?", version.id]).each {|c,s| h[c][0] = s}
31 # Open issues count
32 Issue.count(:group => criteria,
33 :include => :status,
34 :conditions => ["#{Issue.table_name}.fixed_version_id = ? AND #{IssueStatus.table_name}.is_closed = ?", version.id, false]).each {|c,s| h[c][1] = s}
35 rescue ActiveRecord::RecordNotFound
36 # When grouping by an association, Rails throws this exception if there's no result (bug)
37 end
38 counts = h.keys.compact.sort.collect {|k| {:group => k, :total => h[k][0], :open => h[k][1], :closed => (h[k][0] - h[k][1])}}
39 max = counts.collect {|c| c[:total]}.max
40
41 render :partial => 'issue_counts', :locals => {:version => version, :criteria => criteria, :counts => counts, :max => max}
42 end
43
44 def status_by_options_for_select(value)
45 options_for_select(STATUS_BY_CRITERIAS.collect {|criteria| [l("field_#{criteria}".to_sym), criteria]}, value)
46 end
19 end
47 end
@@ -35,5 +35,9 class IssueCategory < ActiveRecord::Base
35 destroy_without_reassign
35 destroy_without_reassign
36 end
36 end
37
37
38 def <=>(category)
39 name <=> category.name
40 end
41
38 def to_s; name end
42 def to_s; name end
39 end
43 end
@@ -29,6 +29,10 class Tracker < ActiveRecord::Base
29
29
30 def to_s; name end
30 def to_s; name end
31
31
32 def <=>(tracker)
33 name <=> tracker.name
34 end
35
32 def self.all
36 def self.all
33 find(:all, :order => 'position')
37 find(:all, :order => 'position')
34 end
38 end
@@ -5,48 +5,28
5 <% end %>
5 <% end %>
6
6
7 <% @versions.each do |version| %>
7 <% @versions.each do |version| %>
8 <a name="<%= version.name %>"><h3 class="icon22 icon22-package"><%= version.name %></h3></a>
8 <%= tag 'a', :name => version.name %>
9 <% if version.completed? %>
9 <h3 class="icon22 icon22-package"><%= link_to h(version.name), :controller => 'versions', :action => 'show', :id => version %></h3>
10 <p><%= format_date(version.effective_date) %></p>
10 <%= render :partial => 'versions/overview', :locals => {:version => version} %>
11 <% elsif version.overdue? %>
11 <%= render(:partial => "wiki/content", :locals => {:content => version.wiki_page.content}) if version.wiki_page %>
12 <p><strong><%= l(:label_roadmap_overdue, distance_of_time_in_words(Time.now, version.effective_date)) %> (<%= format_date(version.effective_date) %>)</strong></p>
12
13 <% elsif version.effective_date %>
13 <% issues = version.fixed_issues.find(:all,
14 <p><strong><%=l(:label_roadmap_due_in)%> <%= distance_of_time_in_words Time.now, version.effective_date %> (<%= format_date(version.effective_date) %>)</strong></p>
14 :include => [:status, :tracker],
15 <% end %>
15 :conditions => ["tracker_id in (#{@selected_tracker_ids.join(',')})"],
16 <p><%=h version.description %></p>
16 :order => "#{Tracker.table_name}.position") unless @selected_tracker_ids.empty?
17
17 issues ||= []
18 <% if version.fixed_issues.count > 0 %>
18 %>
19 <%= progress_bar([version.closed_pourcent, version.completed_pourcent], :width => '40em', :legend => ('%0.0f%' % version.completed_pourcent)) %>
19 <ul>
20 <p class="progress-info">
20 <% if issues.size > 0 %>
21 <%= link_to(version.closed_issues_count, :controller => 'issues', :action => 'index', :project_id => @project, :status_id => 'c', :fixed_version_id => version, :set_filter => 1) %>
21 <% issues.each do |issue| %>
22 <%= lwr(:label_closed_issues, version.closed_issues_count) %>
22 <li>
23 (<%= '%0.0f' % (version.closed_issues_count.to_f / version.fixed_issues.count * 100) %>%)
23 <%= link = link_to_issue(issue)
24 &#160;
24 issue.status.is_closed? ? content_tag("del", link) : link %>: <%=h issue.subject %>
25 <%= link_to(version.open_issues_count, :controller => 'issues', :action => 'index', :project_id => @project, :status_id => 'o', :fixed_version_id => version, :set_filter => 1) %>
25 <%= content_tag "em", "(#{l(:label_closed_issues)})" if issue.status.is_closed? %>
26 <%= lwr(:label_open_issues, version.open_issues_count)%>
26 </li>
27 (<%= '%0.0f' % (version.open_issues_count.to_f / version.fixed_issues.count * 100) %>%)
27 <% end %>
28 </p>
28 <% end %>
29 <%= render(:partial => "wiki/content", :locals => {:content => version.wiki_page.content}) if version.wiki_page %>
29 </ul>
30 <% issues = version.fixed_issues.find(:all,
31 :include => [:status, :tracker],
32 :conditions => ["tracker_id in (#{@selected_tracker_ids.join(',')})"],
33 :order => "#{Tracker.table_name}.position") unless @selected_tracker_ids.empty?
34 issues ||= []
35 %>
36 <ul>
37 <% if issues.size > 0 %>
38 <% issues.each do |issue| %>
39 <li>
40 <%= link = link_to_issue(issue)
41 issue.status.is_closed? ? content_tag("del", link) : link %>: <%=h issue.subject %>
42 <%= content_tag "em", "(#{l(:label_closed_issues)})" if issue.status.is_closed? %>
43 </li>
44 <% end %>
45 <% end %>
46 </ul>
47 <% else %>
48 <p><em><%= l(:label_roadmap_no_issues) %></em></p>
49 <% end %>
50 <% end %>
30 <% end %>
51
31
52 <% content_for :sidebar do %>
32 <% content_for :sidebar do %>
@@ -66,3 +46,5
66 <%= link_to version.name, :anchor => version.name %><br />
46 <%= link_to version.name, :anchor => version.name %><br />
67 <% end %>
47 <% end %>
68 <% end %>
48 <% end %>
49
50 <% set_html_title l(:label_roadmap) %>
@@ -11,7 +11,7
11 <tbody>
11 <tbody>
12 <% for version in @project.versions.sort %>
12 <% for version in @project.versions.sort %>
13 <tr class="<%= cycle 'odd', 'even' %>">
13 <tr class="<%= cycle 'odd', 'even' %>">
14 <td><%=h version.name %></td>
14 <td><%= link_to h(version.name), :controller => 'versions', :action => 'show', :id => version %></td>
15 <td align="center"><%= format_date(version.effective_date) %></td>
15 <td align="center"><%= format_date(version.effective_date) %></td>
16 <td><%=h version.description %></td>
16 <td><%=h version.description %></td>
17 <td><%= link_to(version.wiki_page_title, :controller => 'wiki', :page => Wiki.titleize(version.wiki_page_title)) unless version.wiki_page_title.blank? || @project.wiki.nil? %></td>
17 <td><%= link_to(version.wiki_page_title, :controller => 'wiki', :page => Wiki.titleize(version.wiki_page_title)) unless version.wiki_page_title.blank? || @project.wiki.nil? %></td>
@@ -548,3 +548,4 field_time_zone: Time zone
548 text_caracters_minimum: Must be at least %d characters long.
548 text_caracters_minimum: Must be at least %d characters long.
549 setting_bcc_recipients: Blind carbon copy recipients (bcc)
549 setting_bcc_recipients: Blind carbon copy recipients (bcc)
550 button_annotate: Annotate
550 button_annotate: Annotate
551 label_issues_by: Issues by %s
@@ -548,3 +548,4 field_time_zone: Time zone
548 text_caracters_minimum: Must be at least %d characters long.
548 text_caracters_minimum: Must be at least %d characters long.
549 setting_bcc_recipients: Blind carbon copy recipients (bcc)
549 setting_bcc_recipients: Blind carbon copy recipients (bcc)
550 button_annotate: Annotate
550 button_annotate: Annotate
551 label_issues_by: Issues by %s
@@ -548,3 +548,4 field_time_zone: Zeitzone
548 text_caracters_minimum: Muss mindestens %d Zeichen lang sein.
548 text_caracters_minimum: Muss mindestens %d Zeichen lang sein.
549 setting_bcc_recipients: Blind carbon copy recipients (bcc)
549 setting_bcc_recipients: Blind carbon copy recipients (bcc)
550 button_annotate: Annotate
550 button_annotate: Annotate
551 label_issues_by: Issues by %s
@@ -210,6 +210,7 label_issue: Issue
210 label_issue_new: New issue
210 label_issue_new: New issue
211 label_issue_plural: Issues
211 label_issue_plural: Issues
212 label_issue_view_all: View all issues
212 label_issue_view_all: View all issues
213 label_issues_by: Issues by %s
213 label_document: Document
214 label_document: Document
214 label_document_new: New document
215 label_document_new: New document
215 label_document_plural: Documents
216 label_document_plural: Documents
@@ -551,3 +551,4 notice_account_pending: "Su cuenta ha sido creada y está pendiende de la aproba
551 setting_time_format: Formato de hora
551 setting_time_format: Formato de hora
552 setting_bcc_recipients: Blind carbon copy recipients (bcc)
552 setting_bcc_recipients: Blind carbon copy recipients (bcc)
553 button_annotate: Annotate
553 button_annotate: Annotate
554 label_issues_by: Issues by %s
@@ -210,6 +210,7 label_issue: Demande
210 label_issue_new: Nouvelle demande
210 label_issue_new: Nouvelle demande
211 label_issue_plural: Demandes
211 label_issue_plural: Demandes
212 label_issue_view_all: Voir toutes les demandes
212 label_issue_view_all: Voir toutes les demandes
213 label_issues_by: Demandes par %s
213 label_document: Document
214 label_document: Document
214 label_document_new: Nouveau document
215 label_document_new: Nouveau document
215 label_document_plural: Documents
216 label_document_plural: Documents
@@ -548,3 +548,4 field_time_zone: Time zone
548 text_caracters_minimum: Must be at least %d characters long.
548 text_caracters_minimum: Must be at least %d characters long.
549 setting_bcc_recipients: Blind carbon copy recipients (bcc)
549 setting_bcc_recipients: Blind carbon copy recipients (bcc)
550 button_annotate: Annotate
550 button_annotate: Annotate
551 label_issues_by: Issues by %s
@@ -548,3 +548,4 field_time_zone: Time zone
548 text_caracters_minimum: Must be at least %d characters long.
548 text_caracters_minimum: Must be at least %d characters long.
549 setting_bcc_recipients: Blind carbon copy recipients (bcc)
549 setting_bcc_recipients: Blind carbon copy recipients (bcc)
550 button_annotate: Annotate
550 button_annotate: Annotate
551 label_issues_by: Issues by %s
@@ -549,3 +549,4 field_time_zone: Time zone
549 text_caracters_minimum: Must be at least %d characters long.
549 text_caracters_minimum: Must be at least %d characters long.
550 setting_bcc_recipients: Blind carbon copy recipients (bcc)
550 setting_bcc_recipients: Blind carbon copy recipients (bcc)
551 button_annotate: Annotate
551 button_annotate: Annotate
552 label_issues_by: Issues by %s
@@ -548,3 +548,4 field_time_zone: Time zone
548 text_caracters_minimum: Must be at least %d characters long.
548 text_caracters_minimum: Must be at least %d characters long.
549 setting_bcc_recipients: Blind carbon copy recipients (bcc)
549 setting_bcc_recipients: Blind carbon copy recipients (bcc)
550 button_annotate: Annotate
550 button_annotate: Annotate
551 label_issues_by: Issues by %s
@@ -549,3 +549,4 field_time_zone: Time zone
549 text_caracters_minimum: Must be at least %d characters long.
549 text_caracters_minimum: Must be at least %d characters long.
550 setting_bcc_recipients: Blind carbon copy recipients (bcc)
550 setting_bcc_recipients: Blind carbon copy recipients (bcc)
551 button_annotate: Annotate
551 button_annotate: Annotate
552 label_issues_by: Issues by %s
@@ -548,3 +548,4 field_time_zone: Strefa czasowa
548 text_caracters_minimum: Must be at least %d characters long.
548 text_caracters_minimum: Must be at least %d characters long.
549 setting_bcc_recipients: Blind carbon copy recipients (bcc)
549 setting_bcc_recipients: Blind carbon copy recipients (bcc)
550 button_annotate: Annotate
550 button_annotate: Annotate
551 label_issues_by: Issues by %s
@@ -548,3 +548,4 field_time_zone: Time zone
548 text_caracters_minimum: Must be at least %d characters long.
548 text_caracters_minimum: Must be at least %d characters long.
549 setting_bcc_recipients: Blind carbon copy recipients (bcc)
549 setting_bcc_recipients: Blind carbon copy recipients (bcc)
550 button_annotate: Annotate
550 button_annotate: Annotate
551 label_issues_by: Issues by %s
@@ -548,3 +548,4 field_time_zone: Time zone
548 text_caracters_minimum: Must be at least %d characters long.
548 text_caracters_minimum: Must be at least %d characters long.
549 setting_bcc_recipients: Blind carbon copy recipients (bcc)
549 setting_bcc_recipients: Blind carbon copy recipients (bcc)
550 button_annotate: Annotate
550 button_annotate: Annotate
551 label_issues_by: Issues by %s
@@ -548,3 +548,4 field_time_zone: Time zone
548 text_caracters_minimum: Must be at least %d characters long.
548 text_caracters_minimum: Must be at least %d characters long.
549 setting_bcc_recipients: Blind carbon copy recipients (bcc)
549 setting_bcc_recipients: Blind carbon copy recipients (bcc)
550 button_annotate: Annotate
550 button_annotate: Annotate
551 label_issues_by: Issues by %s
@@ -548,3 +548,4 field_time_zone: Часовой пояс
548 text_caracters_minimum: Must be at least %d characters long.
548 text_caracters_minimum: Must be at least %d characters long.
549 setting_bcc_recipients: Blind carbon copy recipients (bcc)
549 setting_bcc_recipients: Blind carbon copy recipients (bcc)
550 button_annotate: Annotate
550 button_annotate: Annotate
551 label_issues_by: Issues by %s
@@ -549,3 +549,4 field_time_zone: Time zone
549 text_caracters_minimum: Must be at least %d characters long.
549 text_caracters_minimum: Must be at least %d characters long.
550 setting_bcc_recipients: Blind carbon copy recipients (bcc)
550 setting_bcc_recipients: Blind carbon copy recipients (bcc)
551 button_annotate: Annotate
551 button_annotate: Annotate
552 label_issues_by: Issues by %s
@@ -549,3 +549,4 field_time_zone: Time zone
549 text_caracters_minimum: Must be at least %d characters long.
549 text_caracters_minimum: Must be at least %d characters long.
550 setting_bcc_recipients: Blind carbon copy recipients (bcc)
550 setting_bcc_recipients: Blind carbon copy recipients (bcc)
551 button_annotate: Annotate
551 button_annotate: Annotate
552 label_issues_by: Issues by %s
@@ -551,3 +551,4 field_time_zone: Time zone
551 text_caracters_minimum: Must be at least %d characters long.
551 text_caracters_minimum: Must be at least %d characters long.
552 setting_bcc_recipients: Blind carbon copy recipients (bcc)
552 setting_bcc_recipients: Blind carbon copy recipients (bcc)
553 button_annotate: Annotate
553 button_annotate: Annotate
554 label_issues_by: Issues by %s
@@ -27,6 +27,7 Redmine::AccessControl.map do |map|
27 # Issues
27 # Issues
28 map.permission :view_issues, {:projects => [:changelog, :roadmap],
28 map.permission :view_issues, {:projects => [:changelog, :roadmap],
29 :issues => [:index, :changes, :show, :context_menu],
29 :issues => [:index, :changes, :show, :context_menu],
30 :versions => [:show, :status_by],
30 :queries => :index,
31 :queries => :index,
31 :reports => :issue_report}, :public => true
32 :reports => :issue_report}, :public => true
32 map.permission :add_issues, {:projects => :add_issue}
33 map.permission :add_issues, {:projects => :add_issue}
@@ -267,6 +267,8 table.progress td.open { background: #FFF none repeat scroll 0%; }
267 p.pourcent {font-size: 80%;}
267 p.pourcent {font-size: 80%;}
268 p.progress-info {clear: left; font-style: italic; font-size: 80%;}
268 p.progress-info {clear: left; font-style: italic; font-size: 80%;}
269
269
270 div#status_by { margin-left: 16px; margin-bottom: 16px; }
271
270 /***** Tabs *****/
272 /***** Tabs *****/
271 #content .tabs{height: 2.6em;}
273 #content .tabs{height: 2.6em;}
272 #content .tabs ul{margin:0;}
274 #content .tabs ul{margin:0;}
General Comments 0
You need to be logged in to leave comments. Login now