Project

General

Profile

Patch #7443 » found-in-version-1.4.4-full.patch

Roman Yeryomin, 2012-08-14 13:08

View differences:

config/locales/fr.yml (copie de travail)
252 252
  field_due_date: Echéance
253 253
  field_assigned_to: Assigné à
254 254
  field_priority: Priorité
255
  field_found_version: Détécté dans Version
255 256
  field_fixed_version: Version cible
256 257
  field_user: Utilisateur
257 258
  field_role: Rôle
config/locales/en.yml (copie de travail)
244 244
  field_due_date: Due date
245 245
  field_assigned_to: Assignee
246 246
  field_priority: Priority
247
  field_found_version: Detected version
247 248
  field_fixed_version: Target version
248 249
  field_user: User
249 250
  field_principal: Principal
app/helpers/issues_helper.rb (copie de travail)
172 172
        value = format_date(detail.value.to_date) if detail.value
173 173
        old_value = format_date(detail.old_value.to_date) if detail.old_value
174 174

  
175
      when ['project_id', 'status_id', 'tracker_id', 'assigned_to_id', 'priority_id', 'category_id', 'fixed_version_id'].include?(detail.prop_key)
175
      when ['project_id', 'status_id', 'tracker_id', 'assigned_to_id', 'priority_id', 'category_id', 'found_version_id', 'fixed_version_id'].include?(detail.prop_key)
176 176
        value = find_name_by_reflection(field, detail.value)
177 177
        old_value = find_name_by_reflection(field, detail.old_value)
178 178

  
app/models/project.rb (copie de travail)
727 727
      new_issue = Issue.new
728 728
      new_issue.copy_from(issue)
729 729
      new_issue.project = self
730
      # Reassign fixed_versions by name, since names are unique per
730
      # Reassign versions by name, since names are unique per
731 731
      # project and the versions for self are not yet saved
732
      if issue.found_version
733
        new_issue.found_version = self.versions.select {|v| v.name == issue.found_version.name}.first
734
      end	  
732 735
      if issue.fixed_version
733 736
        new_issue.fixed_version = self.versions.select {|v| v.name == issue.fixed_version.name}.first
734 737
      end
app/models/query.rb (copie de travail)
144 144
    QueryColumn.new(:assigned_to, :sortable => lambda {User.fields_for_order_statement}, :groupable => true),
145 145
    QueryColumn.new(:updated_on, :sortable => "#{Issue.table_name}.updated_on", :default_order => 'desc'),
146 146
    QueryColumn.new(:category, :sortable => "#{IssueCategory.table_name}.name", :groupable => true),
147
	QueryColumn.new(:found_version, :sortable => ["#{Version.table_name}.effective_date", "#{Version.table_name}.name"], :default_order => 'desc', :groupable => true),
147 148
    QueryColumn.new(:fixed_version, :sortable => ["#{Version.table_name}.effective_date", "#{Version.table_name}.name"], :default_order => 'desc', :groupable => true),
148 149
    QueryColumn.new(:start_date, :sortable => "#{Issue.table_name}.start_date"),
149 150
    QueryColumn.new(:due_date, :sortable => "#{Issue.table_name}.due_date"),
......
220 221
    @available_filters = { "status_id" => { :type => :list_status, :order => 1, :values => IssueStatus.find(:all, :order => 'position').collect{|s| [s.name, s.id.to_s] } },
221 222
                           "tracker_id" => { :type => :list, :order => 2, :values => trackers.collect{|s| [s.name, s.id.to_s] } },
222 223
                           "priority_id" => { :type => :list, :order => 3, :values => IssuePriority.all.collect{|s| [s.name, s.id.to_s] } },
223
                           "subject" => { :type => :text, :order => 8 },
224
                           "created_on" => { :type => :date_past, :order => 9 },
225
                           "updated_on" => { :type => :date_past, :order => 10 },
226
                           "start_date" => { :type => :date, :order => 11 },
227
                           "due_date" => { :type => :date, :order => 12 },
228
                           "estimated_hours" => { :type => :float, :order => 13 },
229
                           "done_ratio" =>  { :type => :integer, :order => 14 }}
224
						   "subject" => { :type => :text, :order => 9 },
225
                           "created_on" => { :type => :date_past, :order => 10 },
226
                           "updated_on" => { :type => :date_past, :order => 11 },
227
                           "start_date" => { :type => :date, :order => 12 },
228
                           "due_date" => { :type => :date, :order => 13 },
229
                           "estimated_hours" => { :type => :integer, :order => 14 },
230
                           "done_ratio" =>  { :type => :integer, :order => 15 }}
230 231

  
231 232
    principals = []
232 233
    if project
......
265 266
    @available_filters["assigned_to_role"] = { :type => :list_optional, :order => 7, :values => role_values } unless role_values.empty?
266 267

  
267 268
    if User.current.logged?
268
      @available_filters["watcher_id"] = { :type => :list, :order => 15, :values => [["<< #{l(:label_me)} >>", "me"]] }
269
      @available_filters["watcher_id"] = { :type => :list, :order => 16, :values => [["<< #{l(:label_me)} >>", "me"]] }
269 270
    end
270 271

  
271 272
    if project
......
276 277
      end
277 278
      versions = project.shared_versions.all
278 279
      unless versions.empty?
279
        @available_filters["fixed_version_id"] = { :type => :list_optional, :order => 7, :values => versions.sort.collect{|s| ["#{s.project.name} - #{s.name}", s.id.to_s] } }
280
        @available_filters["found_version_id"] = { :type => :list_optional, :order => 7, :values => versions.sort.collect{|s| ["#{s.project.name} - #{s.name}", s.id.to_s] } }
281
        @available_filters["fixed_version_id"] = { :type => :list_optional, :order => 8, :values => versions.sort.collect{|s| ["#{s.project.name} - #{s.name}", s.id.to_s] } }
280 282
      end
281 283
      unless project.leaf?
282 284
        subprojects = project.descendants.visible.all
......
289 291
      # global filters for cross project issue list
290 292
      system_shared_versions = Version.visible.find_all_by_sharing('system')
291 293
      unless system_shared_versions.empty?
292
        @available_filters["fixed_version_id"] = { :type => :list_optional, :order => 7, :values => system_shared_versions.sort.collect{|s| ["#{s.project.name} - #{s.name}", s.id.to_s] } }
294
        @available_filters["found_version_id"] = { :type => :list_optional, :order => 7, :values => system_shared_versions.sort.collect{|s| ["#{s.project.name} - #{s.name}", s.id.to_s] } }
295
        @available_filters["fixed_version_id"] = { :type => :list_optional, :order => 8, :values => system_shared_versions.sort.collect{|s| ["#{s.project.name} - #{s.name}", s.id.to_s] } }
293 296
      end
294 297
      add_custom_fields_filters(IssueCustomField.find(:all, :conditions => {:is_filter => true, :is_for_all => true}))
295 298
    end
app/models/mail_handler.rb (copie de travail)
269 269
      'priority_id' => (k = get_keyword(:priority)) && IssuePriority.named(k).first.try(:id),
270 270
      'category_id' => (k = get_keyword(:category)) && issue.project.issue_categories.named(k).first.try(:id),
271 271
      'assigned_to_id' => assigned_to.try(:id),
272
	  'found_version_id' => (k = get_keyword(:found_version, :override => true)) && issue.project.shared_versions.named(k).first.try(:id),
272 273
      'fixed_version_id' => (k = get_keyword(:fixed_version, :override => true)) && issue.project.shared_versions.named(k).first.try(:id),
273 274
      'start_date' => get_keyword(:start_date, :override => true, :format => '\d{4}-\d{2}-\d{2}'),
274 275
      'due_date' => get_keyword(:due_date, :override => true, :format => '\d{4}-\d{2}-\d{2}'),
app/models/issue.rb (copie de travail)
23 23
  belongs_to :status, :class_name => 'IssueStatus', :foreign_key => 'status_id'
24 24
  belongs_to :author, :class_name => 'User', :foreign_key => 'author_id'
25 25
  belongs_to :assigned_to, :class_name => 'Principal', :foreign_key => 'assigned_to_id'
26
  belongs_to :found_version, :class_name => 'Version', :foreign_key => 'found_version_id'
26 27
  belongs_to :fixed_version, :class_name => 'Version', :foreign_key => 'fixed_version_id'
27 28
  belongs_to :priority, :class_name => 'IssuePriority', :foreign_key => 'priority_id'
28 29
  belongs_to :category, :class_name => 'IssueCategory', :foreign_key => 'category_id'
......
54 55
  attr_reader :current_journal
55 56

  
56 57
  validates_presence_of :subject, :priority, :project, :tracker, :author, :status
57

  
58
  validates_presence_of :found_version, :unless => Proc.new { |issue| issue.found_assignable_versions.empty? }
59
  
58 60
  validates_length_of :subject, :maximum => 255
59 61
  validates_inclusion_of :done_ratio, :in => 0..100
60 62
  validates_numericality_of :estimated_hours, :allow_nil => true
......
164 166
      # reassign to the category with same name if any
165 167
      new_category = issue.category.nil? ? nil : new_project.issue_categories.find_by_name(issue.category.name)
166 168
      issue.category = new_category
167
      # Keep the fixed_version if it's still valid in the new_project
169
	  # Keep the found version if it's still valid in the new_project
170
      unless new_project.shared_versions.include?(issue.found_version)
171
        issue.found_version = nil
172
      end
173
      # Keep the fixed version if it's still valid in the new_project
168 174
      unless new_project.shared_versions.include?(issue.fixed_version)
169 175
        issue.fixed_version = nil
170 176
      end
......
260 266
    'category_id',
261 267
    'assigned_to_id',
262 268
    'priority_id',
269
	'found_version_id',
263 270
    'fixed_version_id',
264 271
    'subject',
265 272
    'description',
......
351 358
      errors.add :start_date, :invalid
352 359
    end
353 360

  
361
    if found_version
362
      if !found_assignable_versions.include?(found_version)
363
        errors.add :found_version_id, :inclusion
364
      end
365
    end
366

  
367
	
354 368
    if fixed_version
355
      if !assignable_versions.include?(fixed_version)
369
      if !fixed_assignable_versions.include?(fixed_version)
356 370
        errors.add :fixed_version_id, :inclusion
357 371
      elsif reopened? && fixed_version.closed?
358 372
        errors.add :base, I18n.t(:error_can_not_reopen_issue_on_closed_version)
......
456 470
    users.uniq.sort
457 471
  end
458 472

  
459
  # Versions that the issue can be assigned to
460
  def assignable_versions
461
    @assignable_versions ||= (project.shared_versions.open + [Version.find_by_id(fixed_version_id_was)]).compact.uniq.sort
473
  # Versions that the issue can be assigned as fixed to
474
  def found_assignable_versions
475
    @found_assignable_versions ||= project.shared_versions.locked
462 476
  end
463 477

  
478
  # Versions that the issue can be assigned as fixed to
479
  def fixed_assignable_versions
480
    @fixed_assignable_versions ||= (project.shared_versions.open + [Version.find_by_id(fixed_version_id_was)]).compact.uniq.sort
481
   end
482

  
464 483
  # Returns true if this issue is blocked by another issue that is still open
465 484
  def blocked?
466 485
    !relations_to.detect {|ir| ir.relation_type == 'blocks' && !ir.issue_from.closed?}.nil?
......
644 663
  # Unassigns issues from +version+ if it's no longer shared with issue's project
645 664
  def self.update_versions_from_sharing_change(version)
646 665
    # Update issues assigned to the version
666
	update_versions(["#{Issue.table_name}.found_version_id = ?", version.id])
647 667
    update_versions(["#{Issue.table_name}.fixed_version_id = ?", version.id])
648 668
  end
649 669

  
......
680 700
                       :joins => Tracker.table_name)
681 701
  end
682 702

  
683
  def self.by_version(project)
703
  def self.by_found_version(project)
684 704
    count_and_group_by(:project => project,
705
                       :field => 'found_version_id',
706
                       :joins => Version.table_name)
707
  end
708

  
709
  def self.by_fixed_version(project)
710
    count_and_group_by(:project => project,
685 711
                       :field => 'fixed_version_id',
686 712
                       :joins => Version.table_name)
687 713
  end
......
850 876
        issue.save
851 877
      end
852 878
    end
879
    # Only need to update issues with a found_version from
880
    # a different project and that is not systemwide shared
881
    Issue.all(:conditions => merge_conditions("#{Issue.table_name}.found_version_id IS NOT NULL" +
882
                                                " AND #{Issue.table_name}.project_id <> #{Version.table_name}.project_id" +
883
                                                " AND #{Version.table_name}.sharing <> 'system'",
884
                                                conditions),
885
              :include => [:project, :found_version]
886
              ).each do |issue|
887
      next if issue.project.nil? || issue.found_version.nil?
888
      unless issue.project.shared_versions.include?(issue.found_version)
889
        issue.init_journal(User.current)
890
        issue.found_version = nil
891
        issue.save
892
      end
893
    end
894
	
853 895
  end
854 896

  
855 897
  # Callback on attachment deletion
app/models/version.rb (copie de travail)
19 19
  include Redmine::SafeAttributes
20 20
  after_update :update_issues_from_sharing_change
21 21
  belongs_to :project
22
  has_many :found_issues, :class_name => 'Issue', :foreign_key => 'found_version_id', :dependent => :nullify
22 23
  has_many :fixed_issues, :class_name => 'Issue', :foreign_key => 'fixed_version_id', :dependent => :nullify
23 24
  acts_as_customizable
24 25
  acts_as_attachable :view_permission => :view_files,
......
36 37

  
37 38
  named_scope :named, lambda {|arg| { :conditions => ["LOWER(#{table_name}.name) = LOWER(?)", arg.to_s.strip]}}
38 39
  named_scope :open, :conditions => {:status => 'open'}
40
  named_scope :locked, :conditions => {:status => 'locked'}
41
  named_scope :closed, :conditions => {:status => 'closed'}  
39 42
  named_scope :visible, lambda {|*args| { :include => :project,
40 43
                                          :conditions => Project.allowed_to_condition(args.first || User.current, :view_issues) } }
41 44

  
app/controllers/versions_controller.rb (copie de travail)
151 151

  
152 152
  verify :method => :delete, :only => :destroy, :render => {:nothing => true, :status => :method_not_allowed }
153 153
  def destroy
154
    if @version.fixed_issues.empty?
154
    if @version.found_issues.empty? && @version.fixed_issues.empty?
155 155
      @version.destroy
156 156
      respond_to do |format|
157 157
        format.html { redirect_back_or_default :controller => 'projects', :action => 'settings', :tab => 'versions', :id => @project }
app/controllers/issues_controller.rb (copie de travail)
82 82
      @issue_count = @query.issue_count
83 83
      @issue_pages = Paginator.new self, @issue_count, @limit, params['page']
84 84
      @offset ||= @issue_pages.current.offset
85
      @issues = @query.issues(:include => [:assigned_to, :tracker, :priority, :category, :fixed_version],
85
      @issues = @query.issues(:include => [:assigned_to, :tracker, :priority, :category, :found_version, :fixed_version],
86 86
                              :order => sort_clause,
87 87
                              :offset => @offset,
88 88
                              :limit => @limit)
app/controllers/reports_controller.rb (copie de travail)
29 29
    @subprojects = @project.descendants.visible
30 30

  
31 31
    @issues_by_tracker = Issue.by_tracker(@project)
32
    @issues_by_version = Issue.by_version(@project)
32
    @issues_by_found_version = Issue.by_found_version(@project)
33
	@issues_by_fixed_version = Issue.by_fixed_version(@project)
33 34
    @issues_by_priority = Issue.by_priority(@project)
34 35
    @issues_by_category = Issue.by_category(@project)
35 36
    @issues_by_assigned_to = Issue.by_assigned_to(@project)
......
46 47
      @rows = @project.trackers
47 48
      @data = Issue.by_tracker(@project)
48 49
      @report_title = l(:field_tracker)
49
    when "version"
50
	when "found_version"
51
	  @field = "found_version_id"
52
	  @rows = @project.shared_versions.sort
53
	  @data = Issue.by_found_version(@project)
54
	  @report_title = l(:field_found_version)
55
    when "fixed_version"
50 56
      @field = "fixed_version_id"
51 57
      @rows = @project.shared_versions.sort
52
      @data = Issue.by_version(@project)
53
      @report_title = l(:field_version)
58
      @data = Issue.by_fixed_version(@project)
59
      @report_title = l(:field_fixed_version)
54 60
    when "priority"
55 61
      @field = "priority_id"
56 62
      @rows = IssuePriority.all
app/controllers/issue_moves_controller.rb (copie de travail)
70 70
    @target_project ||= @project
71 71
    @trackers = @target_project.trackers
72 72
    @available_statuses = Workflow.available_statuses(@project)
73
	@found_versions = @target_project.shared_versions.locked
73 74
    @notes = params[:notes]
74 75
    @notes ||= ''
75 76
  end
76 77

  
77 78
  def extract_changed_attributes_for_move(params)
78 79
    changed_attributes = {}
79
    [:assigned_to_id, :status_id, :start_date, :due_date, :priority_id].each do |valid_attribute|
80
    [:assigned_to_id, :status_id, :found_version_id, :start_date, :due_date, :priority_id].each do |valid_attribute|
80 81
      unless params[valid_attribute].blank?
81 82
        changed_attributes[valid_attribute] = (params[valid_attribute] == 'none' ? nil : params[valid_attribute])
82 83
      end
app/views/issues/show.html.erb (copie de travail)
36 36
    <% end %>
37 37
</tr>
38 38
<tr>
39
    <th class="fixed-version"><%=l(:field_fixed_version)%>:</th><td class="fixed-version"><%= @issue.fixed_version ? link_to_version(@issue.fixed_version) : "-" %></td>
39
    <th class="fixed-version"><%=l(:field_found_version)%>:</th><td class="fixed-version"><%= @issue.found_version ? link_to_version(@issue.found_version) : "-" %></td>
40 40
    <% if @issue.estimated_hours %>
41 41
    <th class="estimated-hours"><%=l(:field_estimated_hours)%>:</th><td class="estimated-hours"><%= l_hours(@issue.estimated_hours) %></td>
42 42
    <% end %>
43 43
</tr>
44
<tr>
45
    <th class="fixed-version"><%=l(:field_fixed_version)%>:</th><td class="fixed-version"><%= @issue.fixed_version ? link_to_version(@issue.fixed_version) : "-" %></td>
46
</tr>
44 47
<%= render_custom_fields_rows(@issue) %>
45 48
<%= call_hook(:view_issues_show_details_bottom, :issue => @issue) %>
46 49
</table>
app/views/issues/_attributes.html.erb (copie de travail)
18 18
                     :title => l(:label_issue_category_new),
19 19
                     :tabindex => 199) if authorize_for('issue_categories', 'new') %></p>
20 20
<% end %>
21
<% unless @issue.assignable_versions.empty? %>
22
<p><%= f.select :fixed_version_id, version_options_for_select(@issue.assignable_versions, @issue.fixed_version), :include_blank => true %>
21
<% unless @issue.found_assignable_versions.empty? %>
22
<p><%= f.select :found_version_id, version_options_for_select(@issue.found_assignable_versions, @issue.found_version), :include_blank => true, :required => true %></p>
23
<% end %>
24
<% unless @issue.fixed_assignable_versions.empty? %>
25
<p><%= f.select :fixed_version_id, version_options_for_select(@issue.fixed_assignable_versions, @issue.fixed_version), :include_blank => true %>
23 26
<%= prompt_to_remote(image_tag('add.png', :style => 'vertical-align: middle;'),
24 27
                     l(:label_version_new),
25 28
                     'version[name]',
app/views/issues/index.api.rsb (copie de travail)
9 9
      api.author(:id => issue.author_id, :name => issue.author.name) unless issue.author.nil?
10 10
      api.assigned_to(:id => issue.assigned_to_id, :name => issue.assigned_to.name) unless issue.assigned_to.nil?
11 11
      api.category(:id => issue.category_id, :name => issue.category.name) unless issue.category.nil?
12
      api.fixed_version(:id => issue.fixed_version_id, :name => issue.fixed_version.name) unless issue.fixed_version.nil?
12
      api.found_version(:id => issue.found_version_id, :name => issue.found_version.name) unless issue.found_version.nil?
13
	  api.fixed_version(:id => issue.fixed_version_id, :name => issue.fixed_version.name) unless issue.fixed_version.nil?
13 14
      api.parent(:id => issue.parent_id) unless issue.parent.nil?
14 15

  
15 16
      api.subject     issue.subject
app/views/issues/bulk_edit.html.erb (copie de travail)
40 40
<% #TODO: allow editing versions when multiple projects %>
41 41
<% if @project %>
42 42
<p>
43
	<label for='issue_found_version_id'><%= l(:field_found_version) %></label>
44
	<%= select_tag('issue[found_version_id]', content_tag('option', l(:label_no_change_option), :value => '') +
45
                                   content_tag('option', l(:label_none), :value => 'none') +
46
                                   version_options_for_select(@project.shared_versions.locked)) %>
47
</p>
48
<p>
43 49
  <label for='issue_fixed_version_id'><%= l(:field_fixed_version) %></label>
44 50
  <%= select_tag('issue[fixed_version_id]', content_tag('option', l(:label_no_change_option), :value => '') +
45 51
                                   content_tag('option', l(:label_none), :value => 'none') +
46
                                   version_options_for_select(@project.shared_versions.open.sort)) %>
52
                                   version_options_for_select(@project.shared_versions.open)) %>
47 53
</p>
48 54
<% end %>
49 55

  
app/views/issues/show.api.rsb (copie de travail)
7 7
  api.author(:id => @issue.author_id, :name => @issue.author.name) unless @issue.author.nil?
8 8
  api.assigned_to(:id => @issue.assigned_to_id, :name => @issue.assigned_to.name) unless @issue.assigned_to.nil?
9 9
  api.category(:id => @issue.category_id, :name => @issue.category.name) unless @issue.category.nil?
10
  api.found_version(:id => @issue.found_version_id, :name => @issue.found_version.name) unless @issue.found_version.nil?
10 11
  api.fixed_version(:id => @issue.fixed_version_id, :name => @issue.fixed_version.name) unless @issue.fixed_version.nil?
11 12
  api.parent(:id => @issue.parent_id) unless @issue.parent.nil?
12 13

  
app/views/issues/_form_update.html.erb (copie de travail)
7 7
<% if Issue.use_field_for_done_ratio? %>
8 8
<p><%= f.select :done_ratio, ((0..10).to_a.collect {|r| ["#{r*10} %", r*10] }) %></p>
9 9
<% end %>
10
<% unless @issue.assignable_versions.empty? %>
11
<p><%= f.select :fixed_version_id, (@issue.assignable_versions.collect {|v| [v.name, v.id]}), :include_blank => true %></p>
10
+<% unless @issue.fixed_assignable_versions.empty? %>
11
+<p><%= f.select :fixed_version_id, (@issue.fixed_assignable_versions.collect {|v| [v.name, v.id]}), :include_blank => true %></p>
12 12
<% end %>
13 13
</div>
14 14
</div>
app/views/issue_moves/new.html.erb (copie de travail)
29 29
  <label for='status_id'><%= l(:field_status) %></label>
30 30
  <%= select_tag('status_id', "<option value=\"\">#{l(:label_no_change_option)}</option>" + options_from_collection_for_select(@available_statuses, :id, :name)) %>
31 31
</p>
32
<% if !@found_versions.empty? %>
33
<p>
34
  <label for="new_found_version_id"><%=l(:field_found_version) %></label>
35
  <%= select_tag('new_found_version_id', "<option value=\"\">#{l(:label_no_change_option)}</option>" + options_from_collection_for_select(@found_versions, :id, :name)) %>
36
</p>
37
<% end %>
32 38

  
33 39
<p>
34 40
  <label for='priority_id'><%= l(:field_priority) %></label>
app/views/reports/issue_report.html.erb (copie de travail)
17 17
</div>
18 18

  
19 19
<div class="splitcontentright">
20
<h3><%=l(:field_version)%>&nbsp;&nbsp;<%= link_to image_tag('zoom_in.png'), :action => 'issue_report_details', :detail => 'version' %></h3>
21
<%= render :partial => 'simple', :locals => { :data => @issues_by_version, :field_name => "fixed_version_id", :rows => @versions } %>
20
<h3><%=l(:field_found_version)%>&nbsp;&nbsp;<%= link_to image_tag('zoom_in.png'), :action => 'issue_report_details', :detail => 'found_version' %></h3>
21
<%= render :partial => 'simple', :locals => { :data => @issues_by_found_version, :field_name => "found_version_id", :rows => @versions } %>
22 22
<br />
23
<h3><%=l(:field_fixed_version)%>&nbsp;&nbsp;<%= link_to image_tag('zoom_in.png'), :action => 'issue_report_details', :detail => 'fixed_version' %></h3>
24
<%= render :partial => 'simple', :locals => { :data => @issues_by_fixed_version, :field_name => "fixed_version_id", :rows => @versions } %>
25
<br />
23 26
<% if @project.children.any? %>
24 27
<h3><%=l(:field_subproject)%>&nbsp;&nbsp;<%= link_to image_tag('zoom_in.png'), :action => 'issue_report_details', :detail => 'subproject' %></h3>
25 28
<%= render :partial => 'simple', :locals => { :data => @issues_by_subproject, :field_name => "project_id", :rows => @subprojects } %>
app/views/mailer/_issue.html.erb (copie de travail)
6 6
<li><%=l(:field_priority)%>: <%=h issue.priority %></li>
7 7
<li><%=l(:field_assigned_to)%>: <%=h issue.assigned_to %></li>
8 8
<li><%=l(:field_category)%>: <%=h issue.category %></li>
9
<li><%=l(:field_found_version)%>: <%= issue.found_version %> </li>
9 10
<li><%=l(:field_fixed_version)%>: <%=h issue.fixed_version %></li>
10 11
<% issue.custom_field_values.each do |c| %>
11 12
  <li><%=h c.custom_field.name %>: <%=h show_value(c) %></li>
app/views/mailer/_issue.text.erb (copie de travail)
6 6
<%=l(:field_priority)%>: <%= issue.priority %>
7 7
<%=l(:field_assigned_to)%>: <%= issue.assigned_to %>
8 8
<%=l(:field_category)%>: <%= issue.category %>
9
<%=l(:field_found_version)%>: <%= issue.found_version %>
9 10
<%=l(:field_fixed_version)%>: <%= issue.fixed_version %>
10 11
<% issue.custom_field_values.each do |c| %><%= c.custom_field.name %>: <%= show_value(c) %>
11 12
<% end %>
12 13
Index: db/migrate/20120328183300_add_found_version.rb
13 14
===================================================================
15
++ db/migrate/20120328183300_add_found_version.rb	2011-02-10 17:13:06.393825200 -0700
......
1
class AddFoundVersion < ActiveRecord::Migration
2
  def self.up
3
    add_column :issues, :found_version_id, :integer
4
    add_index :issues, :found_version_id
5
  end
6

  
7
  def self.down
8
    remove_index :issues, :found_version_id
9
    remove_column :issues, :found_version_id
10
  end
11
end
(14-14/15)