Feature #16188 ยป 2021-09-25-133700-archive_issue_categories.patch
app/controllers/issue_categories_controller.rb | ||
---|---|---|
23 | 23 |
before_action :find_model_object, :except => [:index, :new, :create] |
24 | 24 |
before_action :find_project_from_association, :except => [:index, :new, :create] |
25 | 25 |
before_action :find_project_by_project_id, :only => [:index, :new, :create] |
26 |
before_action :authorize |
|
27 |
accept_api_auth :index, :show, :create, :update, :destroy |
|
26 |
before_action :authorize, :except => [:archive, :unarchive]
|
|
27 |
accept_api_auth :index, :show, :create, :update, :destroy, :archive, :unarchive
|
|
28 | 28 | |
29 | 29 |
def index |
30 | 30 |
respond_to do |format| |
... | ... | |
94 | 94 |
end |
95 | 95 |
end |
96 | 96 |
end |
97 |
|
|
98 |
def archive |
|
99 |
@category.archived = true |
|
100 |
if @category.save |
|
101 |
respond_to do |format| |
|
102 |
format.html do |
|
103 |
flash[:notice] = l(:notice_successful_update) |
|
104 |
redirect_to_settings_in_projects |
|
105 |
end |
|
106 |
format.js |
|
107 |
format.api { render :action => 'show', :status => :created, :location => issue_category_path(@category) } |
|
108 |
end |
|
109 |
end |
|
110 |
end |
|
111 |
|
|
112 |
def unarchive |
|
113 |
@category.archived = false |
|
114 |
if @category.save |
|
115 |
respond_to do |format| |
|
116 |
format.html do |
|
117 |
flash[:notice] = l(:notice_successful_update) |
|
118 |
redirect_to_settings_in_projects |
|
119 |
end |
|
120 |
format.js |
|
121 |
format.api { render :action => 'show', :status => :created, :location => issue_category_path(@category) } |
|
122 |
end |
|
123 |
end |
|
124 |
end |
|
97 | 125 | |
98 | 126 |
def destroy |
99 | 127 |
@issue_count = @category.issues.size |
app/controllers/issues_controller.rb | ||
---|---|---|
316 | 316 |
@assignables = target_projects.map(&:assignable_users).reduce(:&) |
317 | 317 |
@versions = target_projects.map {|p| p.shared_versions.open}.reduce(:&) |
318 | 318 |
@categories = target_projects.map {|p| p.issue_categories}.reduce(:&) |
319 |
@active_categories = @categories.reject { |c| c.archived } |
|
319 | 320 |
if @copy |
320 | 321 |
@attachments_present = @issues.detect {|i| i.attachments.any?}.present? |
321 | 322 |
@subtasks_present = @issues.detect {|i| !i.leaf?}.present? |
app/models/issue.rb | ||
---|---|---|
982 | 982 |
users.uniq.sort |
983 | 983 |
end |
984 | 984 | |
985 |
def assignable_issue_categories |
|
986 |
return [] if project.nil? |
|
987 | ||
988 |
categories = project.active_issue_categories |
|
989 |
if category && category.archived |
|
990 |
categories << category |
|
991 |
end |
|
992 |
categories.uniq.sort |
|
993 |
end |
|
994 |
|
|
985 | 995 |
# Versions that the issue can be assigned to |
986 | 996 |
def assignable_versions |
987 | 997 |
return @assignable_versions if @assignable_versions |
app/models/project.rb | ||
---|---|---|
974 | 974 |
value.custom_field.visible_by?(project, user) |
975 | 975 |
end |
976 | 976 |
end |
977 |
|
|
978 |
def active_issue_categories |
|
979 |
issue_categories.reject { |c| c.archived } |
|
980 |
end |
|
977 | 981 | |
978 | 982 |
private |
979 | 983 |
app/views/context_menus/issues.html.erb | ||
---|---|---|
86 | 86 |
</li> |
87 | 87 |
<% end %> |
88 | 88 | |
89 |
<% if @safe_attributes.include?('category_id') && @project && @project.issue_categories.any? -%> |
|
89 |
<% if @safe_attributes.include?('category_id') && @project && @project.active_issue_categories.any? -%>
|
|
90 | 90 |
<li class="folder"> |
91 | 91 |
<a href="#" class="submenu"><%= l(:field_category) %></a> |
92 | 92 |
<ul> |
93 |
<% @project.issue_categories.each do |u| -%> |
|
93 |
<% @project.active_issue_categories.each do |u| -%>
|
|
94 | 94 |
<li><%= context_menu_link u.name, _bulk_update_issues_path(@issue, :ids => @issue_ids, :issue => {'category_id' => u}, :back_url => @back), :method => :patch, |
95 | 95 |
:selected => (@issue && u == @issue.category), :disabled => !@can[:edit] %></li> |
96 | 96 |
<% end -%> |
app/views/issues/_attributes.html.erb | ||
---|---|---|
29 | 29 |
</p> |
30 | 30 |
<% end %> |
31 | 31 | |
32 |
<% if @issue.safe_attribute?('category_id') && @issue.project.issue_categories.any? %>
|
|
33 |
<p><%= f.select :category_id, (@issue.project.issue_categories.collect {|c| [c.name, c.id]}),
|
|
32 |
<% if @issue.safe_attribute?('category_id') && @issue.assignable_issue_categories.any? %>
|
|
33 |
<p><%= f.select :category_id, (@issue.assignable_issue_categories.collect {|c| [c.name, c.id]}),
|
|
34 | 34 |
{:include_blank => true, :required => @issue.required_attribute?('category_id')}, |
35 | 35 |
:onchange => ("updateIssueFrom('#{escape_javascript(update_issue_form_path(@project, @issue))}', this)" if @issue.new_record?) %> |
36 | 36 |
<%= link_to(l(:label_issue_category_new), |
app/views/issues/bulk_edit.html.erb | ||
---|---|---|
81 | 81 |
<label for='issue_category_id'><%= l(:field_category) %></label> |
82 | 82 |
<%= select_tag('issue[category_id]', content_tag('option', l(:label_no_change_option), :value => '') + |
83 | 83 |
content_tag('option', l(:label_none), :value => 'none', :selected => (@issue_params[:category_id] == 'none')) + |
84 |
options_from_collection_for_select(@categories, :id, :name, @issue_params[:category_id])) %> |
|
84 |
options_from_collection_for_select(@active_categories, :id, :name, @issue_params[:category_id])) %>
|
|
85 | 85 |
</p> |
86 | 86 |
<% end %> |
87 | 87 |
app/views/projects/settings/_issue_categories.html.erb | ||
---|---|---|
16 | 16 |
<td class="buttons"> |
17 | 17 |
<% if User.current.allowed_to?(:manage_categories, @project) %> |
18 | 18 |
<%= link_to l(:button_edit), edit_issue_category_path(category), :class => 'icon icon-edit' %> |
19 |
<%= link_to(l(:button_archive), archive_issue_category_path(category), :method => :post, :class => 'icon icon-lock') unless category.archived? %> |
|
20 |
<%= link_to(l(:button_unarchive), unarchive_issue_category_path(category), :method => :post, :class => 'icon icon-lock') if category.archived? %> |
|
19 | 21 |
<%= delete_link issue_category_path(category) %> |
20 | 22 |
<% end %> |
21 | 23 |
</td> |
config/routes.rb | ||
---|---|---|
405 | 405 |
end |
406 | 406 |
end |
407 | 407 |
end |
408 |
|
|
409 |
resources :issue_categories do |
|
410 |
member do |
|
411 |
post 'archive' |
|
412 |
post 'unarchive' |
|
413 |
end |
|
414 |
end |
|
408 | 415 |
end |
db/migrate/20210908145200_issue_categories_add_column.rb | ||
---|---|---|
1 |
class IssueCategoriesAddColumn < ActiveRecord::Migration[6.1] |
|
2 |
def self.up |
|
3 |
add_column :issue_categories, :archived, :boolean, :default => false |
|
4 |
end |
|
5 | ||
6 |
def self.down |
|
7 |
remove_column :issue_categories, :archived |
|
8 |
end |
|
9 |
end |
test/functional/issue_categories_controller_test.rb | ||
---|---|---|
216 | 216 |
# check that the issue category was nullified |
217 | 217 |
assert_nil issue.reload.category_id |
218 | 218 |
end |
219 |
|
|
220 |
def test_archive_unarchive |
|
221 |
assert_no_difference 'IssueCategory.count' do |
|
222 |
put( |
|
223 |
:archive, |
|
224 |
:params => { |
|
225 |
:id => 2, |
|
226 |
} |
|
227 |
) |
|
228 |
end |
|
229 |
assert_redirected_to '/projects/ecookbook/settings/categories' |
|
230 |
assert_equal true, IssueCategory.find(2).archived |
|
231 |
|
|
232 |
assert_no_difference 'IssueCategory.count' do |
|
233 |
put( |
|
234 |
:unarchive, |
|
235 |
:params => { |
|
236 |
:id => 2, |
|
237 |
} |
|
238 |
) |
|
239 |
end |
|
240 |
assert_redirected_to '/projects/ecookbook/settings/categories' |
|
241 |
assert_equal false, IssueCategory.find(2).archived |
|
242 |
end |
|
219 | 243 |
end |
test/unit/issue_test.rb | ||
---|---|---|
3406 | 3406 | |
3407 | 3407 |
assert_equal [5], issue2.filter_projects_scope('').ids.sort |
3408 | 3408 |
end |
3409 |
|
|
3410 |
def test_issue_categories_archived |
|
3411 |
issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1, :subject => 'Default') |
|
3412 |
assert_save issue |
|
3413 |
|
|
3414 |
project = issue.project |
|
3415 |
|
|
3416 |
assert_nil issue.category_id |
|
3417 |
assert_nil issue.category |
|
3418 |
assert_equal 1, project.id |
|
3419 |
assert_equal 2, project.issue_categories.size |
|
3420 |
assert_equal 2, project.active_issue_categories.size |
|
3421 |
assert_equal 2, issue.assignable_issue_categories.size |
|
3422 |
|
|
3423 |
category = project.issue_categories.first |
|
3424 |
category.archived = true |
|
3425 |
|
|
3426 |
assert_equal 2, project.issue_categories.size |
|
3427 |
assert_equal 1, project.active_issue_categories.size |
|
3428 |
assert_equal 1, issue.assignable_issue_categories.size |
|
3429 |
assert_not_equal category, issue.assignable_issue_categories.first |
|
3430 |
|
|
3431 |
issue.category = category |
|
3432 |
assert_equal 1, project.active_issue_categories.size |
|
3433 |
assert_equal 2, issue.assignable_issue_categories.size |
|
3434 |
|
|
3435 |
category.archived = false |
|
3436 |
assert_equal 2, project.active_issue_categories.size |
|
3437 |
assert_equal 2, issue.assignable_issue_categories.size |
|
3438 |
end |
|
3409 | 3439 |
end |
test/unit/project_test.rb | ||
---|---|---|
1127 | 1127 |
assert_equal 'valuea', project.custom_field_value(cf1) |
1128 | 1128 |
assert_nil project.custom_field_value(cf2) |
1129 | 1129 |
end |
1130 |
|
|
1131 |
def test_issue_categories_archived |
|
1132 |
project = Project.find(1) |
|
1133 |
assert_equal 2, project.issue_categories.size |
|
1134 |
assert_equal 2, project.active_issue_categories.size |
|
1135 |
|
|
1136 |
project.issue_categories.each do |cat| |
|
1137 |
cat.archived = true |
|
1138 |
end |
|
1139 |
|
|
1140 |
assert_equal 2, project.issue_categories.size |
|
1141 |
assert_equal 0, project.active_issue_categories.size |
|
1142 |
|
|
1143 |
project.issue_categories.each do |cat| |
|
1144 |
cat.archived = false |
|
1145 |
end |
|
1146 |
|
|
1147 |
assert_equal 2, project.issue_categories.size |
|
1148 |
assert_equal 2, project.active_issue_categories.size |
|
1149 |
end |
|
1130 | 1150 |
end |