Project

General

Profile

Feature #17442 ยป multiple_fixed_versions.patch

Alice Etchegaray, 2014-07-10 16:53

View differences:

app/models/issue.rb (working copy)
22 22
  belongs_to :status, :class_name => 'IssueStatus', :foreign_key => 'status_id'
23 23
  belongs_to :author, :class_name => 'User', :foreign_key => 'author_id'
24 24
  belongs_to :assigned_to, :class_name => 'User', :foreign_key => 'assigned_to_id'
25
  belongs_to :fixed_version, :class_name => 'Version', :foreign_key => 'fixed_version_id'
26 25
  belongs_to :priority, :class_name => 'Enumeration', :foreign_key => 'priority_id'
27 26
  belongs_to :category, :class_name => 'IssueCategory', :foreign_key => 'category_id'
28 27

  
......
32 31
  has_many :custom_values, :dependent => :delete_all, :as => :customized
33 32
  has_many :custom_fields, :through => :custom_values
34 33
  has_and_belongs_to_many :changesets, :order => "revision ASC"
34
  has_and_belongs_to_many :fixed_versions, :class_name => 'Version'
35 35
  
36 36
  acts_as_watchable
37 37
  
app/models/version.rb (working copy)
18 18
class Version < ActiveRecord::Base
19 19
  before_destroy :check_integrity
20 20
  belongs_to :project
21
  has_many :fixed_issues, :class_name => 'Issue', :foreign_key => 'fixed_version_id'
21
  has_and_belongs_to_many :fixed_issues, :class_name => 'Issue'
22 22
  has_many :attachments, :as => :container, :dependent => :destroy
23 23

  
24 24
  validates_presence_of :name
app/controllers/issues_controller.rb (working copy)
46 46
    @priorities = Enumeration::get_values('IPRI')
47 47
    if request.get?
48 48
      @custom_values = @project.custom_fields_for_issues(@issue.tracker).collect { |x| @issue.custom_values.find_by_custom_field_id(x.id) || CustomValue.new(:custom_field => x, :customized => @issue) }
49
      setup_versions()
49 50
    else
50 51
      begin
51 52
        @issue.init_journal(self.logged_in_user)
......
53 54
        @custom_values = @project.custom_fields_for_issues(@issue.tracker).collect { |x| CustomValue.new(:custom_field => x, :customized => @issue, :value => params["custom_fields"][x.id.to_s]) }
54 55
        @issue.custom_values = @custom_values
55 56
        @issue.attributes = params[:issue]
57
        ensure_versions_saved()
56 58
        if @issue.save
57 59
          flash[:notice] = l(:notice_successful_update)
58 60
          redirect_to :action => 'show', :id => @issue
......
81 83
  def change_status
82 84
    @status_options = @issue.status.find_new_statuses_allowed_to(logged_in_user.role_for_project(@project), @issue.tracker) if logged_in_user
83 85
    @new_status = IssueStatus.find(params[:new_status_id])
86
    setup_versions()
84 87
    if params[:confirm]
85 88
      begin
86 89
        journal = @issue.init_journal(self.logged_in_user, params[:notes])
87 90
        @issue.status = @new_status
88 91
        if @issue.update_attributes(params[:issue])
92
          ensure_versions_saved()
89 93
          # Save attachments
90 94
          params[:attachments].each { |file|
91 95
            next unless file.size > 0
......
156 160
  rescue ActiveRecord::RecordNotFound
157 161
    render_404
158 162
  end  
163

  
164
  def setup_versions
165
    @released_versions = []
166
    @unreleased_versions = []
167
    @project.versions.find(:all, :order => "#{Version.table_name}.effective_date ASC").each { |v| (v.effective_date < Date.today ? @released_versions : @unreleased_versions) << v }
168
  end
169

  
170
  def ensure_versions_saved
171
    @issue.fixed_versions = [] unless params[:issue][:fixed_version_ids] 
172
  end
159 173
end
app/controllers/projects_controller.rb (working copy)
434 434
  def changelog
435 435
    @trackers = Tracker.find(:all, :conditions => ["is_in_chlog=?", true], :order => 'position')
436 436
    retrieve_selected_tracker_ids(@trackers)
437
    
438
    @fixed_issues = @project.issues.find(:all, 
439
      :include => [ :fixed_version, :status, :tracker ], 
440
      :conditions => [ "#{IssueStatus.table_name}.is_closed=? and #{Issue.table_name}.tracker_id in (#{@selected_tracker_ids.join(',')}) and #{Issue.table_name}.fixed_version_id is not null", true],
441
      :order => "#{Version.table_name}.effective_date DESC, #{Issue.table_name}.id DESC"
437

  
438
    @versions = @project.versions.find(:all, 
439
      :conditions => [ "#{Version.table_name}.effective_date<?", Date.today],
440
      :order => "#{Version.table_name}.effective_date DESC"
442 441
    ) unless @selected_tracker_ids.empty?
443
    @fixed_issues ||= []
444 442
  end
445 443

  
446 444
  def roadmap
app/views/projects/changelog.rhtml (working copy)
13 13
<% end %>
14 14
</div>
15 15

  
16
<% if @fixed_issues.empty? %><p><i><%= l(:label_no_data) %></i></p><% end %>
16
<% if @versions.empty? %><p><i><%= l(:label_no_data) %></i></p><% end %>
17 17

  
18
<% ver_id = nil
19
   @fixed_issues.each do |issue| %>   
20
    <% unless ver_id == issue.fixed_version_id %>
21
    <% if ver_id %></ul><% end %>
22
    <h3 class="icon22 icon22-package"><%= issue.fixed_version.name %></h3>
23
    <p><%= format_date(issue.fixed_version.effective_date) %><br />
24
    <%=h issue.fixed_version.description %></p>
18
<% @versions.each do |version| %>
19
    <h3 class="icon22 icon22-package"><%= version.name %></h3>
20
    <p><%= format_date(version.effective_date) %><br />
21
    <p><%=h version.description %></p>
22

  
23
    <%
24
      issues = version.fixed_issues.find(:all,
25
                 :include => :status,
26
                 :conditions => ["tracker_id in (#{@selected_tracker_ids.join(',')}) and is_closed is true"],
27
                 :order => "position")
28
    %>
29

  
25 30
    <ul>
26
    <% ver_id = issue.fixed_version_id
27
    end %>
28
    <li><%= link_to_issue issue %>: <%=h issue.subject %></li>
31
      <% if issues.size == 0 %>
32
        <li><%=l(:label_change_log_no_issues)%></li>
33
      <% else %>
34
        <% issues.each do |issue| %>
35
          <li>
36
            <%= link_to_issue(issue) %>: <%=h issue.subject %>
37
          </li>
38
        <% end %>
39
      <% end %>
40
    </ul>
29 41
<% end %>
30
</div>
42
</div>
app/views/issues/show.rhtml (working copy)
27 27
    <td><b><%=l(:field_done_ratio)%> :</b></td><td><%= @issue.done_ratio %> %</td>
28 28
</tr>
29 29
<tr>
30
    <td><b><%=l(:field_fixed_version)%> :</b></td><td><%= @issue.fixed_version ? @issue.fixed_version.name : "-" %></td>
30
    <td><b><%=l(:field_fixed_version_plural)%> :</b></td><td><%= @issue.fixed_versions.map{|v| v.name}.join(", ") %></td>
31 31
    <td><b><%=l(:label_spent_time)%> :</b></td>
32 32
    <td><%= @issue.spent_hours > 0 ? (link_to lwr(:label_f_hour, @issue.spent_hours), {:controller => 'timelog', :action => 'details', :issue_id => @issue}, :class => 'icon icon-time') : "-" %></td>
33 33
</tr>
app/views/issues/edit.rhtml (working copy)
25 25
	<p><%= custom_field_tag_with_label @custom_value %></p>
26 26
<% end %>
27 27

  
28
<p><%= f.select :fixed_version_id, (@project.versions.collect {|v| [v.name, v.id]}), { :include_blank => true } %></p>
28
<p><%= render(:partial => 'fixed_versions') %></p>
29

  
29 30
</div>
30 31
<!--[eoform:issue]-->
31 32
</div>
......
52 53
<%= javascript_include_tag "calendar/lang/calendar-#{current_language}.js" %>
53 54
<%= javascript_include_tag 'calendar/calendar-setup' %>
54 55
<%= stylesheet_link_tag 'calendar' %>
55
<% end %>
56
<% end %>
app/views/issues/_fixed_versions.rhtml (revision 0)
1
<% selected_fixed_versions = @issue.fixed_versions.collect { |v| v.id.to_i } %>
2
<select name="issue[fixed_version_ids][]" multiple="multiple" size="5">
3
  <optgroup label="<%=l(:field_fixed_versions_unreleased)%>">
4
    <%= options_from_collection_for_select @unreleased_versions, "id", "name", selected_fixed_versions %>
5
  </optgroup>
6
  <optgroup label="<%=l(:field_fixed_versions_released)%>">
7
    <%= options_from_collection_for_select @released_versions, "id", "name", selected_fixed_versions %>
8
  </optgroup>
9
</select>
app/views/issues/change_status.rhtml (working copy)
11 11
<p><label><%=l(:label_issue_status_new)%></label> <%= @new_status.name %></p>
12 12
<p><%= f.select :assigned_to_id, (@issue.project.members.collect {|m| [m.name, m.user_id]}), :include_blank => true %></p>
13 13
<p><%= f.select :done_ratio, ((0..10).to_a.collect {|r| ["#{r*10} %", r*10] }) %></p>
14
<p><%= f.select :fixed_version_id, (@project.versions.collect {|v| [v.name, v.id]}), { :include_blank => true } %></p>
14
<p><%= render(:partial => 'fixed_versions') %></p>
15 15

  
16 16
<p><label for="notes"><%= l(:field_notes) %></label>
17 17
<%= text_area_tag 'notes', @notes, :cols => 60, :rows => 10, :class => 'wiki-edit' %></p>
lang/en.yml (working copy)
109 109
field_assigned_to: Assigned to
110 110
field_priority: Priority
111 111
field_fixed_version: Fixed version
112
field_fixed_version_plural: Fixed versions
113
field_fixed_versions_released: Released versions
114
field_fixed_versions_unreleased: Unreleased versions
112 115
field_user: User
113 116
field_role: Role
114 117
field_homepage: Homepage
......
258 261
label_news_latest: Latest news
259 262
label_news_view_all: View all news
260 263
label_change_log: Change log
264
label_change_log_no_issues: No issues for this version
261 265
label_settings: Settings
262 266
label_overview: Overview
263 267
label_version: Version
db/migrate/042_issue_version_relationship.rb (revision 0)
1
class IssueVersionRelationship < ActiveRecord::Migration
2
  class Issue < ActiveRecord::Base
3
    belongs_to :old_fixed_version, :class_name => 'Version', :foreign_key => 'fixed_version_id'
4
    has_and_belongs_to_many :versions
5
  end
6

  
7
  class Version < ActiveRecord::Base
8
    has_and_belongs_to_many :issues
9
  end
10

  
11
  def self.up
12
    create_table :issues_versions, :id => false do |t|
13
      t.column :issue_id, :integer
14
      t.column :version_id, :integer
15
    end
16

  
17
    Issue.find(:all).each do |issue|
18
      if issue.old_fixed_version
19
        issue.versions << issue.old_fixed_version
20
      end
21
    end
22

  
23
    remove_column :issues, :fixed_version_id
24
  end
25

  
26
  def self.down
27
    add_column :issues, :fixed_version_id, :integer
28

  
29
    Issue.find(:all).each do |issue|
30

  
31
      if issue.versions.size > 1 
32
        # We cannot rollback if any issues point to multiple versions
33
        remove_column :issues, :fixed_version_id
34
        raise IrreversibleMigration
35
      end
36

  
37
      issue.old_fixed_version = issue.versions[0] if issue.versions.size == 1 
38
    end
39

  
40
    drop_table :issues_versions
41
  end
42
end
public/stylesheets/application.css (working copy)
665 665
padding-left: 26px;
666 666
vertical-align: bottom;
667 667
}
668

  
669
optgroup {
670
background-color: #EEE;
671
font-style: normal;
672
}
673

  
674
option {
675
background-color: white;
676
}
    (1-1/1)