Adds version status to limit issue assignments (#1245).
Available version statuses are: * open: no restriction * locked: can not assign new issues to the version * closed: can not assign new issues and can not reopen assigned issues git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@3020 e93f8b46-1217-0410-a6f0-8f06a7374b81
This commit is contained in:
parent
7c14c6d42e
commit
d201c54455
|
@ -143,6 +143,14 @@ class Issue < ActiveRecord::Base
|
||||||
if start_date && soonest_start && start_date < soonest_start
|
if start_date && soonest_start && start_date < soonest_start
|
||||||
errors.add :start_date, :invalid
|
errors.add :start_date, :invalid
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if fixed_version
|
||||||
|
if !assignable_versions.include?(fixed_version)
|
||||||
|
errors.add :fixed_version_id, :inclusion
|
||||||
|
elsif reopened? && fixed_version.closed?
|
||||||
|
errors.add_to_base I18n.t(:error_can_not_reopen_issue_on_closed_version)
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def validate_on_create
|
def validate_on_create
|
||||||
|
@ -193,6 +201,18 @@ class Issue < ActiveRecord::Base
|
||||||
self.status.is_closed?
|
self.status.is_closed?
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Return true if the issue is being reopened
|
||||||
|
def reopened?
|
||||||
|
if !new_record? && status_id_changed?
|
||||||
|
status_was = IssueStatus.find_by_id(status_id_was)
|
||||||
|
status_new = IssueStatus.find_by_id(status_id)
|
||||||
|
if status_was && status_new && status_was.is_closed? && !status_new.is_closed?
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
false
|
||||||
|
end
|
||||||
|
|
||||||
# Returns true if the issue is overdue
|
# Returns true if the issue is overdue
|
||||||
def overdue?
|
def overdue?
|
||||||
!due_date.nil? && (due_date < Date.today) && !status.is_closed?
|
!due_date.nil? && (due_date < Date.today) && !status.is_closed?
|
||||||
|
@ -203,6 +223,11 @@ class Issue < ActiveRecord::Base
|
||||||
project.assignable_users
|
project.assignable_users
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Versions that the issue can be assigned to
|
||||||
|
def assignable_versions
|
||||||
|
@assignable_versions ||= (project.versions.open + [Version.find_by_id(fixed_version_id_was)]).compact.uniq.sort
|
||||||
|
end
|
||||||
|
|
||||||
# Returns true if this issue is blocked by another issue that is still open
|
# Returns true if this issue is blocked by another issue that is still open
|
||||||
def blocked?
|
def blocked?
|
||||||
!relations_to.detect {|ir| ir.relation_type == 'blocks' && !ir.issue_from.closed?}.nil?
|
!relations_to.detect {|ir| ir.relation_type == 'blocks' && !ir.issue_from.closed?}.nil?
|
||||||
|
|
|
@ -22,11 +22,16 @@ class Version < ActiveRecord::Base
|
||||||
acts_as_attachable :view_permission => :view_files,
|
acts_as_attachable :view_permission => :view_files,
|
||||||
:delete_permission => :manage_files
|
:delete_permission => :manage_files
|
||||||
|
|
||||||
|
VERSION_STATUSES = %w(open locked closed)
|
||||||
|
|
||||||
validates_presence_of :name
|
validates_presence_of :name
|
||||||
validates_uniqueness_of :name, :scope => [:project_id]
|
validates_uniqueness_of :name, :scope => [:project_id]
|
||||||
validates_length_of :name, :maximum => 60
|
validates_length_of :name, :maximum => 60
|
||||||
validates_format_of :effective_date, :with => /^\d{4}-\d{2}-\d{2}$/, :message => :not_a_date, :allow_nil => true
|
validates_format_of :effective_date, :with => /^\d{4}-\d{2}-\d{2}$/, :message => :not_a_date, :allow_nil => true
|
||||||
|
validates_inclusion_of :status, :in => VERSION_STATUSES
|
||||||
|
|
||||||
|
named_scope :open, :conditions => {:status => 'open'}
|
||||||
|
|
||||||
def start_date
|
def start_date
|
||||||
effective_date
|
effective_date
|
||||||
end
|
end
|
||||||
|
@ -45,6 +50,10 @@ class Version < ActiveRecord::Base
|
||||||
@spent_hours ||= TimeEntry.sum(:hours, :include => :issue, :conditions => ["#{Issue.table_name}.fixed_version_id = ?", id]).to_f
|
@spent_hours ||= TimeEntry.sum(:hours, :include => :issue, :conditions => ["#{Issue.table_name}.fixed_version_id = ?", id]).to_f
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def closed?
|
||||||
|
status == 'closed'
|
||||||
|
end
|
||||||
|
|
||||||
# Returns true if the version is completed: due date reached and no open issues
|
# Returns true if the version is completed: due date reached and no open issues
|
||||||
def completed?
|
def completed?
|
||||||
effective_date && (effective_date <= Date.today) && (open_issues_count == 0)
|
effective_date && (effective_date <= Date.today) && (open_issues_count == 0)
|
||||||
|
|
|
@ -32,9 +32,9 @@
|
||||||
{:controller => 'projects', :action => 'add_issue_category', :id => @project},
|
{:controller => 'projects', :action => 'add_issue_category', :id => @project},
|
||||||
:class => 'small', :tabindex => 199) if authorize_for('projects', 'add_issue_category') %></p>
|
:class => 'small', :tabindex => 199) if authorize_for('projects', 'add_issue_category') %></p>
|
||||||
<% end %>
|
<% end %>
|
||||||
<%= content_tag('p', f.select(:fixed_version_id,
|
<% unless @issue.assignable_versions.empty? %>
|
||||||
(@project.versions.sort.collect {|v| [v.name, v.id]}),
|
<p><%= f.select :fixed_version_id, (@issue.assignable_versions.collect {|v| [v.name, v.id]}), :include_blank => true %></p>
|
||||||
{ :include_blank => true })) unless @project.versions.empty? %>
|
<% end %>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="splitcontentright">
|
<div class="splitcontentright">
|
||||||
|
|
|
@ -5,8 +5,8 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="splitcontentright">
|
<div class="splitcontentright">
|
||||||
<p><%= f.select :done_ratio, ((0..10).to_a.collect {|r| ["#{r*10} %", r*10] }) %></p>
|
<p><%= f.select :done_ratio, ((0..10).to_a.collect {|r| ["#{r*10} %", r*10] }) %></p>
|
||||||
<%= content_tag('p', f.select(:fixed_version_id,
|
<% unless @issue.assignable_versions.empty? %>
|
||||||
(@project.versions.sort.collect {|v| [v.name, v.id]}),
|
<p><%= f.select :fixed_version_id, (@issue.assignable_versions.collect {|v| [v.name, v.id]}), :include_blank => true %></p>
|
||||||
{ :include_blank => true })) unless @project.versions.empty? %>
|
<% end %>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -27,7 +27,7 @@
|
||||||
<label><%= l(:field_fixed_version) %>:
|
<label><%= l(:field_fixed_version) %>:
|
||||||
<%= select_tag('fixed_version_id', content_tag('option', l(:label_no_change_option), :value => '') +
|
<%= select_tag('fixed_version_id', content_tag('option', l(:label_no_change_option), :value => '') +
|
||||||
content_tag('option', l(:label_none), :value => 'none') +
|
content_tag('option', l(:label_none), :value => 'none') +
|
||||||
options_from_collection_for_select(@project.versions.sort, :id, :name)) %></label>
|
options_from_collection_for_select(@project.versions.open.sort, :id, :name)) %></label>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
|
|
|
@ -27,11 +27,11 @@
|
||||||
<% end -%>
|
<% end -%>
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
<% unless @project.nil? || @project.versions.empty? -%>
|
<% unless @project.nil? || @project.versions.open.empty? -%>
|
||||||
<li class="folder">
|
<li class="folder">
|
||||||
<a href="#" class="submenu"><%= l(:field_fixed_version) %></a>
|
<a href="#" class="submenu"><%= l(:field_fixed_version) %></a>
|
||||||
<ul>
|
<ul>
|
||||||
<% @project.versions.sort.each do |v| -%>
|
<% @project.versions.open.sort.each do |v| -%>
|
||||||
<li><%= context_menu_link v.name, {:controller => 'issues', :action => 'bulk_edit', :ids => @issues.collect(&:id), 'fixed_version_id' => v, :back_to => @back}, :method => :post,
|
<li><%= context_menu_link v.name, {:controller => 'issues', :action => 'bulk_edit', :ids => @issues.collect(&:id), 'fixed_version_id' => v, :back_to => @back}, :method => :post,
|
||||||
:selected => (@issue && v == @issue.fixed_version), :disabled => !@can[:update] %></li>
|
:selected => (@issue && v == @issue.fixed_version), :disabled => !@can[:update] %></li>
|
||||||
<% end -%>
|
<% end -%>
|
||||||
|
|
|
@ -1,22 +1,25 @@
|
||||||
<% if @project.versions.any? %>
|
<% if @project.versions.any? %>
|
||||||
<table class="list">
|
<table class="list versions">
|
||||||
<thead>
|
<thead>
|
||||||
<th><%= l(:label_version) %></th>
|
<th><%= l(:label_version) %></th>
|
||||||
<th><%= l(:field_effective_date) %></th>
|
<th><%= l(:field_effective_date) %></th>
|
||||||
<th><%= l(:field_description) %></th>
|
<th><%= l(:field_description) %></th>
|
||||||
|
<th><%= l(:field_status) %></th>
|
||||||
<th><%= l(:label_wiki_page) unless @project.wiki.nil? %></th>
|
<th><%= l(:label_wiki_page) unless @project.wiki.nil? %></th>
|
||||||
<th style="width:15%"></th>
|
<th style="width:15%"></th>
|
||||||
<th style="width:15%"></th>
|
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
<% for version in @project.versions.sort %>
|
<% for version in @project.versions.sort %>
|
||||||
<tr class="<%= cycle 'odd', 'even' %>">
|
<tr class="version <%= cycle 'odd', 'even' %> <%=h version.status %>">
|
||||||
<td><%= link_to h(version.name), :controller => 'versions', :action => 'show', :id => version %></td>
|
<td><%= link_to h(version.name), :controller => 'versions', :action => 'show', :id => version %></td>
|
||||||
<td align="center"><%= format_date(version.effective_date) %></td>
|
<td align="center"><%= format_date(version.effective_date) %></td>
|
||||||
<td><%=h version.description %></td>
|
<td><%=h version.description %></td>
|
||||||
|
<td><%= l("version_status_#{version.status}") %></td>
|
||||||
<td><%= link_to(h(version.wiki_page_title), :controller => 'wiki', :page => Wiki.titleize(version.wiki_page_title)) unless version.wiki_page_title.blank? || @project.wiki.nil? %></td>
|
<td><%= link_to(h(version.wiki_page_title), :controller => 'wiki', :page => Wiki.titleize(version.wiki_page_title)) unless version.wiki_page_title.blank? || @project.wiki.nil? %></td>
|
||||||
<td align="center"><%= link_to_if_authorized l(:button_edit), { :controller => 'versions', :action => 'edit', :id => version }, :class => 'icon icon-edit' %></td>
|
<td class="buttons">
|
||||||
<td align="center"><%= link_to_if_authorized l(:button_delete), {:controller => 'versions', :action => 'destroy', :id => version}, :confirm => l(:text_are_you_sure), :method => :post, :class => 'icon icon-del' %></td>
|
<%= link_to_if_authorized l(:button_edit), {:controller => 'versions', :action => 'edit', :id => version }, :class => 'icon icon-edit' %>
|
||||||
|
<%= link_to_if_authorized l(:button_delete), {:controller => 'versions', :action => 'destroy', :id => version}, :confirm => l(:text_are_you_sure), :method => :post, :class => 'icon icon-del' %>
|
||||||
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<% end; reset_cycle %>
|
<% end; reset_cycle %>
|
||||||
</tbody>
|
</tbody>
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
<div class="box">
|
<div class="box">
|
||||||
<p><%= f.text_field :name, :size => 60, :required => true %></p>
|
<p><%= f.text_field :name, :size => 60, :required => true %></p>
|
||||||
<p><%= f.text_field :description, :size => 60 %></p>
|
<p><%= f.text_field :description, :size => 60 %></p>
|
||||||
|
<p><%= f.select :status, Version::VERSION_STATUSES.collect {|s| [l("version_status_#{s}"), s]} %></p>
|
||||||
<p><%= f.text_field :wiki_page_title, :label => :label_wiki_page, :size => 60, :disabled => @project.wiki.nil? %></p>
|
<p><%= f.text_field :wiki_page_title, :label => :label_wiki_page, :size => 60, :disabled => @project.wiki.nil? %></p>
|
||||||
<p><%= f.text_field :effective_date, :size => 10 %><%= calendar_for('version_effective_date') %></p>
|
<p><%= f.text_field :effective_date, :size => 10 %><%= calendar_for('version_effective_date') %></p>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -827,3 +827,7 @@ bg:
|
||||||
field_active: Active
|
field_active: Active
|
||||||
enumeration_system_activity: System Activity
|
enumeration_system_activity: System Activity
|
||||||
permission_delete_issue_watchers: Delete watchers
|
permission_delete_issue_watchers: Delete watchers
|
||||||
|
version_status_closed: closed
|
||||||
|
version_status_locked: locked
|
||||||
|
version_status_open: open
|
||||||
|
error_can_not_reopen_issue_on_closed_version: An issue assigned to a closed version can not be reopened
|
||||||
|
|
|
@ -851,3 +851,7 @@ bs:
|
||||||
field_active: Active
|
field_active: Active
|
||||||
enumeration_system_activity: System Activity
|
enumeration_system_activity: System Activity
|
||||||
permission_delete_issue_watchers: Delete watchers
|
permission_delete_issue_watchers: Delete watchers
|
||||||
|
version_status_closed: closed
|
||||||
|
version_status_locked: locked
|
||||||
|
version_status_open: open
|
||||||
|
error_can_not_reopen_issue_on_closed_version: An issue assigned to a closed version can not be reopened
|
||||||
|
|
|
@ -830,3 +830,7 @@ ca:
|
||||||
field_active: Active
|
field_active: Active
|
||||||
enumeration_system_activity: System Activity
|
enumeration_system_activity: System Activity
|
||||||
permission_delete_issue_watchers: Delete watchers
|
permission_delete_issue_watchers: Delete watchers
|
||||||
|
version_status_closed: closed
|
||||||
|
version_status_locked: locked
|
||||||
|
version_status_open: open
|
||||||
|
error_can_not_reopen_issue_on_closed_version: An issue assigned to a closed version can not be reopened
|
||||||
|
|
|
@ -833,3 +833,7 @@ cs:
|
||||||
field_active: Active
|
field_active: Active
|
||||||
enumeration_system_activity: System Activity
|
enumeration_system_activity: System Activity
|
||||||
permission_delete_issue_watchers: Delete watchers
|
permission_delete_issue_watchers: Delete watchers
|
||||||
|
version_status_closed: closed
|
||||||
|
version_status_locked: locked
|
||||||
|
version_status_open: open
|
||||||
|
error_can_not_reopen_issue_on_closed_version: An issue assigned to a closed version can not be reopened
|
||||||
|
|
|
@ -853,3 +853,7 @@ da:
|
||||||
field_active: Active
|
field_active: Active
|
||||||
enumeration_system_activity: System Activity
|
enumeration_system_activity: System Activity
|
||||||
permission_delete_issue_watchers: Delete watchers
|
permission_delete_issue_watchers: Delete watchers
|
||||||
|
version_status_closed: closed
|
||||||
|
version_status_locked: locked
|
||||||
|
version_status_open: open
|
||||||
|
error_can_not_reopen_issue_on_closed_version: An issue assigned to a closed version can not be reopened
|
||||||
|
|
|
@ -853,3 +853,7 @@ de:
|
||||||
field_active: Active
|
field_active: Active
|
||||||
enumeration_system_activity: System Activity
|
enumeration_system_activity: System Activity
|
||||||
permission_delete_issue_watchers: Delete watchers
|
permission_delete_issue_watchers: Delete watchers
|
||||||
|
version_status_closed: closed
|
||||||
|
version_status_locked: locked
|
||||||
|
version_status_open: open
|
||||||
|
error_can_not_reopen_issue_on_closed_version: An issue assigned to a closed version can not be reopened
|
||||||
|
|
|
@ -833,3 +833,7 @@ el:
|
||||||
field_active: Active
|
field_active: Active
|
||||||
enumeration_system_activity: System Activity
|
enumeration_system_activity: System Activity
|
||||||
permission_delete_issue_watchers: Delete watchers
|
permission_delete_issue_watchers: Delete watchers
|
||||||
|
version_status_closed: closed
|
||||||
|
version_status_locked: locked
|
||||||
|
version_status_open: open
|
||||||
|
error_can_not_reopen_issue_on_closed_version: An issue assigned to a closed version can not be reopened
|
||||||
|
|
|
@ -155,6 +155,7 @@ en:
|
||||||
error_issue_not_found_in_project: 'The issue was not found or does not belong to this project'
|
error_issue_not_found_in_project: 'The issue was not found or does not belong to this project'
|
||||||
error_no_tracker_in_project: 'No tracker is associated to this project. Please check the Project settings.'
|
error_no_tracker_in_project: 'No tracker is associated to this project. Please check the Project settings.'
|
||||||
error_no_default_issue_status: 'No default issue status is defined. Please check your configuration (Go to "Administration -> Issue statuses").'
|
error_no_default_issue_status: 'No default issue status is defined. Please check your configuration (Go to "Administration -> Issue statuses").'
|
||||||
|
error_can_not_reopen_issue_on_closed_version: 'An issue assigned to a closed version can not be reopened'
|
||||||
|
|
||||||
warning_attachments_not_saved: "{{count}} file(s) could not be saved."
|
warning_attachments_not_saved: "{{count}} file(s) could not be saved."
|
||||||
|
|
||||||
|
@ -749,6 +750,10 @@ en:
|
||||||
status_active: active
|
status_active: active
|
||||||
status_registered: registered
|
status_registered: registered
|
||||||
status_locked: locked
|
status_locked: locked
|
||||||
|
|
||||||
|
version_status_open: open
|
||||||
|
version_status_locked: locked
|
||||||
|
version_status_closed: closed
|
||||||
|
|
||||||
field_active: Active
|
field_active: Active
|
||||||
|
|
||||||
|
|
|
@ -874,3 +874,7 @@ es:
|
||||||
field_active: Active
|
field_active: Active
|
||||||
enumeration_system_activity: System Activity
|
enumeration_system_activity: System Activity
|
||||||
permission_delete_issue_watchers: Delete watchers
|
permission_delete_issue_watchers: Delete watchers
|
||||||
|
version_status_closed: closed
|
||||||
|
version_status_locked: locked
|
||||||
|
version_status_open: open
|
||||||
|
error_can_not_reopen_issue_on_closed_version: An issue assigned to a closed version can not be reopened
|
||||||
|
|
|
@ -863,3 +863,7 @@ fi:
|
||||||
field_active: Active
|
field_active: Active
|
||||||
enumeration_system_activity: System Activity
|
enumeration_system_activity: System Activity
|
||||||
permission_delete_issue_watchers: Delete watchers
|
permission_delete_issue_watchers: Delete watchers
|
||||||
|
version_status_closed: closed
|
||||||
|
version_status_locked: locked
|
||||||
|
version_status_open: open
|
||||||
|
error_can_not_reopen_issue_on_closed_version: An issue assigned to a closed version can not be reopened
|
||||||
|
|
|
@ -177,6 +177,7 @@ fr:
|
||||||
error_scm_command_failed: "Une erreur s'est produite lors de l'accès au dépôt: {{value}}"
|
error_scm_command_failed: "Une erreur s'est produite lors de l'accès au dépôt: {{value}}"
|
||||||
error_scm_annotate: "L'entrée n'existe pas ou ne peut pas être annotée."
|
error_scm_annotate: "L'entrée n'existe pas ou ne peut pas être annotée."
|
||||||
error_issue_not_found_in_project: "La demande n'existe pas ou n'appartient pas à ce projet"
|
error_issue_not_found_in_project: "La demande n'existe pas ou n'appartient pas à ce projet"
|
||||||
|
error_can_not_reopen_issue_on_closed_version: 'Une demande assignée à une version fermée ne peut pas être réouverte'
|
||||||
|
|
||||||
warning_attachments_not_saved: "{{count}} fichier(s) n'ont pas pu être sauvegardés."
|
warning_attachments_not_saved: "{{count}} fichier(s) n'ont pas pu être sauvegardés."
|
||||||
|
|
||||||
|
@ -767,6 +768,10 @@ fr:
|
||||||
status_registered: enregistré
|
status_registered: enregistré
|
||||||
status_locked: vérouillé
|
status_locked: vérouillé
|
||||||
|
|
||||||
|
version_status_open: ouvert
|
||||||
|
version_status_locked: vérouillé
|
||||||
|
version_status_closed: fermé
|
||||||
|
|
||||||
text_select_mail_notifications: Actions pour lesquelles une notification par e-mail est envoyée
|
text_select_mail_notifications: Actions pour lesquelles une notification par e-mail est envoyée
|
||||||
text_regexp_info: ex. ^[A-Z0-9]+$
|
text_regexp_info: ex. ^[A-Z0-9]+$
|
||||||
text_min_max_length_info: 0 pour aucune restriction
|
text_min_max_length_info: 0 pour aucune restriction
|
||||||
|
|
|
@ -853,3 +853,7 @@ gl:
|
||||||
field_active: Active
|
field_active: Active
|
||||||
enumeration_system_activity: System Activity
|
enumeration_system_activity: System Activity
|
||||||
permission_delete_issue_watchers: Delete watchers
|
permission_delete_issue_watchers: Delete watchers
|
||||||
|
version_status_closed: closed
|
||||||
|
version_status_locked: locked
|
||||||
|
version_status_open: open
|
||||||
|
error_can_not_reopen_issue_on_closed_version: An issue assigned to a closed version can not be reopened
|
||||||
|
|
|
@ -837,3 +837,7 @@ he:
|
||||||
field_active: Active
|
field_active: Active
|
||||||
enumeration_system_activity: System Activity
|
enumeration_system_activity: System Activity
|
||||||
permission_delete_issue_watchers: Delete watchers
|
permission_delete_issue_watchers: Delete watchers
|
||||||
|
version_status_closed: closed
|
||||||
|
version_status_locked: locked
|
||||||
|
version_status_open: open
|
||||||
|
error_can_not_reopen_issue_on_closed_version: An issue assigned to a closed version can not be reopened
|
||||||
|
|
|
@ -858,3 +858,7 @@
|
||||||
field_active: Active
|
field_active: Active
|
||||||
enumeration_system_activity: System Activity
|
enumeration_system_activity: System Activity
|
||||||
permission_delete_issue_watchers: Delete watchers
|
permission_delete_issue_watchers: Delete watchers
|
||||||
|
version_status_closed: closed
|
||||||
|
version_status_locked: locked
|
||||||
|
version_status_open: open
|
||||||
|
error_can_not_reopen_issue_on_closed_version: An issue assigned to a closed version can not be reopened
|
||||||
|
|
|
@ -840,3 +840,7 @@ it:
|
||||||
field_active: Active
|
field_active: Active
|
||||||
enumeration_system_activity: System Activity
|
enumeration_system_activity: System Activity
|
||||||
permission_delete_issue_watchers: Delete watchers
|
permission_delete_issue_watchers: Delete watchers
|
||||||
|
version_status_closed: closed
|
||||||
|
version_status_locked: locked
|
||||||
|
version_status_open: open
|
||||||
|
error_can_not_reopen_issue_on_closed_version: An issue assigned to a closed version can not be reopened
|
||||||
|
|
|
@ -862,3 +862,7 @@ ja:
|
||||||
field_active: Active
|
field_active: Active
|
||||||
enumeration_system_activity: System Activity
|
enumeration_system_activity: System Activity
|
||||||
permission_delete_issue_watchers: Delete watchers
|
permission_delete_issue_watchers: Delete watchers
|
||||||
|
version_status_closed: closed
|
||||||
|
version_status_locked: locked
|
||||||
|
version_status_open: open
|
||||||
|
error_can_not_reopen_issue_on_closed_version: An issue assigned to a closed version can not be reopened
|
||||||
|
|
|
@ -893,3 +893,7 @@ ko:
|
||||||
field_active: Active
|
field_active: Active
|
||||||
enumeration_system_activity: System Activity
|
enumeration_system_activity: System Activity
|
||||||
permission_delete_issue_watchers: Delete watchers
|
permission_delete_issue_watchers: Delete watchers
|
||||||
|
version_status_closed: closed
|
||||||
|
version_status_locked: locked
|
||||||
|
version_status_open: open
|
||||||
|
error_can_not_reopen_issue_on_closed_version: An issue assigned to a closed version can not be reopened
|
||||||
|
|
|
@ -863,3 +863,7 @@ lt:
|
||||||
field_active: Active
|
field_active: Active
|
||||||
enumeration_system_activity: System Activity
|
enumeration_system_activity: System Activity
|
||||||
permission_delete_issue_watchers: Delete watchers
|
permission_delete_issue_watchers: Delete watchers
|
||||||
|
version_status_closed: closed
|
||||||
|
version_status_locked: locked
|
||||||
|
version_status_open: open
|
||||||
|
error_can_not_reopen_issue_on_closed_version: An issue assigned to a closed version can not be reopened
|
||||||
|
|
|
@ -815,3 +815,7 @@ nl:
|
||||||
field_active: Active
|
field_active: Active
|
||||||
enumeration_system_activity: System Activity
|
enumeration_system_activity: System Activity
|
||||||
permission_delete_issue_watchers: Delete watchers
|
permission_delete_issue_watchers: Delete watchers
|
||||||
|
version_status_closed: closed
|
||||||
|
version_status_locked: locked
|
||||||
|
version_status_open: open
|
||||||
|
error_can_not_reopen_issue_on_closed_version: An issue assigned to a closed version can not be reopened
|
||||||
|
|
|
@ -828,3 +828,7 @@
|
||||||
field_active: Active
|
field_active: Active
|
||||||
enumeration_system_activity: System Activity
|
enumeration_system_activity: System Activity
|
||||||
permission_delete_issue_watchers: Delete watchers
|
permission_delete_issue_watchers: Delete watchers
|
||||||
|
version_status_closed: closed
|
||||||
|
version_status_locked: locked
|
||||||
|
version_status_open: open
|
||||||
|
error_can_not_reopen_issue_on_closed_version: An issue assigned to a closed version can not be reopened
|
||||||
|
|
|
@ -856,3 +856,7 @@ pl:
|
||||||
field_active: Aktywne
|
field_active: Aktywne
|
||||||
enumeration_system_activity: Aktywność Systemowa
|
enumeration_system_activity: Aktywność Systemowa
|
||||||
permission_delete_issue_watchers: Delete watchers
|
permission_delete_issue_watchers: Delete watchers
|
||||||
|
version_status_closed: closed
|
||||||
|
version_status_locked: locked
|
||||||
|
version_status_open: open
|
||||||
|
error_can_not_reopen_issue_on_closed_version: An issue assigned to a closed version can not be reopened
|
||||||
|
|
|
@ -859,3 +859,7 @@ pt-BR:
|
||||||
field_active: Ativo
|
field_active: Ativo
|
||||||
enumeration_system_activity: Atividade do sistema
|
enumeration_system_activity: Atividade do sistema
|
||||||
permission_delete_issue_watchers: Deletar observadores
|
permission_delete_issue_watchers: Deletar observadores
|
||||||
|
version_status_closed: closed
|
||||||
|
version_status_locked: locked
|
||||||
|
version_status_open: open
|
||||||
|
error_can_not_reopen_issue_on_closed_version: An issue assigned to a closed version can not be reopened
|
||||||
|
|
|
@ -845,3 +845,7 @@ pt:
|
||||||
field_active: Active
|
field_active: Active
|
||||||
enumeration_system_activity: System Activity
|
enumeration_system_activity: System Activity
|
||||||
permission_delete_issue_watchers: Delete watchers
|
permission_delete_issue_watchers: Delete watchers
|
||||||
|
version_status_closed: closed
|
||||||
|
version_status_locked: locked
|
||||||
|
version_status_open: open
|
||||||
|
error_can_not_reopen_issue_on_closed_version: An issue assigned to a closed version can not be reopened
|
||||||
|
|
|
@ -830,3 +830,7 @@ ro:
|
||||||
field_active: Active
|
field_active: Active
|
||||||
enumeration_system_activity: System Activity
|
enumeration_system_activity: System Activity
|
||||||
permission_delete_issue_watchers: Delete watchers
|
permission_delete_issue_watchers: Delete watchers
|
||||||
|
version_status_closed: closed
|
||||||
|
version_status_locked: locked
|
||||||
|
version_status_open: open
|
||||||
|
error_can_not_reopen_issue_on_closed_version: An issue assigned to a closed version can not be reopened
|
||||||
|
|
|
@ -941,3 +941,7 @@ ru:
|
||||||
field_active: Active
|
field_active: Active
|
||||||
enumeration_system_activity: System Activity
|
enumeration_system_activity: System Activity
|
||||||
permission_delete_issue_watchers: Delete watchers
|
permission_delete_issue_watchers: Delete watchers
|
||||||
|
version_status_closed: closed
|
||||||
|
version_status_locked: locked
|
||||||
|
version_status_open: open
|
||||||
|
error_can_not_reopen_issue_on_closed_version: An issue assigned to a closed version can not be reopened
|
||||||
|
|
|
@ -832,3 +832,7 @@ sk:
|
||||||
field_active: Active
|
field_active: Active
|
||||||
enumeration_system_activity: System Activity
|
enumeration_system_activity: System Activity
|
||||||
permission_delete_issue_watchers: Delete watchers
|
permission_delete_issue_watchers: Delete watchers
|
||||||
|
version_status_closed: closed
|
||||||
|
version_status_locked: locked
|
||||||
|
version_status_open: open
|
||||||
|
error_can_not_reopen_issue_on_closed_version: An issue assigned to a closed version can not be reopened
|
||||||
|
|
|
@ -829,3 +829,7 @@ sl:
|
||||||
field_active: Active
|
field_active: Active
|
||||||
enumeration_system_activity: System Activity
|
enumeration_system_activity: System Activity
|
||||||
permission_delete_issue_watchers: Delete watchers
|
permission_delete_issue_watchers: Delete watchers
|
||||||
|
version_status_closed: closed
|
||||||
|
version_status_locked: locked
|
||||||
|
version_status_open: open
|
||||||
|
error_can_not_reopen_issue_on_closed_version: An issue assigned to a closed version can not be reopened
|
||||||
|
|
|
@ -848,3 +848,7 @@
|
||||||
field_active: Active
|
field_active: Active
|
||||||
enumeration_system_activity: System Activity
|
enumeration_system_activity: System Activity
|
||||||
permission_delete_issue_watchers: Delete watchers
|
permission_delete_issue_watchers: Delete watchers
|
||||||
|
version_status_closed: closed
|
||||||
|
version_status_locked: locked
|
||||||
|
version_status_open: open
|
||||||
|
error_can_not_reopen_issue_on_closed_version: An issue assigned to a closed version can not be reopened
|
||||||
|
|
|
@ -881,3 +881,7 @@ sv:
|
||||||
enumeration_doc_categories: Dokumentkategorier
|
enumeration_doc_categories: Dokumentkategorier
|
||||||
enumeration_activities: Aktiviteter (tidsuppföljning)
|
enumeration_activities: Aktiviteter (tidsuppföljning)
|
||||||
enumeration_system_activity: Systemaktivitet
|
enumeration_system_activity: Systemaktivitet
|
||||||
|
version_status_closed: closed
|
||||||
|
version_status_locked: locked
|
||||||
|
version_status_open: open
|
||||||
|
error_can_not_reopen_issue_on_closed_version: An issue assigned to a closed version can not be reopened
|
||||||
|
|
|
@ -830,3 +830,7 @@ th:
|
||||||
field_active: Active
|
field_active: Active
|
||||||
enumeration_system_activity: System Activity
|
enumeration_system_activity: System Activity
|
||||||
permission_delete_issue_watchers: Delete watchers
|
permission_delete_issue_watchers: Delete watchers
|
||||||
|
version_status_closed: closed
|
||||||
|
version_status_locked: locked
|
||||||
|
version_status_open: open
|
||||||
|
error_can_not_reopen_issue_on_closed_version: An issue assigned to a closed version can not be reopened
|
||||||
|
|
|
@ -860,3 +860,7 @@ tr:
|
||||||
field_active: Active
|
field_active: Active
|
||||||
enumeration_system_activity: System Activity
|
enumeration_system_activity: System Activity
|
||||||
permission_delete_issue_watchers: Delete watchers
|
permission_delete_issue_watchers: Delete watchers
|
||||||
|
version_status_closed: closed
|
||||||
|
version_status_locked: locked
|
||||||
|
version_status_open: open
|
||||||
|
error_can_not_reopen_issue_on_closed_version: An issue assigned to a closed version can not be reopened
|
||||||
|
|
|
@ -829,3 +829,7 @@ uk:
|
||||||
field_active: Active
|
field_active: Active
|
||||||
enumeration_system_activity: System Activity
|
enumeration_system_activity: System Activity
|
||||||
permission_delete_issue_watchers: Delete watchers
|
permission_delete_issue_watchers: Delete watchers
|
||||||
|
version_status_closed: closed
|
||||||
|
version_status_locked: locked
|
||||||
|
version_status_open: open
|
||||||
|
error_can_not_reopen_issue_on_closed_version: An issue assigned to a closed version can not be reopened
|
||||||
|
|
|
@ -892,3 +892,7 @@ vi:
|
||||||
field_active: Active
|
field_active: Active
|
||||||
enumeration_system_activity: System Activity
|
enumeration_system_activity: System Activity
|
||||||
permission_delete_issue_watchers: Delete watchers
|
permission_delete_issue_watchers: Delete watchers
|
||||||
|
version_status_closed: closed
|
||||||
|
version_status_locked: locked
|
||||||
|
version_status_open: open
|
||||||
|
error_can_not_reopen_issue_on_closed_version: An issue assigned to a closed version can not be reopened
|
||||||
|
|
|
@ -923,3 +923,7 @@
|
||||||
enumeration_doc_categories: 文件分類
|
enumeration_doc_categories: 文件分類
|
||||||
enumeration_activities: 活動 (時間追蹤)
|
enumeration_activities: 活動 (時間追蹤)
|
||||||
enumeration_system_activity: 系統活動
|
enumeration_system_activity: 系統活動
|
||||||
|
version_status_closed: closed
|
||||||
|
version_status_locked: locked
|
||||||
|
version_status_open: open
|
||||||
|
error_can_not_reopen_issue_on_closed_version: An issue assigned to a closed version can not be reopened
|
||||||
|
|
|
@ -855,3 +855,7 @@ zh:
|
||||||
field_active: Active
|
field_active: Active
|
||||||
enumeration_system_activity: System Activity
|
enumeration_system_activity: System Activity
|
||||||
permission_delete_issue_watchers: Delete watchers
|
permission_delete_issue_watchers: Delete watchers
|
||||||
|
version_status_closed: closed
|
||||||
|
version_status_locked: locked
|
||||||
|
version_status_open: open
|
||||||
|
error_can_not_reopen_issue_on_closed_version: An issue assigned to a closed version can not be reopened
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
class AddVersionsStatus < ActiveRecord::Migration
|
||||||
|
def self.up
|
||||||
|
add_column :versions, :status, :string, :default => 'open'
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.down
|
||||||
|
remove_column :versions, :status
|
||||||
|
end
|
||||||
|
end
|
|
@ -124,6 +124,8 @@ tr.message td.last_message { font-size: 80%; }
|
||||||
tr.message.locked td.subject a { background-image: url(../images/locked.png); }
|
tr.message.locked td.subject a { background-image: url(../images/locked.png); }
|
||||||
tr.message.sticky td.subject a { background-image: url(../images/sticky.png); font-weight: bold; }
|
tr.message.sticky td.subject a { background-image: url(../images/sticky.png); font-weight: bold; }
|
||||||
|
|
||||||
|
tr.version.closed, tr.version.closed a { color: #999; }
|
||||||
|
|
||||||
tr.user td { width:13%; }
|
tr.user td { width:13%; }
|
||||||
tr.user td.email { width:18%; }
|
tr.user td.email { width:18%; }
|
||||||
tr.user td { white-space: nowrap; }
|
tr.user td { white-space: nowrap; }
|
||||||
|
|
|
@ -157,3 +157,35 @@ issues_010:
|
||||||
status_id: 1
|
status_id: 1
|
||||||
start_date: <%= Date.today.to_s(:db) %>
|
start_date: <%= Date.today.to_s(:db) %>
|
||||||
due_date: <%= 1.days.from_now.to_date.to_s(:db) %>
|
due_date: <%= 1.days.from_now.to_date.to_s(:db) %>
|
||||||
|
issues_011:
|
||||||
|
created_on: <%= 3.days.ago.to_date.to_s(:db) %>
|
||||||
|
project_id: 1
|
||||||
|
updated_on: <%= 1.day.ago.to_date.to_s(:db) %>
|
||||||
|
priority_id: 5
|
||||||
|
subject: Closed issue on a closed version
|
||||||
|
id: 11
|
||||||
|
fixed_version_id: 1
|
||||||
|
category_id: 1
|
||||||
|
description:
|
||||||
|
tracker_id: 1
|
||||||
|
assigned_to_id:
|
||||||
|
author_id: 2
|
||||||
|
status_id: 5
|
||||||
|
start_date: <%= 1.day.ago.to_date.to_s(:db) %>
|
||||||
|
due_date:
|
||||||
|
issues_012:
|
||||||
|
created_on: <%= 3.days.ago.to_date.to_s(:db) %>
|
||||||
|
project_id: 1
|
||||||
|
updated_on: <%= 1.day.ago.to_date.to_s(:db) %>
|
||||||
|
priority_id: 5
|
||||||
|
subject: Closed issue on a locked version
|
||||||
|
id: 12
|
||||||
|
fixed_version_id: 2
|
||||||
|
category_id: 1
|
||||||
|
description:
|
||||||
|
tracker_id: 1
|
||||||
|
assigned_to_id:
|
||||||
|
author_id: 2
|
||||||
|
status_id: 5
|
||||||
|
start_date: <%= 1.day.ago.to_date.to_s(:db) %>
|
||||||
|
due_date:
|
||||||
|
|
|
@ -7,6 +7,7 @@ versions_001:
|
||||||
id: 1
|
id: 1
|
||||||
description: Beta
|
description: Beta
|
||||||
effective_date: 2006-07-01
|
effective_date: 2006-07-01
|
||||||
|
status: closed
|
||||||
versions_002:
|
versions_002:
|
||||||
created_on: 2006-07-19 21:00:33 +02:00
|
created_on: 2006-07-19 21:00:33 +02:00
|
||||||
name: "1.0"
|
name: "1.0"
|
||||||
|
@ -15,6 +16,7 @@ versions_002:
|
||||||
id: 2
|
id: 2
|
||||||
description: Stable release
|
description: Stable release
|
||||||
effective_date: <%= 20.day.from_now.to_date.to_s(:db) %>
|
effective_date: <%= 20.day.from_now.to_date.to_s(:db) %>
|
||||||
|
status: locked
|
||||||
versions_003:
|
versions_003:
|
||||||
created_on: 2006-07-19 21:00:33 +02:00
|
created_on: 2006-07-19 21:00:33 +02:00
|
||||||
name: "2.0"
|
name: "2.0"
|
||||||
|
@ -23,4 +25,5 @@ versions_003:
|
||||||
id: 3
|
id: 3
|
||||||
description: Future version
|
description: Future version
|
||||||
effective_date:
|
effective_date:
|
||||||
|
status: open
|
||||||
|
|
|
@ -20,6 +20,7 @@ require File.dirname(__FILE__) + '/../test_helper'
|
||||||
class IssueTest < ActiveSupport::TestCase
|
class IssueTest < ActiveSupport::TestCase
|
||||||
fixtures :projects, :users, :members, :member_roles,
|
fixtures :projects, :users, :members, :member_roles,
|
||||||
:trackers, :projects_trackers,
|
:trackers, :projects_trackers,
|
||||||
|
:versions,
|
||||||
:issue_statuses, :issue_categories, :issue_relations, :workflows,
|
:issue_statuses, :issue_categories, :issue_relations, :workflows,
|
||||||
:enumerations,
|
:enumerations,
|
||||||
:issues,
|
:issues,
|
||||||
|
@ -184,6 +185,56 @@ class IssueTest < ActiveSupport::TestCase
|
||||||
assert !issue1.reload.closed?
|
assert !issue1.reload.closed?
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_assignable_versions
|
||||||
|
issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1, :status_id => 1, :fixed_version_id => 1, :subject => 'New issue')
|
||||||
|
assert_equal ['open'], issue.assignable_versions.collect(&:status).uniq
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_should_not_be_able_to_assign_a_new_issue_to_a_closed_version
|
||||||
|
issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1, :status_id => 1, :fixed_version_id => 1, :subject => 'New issue')
|
||||||
|
assert !issue.save
|
||||||
|
assert_not_nil issue.errors.on(:fixed_version_id)
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_should_not_be_able_to_assign_a_new_issue_to_a_locked_version
|
||||||
|
issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1, :status_id => 1, :fixed_version_id => 2, :subject => 'New issue')
|
||||||
|
assert !issue.save
|
||||||
|
assert_not_nil issue.errors.on(:fixed_version_id)
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_should_be_able_to_assign_a_new_issue_to_an_open_version
|
||||||
|
issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1, :status_id => 1, :fixed_version_id => 3, :subject => 'New issue')
|
||||||
|
assert issue.save
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_should_be_able_to_update_an_issue_assigned_to_a_closed_version
|
||||||
|
issue = Issue.find(11)
|
||||||
|
assert_equal 'closed', issue.fixed_version.status
|
||||||
|
issue.subject = 'Subject changed'
|
||||||
|
assert issue.save
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_should_not_be_able_to_reopen_an_issue_assigned_to_a_closed_version
|
||||||
|
issue = Issue.find(11)
|
||||||
|
issue.status_id = 1
|
||||||
|
assert !issue.save
|
||||||
|
assert_not_nil issue.errors.on_base
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_should_be_able_to_reopen_and_reassign_an_issue_assigned_to_a_closed_version
|
||||||
|
issue = Issue.find(11)
|
||||||
|
issue.status_id = 1
|
||||||
|
issue.fixed_version_id = 3
|
||||||
|
assert issue.save
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_should_be_able_to_reopen_an_issue_assigned_to_a_locked_version
|
||||||
|
issue = Issue.find(12)
|
||||||
|
assert_equal 'locked', issue.fixed_version.status
|
||||||
|
issue.status_id = 1
|
||||||
|
assert issue.save
|
||||||
|
end
|
||||||
|
|
||||||
def test_move_to_another_project_with_same_category
|
def test_move_to_another_project_with_same_category
|
||||||
issue = Issue.find(1)
|
issue = Issue.find(1)
|
||||||
assert issue.move_to(Project.find(2))
|
assert issue.move_to(Project.find(2))
|
||||||
|
|
|
@ -26,6 +26,7 @@ class VersionTest < ActiveSupport::TestCase
|
||||||
def test_create
|
def test_create
|
||||||
v = Version.new(:project => Project.find(1), :name => '1.1', :effective_date => '2011-03-25')
|
v = Version.new(:project => Project.find(1), :name => '1.1', :effective_date => '2011-03-25')
|
||||||
assert v.save
|
assert v.save
|
||||||
|
assert_equal 'open', v.status
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_invalid_effective_date_validation
|
def test_invalid_effective_date_validation
|
||||||
|
|
Loading…
Reference in New Issue