additional_tags 1.0.6 → 3.0.9
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +26 -7
- data/app/controllers/additional_tags_controller.rb +9 -9
- data/app/controllers/issue_tags_controller.rb +6 -1
- data/app/helpers/additional_tags_helper.rb +41 -32
- data/app/helpers/additional_tags_issues_helper.rb +13 -5
- data/app/helpers/additional_tags_wiki_helper.rb +6 -5
- data/app/models/additional_tag.rb +98 -0
- data/app/views/additional_tags/_tag_list.html.slim +10 -4
- data/app/views/additional_tags/merge.html.slim +0 -1
- data/app/views/additional_tags/settings/_general.html.slim +7 -1
- data/app/views/additional_tags/settings/_manage_tags.html.slim +8 -1
- data/app/views/context_menus/_issues_tags.html.slim +7 -1
- data/app/views/dashboards/blocks/_issue_tags.html.slim +3 -1
- data/app/views/issue_tags/_edit_modal.html.slim +7 -7
- data/app/views/issues/_tags.html.slim +6 -1
- data/app/views/issues/_tags_bulk_edit.html.slim +2 -1
- data/app/views/wiki/_tags_form.html.slim +4 -0
- data/app/views/wiki/_tags_show.html.slim +1 -1
- data/assets/javascripts/tags.js +3 -3
- data/assets/stylesheets/tags.css +41 -16
- data/config/locales/bg.yml +17 -11
- data/config/locales/cs.yml +18 -12
- data/config/locales/de.yml +18 -12
- data/config/locales/en.yml +18 -12
- data/config/locales/es.yml +18 -12
- data/config/locales/fr.yml +18 -12
- data/config/locales/it.yml +18 -12
- data/config/locales/ja.yml +17 -11
- data/config/locales/ko.yml +17 -11
- data/config/locales/pl.yml +18 -12
- data/config/locales/pt-BR.yml +17 -11
- data/config/locales/ru.yml +33 -27
- data/config/settings.yml +5 -5
- data/lib/additional_tags/hooks/view_hook.rb +17 -5
- data/lib/additional_tags/patches/issue_patch.rb +54 -9
- data/lib/additional_tags/patches/issue_query_patch.rb +18 -0
- data/lib/additional_tags/patches/queries_helper_patch.rb +13 -3
- data/lib/additional_tags/patches/query_patch.rb +23 -2
- data/lib/additional_tags/patches/wiki_page_patch.rb +6 -1
- data/lib/additional_tags/plugin_version.rb +1 -1
- data/lib/additional_tags/tags.rb +35 -13
- data/lib/additional_tags.rb +5 -0
- metadata +5 -44
- data/.eslintrc.yml +0 -17
- data/.github/workflows/codeql-analysis.yml +0 -70
- data/.github/workflows/linters.yml +0 -43
- data/.github/workflows/tests.yml +0 -134
- data/.gitignore +0 -11
- data/.rubocop.yml +0 -133
- data/.slim-lint.yml +0 -27
- data/.stylelintrc.json +0 -163
- data/Rakefile +0 -13
- data/additional_tags.gemspec +0 -32
- data/doc/images/additional-tags-framework.png +0 -0
- data/doc/images/additional-tags.gif +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c412788c20ba3626ad2707dea2a34a96b9d2e0378c70b55bd5b8f116d92dc8cf
|
4
|
+
data.tar.gz: 6b2dd7625fe8b4e4249631bee75ad0e2a0f1be4a481382e1f346026683059246
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9293e12799c232dca72262bf3af55c84a23481e0fd1b0c6a38199f145ce3f7dca95ee218bb661f764eb49251de602abaefef41dc4da1463f4e97714097d0aa93
|
7
|
+
data.tar.gz: 57377f76241c07b63651ddece4ee6a14f983dd1faea0544b2d7ca5e3453a302142b19442252b6d71c1884c54fed4083eb84f818dc72e0b0f91927de39b381b8f
|
data/README.md
CHANGED
@@ -4,16 +4,35 @@
|
|
4
4
|
|
5
5
|
## Features
|
6
6
|
|
7
|
-
- Tags for issues
|
8
|
-
-
|
7
|
+
- Tags for issues. To use them you need to:
|
8
|
+
- *Activate issue tags* in the plugin configuration
|
9
|
+
- and update your role permissions in the Redmine administration *Roles & permissions / Issue tracking*.
|
10
|
+
- Tags for wiki pages. To use them you need to:
|
11
|
+
- *Activate wiki tags* in the plugin configuration
|
12
|
+
- and update your role permissions in the Redmine administration *Roles & permissions / Wiki*
|
13
|
+
- Available role permissions for issue tags (section *Issue tracking*):
|
14
|
+
- Add issue tags
|
15
|
+
- Edit issue tags
|
16
|
+
- Display issue tags
|
17
|
+
- Available role permissions wiki tags (section *Wiki*):
|
18
|
+
- Add wiki tags
|
19
|
+
- Managing tags centrally in the plugin settings (edit, delete, merge)-
|
20
|
+
- Grouped tags.
|
21
|
+
- Grouping of tags possible, when using a colon in tag (all tags with same base name get the same color). Typo example: ``Plugin:HRM``
|
22
|
+
- Scoped tags:
|
23
|
+
- Grouping of tags via *Scoped tags* possible, when using two colons in tag. Typo example: ``Product::Sprint 1``
|
24
|
+
- Only one tag of the same base name is allowed for an entity
|
25
|
+
- Base name and tag value are displayed seperatly
|
9
26
|
- Accented and non-latin characters supported for tag order
|
10
|
-
-
|
11
|
-
-
|
12
|
-
|
13
|
-
- Custom tags and tagging tables (additional_tags and additional_taggings). If a other plugin
|
14
|
-
used tags or tagging tables for issue or wiki tagging, there tags will be migrated automatically
|
27
|
+
- Color theme selection possible
|
28
|
+
- Custom tags and tagging tables (additional_tags and additional_taggings). If another plugin
|
29
|
+
used tags or tagging tables for issue or wiki tagging, tags will be migrated automatically there
|
15
30
|
- Based on the very popular [acts-as-taggable-on](https://github.com/mbleigh/acts-as-taggable-on)
|
16
31
|
|
32
|
+
![screenshot](https://raw.githubusercontent.com/AlphaNodes/additional_tags/master/doc/images/tag-overview.png)
|
33
|
+
|
34
|
+
The screenshot shows: regular tags, grouped tags and scoped tags. The colors are assigned randomly. But you can change the color by choosing a *Color theme* in the plugin settings.
|
35
|
+
|
17
36
|
![screenshot](https://raw.githubusercontent.com/AlphaNodes/additional_tags/master/doc/images/additional-tags.gif)
|
18
37
|
|
19
38
|
Other plugins use additional_tags as framework in order to support tags for their entities.
|
@@ -33,15 +33,6 @@ class AdditionalTagsController < ApplicationController
|
|
33
33
|
|
34
34
|
def edit; end
|
35
35
|
|
36
|
-
def destroy
|
37
|
-
@tags.each do |tag|
|
38
|
-
tag.reload.destroy!
|
39
|
-
rescue ::ActiveRecord::RecordNotFound, ::ActiveRecord::RecordNotDestroyed
|
40
|
-
Rails.logger.warn "Tag #{tag} could not be deleted"
|
41
|
-
end
|
42
|
-
redirect_back_or_default @tag_list_path
|
43
|
-
end
|
44
|
-
|
45
36
|
def update
|
46
37
|
@tag.name = params[:tag][:name] if params[:tag]
|
47
38
|
if @tag.save
|
@@ -59,6 +50,15 @@ class AdditionalTagsController < ApplicationController
|
|
59
50
|
end
|
60
51
|
end
|
61
52
|
|
53
|
+
def destroy
|
54
|
+
@tags.each do |tag|
|
55
|
+
tag.reload.destroy!
|
56
|
+
rescue ::ActiveRecord::RecordNotFound, ::ActiveRecord::RecordNotDestroyed
|
57
|
+
Rails.logger.warn "Tag #{tag} could not be deleted"
|
58
|
+
end
|
59
|
+
redirect_back_or_default @tag_list_path
|
60
|
+
end
|
61
|
+
|
62
62
|
def context_menu
|
63
63
|
@tag = @tags.first if @tags.size == 1
|
64
64
|
@back = back_url
|
@@ -19,6 +19,7 @@ class IssueTagsController < ApplicationController
|
|
19
19
|
|
20
20
|
@issue_tags.sort!
|
21
21
|
@most_used_tags = Issue.available_tags.most_used 10
|
22
|
+
@append = params[:append] == 'true'
|
22
23
|
end
|
23
24
|
|
24
25
|
def update
|
@@ -33,7 +34,11 @@ class IssueTagsController < ApplicationController
|
|
33
34
|
|
34
35
|
Issue.transaction do
|
35
36
|
@issues.each do |issue|
|
36
|
-
issue.
|
37
|
+
issue.init_journal User.current
|
38
|
+
# add tags added in placeholder for a single/multiple issue or overwrite tags for single issue
|
39
|
+
params[:append] == 'true' ? issue.tag_list << tags : issue.tag_list = tags
|
40
|
+
|
41
|
+
issue.tags_to_journal issue.tag_list_was&.to_s, issue.tag_list.to_s
|
37
42
|
issue.save!
|
38
43
|
end
|
39
44
|
end
|
@@ -53,7 +53,7 @@ module AdditionalTagsHelper
|
|
53
53
|
when 'name:desc'
|
54
54
|
tags = AdditionalTags::Tags.sort_tag_list(tags).reverse
|
55
55
|
when 'count:asc'
|
56
|
-
tags.
|
56
|
+
tags.sort_by!(&:count)
|
57
57
|
when 'count:desc'
|
58
58
|
tags.sort! { |a, b| b.count <=> a.count }
|
59
59
|
else
|
@@ -66,7 +66,11 @@ module AdditionalTagsHelper
|
|
66
66
|
def render_tags_list(tags, **options)
|
67
67
|
return if tags.blank?
|
68
68
|
|
69
|
-
|
69
|
+
options[:show_count] = AdditionalTags.setting? :show_with_count unless options.key? :show_count
|
70
|
+
options[:color_theme] = AdditionalTags.setting :tags_color_theme unless options.key? :color_theme
|
71
|
+
options[:use_colors] = AdditionalTags.use_colors? unless options.key? :use_colors
|
72
|
+
|
73
|
+
style = options.key?(:style) ? options.delete(:style) : AdditionalTags.setting(:tags_sidebar).to_sym
|
70
74
|
tags = tags.all.to_a if tags.respond_to? :all
|
71
75
|
tags = sort_tags_for_list tags
|
72
76
|
|
@@ -94,22 +98,36 @@ module AdditionalTagsHelper
|
|
94
98
|
content_tag(list_el, content, class: 'tags-cloud', style: (style == :simple_cloud ? 'text-align: left;' : ''))
|
95
99
|
end
|
96
100
|
|
97
|
-
def additional_tag_link(tag_object,
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
101
|
+
def additional_tag_link(tag_object,
|
102
|
+
link: nil,
|
103
|
+
link_wiki_tag: false,
|
104
|
+
show_count: false,
|
105
|
+
use_colors: nil,
|
106
|
+
name: nil,
|
107
|
+
color_theme: nil,
|
108
|
+
**options)
|
105
109
|
options[:project] = @project if options[:project].blank? && @project.present?
|
106
|
-
|
110
|
+
if !options.key?(:display_type) && @query && @query.display_type != @query.default_display_type
|
111
|
+
options[:display_type] = @query.display_type
|
112
|
+
end
|
113
|
+
|
114
|
+
use_colors = AdditionalTags.use_colors? if use_colors.nil?
|
115
|
+
color_theme = AdditionalTags.setting :tags_color_theme if color_theme.nil?
|
116
|
+
|
117
|
+
tag_info = AdditionalTag.new name: name.nil? ? tag_object.name : name,
|
118
|
+
disable_grouping: !use_colors,
|
119
|
+
color_theme: color_theme
|
120
|
+
tag_name = [tag_info.tag_name]
|
121
|
+
|
122
|
+
tag_style = "background-color: #{tag_info.tag_bg_color}; color: #{tag_info.tag_fg_color}" if use_colors
|
107
123
|
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
124
|
+
if tag_info.scoped?
|
125
|
+
tag_name << if show_count
|
126
|
+
tag.span tag_info.group_value, class: 'tag-group-value'
|
127
|
+
else
|
128
|
+
tag.span tag_info.group_value, class: 'tag-group-value tag-group-nocount'
|
129
|
+
end
|
130
|
+
end
|
113
131
|
|
114
132
|
tag_name << tag.span(tag_object.count, class: 'tag-count') if show_count
|
115
133
|
|
@@ -139,20 +157,6 @@ module AdditionalTagsHelper
|
|
139
157
|
tag.span content, **style
|
140
158
|
end
|
141
159
|
|
142
|
-
def additional_tag_color(tag_name)
|
143
|
-
"##{Digest::SHA256.hexdigest(tag_name)[0..5]}"
|
144
|
-
end
|
145
|
-
|
146
|
-
def additional_tag_fg_color(bg_color)
|
147
|
-
# calculate contrast text color according to YIQ method
|
148
|
-
# https://24ways.org/2010/calculating-color-contrast/
|
149
|
-
# https://stackoverflow.com/questions/3942878/how-to-decide-font-color-in-white-or-black-depending-on-background-color
|
150
|
-
r = bg_color[1..2].hex
|
151
|
-
g = bg_color[3..4].hex
|
152
|
-
b = bg_color[5..6].hex
|
153
|
-
(r * 299 + g * 587 + b * 114) >= 128_000 ? 'black' : 'white'
|
154
|
-
end
|
155
|
-
|
156
160
|
# plain list of tags
|
157
161
|
def additional_plain_tag_list(tags, sep: nil)
|
158
162
|
sep ||= "#{Query.additional_csv_separator} "
|
@@ -177,12 +181,16 @@ module AdditionalTagsHelper
|
|
177
181
|
unsorted = options.delete :unsorted
|
178
182
|
tag_list = AdditionalTags::Tags.sort_tag_list tag_list unless unsorted
|
179
183
|
|
184
|
+
# set defaults if not defined
|
185
|
+
options[:use_colors] = AdditionalTags.use_colors? unless options.key? :use_colors
|
186
|
+
options[:color_theme] = AdditionalTags.setting :tags_color_theme unless options.key? :color_theme
|
187
|
+
|
180
188
|
safe_join tag_list.map { |tag| additional_tag_link tag, **options },
|
181
189
|
additional_tag_sep(use_colors: options[:use_colors])
|
182
190
|
end
|
183
191
|
|
184
192
|
def link_to_issue_tags_totals(entries:, project:, open_issues_only:)
|
185
|
-
sum = if entries.blank? || entries.
|
193
|
+
sum = if entries.blank? || entries.empty?
|
186
194
|
0
|
187
195
|
else
|
188
196
|
query = IssueQuery.new project: project, name: '_'
|
@@ -208,7 +216,7 @@ module AdditionalTagsHelper
|
|
208
216
|
|
209
217
|
private
|
210
218
|
|
211
|
-
def tag_url(tag_name, filter: nil, tag_action: nil, tag_controller: nil, project: nil)
|
219
|
+
def tag_url(tag_name, filter: nil, tag_action: nil, tag_controller: nil, project: nil, display_type: nil)
|
212
220
|
action = tag_action.presence || (controller_name == 'hrm_user_resources' ? 'show' : 'index')
|
213
221
|
|
214
222
|
fields = [:tags]
|
@@ -225,6 +233,7 @@ module AdditionalTagsHelper
|
|
225
233
|
{ controller: tag_controller.presence || controller_name,
|
226
234
|
action: action,
|
227
235
|
set_filter: 1,
|
236
|
+
display_type: display_type,
|
228
237
|
project_id: project,
|
229
238
|
f: fields,
|
230
239
|
v: values,
|
@@ -10,8 +10,18 @@ module AdditionalTagsIssuesHelper
|
|
10
10
|
AdditionalTags.setting?(:active_issue_tags) && User.current.allowed_to?(:view_issue_tags, @project)
|
11
11
|
|
12
12
|
api.array :tags do
|
13
|
-
|
14
|
-
|
13
|
+
# support tags, which are not saved to database
|
14
|
+
if @issue.tag_list.present?
|
15
|
+
if @issue.tags.present? && @issue.tags.map(&:name) == @issue.tag_list
|
16
|
+
@issue.tags.each do |tag|
|
17
|
+
api.tag id: tag.id, name: tag.name
|
18
|
+
end
|
19
|
+
else
|
20
|
+
@issue.tag_list.each do |tag_name|
|
21
|
+
# there is no id for unsaved tags
|
22
|
+
api.tag name: tag_name
|
23
|
+
end
|
24
|
+
end
|
15
25
|
end
|
16
26
|
end
|
17
27
|
end
|
@@ -44,9 +54,7 @@ module AdditionalTagsIssuesHelper
|
|
44
54
|
end
|
45
55
|
|
46
56
|
def render_sidebar_tags
|
47
|
-
options = {
|
48
|
-
filter: AdditionalTags.setting?(:open_issues_only) ? { field: :status_id, operator: 'o' } : nil,
|
49
|
-
style: AdditionalTags.setting(:tags_sidebar).to_sym,
|
57
|
+
options = { filter: AdditionalTags.setting?(:open_issues_only) ? { field: :status_id, operator: 'o' } : nil,
|
50
58
|
project: @project }
|
51
59
|
|
52
60
|
options[:tag_action] = 'show' if %w[gantts calendars].include? controller_name
|
@@ -10,9 +10,7 @@ module AdditionalTagsWikiHelper
|
|
10
10
|
end
|
11
11
|
|
12
12
|
def render_sidebar_tags
|
13
|
-
options = {
|
14
|
-
style: AdditionalTags.setting(:tags_sidebar).to_sym,
|
15
|
-
link_wiki_tag: true,
|
13
|
+
options = { link_wiki_tag: true,
|
16
14
|
project: @project }
|
17
15
|
|
18
16
|
render_tags_list sidebar_tags, **options
|
@@ -20,12 +18,15 @@ module AdditionalTagsWikiHelper
|
|
20
18
|
|
21
19
|
def render_wiki_index_title(project: nil, name: nil, tag: nil, title: :label_wiki)
|
22
20
|
if tag.present?
|
21
|
+
tag_object = ActsAsTaggableOn::Tag.new name: tag
|
22
|
+
|
23
23
|
if project
|
24
|
-
|
24
|
+
safe_join [l(:label_wiki_index_for_tag), additional_tag_link(tag_object, link: '#')], ' '
|
25
25
|
else
|
26
26
|
title = [link_to(l(title), wiki_index_path)]
|
27
27
|
title << Additionals::LIST_SEPARATOR
|
28
|
-
title <<
|
28
|
+
title << l(:label_wiki_index_for_tag)
|
29
|
+
title << additional_tag_link(tag_object, link: '#')
|
29
30
|
safe_join title, ' '
|
30
31
|
end
|
31
32
|
elsif name.present?
|
@@ -0,0 +1,98 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class AdditionalTag
|
4
|
+
GROUP_SEP = ':'
|
5
|
+
SCOPE_SEP = '::'
|
6
|
+
|
7
|
+
class << self
|
8
|
+
def valid_mutually_exclusive_tag(tag_list)
|
9
|
+
return true if tag_list.blank?
|
10
|
+
|
11
|
+
tags = tag_list.select { |t| t.include? SCOPE_SEP }
|
12
|
+
return true if tags.blank?
|
13
|
+
|
14
|
+
groups = tags.map { |t| new(name: t).group_name }
|
15
|
+
groups == groups.uniq
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
# NOTE: only use bg_color parameter, if background color should not
|
20
|
+
# calculated by AdditionalTag - if you want to assign manual color
|
21
|
+
def initialize(name:, disable_grouping: false, color_theme: nil, bg_color: nil)
|
22
|
+
@tag_name = name.to_s
|
23
|
+
@disable_grouping = disable_grouping
|
24
|
+
@color_theme = color_theme.to_s
|
25
|
+
@bg_color = bg_color
|
26
|
+
end
|
27
|
+
|
28
|
+
def name_for_color
|
29
|
+
# different colors for non-grouped, grouped and scoped tag
|
30
|
+
name = if scoped? || grouped?
|
31
|
+
"#{group_name}#{sep}"
|
32
|
+
else
|
33
|
+
tag_name
|
34
|
+
end
|
35
|
+
|
36
|
+
if @color_theme.present? && @color_theme != '0' && @color_theme != '1'
|
37
|
+
"#{name}#{@color_theme}"
|
38
|
+
else
|
39
|
+
name
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def tag_bg_color
|
44
|
+
@tag_bg_color ||= @bg_color || "##{Digest::SHA256.hexdigest(name_for_color)[0..5]}"
|
45
|
+
end
|
46
|
+
|
47
|
+
# calculate contrast text color according to YIQ method
|
48
|
+
# https://24ways.org/2010/calculating-color-contrast/
|
49
|
+
# https://stackoverflow.com/questions/3942878/how-to-decide-font-color-in-white-or-black-depending-on-background-color
|
50
|
+
def tag_fg_color
|
51
|
+
@tag_fg_color ||= begin
|
52
|
+
r = tag_bg_color[1..2].hex
|
53
|
+
g = tag_bg_color[3..4].hex
|
54
|
+
b = tag_bg_color[5..6].hex
|
55
|
+
(r * 299 + g * 587 + b * 114) >= 128_000 ? 'black' : 'white'
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def sep
|
60
|
+
scoped? ? SCOPE_SEP : GROUP_SEP
|
61
|
+
end
|
62
|
+
|
63
|
+
def tag_name
|
64
|
+
scoped? ? group_name : @tag_name
|
65
|
+
end
|
66
|
+
|
67
|
+
def labels
|
68
|
+
@labels ||= scoped? ? scope_labels : group_labels
|
69
|
+
end
|
70
|
+
|
71
|
+
def scope_labels
|
72
|
+
@scope_labels ||= @tag_name.split(SCOPE_SEP).map(&:strip)
|
73
|
+
end
|
74
|
+
|
75
|
+
def group_labels
|
76
|
+
@group_labels ||= @tag_name.split(GROUP_SEP).map(&:strip)
|
77
|
+
end
|
78
|
+
|
79
|
+
def group_name
|
80
|
+
if labels.length > 2
|
81
|
+
labels[0...-1].join sep
|
82
|
+
else
|
83
|
+
labels.first
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
def group_value
|
88
|
+
labels.last
|
89
|
+
end
|
90
|
+
|
91
|
+
def scoped?
|
92
|
+
!@disable_grouping && scope_labels.length > 1
|
93
|
+
end
|
94
|
+
|
95
|
+
def grouped?
|
96
|
+
!@disable_grouping && group_labels.length > 1
|
97
|
+
end
|
98
|
+
end
|
@@ -15,17 +15,23 @@
|
|
15
15
|
span.contextual
|
16
16
|
= link_to l(:label_edit_tags),
|
17
17
|
{},
|
18
|
-
onclick: "$('#
|
19
|
-
id: '
|
18
|
+
onclick: "$('#edit-tags-form').show(); $('#tags-data').hide(); return false;",
|
19
|
+
id: 'edit-tags-link'
|
20
20
|
|
21
|
-
#
|
21
|
+
#edit-tags-form.hidden
|
22
22
|
= form_tag update_url, method: :put do
|
23
23
|
= render defined?(tags_form) ? tags_form : 'tags_form',
|
24
24
|
css_id: defined?(css_id) ? css_id : nil
|
25
25
|
'
|
26
26
|
= submit_tag l(:button_save), class: 'button-small'
|
27
27
|
'
|
28
|
-
= link_to l(:button_cancel), {}, onclick: "$('#
|
28
|
+
= link_to l(:button_cancel), {}, onclick: "$('#edit-tags-form').hide(); $('#tags-data').show(); return false;"
|
29
|
+
|
30
|
+
javascript:
|
31
|
+
$(function() {
|
32
|
+
var eventSelect = $('#issue_tag_list');
|
33
|
+
eventSelect.on('select2:close', function(e) { fixScopedTags(e, eventSelect); });
|
34
|
+
})
|
29
35
|
|
30
36
|
- else
|
31
37
|
= additional_tag_links entry.tags,
|
@@ -23,7 +23,13 @@ fieldset.settings
|
|
23
23
|
options_for_select(%w[name last_created count].collect { |v| [l("tags_order_by_#{v}"), v] },
|
24
24
|
@settings['tags_suggestion_order'])
|
25
25
|
p
|
26
|
-
=
|
26
|
+
= additionals_settings_select :tags_color_theme, options_for_select([[l(:label_tags_without_color), '0'],
|
27
|
+
[l(:label_tag_color_theme, value: 1), '1'],
|
28
|
+
[l(:label_tag_color_theme, value: 2), 'a'],
|
29
|
+
[l(:label_tag_color_theme, value: 3), 'b'],
|
30
|
+
[l(:label_tag_color_theme, value: 4), 'c'],
|
31
|
+
[l(:label_tag_color_theme, value: 5), 'd']],
|
32
|
+
@settings['tags_color_theme'])
|
27
33
|
|
28
34
|
fieldset.settings
|
29
35
|
legend = l :label_issue_plural
|
@@ -13,11 +13,18 @@
|
|
13
13
|
th = column_values[:label]
|
14
14
|
th
|
15
15
|
tbody
|
16
|
+
- use_colors = AdditionalTags.use_colors?
|
17
|
+
- color_theme = AdditionalTags.setting :tags_color_theme
|
16
18
|
- tags.each do |tag|
|
17
19
|
tr.hascontextmenu id="#{tag.id}"
|
18
20
|
td.checkbox.hide-when-print
|
19
21
|
= check_box_tag 'ids[]', tag.id, false, id: nil
|
20
|
-
td
|
22
|
+
td
|
23
|
+
= additional_tag_link tag,
|
24
|
+
link: edit_additional_tag_path(tag),
|
25
|
+
use_colors: use_colors,
|
26
|
+
color_theme: color_theme
|
27
|
+
|
21
28
|
- manageable_tag_column_values(tag).each do |column|
|
22
29
|
td = column
|
23
30
|
td.buttons
|
@@ -5,6 +5,12 @@
|
|
5
5
|
ul
|
6
6
|
li
|
7
7
|
= context_menu_link l(:button_add),
|
8
|
-
edit_issue_tags_path(ids: @issue_ids, search: params[:search]),
|
8
|
+
edit_issue_tags_path(ids: @issue_ids, search: params[:search], append: 'true'),
|
9
9
|
remote: true,
|
10
10
|
class: 'icon icon-add'
|
11
|
+
- if @issue_ids.size == 1
|
12
|
+
li
|
13
|
+
= context_menu_link l(:button_edit),
|
14
|
+
edit_issue_tags_path(ids: @issue_ids, search: params[:search]),
|
15
|
+
remote: true,
|
16
|
+
class: 'icon icon-edit'
|
@@ -28,13 +28,15 @@ h3 = block_definition[:label]
|
|
28
28
|
th = l :label_closed_issues_plural
|
29
29
|
th = l :label_total
|
30
30
|
tbody
|
31
|
+
- color_theme = AdditionalTags.setting :tags_color_theme
|
31
32
|
- tags.each do |tag|
|
32
33
|
tr
|
33
34
|
td.name = additional_tag_link tag,
|
34
35
|
tag_action: 'index',
|
35
36
|
tag_controller: 'issues',
|
36
37
|
filter: issue_tag_status_filter(open_issues_only: open_issues_only),
|
37
|
-
use_colors: RedminePluginKit.true?(settings[:use_colors])
|
38
|
+
use_colors: RedminePluginKit.true?(settings[:use_colors]),
|
39
|
+
color_theme: color_theme
|
38
40
|
- unless open_issues_only
|
39
41
|
td.value = additional_tag_link tag,
|
40
42
|
tag_action: 'index',
|
@@ -1,4 +1,4 @@
|
|
1
|
-
h3.title = l :
|
1
|
+
h3.title = @append ? l(:label_add_tags) : l(:label_edit_tags)
|
2
2
|
|
3
3
|
- if @is_bulk_editing
|
4
4
|
h3 = l :label_bulk_edit_selected_issues
|
@@ -9,24 +9,24 @@ h3.title = l :label_add_tags
|
|
9
9
|
h3
|
10
10
|
span = link_to_issue @issues.first
|
11
11
|
|
12
|
-
= form_tag issue_tags_path(ids: @issue_ids, search: params[:search]) do
|
12
|
+
= form_tag issue_tags_path(ids: @issue_ids, search: params[:search], append: @append.to_s) do
|
13
13
|
fieldset.box
|
14
14
|
legend = l :field_tags
|
15
15
|
#issue_tags
|
16
16
|
= additionals_select2_tag 'issue[tag_list]',
|
17
|
-
options_for_select(@issue_tags.map { |tag| [tag, tag] }, @issue_tags),
|
17
|
+
options_for_select(@append ? {} : @issue_tags.map { |tag| [tag, tag] }, @issue_tags),
|
18
18
|
multiple: true,
|
19
19
|
style: 'width: 100%;',
|
20
20
|
url: issue_tags_auto_completes_path(project_id: @project),
|
21
21
|
placeholder: @is_bulk_editing ? t(:label_no_change_option) : '+ add tag',
|
22
22
|
tags: User.current.allowed_to?(:create_issue_tags, @project)
|
23
|
-
p.
|
24
|
-
= safe_join @most_used_tags.collect { |t| tag.span t.name, class: '
|
23
|
+
p.most-used-tags
|
24
|
+
= safe_join @most_used_tags.collect { |t| tag.span t.name, class: 'most-used-tag' }, ', '
|
25
25
|
|
26
26
|
.buttons
|
27
|
-
= submit_tag l(:button_add), name: nil
|
27
|
+
= submit_tag l(@append ? :button_add : :button_save), name: nil
|
28
28
|
'
|
29
|
-
= link_to_function l(:button_cancel), 'hideModal(this)
|
29
|
+
= link_to_function l(:button_cancel), 'hideModal(this)'
|
30
30
|
|
31
31
|
javascript:
|
32
32
|
var mostUsedTags = #{raw @most_used_tags.map(&:name)};
|
@@ -5,4 +5,9 @@
|
|
5
5
|
editable: issue.editable?(User.current),
|
6
6
|
css_id: 'issue_tag_list_show',
|
7
7
|
update_url: issue_path(issue),
|
8
|
-
use_colors: AdditionalTags.
|
8
|
+
use_colors: AdditionalTags.use_colors?
|
9
|
+
|
10
|
+
- if issue.editable? User.current
|
11
|
+
javascript:
|
12
|
+
var eventSelect = $('#issue_tag_list_show');
|
13
|
+
eventSelect.on('select2:close', function(e) { fixScopedTags(e, eventSelect); });
|
@@ -1,7 +1,8 @@
|
|
1
|
-
- tags =
|
1
|
+
- tags = Issue.common_tag_list_from_issues(@issues.map(&:id))
|
2
2
|
= additionals_select2_tag 'issue[tag_list]',
|
3
3
|
options_for_select(tags.map { |tag| [tag, tag] }, tags),
|
4
4
|
multiple: true,
|
5
5
|
url: issue_tags_auto_completes_path,
|
6
6
|
placeholder: l(:label_add_tags),
|
7
7
|
tags: true
|
8
|
+
= hidden_field_tag 'common_tags', tags.to_s
|
data/assets/javascripts/tags.js
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
/* global mostUsedTags:writable */
|
2
2
|
$(function() {
|
3
|
-
$('body').on('click', '.
|
3
|
+
$('body').on('click', '.most-used-tags .most-used-tag', function(e) {
|
4
4
|
var $tagsSelect = $('select#issue_tag_list');
|
5
5
|
var tag = e.target.innerText;
|
6
6
|
if ($tagsSelect.find('option[value=\'' + tag + '\']').length === 0) {
|
@@ -10,10 +10,10 @@ $(function() {
|
|
10
10
|
|
11
11
|
mostUsedTags = $.grep(mostUsedTags, function(t) { return t != tag; });
|
12
12
|
var tagsHtml = mostUsedTags.map(function(tag) {
|
13
|
-
return '<span class="
|
13
|
+
return '<span class="most-used-tag">' + tag + '</span>';
|
14
14
|
}).join(', ');
|
15
15
|
|
16
|
-
var $mostUsedTagsContainer = $(e.target).parent('.
|
16
|
+
var $mostUsedTagsContainer = $(e.target).parent('.most-used-tags');
|
17
17
|
$mostUsedTagsContainer.empty();
|
18
18
|
$mostUsedTagsContainer.append(tagsHtml);
|
19
19
|
});
|