diff --git a/.gitignore b/.gitignore index 021d4b6..ddee74a 100644 --- a/.gitignore +++ b/.gitignore @@ -11,3 +11,6 @@ Desktop.ini # Application .rvmrc /tmp + +# vsCode +.vscode \ No newline at end of file diff --git a/app/controllers/tags_controller.rb b/app/controllers/tags_controller.rb index 86c650e..75a3d5d 100755 --- a/app/controllers/tags_controller.rb +++ b/app/controllers/tags_controller.rb @@ -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 @@ -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 diff --git a/app/views/issues/_add_context_menu.html.erb b/app/views/issues/_add_context_menu.html.erb new file mode 100644 index 0000000..235c262 --- /dev/null +++ b/app/views/issues/_add_context_menu.html.erb @@ -0,0 +1,13 @@ +<% if @can[:edit] %> +
  • + <%= l(:field_tags) %> + +
  • +<% end %> diff --git a/app/views/tags/_add_tag.html.erb b/app/views/tags/_add_tag.html.erb new file mode 100644 index 0000000..868a76b --- /dev/null +++ b/app/views/tags/_add_tag.html.erb @@ -0,0 +1,43 @@ +

    <%= l(:label_add_tag) %>

    + +<%= 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' %> + +

    + + <%= text_field_tag :tag_list, '', size: 30, id: 'add-issue-tag-list' %> +

    + +

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

    +<% 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}, +});" %> diff --git a/app/views/tags/_delete_tag.html.erb b/app/views/tags/_delete_tag.html.erb new file mode 100644 index 0000000..49e9818 --- /dev/null +++ b/app/views/tags/_delete_tag.html.erb @@ -0,0 +1,28 @@ +

    <%= l(:label_delete_tag) %>

    + +<%= 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' %> + +
    + <% @candidate_tags.each do |t| %> + + <% end %> +
    + +

    + <%= submit_tag l(:button_delete), name: nil, onclick: "hideModal(this); setTimeout(function(){location.reload(false);},300);" %> + <%= link_to_function l(:button_cancel), "hideModal(this);" %> +

    +<% end %> diff --git a/app/views/tags/add_tag.js.erb b/app/views/tags/add_tag.js.erb new file mode 100644 index 0000000..55992de --- /dev/null +++ b/app/views/tags/add_tag.js.erb @@ -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); diff --git a/app/views/tags/delete_tag.js.erb b/app/views/tags/delete_tag.js.erb new file mode 100644 index 0000000..cf38113 --- /dev/null +++ b/app/views/tags/delete_tag.js.erb @@ -0,0 +1,3 @@ +$('#ajax-modal').html('<%= escape_javascript(render partial: 'tags/delete_tag') %>'); +showModal('ajax-modal', '400px'); +$('#ajax-modal').addClass('delete-tag'); diff --git a/config/locales/en.yml b/config/locales/en.yml index 2e3eace..8601adc 100755 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -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" diff --git a/config/locales/ja.yml b/config/locales/ja.yml index d4f3871..138ad1f 100644 --- a/config/locales/ja.yml +++ b/config/locales/ja.yml @@ -26,3 +26,6 @@ ja: issue_tags_tag: タグ issue_tags_button_merge: 結合 issue_tags_label_merge: 選択したタグを結合します + + label_add_tag: "タグを追加" + label_delete_tag: "タグを削除" diff --git a/config/routes.rb b/config/routes.rb index bfae960..c3d8804 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -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 diff --git a/lib/redmine_tags/hooks/views_issues_hook.rb b/lib/redmine_tags/hooks/views_issues_hook.rb index 08dd916..53236ea 100755 --- a/lib/redmine_tags/hooks/views_issues_hook.rb +++ b/lib/redmine_tags/hooks/views_issues_hook.rb @@ -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