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

Add tags to issue with context menu #194

Open
wants to merge 8 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
31 changes: 31 additions & 0 deletions app/controllers/tags_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ class TagsController < ApplicationController

helper :issues_tags

delegate :save_tags_to_issue, to: "RedmineTags::Hooks::ModelIssueHook.instance"

def edit; end

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

def tagging_issue
if params[:object_type] == 'issue' && params[:object_id] && @issue = Issue.find_by(id: params[:object_id])
@issue_tags = @issue.tags
@checked = {}; @issue_tags.each { |tag| @checked[tag.name] = true }
@available_tags = Issue.available_tags - @issue_tags
@project = @issue.project
case request.method_symbol
when :get
respond_to do |format|
format.js { render layout: false }
end
when :post
tag_ids = []
if params[:tagged]
tag_ids << (params[:tagged][:tag_ids] || params[:tagged][:tag_id])
else
tag_ids << params[:tag_id]
end
tags = ActsAsTaggableOn::Tag.where(id: tag_ids.flatten).all
tags_context = { issue: @issue, params: {} }
tags_context[:params].store :issue, { tag_list: tags }
@issue.init_journal(User.current)
save_tags_to_issue tags_context, true
@issue.current_journal.save
render nothing: true, status: :ok
end
end
end

private

def bulk_find_tags
Expand Down
28 changes: 21 additions & 7 deletions app/helpers/tags_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,11 @@ module TagsHelper
# * show_count - Boolean. Whenever show tag counts
# * open_only - Boolean. Whenever link to the filter with "open" issues
# only limit.
# * with_checkbox - Boolean. Renders tag as checkbox considering additional
# "checked" option
def render_tag_link(tag, options = {})
use_colors = RedmineTags.settings[:issues_use_colors].to_i > 0
use_colors = options[:use_colors]
use_colors = RedmineTags.settings[:issues_use_colors].to_i > 0 if use_colors.nil?
if use_colors
tag_bg_color = tag_color(tag)
tag_fg_color = tag_fg_color(tag_bg_color)
Expand All @@ -25,14 +28,18 @@ def render_tag_link(tag, options = {})
content = link_to tag, { controller: 'search', action: 'index',
id: @project, q: tag.name, wiki_pages: true, issues: true,
style: tag_style }
elsif options[:with_checkbox]
id_name = options[:id_name] || tag.name
with_tick = options[:checked] || {}
content = check_box_tag(id_name, tag.id, with_tick[tag.name] || false, id: nil, project_id: @project) + tag.name
else
content = link_to_filter tag.name, filters, project_id: @project
end
if options[:show_count]
content << content_tag('span', "(#{ tag.count })", class: 'tag-count')
content << content_tag('span', "(#{ tag.count })", class: 'tag-count', style: tag_style)
end

style = if use_colors
style = if use_colors
{ class: 'tag-label-color',
style: tag_style }
else
Expand Down Expand Up @@ -65,7 +72,7 @@ def tag_fg_color(bg_color)
# * show_count - Boolean. Whenever show tag counts
# * open_only - Boolean. Whenever link to the filter with "open" issues
# only limit.
# * style - list, cloud
# * style - list, cloud, simple_list, simple_cloud, with_checkbox
def render_tags_list(tags, options = {})
unless tags.nil? or tags.empty?
content, style = '', options.delete(:style)
Expand All @@ -86,13 +93,16 @@ def render_tags_list(tags, options = {})
logger.warn "[redmine_tags] Unknown sorting option: <#{ sorting }>"
tags.sort! {|a, b| a.name <=> b.name }
end
if :list == style
if :list == style || :simple_list == style
list_el, item_el = 'ul', 'li'
elsif :simple_cloud == style
list_el, item_el = 'div', 'span'
elsif :cloud == style
list_el, item_el = 'div', 'span'
tags = cloudify tags
elsif :with_checkbox == style
list_el, item_el = 'div', 'label'
options[:with_checkbox] = true
else
raise 'Unknown list style'
end
Expand All @@ -104,8 +114,12 @@ def render_tags_list(tags, options = {})
style: (:simple_cloud == style ? 'font-size: 1em;' : '')) <<
' '.html_safe
end
content_tag list_el, content, class: 'tags',
style: (:simple_cloud == style ? 'text-align: left;' : '')
if :simple_list == style || :with_checkbox == style
content
else
content_tag list_el, content, class: 'tags',
style: (:simple_cloud == style ? 'text-align: left;' : '')
end
end
end

Expand Down
2 changes: 2 additions & 0 deletions app/views/auto_completes/_tag_list_with_checkboxes.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
<% checked = local_assigns.fetch :checked, {} %>
<%= render_tags_list(tags, style: :with_checkbox, id_name: 'tagged[tag_ids][]', checked: checked) %>
8 changes: 8 additions & 0 deletions app/views/issues/_tags_context_menu.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<% if @issue -%>
<li class="folder">
<a href="#" class="submenu"><%= l(:tags) %></a>
<ul class="tags">
<li><%= context_menu_link l(:button_edit), tagging_issue_path(:object_type => 'issue', :object_id => @issue.id), :remote => true, :class => 'icon-edit' %></li>
</ul>
</li>
<% end %>
29 changes: 29 additions & 0 deletions app/views/tags/_tagging_issue.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<h3 class="title"><%= l(:issue_tags_manage_tags) %></h3>

<%= form_tag(tagging_issue_path, remote: true, id: 'tagging-issue-form') do %>

<% if issue.present? %>
<%= hidden_field_tag 'object_type', issue.class.name.underscore %>
<%= hidden_field_tag 'object_id', issue.id %>
<% end %>
<%= hidden_field_tag 'project_id', @project.id if @project %>

<div id="issue_tags" class="tags">
<%= render partial: 'auto_completes/tag_list_with_checkboxes', locals: {tags: issue_tags, checked: checked} %>
</div>
<p><%= label_tag 'tag_search', l(:issue_tags_label_search) %><%= text_field_tag 'tag_search', nil %></p>
<%= javascript_tag "observeSearchfield('tag_search', 'available_tags', '#{ escape_javascript auto_complete_issue_tags_path(
:object_type => (issue.present? ? issue.class.name.underscore : nil),
:object_id => (issue.present? ? issue.id : nil),
:project_id => @project,
:partial => :tag_list_with_checkboxes) }')" %>

<div id="available_tags" class="tags">
<%= render partial: 'auto_completes/tag_list_with_checkboxes', locals: {tags: available_tags} %>
</div>

<p class="buttons">
<%= submit_tag l(:button_change), :name => nil, :onclick => "hideModal(this);" %>
<%= submit_tag l(:button_cancel), :name => nil, :onclick => "hideModal(this);", :type => 'button' %>
</p>
<% end %>
3 changes: 3 additions & 0 deletions app/views/tags/tagging_issue.js.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
$('#ajax-modal').html('<%= escape_javascript(render :partial => 'tags/tagging_issue', :locals => {:issue => @issue, :issue_tags => @issue_tags, :checked => @checked, :available_tags => @available_tags, :project => @project}) %>');
showModal('ajax-modal', '400px');
$('#ajax-modal').addClass('new-watcher');
1 change: 1 addition & 0 deletions config/locales/en.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,4 @@ en:
issue_tags_tag: Tag
issue_tags_button_merge: Merge
issue_tags_label_merge: Merge selected tags
issue_tags_label_search: Search for tag
2 changes: 2 additions & 0 deletions config/routes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,5 @@
get :context_menu, :merge
end
end

match '/tags/tagging_issue', to: 'tags#tagging_issue', as: 'tagging_issue', via: [:get, :post]
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_end, partial: 'issues/tags_context_menu'
end
end
end
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ def self.included(base)

bases = [
IssuesController,
ContextMenusController,
CalendarsController,
GanttsController,
SettingsController
Expand Down
8 changes: 7 additions & 1 deletion lib/redmine_tags/patches/auto_completes_controller_patch.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,20 @@ module RedmineTags
module Patches
module AutoCompletesControllerPatch
def self.included(base)
base.class_eval do
helper TagsHelper
end
base.send :include, InstanceMethods
end

module InstanceMethods
def issue_tags
@name = params[:q].to_s
@tags = Issue.available_tags project: @project, name_like: @name
render layout: false, partial: 'tag_list'
if params[:object_type] == 'issue' && params[:object_id] && issue = Issue.find_by(id: params[:object_id])
@tags -= issue.tags
end
render layout: false, partial: params[:partial] || 'tag_list', locals: {tags: @tags}
end

def wiki_tags
Expand Down