Feature #22802 » manual_set_issue_position_in_versions_v2.patch
| app/controllers/issues_controller.rb | ||
|---|---|---|
| 192 | 192 | |
| 193 | 193 |
respond_to do |format| |
| 194 | 194 |
format.html { redirect_back_or_default issue_path(@issue, previous_and_next_issue_ids_params) }
|
| 195 |
format.js { render :nothing => true }
|
|
| 195 | 196 |
format.api { render_api_ok }
|
| 196 | 197 |
end |
| 197 | 198 |
else |
| 198 | 199 |
respond_to do |format| |
| 199 | 200 |
format.html { render :action => 'edit' }
|
| 201 |
format.js { render :nothing => true, :status => 422 }
|
|
| 200 | 202 |
format.api { render_validation_errors(@issue) }
|
| 201 | 203 |
end |
| 202 | 204 |
end |
| ... | ... | |
| 380 | 382 |
# Overrides Redmine::MenuManager::MenuController::ClassMethods for |
| 381 | 383 |
# when the "New issue" tab is enabled |
| 382 | 384 |
def current_menu_item |
| 383 |
if Setting.new_item_menu_tab == '1' && [:new, :create].include?(action_name.to_sym)
|
|
| 385 |
if Setting.new_item_menu_tab == '1' && [:new, :create].include?(action_name.to_sym) |
|
| 384 | 386 |
:new_issue |
| 385 | 387 |
else |
| 386 | 388 |
super |
| app/controllers/versions_controller.rb | ||
|---|---|---|
| 46 | 46 | |
| 47 | 47 |
@issues_by_version = {}
|
| 48 | 48 |
if @selected_tracker_ids.any? && @versions.any? |
| 49 | ||
| 49 | 50 |
issues = Issue.visible. |
| 50 | 51 |
includes(:project, :tracker). |
| 51 | 52 |
preload(:status, :priority, :fixed_version). |
| 52 | 53 |
where(:tracker_id => @selected_tracker_ids, :project_id => project_ids, :fixed_version_id => @versions.map(&:id)). |
| 53 |
order("#{Project.table_name}.lft, #{Tracker.table_name}.position, #{Issue.table_name}.id")
|
|
| 54 |
order(order_issues_by)
|
|
| 54 | 55 |
@issues_by_version = issues.group_by(&:fixed_version) |
| 55 | 56 |
end |
| 56 | 57 |
@versions.reject! {|version| !project_ids.include?(version.project_id) && @issues_by_version[version].blank?}
|
| ... | ... | |
| 67 | 68 |
@issues = @version.fixed_issues.visible. |
| 68 | 69 |
includes(:status, :tracker, :priority). |
| 69 | 70 |
preload(:project). |
| 70 |
reorder("#{Tracker.table_name}.position, #{Issue.table_name}.id").
|
|
| 71 |
reorder(order_issues_by).
|
|
| 71 | 72 |
to_a |
| 72 | 73 |
} |
| 73 | 74 |
format.api |
| ... | ... | |
| 180 | 181 |
@selected_tracker_ids = (default_trackers || selectable_trackers).collect {|t| t.id.to_s }
|
| 181 | 182 |
end |
| 182 | 183 |
end |
| 184 | ||
| 185 |
def order_issues_by |
|
| 186 |
if Setting.manual_issue_position_in_versions == '1' |
|
| 187 |
return "COALESCE(#{Issue.table_name}.position, 999999)"
|
|
| 188 |
else |
|
| 189 |
return "#{Tracker.table_name}.position, #{Issue.table_name}.id"
|
|
| 190 |
end |
|
| 191 |
end |
|
| 183 | 192 |
end |
| app/models/issue.rb | ||
|---|---|---|
| 56 | 56 | |
| 57 | 57 |
acts_as_activity_provider :scope => preload(:project, :author, :tracker, :status), |
| 58 | 58 |
:author_key => :author_id |
| 59 | ||
| 59 |
acts_as_positioned :scope => [:fixed_version_id] |
|
| 60 | 60 |
DONE_RATIO_OPTIONS = %w(issue_field issue_status) |
| 61 | 61 | |
| 62 | 62 |
attr_accessor :deleted_attachment_ids |
| ... | ... | |
| 468 | 468 |
:if => lambda {|issue, user| (issue.new_record? || issue.attributes_editable?(user)) &&
|
| 469 | 469 |
user.allowed_to?(:manage_subtasks, issue.project)} |
| 470 | 470 | |
| 471 |
safe_attributes 'position', |
|
| 472 |
:if => lambda {|issue, user| user.allowed_to?(:change_issue_position_in_version, issue.project)}
|
|
| 473 | ||
| 471 | 474 |
safe_attributes 'deleted_attachment_ids', |
| 472 | 475 |
:if => lambda {|issue, user| issue.attachments_deletable?(user)}
|
| 473 | 476 | |
| ... | ... | |
| 776 | 779 | |
| 777 | 780 |
# Returns the names of attributes that are journalized when updating the issue |
| 778 | 781 |
def journalized_attribute_names |
| 779 |
names = Issue.column_names - %w(id root_id lft rgt lock_version created_on updated_on closed_on) |
|
| 782 |
names = Issue.column_names - %w(id root_id lft rgt lock_version position created_on updated_on closed_on)
|
|
| 780 | 783 |
if tracker |
| 781 | 784 |
names -= tracker.disabled_core_fields |
| 782 | 785 |
end |
| ... | ... | |
| 1402 | 1405 |
end |
| 1403 | 1406 |
Project.where(condition).having_trackers |
| 1404 | 1407 |
end |
| 1405 |
|
|
| 1408 | ||
| 1406 | 1409 |
# Returns a scope of trackers that user can assign the issue to |
| 1407 | 1410 |
def allowed_target_trackers(user=User.current) |
| 1408 | 1411 |
self.class.allowed_target_trackers(project, user, tracker_id_was) |
| app/views/settings/_issues.html.erb | ||
|---|---|---|
| 13 | 13 | |
| 14 | 14 |
<p><%= setting_check_box :display_subprojects_issues %></p> |
| 15 | 15 | |
| 16 |
<p><%= setting_check_box :manual_issue_position_in_versions %></p> |
|
| 17 | ||
| 16 | 18 |
<p><%= setting_select :issue_done_ratio, Issue::DONE_RATIO_OPTIONS.collect {|i| [l("setting_issue_done_ratio_#{i}"), i]} %></p>
|
| 17 | 19 | |
| 18 | 20 |
<p><%= setting_multiselect :non_working_week_days, (1..7).map {|d| [day_name(d), d.to_s]}, :inline => true %></p>
|
| ... | ... | |
| 20 | 22 |
<p><%= setting_text_field :issues_export_limit, :size => 6 %></p> |
| 21 | 23 | |
| 22 | 24 |
<p><%= setting_text_field :gantt_items_limit, :size => 6 %></p> |
| 25 | ||
| 23 | 26 |
</div> |
| 24 | 27 | |
| 25 | 28 |
<fieldset class="box"> |
| app/views/versions/index.html.erb | ||
|---|---|---|
| 26 | 26 |
<%= form_tag({}) do -%>
|
| 27 | 27 |
<table class="list related-issues"> |
| 28 | 28 |
<caption><%= l(:label_related_issues) %></caption> |
| 29 |
<% issues.each do |issue| -%> |
|
| 30 |
<tr class="hascontextmenu"> |
|
| 31 |
<td class="checkbox"><%= check_box_tag 'ids[]', issue.id, false, :id => nil %></td> |
|
| 32 |
<td class="subject"><%= link_to_issue(issue, :project => (@project != issue.project)) %></td> |
|
| 33 |
</tr> |
|
| 34 |
<% end -%> |
|
| 29 |
<tbody> |
|
| 30 |
<% issues.each do |issue| -%> |
|
| 31 |
<tr class="hascontextmenu"> |
|
| 32 |
<td class="checkbox"><%= check_box_tag 'ids[]', issue.id, false, :id => nil %></td> |
|
| 33 |
<td class="subject"><%= link_to_issue(issue, :project => (@project != issue.project)) %></td> |
|
| 34 |
<% if Setting.manual_issue_position_in_versions == '1' && User.current.allowed_to?(:change_issue_position_in_version, version.project) %> |
|
| 35 |
<td class="sortable"><%= reorder_handle(issue) %></td> |
|
| 36 |
<% end%> |
|
| 37 |
</tr> |
|
| 38 |
<% end -%> |
|
| 39 |
</tbody> |
|
| 35 | 40 |
</table> |
| 36 | 41 |
<% end %> |
| 37 | 42 |
<% end %> |
| ... | ... | |
| 85 | 90 |
</ul> |
| 86 | 91 |
<% if @completed_versions.present? %> |
| 87 | 92 |
<p> |
| 88 |
<%= link_to_function l(:label_completed_versions),
|
|
| 93 |
<%= link_to_function l(:label_completed_versions), |
|
| 89 | 94 |
'$("#toggle-completed-versions").toggleClass("collapsed"); $("#completed-versions").toggle()',
|
| 90 | 95 |
:id => 'toggle-completed-versions', :class => 'collapsible collapsed' %> |
| 91 | 96 |
<ul id = "completed-versions" style = "display:none;"> |
| 92 | 97 |
<% @completed_versions.each do |version| %> |
| 93 | 98 |
<li><%= link_to_version version %></li> |
| 94 |
<% end %>
|
|
| 99 |
<% end %> |
|
| 95 | 100 |
</ul> |
| 96 | 101 |
</p> |
| 97 | 102 |
<% end %> |
| ... | ... | |
| 100 | 105 |
<% html_title(l(:label_roadmap)) %> |
| 101 | 106 | |
| 102 | 107 |
<%= context_menu issues_context_menu_path %> |
| 108 | ||
| 109 |
<% if Setting.manual_issue_position_in_versions == '1' && |
|
| 110 |
User.current.allowed_to?(:change_issue_position_in_version, @project) %> |
|
| 111 |
<%= javascript_tag do %> |
|
| 112 |
$(function() { $("table.related-issues tbody").positionedItems(); });
|
|
| 113 |
<% end %> |
|
| 114 |
<% end %> |
|
| 115 | ||
| app/views/versions/show.html.erb | ||
|---|---|---|
| 38 | 38 |
<% if @issues.present? %> |
| 39 | 39 |
<%= form_tag({}) do -%>
|
| 40 | 40 |
<table class="list related-issues"> |
| 41 |
<caption><%= l(:label_related_issues) %></caption> |
|
| 42 |
<%- @issues.each do |issue| -%> |
|
| 43 |
<tr class="issue hascontextmenu"> |
|
| 44 |
<td class="checkbox"><%= check_box_tag 'ids[]', issue.id, false, :id => nil %></td> |
|
| 45 |
<td class="subject"><%= link_to_issue(issue, :project => (@project != issue.project)) %></td> |
|
| 46 |
</tr> |
|
| 47 |
<% end %> |
|
| 41 |
<caption><%= l(:label_related_issues) %></caption> |
|
| 42 |
<tbody> |
|
| 43 |
<%- @issues.each do |issue| -%> |
|
| 44 |
<tr class="issue hascontextmenu"> |
|
| 45 |
<td class="checkbox"><%= check_box_tag 'ids[]', issue.id, false, :id => nil %></td> |
|
| 46 |
<td class="subject"><%= link_to_issue(issue, :project => (@project != issue.project)) %></td> |
|
| 47 |
<% if Setting.manual_issue_position_in_versions == '1' && !@version.closed? && User.current.allowed_to?(:change_issue_position_in_version, @version.project) %> |
|
| 48 |
<td class="sortable"><%= reorder_handle(issue) %></td> |
|
| 49 |
<% end%> |
|
| 50 |
</tr> |
|
| 51 |
<% end %> |
|
| 52 |
</tbody> |
|
| 48 | 53 |
</table> |
| 49 | 54 |
<% end %> |
| 50 | 55 |
<%= context_menu issues_context_menu_path %> |
| ... | ... | |
| 54 | 59 |
<%= call_hook :view_versions_show_bottom, :version => @version %> |
| 55 | 60 | |
| 56 | 61 |
<% html_title @version.name %> |
| 62 | ||
| 63 |
<% if Setting.manual_issue_position_in_versions == '1' && !@version.closed? && User.current.allowed_to?(:change_issue_position_in_version, @version.project) %> |
|
| 64 |
<%= javascript_tag do %> |
|
| 65 |
$(function() { $("table.related-issues tbody").positionedItems(); });
|
|
| 66 |
<% end %> |
|
| 67 |
<% end %> |
|
| config/locales/en.yml | ||
|---|---|---|
| 447 | 447 |
setting_attachment_extensions_allowed: Allowed extensions |
| 448 | 448 |
setting_attachment_extensions_denied: Disallowed extensions |
| 449 | 449 |
setting_new_item_menu_tab: Project menu tab for creating new objects |
| 450 |
setting_manual_issue_position_in_versions: Enable manually set issue position in versions |
|
| 450 | 451 | |
| 451 | 452 |
permission_add_project: Create project |
| 452 | 453 |
permission_add_subprojects: Create subprojects |
| ... | ... | |
| 513 | 514 |
permission_manage_subtasks: Manage subtasks |
| 514 | 515 |
permission_manage_related_issues: Manage related issues |
| 515 | 516 |
permission_import_issues: Import issues |
| 517 |
permission_change_issue_position_in_version: Change issue position in version |
|
| 516 | 518 | |
| 517 | 519 |
project_module_issue_tracking: Issue tracking |
| 518 | 520 |
project_module_time_tracking: Time tracking |
| config/settings.yml | ||
|---|---|---|
| 169 | 169 |
default: 'derived' |
| 170 | 170 |
link_copied_issue: |
| 171 | 171 |
default: 'ask' |
| 172 |
manual_issue_position_in_versions: |
|
| 173 |
default: 0 |
|
| 172 | 174 |
issue_group_assignment: |
| 173 | 175 |
default: 0 |
| 174 | 176 |
default_issue_start_date_to_creation_date: |
| db/migrate/20160901154541_add_issue_position.rb | ||
|---|---|---|
| 1 |
class AddIssuePosition < ActiveRecord::Migration |
|
| 2 |
def up |
|
| 3 |
add_column :issues, :position, :integer |
|
| 4 |
end |
|
| 5 | ||
| 6 |
def down |
|
| 7 |
remove_column :issues, :position |
|
| 8 |
end |
|
| 9 |
end |
|
| lib/redmine.rb | ||
|---|---|---|
| 110 | 110 |
map.permission :view_private_notes, {}, :read => true, :require => :member
|
| 111 | 111 |
map.permission :set_notes_private, {}, :require => :member
|
| 112 | 112 |
map.permission :delete_issues, {:issues => :destroy}, :require => :member
|
| 113 |
map.permission :change_issue_position_in_version, {}
|
|
| 113 | 114 |
# Queries |
| 114 | 115 |
map.permission :manage_public_queries, {:queries => [:new, :create, :edit, :update, :destroy]}, :require => :member
|
| 115 | 116 |
map.permission :save_queries, {:queries => [:new, :create, :edit, :update, :destroy]}, :require => :loggedin
|
| public/stylesheets/application.css | ||
|---|---|---|
| 472 | 472 | |
| 473 | 473 |
div#roadmap .related-issues { margin-bottom: 1em; }
|
| 474 | 474 |
div#roadmap .related-issues td.checkbox { display: none; }
|
| 475 |
div#roadmap .related-issues td.sortable { text-align: right; }
|
|
| 475 | 476 |
div#roadmap .wiki h1:first-child { display: none; }
|
| 476 | 477 |
div#roadmap .wiki h1 { font-size: 120%; }
|
| 477 | 478 |
div#roadmap .wiki h2 { font-size: 110%; }
|
| test/fixtures/issues.yml | ||
|---|---|---|
| 1 |
---
|
|
| 2 |
issues_001:
|
|
| 1 |
--- |
|
| 2 |
issues_001: |
|
| 3 | 3 |
created_on: <%= 3.days.ago.to_s(:db) %> |
| 4 | 4 |
project_id: 1 |
| 5 | 5 |
updated_on: <%= 1.day.ago.to_s(:db) %> |
| 6 | 6 |
priority_id: 4 |
| 7 | 7 |
subject: Cannot print recipes |
| 8 | 8 |
id: 1 |
| 9 |
fixed_version_id:
|
|
| 9 |
fixed_version_id: |
|
| 10 | 10 |
category_id: 1 |
| 11 | 11 |
description: Unable to print recipes |
| 12 | 12 |
tracker_id: 1 |
| 13 |
assigned_to_id:
|
|
| 13 |
assigned_to_id: |
|
| 14 | 14 |
author_id: 2 |
| 15 | 15 |
status_id: 1 |
| 16 | 16 |
start_date: <%= 1.day.ago.to_date.to_s(:db) %> |
| ... | ... | |
| 19 | 19 |
lft: 1 |
| 20 | 20 |
rgt: 2 |
| 21 | 21 |
lock_version: 3 |
| 22 |
issues_002:
|
|
| 22 |
issues_002: |
|
| 23 | 23 |
created_on: 2006-07-19 21:04:21 +02:00 |
| 24 | 24 |
project_id: 1 |
| 25 | 25 |
updated_on: 2006-07-19 21:09:50 +02:00 |
| ... | ... | |
| 27 | 27 |
subject: Add ingredients categories |
| 28 | 28 |
id: 2 |
| 29 | 29 |
fixed_version_id: 2 |
| 30 |
category_id:
|
|
| 30 |
category_id: |
|
| 31 | 31 |
description: Ingredients of the recipe should be classified by categories |
| 32 | 32 |
tracker_id: 2 |
| 33 | 33 |
assigned_to_id: 3 |
| 34 | 34 |
author_id: 2 |
| 35 | 35 |
status_id: 2 |
| 36 | 36 |
start_date: <%= 2.day.ago.to_date.to_s(:db) %> |
| 37 |
due_date:
|
|
| 37 |
due_date: |
|
| 38 | 38 |
root_id: 2 |
| 39 | 39 |
lft: 1 |
| 40 | 40 |
rgt: 2 |
| 41 | 41 |
lock_version: 3 |
| 42 | 42 |
done_ratio: 30 |
| 43 |
issues_003: |
|
| 43 |
position: 1 |
|
| 44 |
issues_003: |
|
| 44 | 45 |
created_on: 2006-07-19 21:07:27 +02:00 |
| 45 | 46 |
project_id: 1 |
| 46 | 47 |
updated_on: 2006-07-19 21:07:27 +02:00 |
| 47 | 48 |
priority_id: 4 |
| 48 | 49 |
subject: Error 281 when updating a recipe |
| 49 | 50 |
id: 3 |
| 50 |
fixed_version_id:
|
|
| 51 |
category_id:
|
|
| 51 |
fixed_version_id: |
|
| 52 |
category_id: |
|
| 52 | 53 |
description: Error 281 is encountered when saving a recipe |
| 53 | 54 |
tracker_id: 1 |
| 54 | 55 |
assigned_to_id: 3 |
| ... | ... | |
| 59 | 60 |
root_id: 3 |
| 60 | 61 |
lft: 1 |
| 61 | 62 |
rgt: 2 |
| 62 |
issues_004:
|
|
| 63 |
issues_004: |
|
| 63 | 64 |
created_on: <%= 5.days.ago.to_s(:db) %> |
| 64 | 65 |
project_id: 2 |
| 65 | 66 |
updated_on: <%= 2.days.ago.to_s(:db) %> |
| 66 | 67 |
priority_id: 4 |
| 67 | 68 |
subject: Issue on project 2 |
| 68 | 69 |
id: 4 |
| 69 |
fixed_version_id:
|
|
| 70 |
category_id:
|
|
| 70 |
fixed_version_id: |
|
| 71 |
category_id: |
|
| 71 | 72 |
description: Issue on project 2 |
| 72 | 73 |
tracker_id: 1 |
| 73 | 74 |
assigned_to_id: 2 |
| ... | ... | |
| 76 | 77 |
root_id: 4 |
| 77 | 78 |
lft: 1 |
| 78 | 79 |
rgt: 2 |
| 79 |
issues_005:
|
|
| 80 |
issues_005: |
|
| 80 | 81 |
created_on: <%= 5.days.ago.to_s(:db) %> |
| 81 | 82 |
project_id: 3 |
| 82 | 83 |
updated_on: <%= 2.days.ago.to_s(:db) %> |
| 83 | 84 |
priority_id: 4 |
| 84 | 85 |
subject: Subproject issue |
| 85 | 86 |
id: 5 |
| 86 |
fixed_version_id:
|
|
| 87 |
category_id:
|
|
| 87 |
fixed_version_id: |
|
| 88 |
category_id: |
|
| 88 | 89 |
description: This is an issue on a cookbook subproject |
| 89 | 90 |
tracker_id: 1 |
| 90 |
assigned_to_id:
|
|
| 91 |
assigned_to_id: |
|
| 91 | 92 |
author_id: 2 |
| 92 | 93 |
status_id: 1 |
| 93 | 94 |
root_id: 5 |
| 94 | 95 |
lft: 1 |
| 95 | 96 |
rgt: 2 |
| 96 |
issues_006:
|
|
| 97 |
issues_006: |
|
| 97 | 98 |
created_on: <%= 1.minute.ago.to_s(:db) %> |
| 98 | 99 |
project_id: 5 |
| 99 | 100 |
updated_on: <%= 1.minute.ago.to_s(:db) %> |
| 100 | 101 |
priority_id: 4 |
| 101 | 102 |
subject: Issue of a private subproject |
| 102 | 103 |
id: 6 |
| 103 |
fixed_version_id:
|
|
| 104 |
category_id:
|
|
| 104 |
fixed_version_id: |
|
| 105 |
category_id: |
|
| 105 | 106 |
description: This is an issue of a private subproject of cookbook |
| 106 | 107 |
tracker_id: 1 |
| 107 |
assigned_to_id:
|
|
| 108 |
assigned_to_id: |
|
| 108 | 109 |
author_id: 2 |
| 109 | 110 |
status_id: 1 |
| 110 | 111 |
start_date: <%= Date.today.to_s(:db) %> |
| ... | ... | |
| 112 | 113 |
root_id: 6 |
| 113 | 114 |
lft: 1 |
| 114 | 115 |
rgt: 2 |
| 115 |
issues_007:
|
|
| 116 |
issues_007: |
|
| 116 | 117 |
created_on: <%= 10.days.ago.to_s(:db) %> |
| 117 | 118 |
project_id: 1 |
| 118 | 119 |
updated_on: <%= 10.days.ago.to_s(:db) %> |
| 119 | 120 |
priority_id: 5 |
| 120 | 121 |
subject: Issue due today |
| 121 | 122 |
id: 7 |
| 122 |
fixed_version_id:
|
|
| 123 |
category_id:
|
|
| 123 |
fixed_version_id: |
|
| 124 |
category_id: |
|
| 124 | 125 |
description: This is an issue that is due today |
| 125 | 126 |
tracker_id: 1 |
| 126 |
assigned_to_id:
|
|
| 127 |
assigned_to_id: |
|
| 127 | 128 |
author_id: 2 |
| 128 | 129 |
status_id: 1 |
| 129 | 130 |
start_date: <%= 10.days.ago.to_s(:db) %> |
| ... | ... | |
| 132 | 133 |
root_id: 7 |
| 133 | 134 |
lft: 1 |
| 134 | 135 |
rgt: 2 |
| 135 |
issues_008:
|
|
| 136 |
issues_008: |
|
| 136 | 137 |
created_on: <%= 10.days.ago.to_s(:db) %> |
| 137 | 138 |
project_id: 1 |
| 138 | 139 |
updated_on: <%= 10.days.ago.to_s(:db) %> |
| 139 | 140 |
priority_id: 5 |
| 140 | 141 |
subject: Closed issue |
| 141 | 142 |
id: 8 |
| 142 |
fixed_version_id:
|
|
| 143 |
category_id:
|
|
| 143 |
fixed_version_id: |
|
| 144 |
category_id: |
|
| 144 | 145 |
description: This is a closed issue. |
| 145 | 146 |
tracker_id: 1 |
| 146 |
assigned_to_id:
|
|
| 147 |
assigned_to_id: |
|
| 147 | 148 |
author_id: 2 |
| 148 | 149 |
status_id: 5 |
| 149 |
start_date:
|
|
| 150 |
due_date:
|
|
| 150 |
start_date: |
|
| 151 |
due_date: |
|
| 151 | 152 |
lock_version: 0 |
| 152 | 153 |
root_id: 8 |
| 153 | 154 |
lft: 1 |
| 154 | 155 |
rgt: 2 |
| 155 | 156 |
closed_on: <%= 3.days.ago.to_s(:db) %> |
| 156 |
issues_009:
|
|
| 157 |
issues_009: |
|
| 157 | 158 |
created_on: <%= 1.minute.ago.to_s(:db) %> |
| 158 | 159 |
project_id: 5 |
| 159 | 160 |
updated_on: <%= 1.minute.ago.to_s(:db) %> |
| 160 | 161 |
priority_id: 5 |
| 161 | 162 |
subject: Blocked Issue |
| 162 | 163 |
id: 9 |
| 163 |
fixed_version_id:
|
|
| 164 |
category_id:
|
|
| 164 |
fixed_version_id: |
|
| 165 |
category_id: |
|
| 165 | 166 |
description: This is an issue that is blocked by issue #10 |
| 166 | 167 |
tracker_id: 1 |
| 167 |
assigned_to_id:
|
|
| 168 |
assigned_to_id: |
|
| 168 | 169 |
author_id: 2 |
| 169 | 170 |
status_id: 1 |
| 170 | 171 |
start_date: <%= Date.today.to_s(:db) %> |
| ... | ... | |
| 172 | 173 |
root_id: 9 |
| 173 | 174 |
lft: 1 |
| 174 | 175 |
rgt: 2 |
| 175 |
issues_010:
|
|
| 176 |
issues_010: |
|
| 176 | 177 |
created_on: <%= 1.minute.ago.to_s(:db) %> |
| 177 | 178 |
project_id: 5 |
| 178 | 179 |
updated_on: <%= 1.minute.ago.to_s(:db) %> |
| 179 | 180 |
priority_id: 5 |
| 180 | 181 |
subject: Issue Doing the Blocking |
| 181 | 182 |
id: 10 |
| 182 |
fixed_version_id:
|
|
| 183 |
category_id:
|
|
| 183 |
fixed_version_id: |
|
| 184 |
category_id: |
|
| 184 | 185 |
description: This is an issue that blocks issue #9 |
| 185 | 186 |
tracker_id: 1 |
| 186 |
assigned_to_id:
|
|
| 187 |
assigned_to_id: |
|
| 187 | 188 |
author_id: 2 |
| 188 | 189 |
status_id: 1 |
| 189 | 190 |
start_date: <%= Date.today.to_s(:db) %> |
| ... | ... | |
| 191 | 192 |
root_id: 10 |
| 192 | 193 |
lft: 1 |
| 193 | 194 |
rgt: 2 |
| 194 |
issues_011:
|
|
| 195 |
issues_011: |
|
| 195 | 196 |
created_on: <%= 3.days.ago.to_s(:db) %> |
| 196 | 197 |
project_id: 1 |
| 197 | 198 |
updated_on: <%= 1.day.ago.to_s(:db) %> |
| 198 | 199 |
priority_id: 5 |
| 199 | 200 |
subject: Closed issue on a closed version |
| 200 | 201 |
id: 11 |
| 201 |
fixed_version_id: 1
|
|
| 202 |
fixed_version_id: 1 |
|
| 202 | 203 |
category_id: 1 |
| 203 | 204 |
description: |
| 204 | 205 |
tracker_id: 1 |
| 205 |
assigned_to_id:
|
|
| 206 |
assigned_to_id: |
|
| 206 | 207 |
author_id: 2 |
| 207 | 208 |
status_id: 5 |
| 208 | 209 |
start_date: <%= 1.day.ago.to_date.to_s(:db) %> |
| ... | ... | |
| 211 | 212 |
lft: 1 |
| 212 | 213 |
rgt: 2 |
| 213 | 214 |
closed_on: <%= 1.day.ago.to_s(:db) %> |
| 214 |
issues_012:
|
|
| 215 |
issues_012: |
|
| 215 | 216 |
created_on: <%= 3.days.ago.to_s(:db) %> |
| 216 | 217 |
project_id: 1 |
| 217 | 218 |
updated_on: <%= 1.day.ago.to_s(:db) %> |
| 218 | 219 |
priority_id: 5 |
| 219 | 220 |
subject: Closed issue on a locked version |
| 220 | 221 |
id: 12 |
| 221 |
fixed_version_id: 2
|
|
| 222 |
fixed_version_id: 2 |
|
| 222 | 223 |
category_id: 1 |
| 223 | 224 |
description: |
| 224 | 225 |
tracker_id: 1 |
| 225 |
assigned_to_id:
|
|
| 226 |
assigned_to_id: |
|
| 226 | 227 |
author_id: 3 |
| 227 | 228 |
status_id: 5 |
| 228 | 229 |
start_date: <%= 1.day.ago.to_date.to_s(:db) %> |
| ... | ... | |
| 231 | 232 |
lft: 1 |
| 232 | 233 |
rgt: 2 |
| 233 | 234 |
closed_on: <%= 1.day.ago.to_s(:db) %> |
| 235 |
position: 2 |
|
| 234 | 236 |
issues_013: |
| 235 | 237 |
created_on: <%= 5.days.ago.to_s(:db) %> |
| 236 | 238 |
project_id: 3 |
| ... | ... | |
| 238 | 240 |
priority_id: 4 |
| 239 | 241 |
subject: Subproject issue two |
| 240 | 242 |
id: 13 |
| 241 |
fixed_version_id:
|
|
| 242 |
category_id:
|
|
| 243 |
fixed_version_id: |
|
| 244 |
category_id: |
|
| 243 | 245 |
description: This is a second issue on a cookbook subproject |
| 244 | 246 |
tracker_id: 1 |
| 245 |
assigned_to_id:
|
|
| 247 |
assigned_to_id: |
|
| 246 | 248 |
author_id: 2 |
| 247 | 249 |
status_id: 1 |
| 248 | 250 |
root_id: 13 |
| ... | ... | |
| 255 | 257 |
updated_on: <%= 15.days.ago.to_s(:db) %> |
| 256 | 258 |
priority_id: 5 |
| 257 | 259 |
subject: Private issue on public project |
| 258 |
fixed_version_id:
|
|
| 259 |
category_id:
|
|
| 260 |
fixed_version_id: |
|
| 261 |
category_id: |
|
| 260 | 262 |
description: This is a private issue |
| 261 | 263 |
tracker_id: 1 |
| 262 |
assigned_to_id:
|
|
| 264 |
assigned_to_id: |
|
| 263 | 265 |
author_id: 2 |
| 264 | 266 |
status_id: 1 |
| 265 | 267 |
is_private: true |
| test/functional/versions_controller_test.rb | ||
|---|---|---|
| 77 | 77 |
assert_select 'h3', :text => /Subproject version/ |
| 78 | 78 |
end |
| 79 | 79 | |
| 80 |
def test_issues_order_when_manual_issue_position_in_versions_is_disabled |
|
| 81 |
with_settings :manual_issue_position_in_versions => '0' do |
|
| 82 |
get :index, :params => {:project_id => 1}
|
|
| 83 |
assert_response :success |
|
| 84 | ||
| 85 |
assert_select '#roadmap article:first-child' do |
|
| 86 |
assert_select '.related-issues tr:nth-child(1) a[href=?]', '/issues/12', :text => 'Bug #12' |
|
| 87 |
assert_select '.related-issues tr:nth-child(2) a[href=?]', '/issues/2', :text => 'Feature request #2' |
|
| 88 |
end |
|
| 89 | ||
| 90 |
get :show, :params => { :id => 2 }
|
|
| 91 |
assert_response :success |
|
| 92 | ||
| 93 |
assert_select '.related-issues' do |
|
| 94 |
assert_select 'tr:nth-child(1) a[href=?]', '/issues/12', :text => 'Bug #12' |
|
| 95 |
assert_select 'tr:nth-child(2) a[href=?]', '/issues/2', :text => 'Feature request #2' |
|
| 96 |
end |
|
| 97 |
end |
|
| 98 |
end |
|
| 99 | ||
| 100 |
def test_issues_order_when_manual_issue_position_in_versions_is_enabled |
|
| 101 |
with_settings :manual_issue_position_in_versions => '1' do |
|
| 102 |
get :index, :params => {:project_id => 1}
|
|
| 103 |
assert_response :success |
|
| 104 | ||
| 105 |
assert_select '#roadmap article:first-child' do |
|
| 106 |
assert_select '.related-issues tr:nth-child(1) a[href=?]', '/issues/2', :text => 'Feature request #2' |
|
| 107 |
assert_select '.related-issues tr:nth-child(2) a[href=?]', '/issues/12', :text => 'Bug #12' |
|
| 108 |
end |
|
| 109 | ||
| 110 |
get :show, :params => { :id => 2 }
|
|
| 111 |
assert_response :success |
|
| 112 | ||
| 113 |
assert_select '.related-issues' do |
|
| 114 |
assert_select 'tr:nth-child(1) a[href=?]', '/issues/2', :text => 'Feature request #2' |
|
| 115 |
assert_select 'tr:nth-child(2) a[href=?]', '/issues/12', :text => 'Bug #12' |
|
| 116 |
end |
|
| 117 |
end |
|
| 118 |
end |
|
| 119 | ||
| 120 |
def test_user_with_permission_can_change_issue_position |
|
| 121 |
role = Role.find(1) |
|
| 122 |
role.add_permission! :change_issue_position_in_version |
|
| 123 | ||
| 124 |
@request.session[:user_id] = 2 |
|
| 125 |
with_settings :manual_issue_position_in_versions => '1' do |
|
| 126 |
get :index, :params => {:project_id => 1}
|
|
| 127 |
assert_response :success |
|
| 128 | ||
| 129 |
assert_select '#roadmap article' do |
|
| 130 |
assert_select '.related-issues tr td.sortable', 2 |
|
| 131 |
end |
|
| 132 | ||
| 133 |
get :show, :params => { :id => 2 }
|
|
| 134 |
assert_response :success |
|
| 135 | ||
| 136 |
assert_select '.related-issues' do |
|
| 137 |
assert_select '.related-issues tr td.sortable', 2 |
|
| 138 |
end |
|
| 139 |
end |
|
| 140 |
end |
|
| 141 | ||
| 142 |
def test_user_without_permission_cannot_change_issue_position |
|
| 143 |
@request.session[:user_id] = 2 |
|
| 144 |
with_settings :manual_issue_position_in_versions => '1' do |
|
| 145 |
get :index, :params => {:project_id => 1}
|
|
| 146 |
assert_response :success |
|
| 147 | ||
| 148 |
assert_select '#roadmap article' do |
|
| 149 |
assert_select '.related-issues tr td.sortable', 0 |
|
| 150 |
end |
|
| 151 | ||
| 152 |
get :show, :params => { :id => 2 }
|
|
| 153 |
assert_response :success |
|
| 154 | ||
| 155 |
assert_select '.related-issues' do |
|
| 156 |
assert_select '.related-issues tr td.sortable', 0 |
|
| 157 |
end |
|
| 158 |
end |
|
| 159 |
end |
|
| 160 | ||
| 80 | 161 |
def test_index_should_prepend_shared_versions |
| 81 | 162 |
get :index, :params => {:project_id => 1}
|
| 82 | 163 |
assert_response :success |