Skip to content
This repository was archived by the owner on Apr 10, 2023. It is now read-only.

Issue tags add/delete from context menu #231

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,6 @@ Desktop.ini
# Application
.rvmrc
/tmp

# vsCode
.vscode
53 changes: 52 additions & 1 deletion app/controllers/tags_controller.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
class TagsController < ApplicationController
before_action :require_admin
before_action :require_admin, except: [:add_tag, :delete_tag, :update_tag]
before_action :require_login, only: [:update_tag]
before_action :find_tag, only: [:edit, :update]
before_action :bulk_find_tags, only: [:context_menu, :merge, :destroy]
before_action :find_project_by_project_id, only: [:add_tag, :delete_tag]

helper :issues_tags

Expand Down Expand Up @@ -54,6 +56,55 @@ def merge
end
end

def add_tag
@issue_ids = params[:issue_ids]
@back_url = params[:back_url]
end

def delete_tag
@issue_ids = params[:issue_ids]
@back_url = params[:back_url]

issues = Issue.where(id: @issue_ids)
@candidate_tags = ActsAsTaggableOn::Tag
.joins(:taggings)
.where(taggings: {taggable_type: 'Issue', taggable_id: issues})
.distinct
.order('tags.name')
end

def update_tag
operate = params[:operate]
return if operate.blank?

sabun = params[:tag_list]
return if sabun.blank?

sabun = sabun.split(ActsAsTaggableOn.delimiter) unless sabun.is_a?(Array)

Issue.where(id: params[:issue_ids]).each do |issue|
old_tags = issue.tag_list.to_s

case operate
when 'add'
issue.tag_list |= sabun
when 'delete'
issue.tag_list -= sabun
end

new_tags = issue.tag_list.to_s
unless old_tags == new_tags
issue.save_tags
issue.init_journal(User.current) if issue.current_journal.blank?
issue.current_journal.details << JournalDetail.new(
property: 'attr', prop_key: 'tag_list', old_value: old_tags, value: new_tags)
issue.current_journal.save
end
end
Issue.remove_unused_tags!
# redirect_to params[:back_url] if params[:back_url]
end

private

def bulk_find_tags
Expand Down
13 changes: 13 additions & 0 deletions app/views/issues/_add_context_menu.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<% if @can[:edit] %>
<li class="folder">
<a href="#" class="submenu"><%= l(:field_tags) %></a>
<ul>
<li><%= context_menu_link(l(:button_add),
tags_add_path(issue_ids: @issue_ids, project_id: @project, back_url: back),
remote: true) %></li>
<li><%= context_menu_link(l(:button_delete),
tags_delete_path(issue_ids: @issue_ids, project_id: @project, back_url: back),
remote: true) %></li>
</ul>
</li>
<% end %>
43 changes: 43 additions & 0 deletions app/views/tags/_add_tag.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
<h3 class="title"><%= l(:label_add_tag) %></h3>

<%= form_tag({action: :update_tag},
remote: true,
method: :patch,
id: 'add-tag-form') do %>

<%= hidden_field_tag 'project_id', @project.id if @project %>
<% @issue_ids.each do |i| %>
<%= hidden_field_tag 'issue_ids[]', i %>
<% end %>
<%= hidden_field_tag 'back_url', @back_url if @back_url %>
<%= hidden_field_tag 'operate', 'add' %>

<p>
<label for="add-issue-tag-list"><%= l(:tags) %></label>
<%= text_field_tag :tag_list, '', size: 30, id: 'add-issue-tag-list' %>
</p>

<p class="buttons">
<%= submit_tag l(:button_add), name: nil, onclick: "hideModal(this); setTimeout(function(){location.reload(false);},300);" %>
<%= link_to_function l(:button_cancel), "hideModal(this);" %>
</p>
<% end %>

<%= javascript_tag "$('#add-issue-tag-list').tagit({
tagSource: function(search, showChoices) {
var that = this;
$.ajax({
url: '#{escape_javascript auto_complete_issue_tags_path(@project)}',
data: {q: search.term},
success: function(choices) {
showChoices(that._subtractArray(jQuery.parseJSON(choices.replace(/<!--.*-->/g, '')), that.assignedTags()));
}
});
},
allowSpaces: true,
placeholderText: '#{l(:issue_tags_label_add_tag)}',
caseSensitive: false,
removeConfirmation: true,
showAutocompleteOnFocus: true,
autocomplete: {delay: 1, minLength: 1},
});" %>
28 changes: 28 additions & 0 deletions app/views/tags/_delete_tag.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<h3 class="title"><%= l(:label_delete_tag) %></h3>

<%= form_tag({action: :update_tag},
remote: true,
method: :patch,
id: 'delete-tag-form') do %>

<%= hidden_field_tag 'project_id', @project.id if @project %>
<% @issue_ids.each do |i| %>
<%= hidden_field_tag 'issue_ids[]', i %>
<% end %>
<%= hidden_field_tag 'back_url', @back_url if @back_url %>
<%= hidden_field_tag 'operate', 'delete' %>

<div id="delete-tags" style="overflow: auto;">
<% @candidate_tags.each do |t| %>
<label style="display: block;">
<%= check_box_tag 'tag_list[]', t.name, false, id: nil %>
<%= t.name %>
</label>
<% end %>
</div>

<p class="buttons">
<%= submit_tag l(:button_delete), name: nil, onclick: "hideModal(this); setTimeout(function(){location.reload(false);},300);" %>
<%= link_to_function l(:button_cancel), "hideModal(this);" %>
</p>
<% end %>
9 changes: 9 additions & 0 deletions app/views/tags/add_tag.js.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
$('#ajax-modal').html('<%= escape_javascript(render partial: 'tags/add_tag') %>');
showModal('ajax-modal', '400px');
$('#ajax-modal').addClass('add-tag');

var ac = $('.ui-autocomplete');
<%# モーダルダイアログでオートコンプリート候補表示を手前に チケット画面で呼ばれるとissues_catalog.cssが読み込まれないのでここで指定 %>
ac.css('z-index', '2147483647');
<%# ダイアログの子になる場合があり、そうなると表示がクリップされるのでbody直下に移動 %>
$('body').append(ac);
3 changes: 3 additions & 0 deletions app/views/tags/delete_tag.js.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
$('#ajax-modal').html('<%= escape_javascript(render partial: 'tags/delete_tag') %>');
showModal('ajax-modal', '400px');
$('#ajax-modal').addClass('delete-tag');
3 changes: 3 additions & 0 deletions config/locales/en.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,6 @@ en:
issue_tags_tag: Tag
issue_tags_button_merge: Merge
issue_tags_label_merge: Merge selected tags

label_add_tag: "Add Tag"
label_delete_tag: "Delete Tag"
3 changes: 3 additions & 0 deletions config/locales/ja.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,6 @@ ja:
issue_tags_tag: タグ
issue_tags_button_merge: 結合
issue_tags_label_merge: 選択したタグを結合します

label_add_tag: "タグを追加"
label_delete_tag: "タグを削除"
3 changes: 3 additions & 0 deletions config/routes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@
match '/tags/context_menu', to: 'tags#context_menu', as: 'tags_context_menu',
via: [:get, :post]
delete '/tags', controller: 'tags', action: 'destroy'
get '/tags/add_tag', to: 'tags#add_tag', as: 'tags_add'
get '/tags/delete_tag', to: 'tags#delete_tag', as: 'tags_delete'
patch '/tags/update_tag', to: 'tags#update_tag'

resources :tags, only: [:edit, :update] do
collection do
Expand Down
1 change: 1 addition & 0 deletions lib/redmine_tags/hooks/views_issues_hook.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ class ViewsIssuesHook < Redmine::Hook::ViewListener
render_on :view_issues_sidebar_planning_bottom, partial: 'issues/tags_sidebar'
render_on :view_issues_bulk_edit_details_bottom, partial: 'issues/bulk_edit_tags'
render_on :view_layouts_base_html_head, partial: 'tags/header_assets'
render_on :view_issues_context_menu_start, partial: 'issues/add_context_menu'
end
end
end