additional_tags 1.0.1 → 1.0.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/brakeman.yml +2 -1
- data/.github/workflows/linters.yml +2 -1
- data/.gitignore +1 -0
- data/.rubocop.yml +37 -4
- data/.slim-lint.yml +3 -2
- data/Rakefile +2 -0
- data/additional_tags.gemspec +5 -3
- data/app/controllers/additional_tags_controller.rb +4 -1
- data/app/controllers/issue_tags_controller.rb +6 -4
- data/app/helpers/additional_tags_helper.rb +39 -41
- data/app/helpers/additional_tags_issues_helper.rb +3 -1
- data/app/helpers/additional_tags_wiki_helper.rb +6 -4
- data/app/jobs/additional_tags_job.rb +2 -0
- data/app/jobs/additional_tags_remove_unused_tag_job.rb +2 -0
- data/app/models/migrate_tag.rb +2 -0
- data/app/models/migrate_tagging.rb +2 -0
- data/app/models/query_tags_column.rb +7 -0
- data/app/views/additional_tags/_tag_list.html.slim +1 -1
- data/app/views/additional_tags/merge.html.slim +4 -3
- data/app/views/additional_tags/settings/_manage_tags.html.slim +1 -1
- data/app/views/issue_tags/_edit_modal.html.slim +2 -2
- data/app/views/issues/_tags_form.html.slim +1 -1
- data/config/routes.rb +2 -0
- data/db/migrate/20201116145429_acts_as_taggable_migration.rb +3 -1
- data/db/migrate/20201123093214_migrate_existing_tags.rb +4 -2
- data/init.rb +2 -0
- data/lib/additional_tags.rb +5 -15
- data/lib/additional_tags/hooks.rb +2 -0
- data/lib/additional_tags/patches/agile_boards_controller_patch.rb +2 -0
- data/lib/additional_tags/patches/agile_query_patch.rb +11 -9
- data/lib/additional_tags/patches/agile_versions_controller_patch.rb +2 -0
- data/lib/additional_tags/patches/agile_versions_query_patch.rb +3 -1
- data/lib/additional_tags/patches/auto_completes_controller_patch.rb +3 -1
- data/lib/additional_tags/patches/calendars_controller_patch.rb +2 -0
- data/lib/additional_tags/patches/dashboard_async_blocks_controller_patch.rb +2 -0
- data/lib/additional_tags/patches/dashboards_controller_patch.rb +2 -0
- data/lib/additional_tags/patches/gantts_controller_patch.rb +2 -0
- data/lib/additional_tags/patches/imports_controller_patch.rb +2 -0
- data/lib/additional_tags/patches/issue_patch.rb +8 -6
- data/lib/additional_tags/patches/issue_query_patch.rb +17 -14
- data/lib/additional_tags/patches/issues_controller_patch.rb +2 -0
- data/lib/additional_tags/patches/journal_patch.rb +2 -0
- data/lib/additional_tags/patches/my_controller_patch.rb +2 -0
- data/lib/additional_tags/patches/queries_helper_patch.rb +3 -15
- data/lib/additional_tags/patches/query_patch.rb +76 -0
- data/lib/additional_tags/patches/reports_controller_patch.rb +2 -0
- data/lib/additional_tags/patches/settings_controller_patch.rb +2 -0
- data/lib/additional_tags/patches/time_entry_patch.rb +2 -0
- data/lib/additional_tags/patches/time_entry_query_patch.rb +5 -15
- data/lib/additional_tags/patches/time_report_patch.rb +2 -0
- data/lib/additional_tags/patches/timelog_controller_patch.rb +2 -0
- data/lib/additional_tags/patches/wiki_controller_patch.rb +2 -0
- data/lib/additional_tags/patches/wiki_page_patch.rb +4 -2
- data/lib/additional_tags/tags.rb +28 -17
- data/lib/additional_tags/version.rb +3 -1
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: '094d1e57c687d9c643b002e5e6134a457d47791a2b086c3c159d690242228488'
|
4
|
+
data.tar.gz: dbfd7b4cb744aef1df5d132615bc1d8816ac85ccb7b837b04376d2b1eb9a76d6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f95b50b1d98bb7f22c8a2d3bfc5d767ba85a6df06b5e259d9fe2a03ce2980f6577e948f6120f0fb831d3dee5155f88ebdab215534a3264fc24adb31749610122
|
7
|
+
data.tar.gz: 417da0e654d1d966592242c95dd12899638758023b0822499c92e2079d03c28f0b9788046ee161f6ce721df325a0cdd91f1bd6dfe621cb88f910d7b9c12dcd3e
|
data/.gitignore
CHANGED
data/.rubocop.yml
CHANGED
@@ -16,6 +16,10 @@ Metrics/AbcSize:
|
|
16
16
|
Metrics/BlockLength:
|
17
17
|
Enabled: false
|
18
18
|
|
19
|
+
Metrics/ParameterLists:
|
20
|
+
Enabled: true
|
21
|
+
CountKeywordArgs: false
|
22
|
+
|
19
23
|
Metrics/ClassLength:
|
20
24
|
Enabled: false
|
21
25
|
|
@@ -34,6 +38,12 @@ Metrics/ModuleLength:
|
|
34
38
|
Metrics/PerceivedComplexity:
|
35
39
|
Max: 25
|
36
40
|
|
41
|
+
Style/ExpandPathArguments:
|
42
|
+
Enabled: true
|
43
|
+
Exclude:
|
44
|
+
- additional_tags.gemspec
|
45
|
+
- test/**/*
|
46
|
+
|
37
47
|
Rails/ApplicationJob:
|
38
48
|
Enabled: false
|
39
49
|
|
@@ -56,14 +66,37 @@ Style/AutoResourceCleanup:
|
|
56
66
|
Enabled: true
|
57
67
|
|
58
68
|
Style/FrozenStringLiteralComment:
|
59
|
-
Enabled:
|
69
|
+
Enabled: true
|
70
|
+
Exclude:
|
71
|
+
- '/**/*.rsb'
|
60
72
|
|
61
73
|
Style/Documentation:
|
62
74
|
Enabled: false
|
63
75
|
|
64
|
-
|
65
|
-
|
66
|
-
|
76
|
+
Style/OptionHash:
|
77
|
+
Enabled: true
|
78
|
+
SuspiciousParamNames:
|
79
|
+
- options
|
80
|
+
- api_options
|
81
|
+
- opts
|
82
|
+
- args
|
83
|
+
- params
|
84
|
+
- parameters
|
85
|
+
- settings
|
86
|
+
Exclude:
|
87
|
+
- lib/additional_tags/patches/*.rb
|
88
|
+
|
89
|
+
Style/ReturnNil:
|
90
|
+
Enabled: true
|
91
|
+
|
92
|
+
Style/UnlessLogicalOperators:
|
93
|
+
Enabled: true
|
94
|
+
|
95
|
+
Style/MethodCallWithArgsParentheses:
|
96
|
+
Enabled: true
|
97
|
+
AllowParenthesesInMultilineCall: true
|
98
|
+
AllowParenthesesInChaining: true
|
99
|
+
EnforcedStyle: omit_parentheses
|
67
100
|
|
68
101
|
Style/HashTransformKeys:
|
69
102
|
Enabled: false
|
data/.slim-lint.yml
CHANGED
@@ -17,10 +17,11 @@ linters:
|
|
17
17
|
- Layout/MultilineMethodCallIndentation
|
18
18
|
- Layout/MultilineMethodDefinitionBraceLayout
|
19
19
|
- Layout/MultilineOperationIndentation
|
20
|
+
- Layout/SpaceBeforeBrackets
|
20
21
|
- Layout/TrailingEmptyLines
|
21
22
|
- Lint/Void
|
22
23
|
- Rails/OutputSafety
|
24
|
+
- Style/FrozenStringLiteralComment
|
23
25
|
- Style/IfUnlessModifier
|
24
|
-
- Style/WhileUntilModifier
|
25
26
|
- Style/Next
|
26
|
-
-
|
27
|
+
- Style/WhileUntilModifier
|
data/Rakefile
CHANGED
data/additional_tags.gemspec
CHANGED
@@ -1,5 +1,7 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
lib = File.expand_path '../lib', __FILE__
|
2
|
-
$LOAD_PATH.unshift
|
4
|
+
$LOAD_PATH.unshift lib unless $LOAD_PATH.include? lib
|
3
5
|
require 'additional_tags/version'
|
4
6
|
|
5
7
|
Gem::Specification.new do |spec|
|
@@ -14,10 +16,10 @@ Gem::Specification.new do |spec|
|
|
14
16
|
spec.license = 'GPL-2.0'
|
15
17
|
|
16
18
|
spec.files = `git ls-files -z`.split("\x0").reject do |f|
|
17
|
-
f.match
|
19
|
+
f.match %r{^((test|spec|features)/|Gemfile)}
|
18
20
|
end
|
19
21
|
spec.bindir = 'exe'
|
20
|
-
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename
|
22
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename f }
|
21
23
|
spec.require_paths = ['lib']
|
22
24
|
spec.required_ruby_version = '>= 2.5'
|
23
25
|
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
class AdditionalTagsController < ApplicationController
|
2
4
|
before_action :require_admin
|
3
5
|
before_action :find_tag, only: %i[edit update]
|
@@ -56,7 +58,7 @@ class AdditionalTagsController < ApplicationController
|
|
56
58
|
end
|
57
59
|
|
58
60
|
def bulk_find_tags
|
59
|
-
@tags = ActsAsTaggableOn::Tag.joins("JOIN #{ActiveRecord::Base.connection.quote_table_name ActsAsTaggableOn.taggings_table}" \
|
61
|
+
@tags = ActsAsTaggableOn::Tag.joins("LEFT JOIN #{ActiveRecord::Base.connection.quote_table_name ActsAsTaggableOn.taggings_table}" \
|
60
62
|
" ON #{ActiveRecord::Base.connection.quote_table_name ActsAsTaggableOn.taggings_table}.tag_id =" \
|
61
63
|
" #{ActiveRecord::Base.connection.quote_table_name ActsAsTaggableOn.tags_table}.id ")
|
62
64
|
.select("#{ActiveRecord::Base.connection.quote_table_name ActsAsTaggableOn.tags_table}.id," \
|
@@ -67,6 +69,7 @@ class AdditionalTagsController < ApplicationController
|
|
67
69
|
.group("#{ActiveRecord::Base.connection.quote_table_name ActsAsTaggableOn.tags_table}.id" \
|
68
70
|
", #{ActiveRecord::Base.connection.quote_table_name ActsAsTaggableOn.tags_table}.name" \
|
69
71
|
", #{ActiveRecord::Base.connection.quote_table_name ActsAsTaggableOn.tags_table}.taggings_count")
|
72
|
+
|
70
73
|
raise ActiveRecord::RecordNotFound if @tags.empty?
|
71
74
|
end
|
72
75
|
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
class IssueTagsController < ApplicationController
|
2
4
|
before_action :find_issues, only: %i[edit update]
|
3
5
|
|
@@ -25,7 +27,7 @@ class IssueTagsController < ApplicationController
|
|
25
27
|
tags = params[:issue] && params[:issue][:tag_list] ? params[:issue][:tag_list].reject(&:empty?) : []
|
26
28
|
|
27
29
|
unless User.current.allowed_to?(:create_issue_tags, @projects.first) || Issue.allowed_tags?(tags)
|
28
|
-
flash[:error] = t
|
30
|
+
flash[:error] = t :notice_failed_to_add_tags
|
29
31
|
return
|
30
32
|
end
|
31
33
|
|
@@ -35,13 +37,13 @@ class IssueTagsController < ApplicationController
|
|
35
37
|
issue.save!
|
36
38
|
end
|
37
39
|
end
|
38
|
-
flash[:notice] = t
|
40
|
+
flash[:notice] = t :notice_tags_added
|
39
41
|
else
|
40
|
-
flash[:error] = t
|
42
|
+
flash[:error] = t :notice_failed_to_add_tags
|
41
43
|
end
|
42
44
|
rescue StandardError => e
|
43
45
|
Rails.logger.warn "Failed to add tags: #{e.inspect}"
|
44
|
-
flash[:error] = t
|
46
|
+
flash[:error] = t :notice_failed_to_add_tags
|
45
47
|
ensure
|
46
48
|
redirect_to_referer_or { render text: 'Tags updated.', layout: true }
|
47
49
|
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module AdditionalTagsHelper
|
4
4
|
include ActsAsTaggableOn::TagsHelper
|
@@ -12,13 +12,13 @@ module AdditionalTagsHelper
|
|
12
12
|
|
13
13
|
columns = {}
|
14
14
|
|
15
|
-
if AdditionalTags.setting?
|
15
|
+
if AdditionalTags.setting? :active_issue_tags
|
16
16
|
columns[:issue] = { label: l(:label_issue_plural),
|
17
17
|
tag_controller: :issues,
|
18
18
|
counts: Issue.available_tags.map { |tag| [tag.id, tag.count] }.to_h }
|
19
19
|
end
|
20
20
|
|
21
|
-
if AdditionalTags.setting?
|
21
|
+
if AdditionalTags.setting? :active_wiki_tags
|
22
22
|
columns[:wiki] = { label: l(:label_wiki),
|
23
23
|
counts: WikiPage.available_tags.map { |tag| [tag.id, tag.count] }.to_h }
|
24
24
|
end
|
@@ -43,11 +43,11 @@ module AdditionalTagsHelper
|
|
43
43
|
columns
|
44
44
|
end
|
45
45
|
|
46
|
-
def render_tags_list(tags, options
|
46
|
+
def render_tags_list(tags, **options)
|
47
47
|
return if tags.blank?
|
48
48
|
|
49
|
-
style = options.delete
|
50
|
-
tags = tags.all.to_a if tags.respond_to?
|
49
|
+
style = options.delete :style
|
50
|
+
tags = tags.all.to_a if tags.respond_to? :all
|
51
51
|
|
52
52
|
case "#{AdditionalTags.setting :tags_sort_by}:#{AdditionalTags.setting :tags_sort_order}"
|
53
53
|
when 'name:desc'
|
@@ -71,7 +71,7 @@ module AdditionalTagsHelper
|
|
71
71
|
raise 'Unknown list style'
|
72
72
|
end
|
73
73
|
|
74
|
-
content = ''.html_safe
|
74
|
+
content = +''.html_safe
|
75
75
|
if style == :list && AdditionalTags.setting(:tags_sort_by) == 'name'
|
76
76
|
tags.group_by { |tag| tag.name.downcase.first }.each do |letter, grouped_tags|
|
77
77
|
content << content_tag(item_el, letter.upcase, class: 'letter')
|
@@ -84,26 +84,26 @@ module AdditionalTagsHelper
|
|
84
84
|
content_tag(list_el, content, class: 'tags-cloud', style: (style == :simple_cloud ? 'text-align: left;' : ''))
|
85
85
|
end
|
86
86
|
|
87
|
-
def additional_tag_link(tag_object,
|
87
|
+
def additional_tag_link(tag_object, link: nil, link_wiki_tag: false, show_count: false, use_colors: nil, **options)
|
88
88
|
tag_name = []
|
89
89
|
tag_name << tag_object.name
|
90
90
|
|
91
91
|
options[:project] = @project if options[:project].blank? && @project.present?
|
92
92
|
|
93
|
-
use_colors
|
93
|
+
use_colors ||= AdditionalTags.setting? :use_colors
|
94
94
|
if use_colors
|
95
95
|
tag_bg_color = additional_tag_color tag_object.name
|
96
96
|
tag_fg_color = additional_tag_fg_color tag_bg_color
|
97
97
|
tag_style = "background-color: #{tag_bg_color}; color: #{tag_fg_color}"
|
98
98
|
end
|
99
99
|
|
100
|
-
tag_name << tag.span("(#{tag_object.count})", class: 'tag-count') if
|
100
|
+
tag_name << tag.span("(#{tag_object.count})", class: 'tag-count') if show_count
|
101
101
|
|
102
|
-
content = if
|
102
|
+
content = if link
|
103
103
|
link_to safe_join(tag_name),
|
104
|
-
|
104
|
+
link,
|
105
105
|
style: tag_style
|
106
|
-
elsif
|
106
|
+
elsif link_wiki_tag
|
107
107
|
link = if options[:project].present?
|
108
108
|
project_wiki_index_path options[:project], tag: tag_object.name
|
109
109
|
else
|
@@ -112,7 +112,7 @@ module AdditionalTagsHelper
|
|
112
112
|
link_to safe_join(tag_name), link, style: tag_style
|
113
113
|
else
|
114
114
|
link_to safe_join(tag_name),
|
115
|
-
tag_url(tag_object.name, options),
|
115
|
+
tag_url(tag_object.name, **options),
|
116
116
|
style: tag_style
|
117
117
|
end
|
118
118
|
|
@@ -122,11 +122,11 @@ module AdditionalTagsHelper
|
|
122
122
|
{ class: 'tag-label' }
|
123
123
|
end
|
124
124
|
|
125
|
-
tag.span content, style
|
125
|
+
tag.span content, **style
|
126
126
|
end
|
127
127
|
|
128
128
|
def additional_tag_color(tag_name)
|
129
|
-
"##{Digest::
|
129
|
+
"##{Digest::SHA256.hexdigest(tag_name)[0..5]}"
|
130
130
|
end
|
131
131
|
|
132
132
|
def additional_tag_fg_color(bg_color)
|
@@ -140,53 +140,51 @@ module AdditionalTagsHelper
|
|
140
140
|
end
|
141
141
|
|
142
142
|
# plain list of tags
|
143
|
-
def additional_plain_tag_list(tags, sep
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
tags.map(&:name)
|
148
|
-
end
|
143
|
+
def additional_plain_tag_list(tags, sep: nil)
|
144
|
+
sep ||= "#{Query.additional_csv_separator} "
|
145
|
+
|
146
|
+
s = tags.present? ? tags.map(&:name) : ['']
|
149
147
|
s.join sep
|
150
148
|
end
|
151
149
|
|
152
|
-
def additional_tag_sep(use_colors)
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
150
|
+
def additional_tag_sep(use_colors: true)
|
151
|
+
use_colors ? ' ' : ', '
|
152
|
+
end
|
153
|
+
|
154
|
+
def additional_tags_from_string(str)
|
155
|
+
str.to_s.split(',').map(&:strip)
|
158
156
|
end
|
159
157
|
|
160
|
-
def additional_tag_links(tag_list, options
|
158
|
+
def additional_tag_links(tag_list, **options)
|
161
159
|
return if tag_list.blank?
|
162
160
|
|
163
|
-
unsorted = options.delete
|
164
|
-
tag_list = AdditionalTags::Tags.sort_tag_list
|
161
|
+
unsorted = options.delete :unsorted
|
162
|
+
tag_list = AdditionalTags::Tags.sort_tag_list tag_list unless unsorted
|
165
163
|
|
166
|
-
safe_join tag_list.map { |tag| additional_tag_link tag, options },
|
167
|
-
additional_tag_sep(options[:use_colors])
|
164
|
+
safe_join tag_list.map { |tag| additional_tag_link tag, **options },
|
165
|
+
additional_tag_sep(use_colors: options[:use_colors])
|
168
166
|
end
|
169
167
|
|
170
168
|
private
|
171
169
|
|
172
|
-
def tag_url(tag_name,
|
173
|
-
action =
|
170
|
+
def tag_url(tag_name, filter: nil, tag_action: nil, tag_controller: nil, project: nil)
|
171
|
+
action = tag_action.presence || (controller_name == 'hrm_user_resources' ? 'show' : 'index')
|
174
172
|
|
175
173
|
fields = [:tags]
|
176
174
|
values = { tags: [tag_name] }
|
177
175
|
operators = { tags: '=' }
|
178
176
|
|
179
|
-
if
|
180
|
-
field =
|
177
|
+
if filter.present?
|
178
|
+
field = filter[:field]
|
181
179
|
fields << field
|
182
|
-
operators[field] =
|
183
|
-
values[field] =
|
180
|
+
operators[field] = filter[:operator]
|
181
|
+
values[field] = filter[:value] if filter.key? :value
|
184
182
|
end
|
185
183
|
|
186
|
-
{ controller:
|
184
|
+
{ controller: tag_controller.presence || controller_name,
|
187
185
|
action: action,
|
188
186
|
set_filter: 1,
|
189
|
-
project_id:
|
187
|
+
project_id: project,
|
190
188
|
f: fields,
|
191
189
|
v: values,
|
192
190
|
op: operators }
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module AdditionalTagsIssuesHelper
|
2
4
|
# Hacked render_api_custom_values to add plugin values to issue api
|
3
5
|
def render_api_custom_values(custom_values, api)
|
@@ -9,7 +11,7 @@ module AdditionalTagsIssuesHelper
|
|
9
11
|
|
10
12
|
api.array :tags do
|
11
13
|
@issue.tags.each do |tag|
|
12
|
-
api.tag
|
14
|
+
api.tag id: tag.id, name: tag.name
|
13
15
|
end
|
14
16
|
end
|
15
17
|
end
|
@@ -1,8 +1,10 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module AdditionalTagsWikiHelper
|
2
4
|
def sidebar_tags
|
3
5
|
unless @sidebar_tags
|
4
6
|
@sidebar_tags = []
|
5
|
-
@sidebar_tags = WikiPage.available_tags
|
7
|
+
@sidebar_tags = WikiPage.available_tags project: @project if AdditionalTags.show_sidebar_tags?
|
6
8
|
end
|
7
9
|
@sidebar_tags
|
8
10
|
end
|
@@ -37,13 +39,13 @@ module AdditionalTagsWikiHelper
|
|
37
39
|
scope = if wiki
|
38
40
|
wiki.pages
|
39
41
|
else
|
40
|
-
WikiPage.joins
|
42
|
+
WikiPage.joins wiki: :project
|
41
43
|
end
|
42
44
|
|
43
|
-
scope = scope.visible
|
45
|
+
scope = scope.visible User.current, project: project if scope.respond_to? :visible
|
44
46
|
|
45
47
|
scope = scope.joins(AdditionalTags::Tags.tag_to_joins(WikiPage))
|
46
|
-
.where("LOWER(#{ActiveRecord::Base.connection.quote_table_name
|
48
|
+
.where("LOWER(#{ActiveRecord::Base.connection.quote_table_name ActsAsTaggableOn.tags_table}.name) = LOWER(:p)",
|
47
49
|
p: tag.to_s.strip)
|
48
50
|
.with_updated_on
|
49
51
|
.joins(wiki: :project)
|
data/app/models/migrate_tag.rb
CHANGED
@@ -6,9 +6,10 @@ h2
|
|
6
6
|
|
7
7
|
= form_tag merge_additional_tags_path(ids: @tags.map(&:id)), class: 'tabular' do
|
8
8
|
= error_messages_for 'tag'
|
9
|
-
= additional_tag_links @tags,
|
10
|
-
|
11
|
-
|
9
|
+
= additional_tag_links @tags,
|
10
|
+
show_count: true,
|
11
|
+
use_colors: AdditionalTags.setting?(:use_colors),
|
12
|
+
link: '#'
|
12
13
|
.box
|
13
14
|
p
|
14
15
|
label[for="tag_name"]
|
@@ -15,7 +15,7 @@
|
|
15
15
|
- tags.each do |tag|
|
16
16
|
tr.hascontextmenu id="#{tag.id}"
|
17
17
|
td.checkbox.hide-when-print
|
18
|
-
= check_box_tag
|
18
|
+
= check_box_tag 'ids[]', tag.id, false, id: nil
|
19
19
|
td = additional_tag_link tag, link: edit_additional_tag_path(tag)
|
20
20
|
- manageable_tag_column_values(tag).each do |column|
|
21
21
|
td = column
|
@@ -21,10 +21,10 @@ h3.title = l :label_add_tags
|
|
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
23
|
p.most_used_tags
|
24
|
-
= safe_join @most_used_tags.collect { |t| tag.span
|
24
|
+
= safe_join @most_used_tags.collect { |t| tag.span t.name, class: 'most_used_tag' }, ', '
|
25
25
|
= javascript_tag "var mostUsedTags = #{@most_used_tags.map(&:name)}"
|
26
26
|
|
27
27
|
.buttons
|
28
28
|
= submit_tag l(:button_add), name: nil
|
29
29
|
'
|
30
|
-
=
|
30
|
+
= link_to_function l(:button_cancel), 'hideModal(this);'
|
data/config/routes.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
class ActsAsTaggableMigration < ActiveRecord::Migration[5.2]
|
2
4
|
def up
|
3
5
|
create_table ActsAsTaggableOn.tags_table do |t|
|
@@ -30,7 +32,7 @@ class ActsAsTaggableMigration < ActiveRecord::Migration[5.2]
|
|
30
32
|
|
31
33
|
return unless ActsAsTaggableOn::Utils.using_mysql?
|
32
34
|
|
33
|
-
execute
|
35
|
+
execute "ALTER TABLE #{ActsAsTaggableOn.tags_table} MODIFY name varchar(191) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin;"
|
34
36
|
end
|
35
37
|
|
36
38
|
def down
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
class MigrateExistingTags < ActiveRecord::Migration[5.2]
|
2
4
|
def up
|
3
5
|
return unless table_exists?(MigrateTag.table_name) && table_exists?(MigrateTagging.table_name)
|
@@ -11,7 +13,7 @@ class MigrateExistingTags < ActiveRecord::Migration[5.2]
|
|
11
13
|
old_tag.migrate_taggings.each do |tagging|
|
12
14
|
next if excluded_taggable_types.include? tagging.taggable_type
|
13
15
|
|
14
|
-
tag = ActsAsTaggableOn::Tag.create!
|
16
|
+
tag = ActsAsTaggableOn::Tag.create! name: old_tag.name if cnt.zero? && tag.nil?
|
15
17
|
context = tagging.respond_to?('context') && tagging.context.present? ? tagging.context : 'tags'
|
16
18
|
|
17
19
|
# old data can include dups
|
@@ -28,7 +30,7 @@ class MigrateExistingTags < ActiveRecord::Migration[5.2]
|
|
28
30
|
cnt += 1
|
29
31
|
end
|
30
32
|
|
31
|
-
ActsAsTaggableOn::Tag.reset_counters
|
33
|
+
ActsAsTaggableOn::Tag.reset_counters tag.id, :taggings unless tag.nil?
|
32
34
|
end
|
33
35
|
end
|
34
36
|
end
|
data/init.rb
CHANGED
data/lib/additional_tags.rb
CHANGED
@@ -1,9 +1,11 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'additional_tags/version'
|
2
4
|
require 'additional_tags/tags'
|
3
5
|
|
4
6
|
module AdditionalTags
|
5
|
-
TAG_TABLE_NAME = 'additional_tags'
|
6
|
-
TAGGING_TABLE_NAME = 'additional_taggings'
|
7
|
+
TAG_TABLE_NAME = 'additional_tags'
|
8
|
+
TAGGING_TABLE_NAME = 'additional_taggings'
|
7
9
|
|
8
10
|
class << self
|
9
11
|
def setup
|
@@ -22,6 +24,7 @@ module AdditionalTags
|
|
22
24
|
MyController.include AdditionalTags::Patches::MyControllerPatch
|
23
25
|
Issue.include AdditionalTags::Patches::IssuePatch
|
24
26
|
Journal.include AdditionalTags::Patches::JournalPatch
|
27
|
+
Query.include AdditionalTags::Patches::QueryPatch
|
25
28
|
IssuesController.include AdditionalTags::Patches::IssuesControllerPatch
|
26
29
|
ImportsController.include AdditionalTags::Patches::ImportsControllerPatch
|
27
30
|
QueriesHelper.include AdditionalTags::Patches::QueriesHelperPatch
|
@@ -69,19 +72,6 @@ module AdditionalTags
|
|
69
72
|
setting(:tags_sidebar).present? && setting(:tags_sidebar) != 'none'
|
70
73
|
end
|
71
74
|
|
72
|
-
def sql_for_tags_field(klass, operator, values)
|
73
|
-
compare = ['=', '*'].include?(operator) ? 'IN' : 'NOT IN'
|
74
|
-
|
75
|
-
case operator
|
76
|
-
when '=', '!'
|
77
|
-
ids_list = klass.tagged_with(values, any: true).pluck :id
|
78
|
-
"(#{klass.table_name}.id #{compare} (#{ids_list.join ','}))" if ids_list.present?
|
79
|
-
else
|
80
|
-
entries = ActsAsTaggableOn::Tagging.where taggable_type: klass.name
|
81
|
-
"(#{klass.table_name}.id #{compare} (#{entries.select(:taggable_id).to_sql}))"
|
82
|
-
end
|
83
|
-
end
|
84
|
-
|
85
75
|
private
|
86
76
|
|
87
77
|
def settings
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module AdditionalTags
|
2
4
|
module Patches
|
3
5
|
module AgileQueryPatch
|
@@ -10,19 +12,19 @@ module AdditionalTags
|
|
10
12
|
alias_method :initialize_available_filters_without_tags, :initialize_available_filters
|
11
13
|
alias_method :initialize_available_filters, :initialize_available_filters_with_tags
|
12
14
|
|
13
|
-
add_available_column
|
15
|
+
add_available_column ::QueryTagsColumn.new
|
14
16
|
end
|
15
17
|
|
16
18
|
module InstanceMethods
|
17
19
|
def sql_for_tags_field(_field, operator, value)
|
18
|
-
case operator
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
20
|
+
issues = case operator
|
21
|
+
when '=', '!'
|
22
|
+
Issue.tagged_with value.clone, any: true
|
23
|
+
when '!*'
|
24
|
+
Issue.joins(:tags).uniq
|
25
|
+
else
|
26
|
+
Issue.tagged_with(ActsAsTaggableOn::Tag.all.map(&:to_s), any: true)
|
27
|
+
end
|
26
28
|
|
27
29
|
compare = operator.include?('!') ? 'NOT IN' : 'IN'
|
28
30
|
ids_list = issues.collect(&:id).push(0).join(',')
|
@@ -1,10 +1,12 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module AdditionalTags
|
2
4
|
module Patches
|
3
5
|
module AgileVersionsQueryPatch
|
4
6
|
extend ActiveSupport::Concern
|
5
7
|
|
6
8
|
included do
|
7
|
-
add_available_column
|
9
|
+
add_available_column ::QueryTagsColumn.new
|
8
10
|
end
|
9
11
|
end
|
10
12
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module AdditionalTags
|
2
4
|
module Patches
|
3
5
|
module AutoCompletesControllerPatch
|
@@ -30,7 +32,7 @@ module AdditionalTags
|
|
30
32
|
return render_403 unless User.current.admin?
|
31
33
|
|
32
34
|
@name = params[:q].to_s
|
33
|
-
sql_for_where = "LOWER(#{ActiveRecord::Base.connection.quote_table_name
|
35
|
+
sql_for_where = "LOWER(#{ActiveRecord::Base.connection.quote_table_name ActsAsTaggableOn.tags_table}.name) LIKE ?"
|
34
36
|
@tags = ActsAsTaggableOn::Tag.where(sql_for_where, "%#{@name.downcase}%")
|
35
37
|
.order(name: :asc)
|
36
38
|
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module AdditionalTags
|
2
4
|
module Patches
|
3
5
|
module IssuePatch
|
@@ -20,16 +22,16 @@ module AdditionalTags
|
|
20
22
|
class_methods do
|
21
23
|
def allowed_tags?(tags)
|
22
24
|
allowed_tags = available_tags.map(&:name)
|
23
|
-
tags.all? { |tag| allowed_tags.include?
|
25
|
+
tags.all? { |tag| allowed_tags.include? tag }
|
24
26
|
end
|
25
27
|
|
26
28
|
def by_tags(project, with_subprojects: false)
|
27
|
-
count_and_group_by
|
29
|
+
count_and_group_by project: project, association: :tags, with_subprojects: with_subprojects
|
28
30
|
end
|
29
31
|
|
30
|
-
def available_tags(options
|
32
|
+
def available_tags(**options)
|
31
33
|
options[:permission] = :view_issues
|
32
|
-
tags = AdditionalTags::Tags.available_tags self, options
|
34
|
+
tags = AdditionalTags::Tags.available_tags self, **options
|
33
35
|
return tags unless options[:open_issues_only]
|
34
36
|
|
35
37
|
tags.joins("JOIN #{IssueStatus.table_name} ON #{IssueStatus.table_name}.id = #{table_name}.status_id")
|
@@ -65,8 +67,8 @@ module AdditionalTags
|
|
65
67
|
send 'safe_attributes_without_tags=', attrs, user
|
66
68
|
end
|
67
69
|
|
68
|
-
def copy_from_with_tags(arg, options
|
69
|
-
copy_from_without_tags(arg, options)
|
70
|
+
def copy_from_with_tags(arg, **options)
|
71
|
+
copy_from_without_tags(arg, **options)
|
70
72
|
issue = arg.is_a?(Issue) ? arg : Issue.visible.find(arg)
|
71
73
|
self.tag_list = issue.tag_list
|
72
74
|
self
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module AdditionalTags
|
2
4
|
module Patches
|
3
5
|
module IssueQueryPatch
|
@@ -5,6 +7,7 @@ module AdditionalTags
|
|
5
7
|
|
6
8
|
included do
|
7
9
|
include AdditionalsQuery
|
10
|
+
prepend InstanceOverwriteMethods
|
8
11
|
include InstanceMethods
|
9
12
|
|
10
13
|
alias_method :initialize_available_filters_without_tags, :initialize_available_filters
|
@@ -12,9 +15,20 @@ module AdditionalTags
|
|
12
15
|
|
13
16
|
alias_method :available_columns_without_tags, :available_columns
|
14
17
|
alias_method :available_columns, :available_columns_with_tags
|
18
|
+
end
|
19
|
+
|
20
|
+
module InstanceOverwriteMethods
|
21
|
+
def build_from_params(params, defaults = {})
|
22
|
+
super
|
23
|
+
|
24
|
+
return self if params[:tag_id].blank?
|
15
25
|
|
16
|
-
|
17
|
-
|
26
|
+
add_filter 'tags',
|
27
|
+
'=',
|
28
|
+
[ActsAsTaggableOn::Tag.find_by(id: params[:tag_id]).try(:name)]
|
29
|
+
|
30
|
+
self
|
31
|
+
end
|
18
32
|
end
|
19
33
|
|
20
34
|
module InstanceMethods
|
@@ -31,24 +45,13 @@ module AdditionalTags
|
|
31
45
|
@available_columns = available_columns_without_tags
|
32
46
|
|
33
47
|
if AdditionalTags.setting?(:active_issue_tags) && User.current.allowed_to?(:view_issue_tags, project, global: true)
|
34
|
-
@available_columns <<
|
48
|
+
@available_columns << ::QueryTagsColumn.new
|
35
49
|
end
|
36
50
|
else
|
37
51
|
available_columns_without_tags
|
38
52
|
end
|
39
53
|
@available_columns
|
40
54
|
end
|
41
|
-
|
42
|
-
def build_from_params_with_tags(params, defaults = {})
|
43
|
-
build_from_params_without_tags params, defaults
|
44
|
-
return self if params[:tag_id].blank?
|
45
|
-
|
46
|
-
add_filter 'tags',
|
47
|
-
'=',
|
48
|
-
[ActsAsTaggableOn::Tag.find_by(id: params[:tag_id]).try(:name)]
|
49
|
-
|
50
|
-
self
|
51
|
-
end
|
52
55
|
end
|
53
56
|
end
|
54
57
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module AdditionalTags
|
2
4
|
module Patches
|
3
5
|
module QueriesHelperPatch
|
@@ -8,25 +10,11 @@ module AdditionalTags
|
|
8
10
|
|
9
11
|
alias_method :column_content_without_tags, :column_content
|
10
12
|
alias_method :column_content, :column_content_with_tags
|
11
|
-
|
12
|
-
alias_method :csv_content_without_tags, :csv_content
|
13
|
-
alias_method :csv_content, :csv_content_with_tags
|
14
13
|
end
|
15
14
|
|
16
15
|
module InstanceMethods
|
17
|
-
def csv_content_with_tags(column, item)
|
18
|
-
if item.is_a?(Issue) && column.name == :tags ||
|
19
|
-
item.is_a?(TimeEntry) && column.name == :issue_tags
|
20
|
-
|
21
|
-
additional_plain_tag_list column.value_object(item)
|
22
|
-
else
|
23
|
-
csv_content_without_tags column, item
|
24
|
-
end
|
25
|
-
end
|
26
|
-
|
27
16
|
def column_content_with_tags(column, item)
|
28
|
-
if item.is_a?(Issue) && column.name == :tags
|
29
|
-
item.is_a?(TimeEntry) && column.name == :issue_tags
|
17
|
+
if column.name == :issue_tags || item.is_a?(Issue) && column.name == :tags
|
30
18
|
additional_tag_links column.value(item),
|
31
19
|
tag_controller: 'issues',
|
32
20
|
use_colors: AdditionalTags.setting?(:use_colors)
|
@@ -0,0 +1,76 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module AdditionalTags
|
4
|
+
module Patches
|
5
|
+
module QueryPatch
|
6
|
+
extend ActiveSupport::Concern
|
7
|
+
|
8
|
+
included do
|
9
|
+
include InstanceMethods
|
10
|
+
end
|
11
|
+
|
12
|
+
module InstanceMethods
|
13
|
+
def sql_for_tags_field(field, _operator, values)
|
14
|
+
build_sql_for_tags_field klass: queried_class, operator: operator_for(field), values: values
|
15
|
+
end
|
16
|
+
|
17
|
+
def initialize_tags_filter(position: nil)
|
18
|
+
add_available_filter 'tags', order: position,
|
19
|
+
type: :list_optional,
|
20
|
+
values: -> { available_tag_values queried_class }
|
21
|
+
end
|
22
|
+
|
23
|
+
def initialize_issue_tags_filter
|
24
|
+
return unless AdditionalTags.setting?(:active_issue_tags) && User.current.allowed_to?(:view_issue_tags, project, global: true)
|
25
|
+
|
26
|
+
add_available_filter 'issue.tags',
|
27
|
+
type: :list_optional,
|
28
|
+
name: l('label_attribute_of_issue', name: l(:field_tags)),
|
29
|
+
values: -> { available_tag_values Issue }
|
30
|
+
end
|
31
|
+
|
32
|
+
def available_tag_values(klass)
|
33
|
+
klass.available_tags(project: project)
|
34
|
+
.pluck(:name)
|
35
|
+
.map { |name| [name, name] }
|
36
|
+
end
|
37
|
+
|
38
|
+
def build_subquery_for_tags_field(klass:, operator:, values:, joined_table:, joined_field:, target_field: 'issue_id')
|
39
|
+
quoted_joined_table = self.class.connection.quote_table_name joined_table
|
40
|
+
quoted_joined_field = self.class.connection.quote_column_name joined_field
|
41
|
+
quoted_target_field = self.class.connection.quote_column_name target_field
|
42
|
+
subsql = ActsAsTaggableOn::Tagging.joins("INNER JOIN #{quoted_joined_table}" \
|
43
|
+
" ON additional_taggings.taggable_id = #{quoted_joined_table}.#{quoted_target_field}")
|
44
|
+
.where(taggable_type: klass.name)
|
45
|
+
.where("#{self.class.connection.quote_table_name queried_table_name}.id ="\
|
46
|
+
" #{quoted_joined_table}.#{quoted_joined_field}")
|
47
|
+
.select(1)
|
48
|
+
|
49
|
+
if %w[= !].include? operator
|
50
|
+
ids_list = klass.tagged_with(values, any: true).pluck :id
|
51
|
+
subsql = subsql.where taggable_id: ids_list
|
52
|
+
end
|
53
|
+
|
54
|
+
if %w[= *].include? operator
|
55
|
+
" EXISTS(#{subsql.to_sql})"
|
56
|
+
else
|
57
|
+
" NOT EXISTS(#{subsql.to_sql})"
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def build_sql_for_tags_field(klass:, operator:, values:)
|
62
|
+
compare = ['=', '*'].include?(operator) ? 'IN' : 'NOT IN'
|
63
|
+
case operator
|
64
|
+
when '=', '!'
|
65
|
+
ids_list = klass.tagged_with(values, any: true).pluck :id
|
66
|
+
"(#{klass.table_name}.id #{compare} (#{ids_list.join ','}))" if ids_list.present?
|
67
|
+
else
|
68
|
+
entries = ActsAsTaggableOn::Tagging.where taggable_type: klass.name
|
69
|
+
id_table = klass.table_name
|
70
|
+
"(#{id_table}.id #{compare} (#{entries.select(:taggable_id).to_sql}))"
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require_dependency 'time_entry_query'
|
2
4
|
|
3
5
|
module AdditionalTags
|
@@ -18,13 +20,7 @@ module AdditionalTags
|
|
18
20
|
module InstanceMethods
|
19
21
|
def initialize_available_filters_with_tags
|
20
22
|
initialize_available_filters_without_tags
|
21
|
-
|
22
|
-
return unless AdditionalTags.setting?(:active_issue_tags) && User.current.allowed_to?(:view_issue_tags, project, global: true)
|
23
|
-
|
24
|
-
add_available_filter 'issue.tags',
|
25
|
-
type: :list_optional,
|
26
|
-
name: l('label_attribute_of_issue', name: l(:field_tags)),
|
27
|
-
values: -> { available_issue_tags_values }
|
23
|
+
initialize_issue_tags_filter
|
28
24
|
end
|
29
25
|
|
30
26
|
def available_columns_with_tags
|
@@ -39,14 +35,8 @@ module AdditionalTags
|
|
39
35
|
@available_columns
|
40
36
|
end
|
41
37
|
|
42
|
-
def sql_for_issue_tags_field(_field, operator,
|
43
|
-
|
44
|
-
end
|
45
|
-
|
46
|
-
def available_issue_tags_values
|
47
|
-
Issue.available_tags(project: project)
|
48
|
-
.pluck(:name)
|
49
|
-
.map { |name| [name, name] }
|
38
|
+
def sql_for_issue_tags_field(_field, operator, values)
|
39
|
+
build_sql_for_tags_field klass: Issue, operator: operator, values: values
|
50
40
|
end
|
51
41
|
end
|
52
42
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module AdditionalTags
|
2
4
|
module Patches
|
3
5
|
module WikiPagePatch
|
@@ -20,10 +22,10 @@ module AdditionalTags
|
|
20
22
|
"JOIN #{Project.table_name} ON wikis.project_id = #{Project.table_name}.id"]
|
21
23
|
end
|
22
24
|
|
23
|
-
def available_tags(options
|
25
|
+
def available_tags(**options)
|
24
26
|
options[:project_join] = project_joins
|
25
27
|
options[:permission] = :view_wiki_pages
|
26
|
-
AdditionalTags::Tags.available_tags self, options
|
28
|
+
AdditionalTags::Tags.available_tags self, **options
|
27
29
|
end
|
28
30
|
end
|
29
31
|
|
data/lib/additional_tags/tags.rb
CHANGED
@@ -1,20 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module AdditionalTags
|
2
4
|
class Tags
|
3
5
|
class << self
|
4
|
-
def available_tags(klass, options
|
6
|
+
def available_tags(klass, **options)
|
5
7
|
user = options[:user].presence || User.current
|
6
8
|
|
7
9
|
scope = ActsAsTaggableOn::Tag.where({})
|
8
|
-
scope = scope.where
|
10
|
+
scope = scope.where "#{Project.table_name}.id = ?", options[:project] if options[:project]
|
9
11
|
if options[:permission]
|
10
|
-
scope = scope.where
|
12
|
+
scope = scope.where tag_access(options[:permission], user)
|
11
13
|
elsif options[:visible_condition]
|
12
|
-
scope = scope.where
|
14
|
+
scope = scope.where klass.visible_condition(user)
|
13
15
|
end
|
14
|
-
scope = scope.where
|
15
|
-
scope = scope.where
|
16
|
-
scope = scope.where
|
17
|
-
scope = scope.where
|
16
|
+
scope = scope.where "LOWER(#{TAG_TABLE_NAME}.name) LIKE ?", "%#{options[:name_like].downcase}%" if options[:name_like]
|
17
|
+
scope = scope.where "#{TAG_TABLE_NAME}.name=?", options[:name] if options[:name]
|
18
|
+
scope = scope.where "#{TAGGING_TABLE_NAME}.taggable_id!=?", options[:exclude_id] if options[:exclude_id]
|
19
|
+
scope = scope.where options[:where_field] => options[:where_value] if options[:where_field].present? && options[:where_value]
|
18
20
|
|
19
21
|
columns = ["#{TAG_TABLE_NAME}.id",
|
20
22
|
"#{TAG_TABLE_NAME}.name",
|
@@ -24,14 +26,14 @@ module AdditionalTags
|
|
24
26
|
columns << "MIN(#{TAGGING_TABLE_NAME}.created_at) AS last_created" if options[:sort_by] == 'last_created'
|
25
27
|
|
26
28
|
scope.select(columns.join(', '))
|
27
|
-
.joins(tag_for_joins(klass, options))
|
29
|
+
.joins(tag_for_joins(klass, **options.slice(:project_join, :project, :without_projects)))
|
28
30
|
.group("#{TAG_TABLE_NAME}.id, #{TAG_TABLE_NAME}.name, #{TAG_TABLE_NAME}.taggings_count").having('COUNT(*) > 0')
|
29
31
|
.order(build_order_sql(options[:sort_by], options[:order]))
|
30
32
|
end
|
31
33
|
|
32
|
-
def all_type_tags(klass,
|
33
|
-
ActsAsTaggableOn::Tag.
|
34
|
-
.joins(tag_for_joins(klass,
|
34
|
+
def all_type_tags(klass, without_projects: false)
|
35
|
+
ActsAsTaggableOn::Tag.all
|
36
|
+
.joins(tag_for_joins(klass, without_projects: without_projects))
|
35
37
|
.distinct
|
36
38
|
.order("#{TAG_TABLE_NAME}.name")
|
37
39
|
end
|
@@ -61,7 +63,7 @@ module AdditionalTags
|
|
61
63
|
# remove old (merged) tags
|
62
64
|
tags_to_merge.reject { |t| t.id == tag.id }.each(&:destroy)
|
63
65
|
# remove duplicate taggings
|
64
|
-
dup_scope = ActsAsTaggableOn::Tagging.where
|
66
|
+
dup_scope = ActsAsTaggableOn::Tagging.where tag_id: tag.id
|
65
67
|
valid_ids = dup_scope.group(:tag_id, :taggable_id, :taggable_type, :tagger_id, :tagger_type, :context).pluck(Arel.sql('MIN(id)'))
|
66
68
|
dup_scope.where.not(id: valid_ids).destroy_all if valid_ids.any?
|
67
69
|
# recalc count for new tag
|
@@ -83,6 +85,15 @@ module AdditionalTags
|
|
83
85
|
end
|
84
86
|
end
|
85
87
|
|
88
|
+
def build_relation_tags(entries)
|
89
|
+
return [] if entries.none?
|
90
|
+
|
91
|
+
tags = entries.map(&:tags)
|
92
|
+
tags.flatten!
|
93
|
+
|
94
|
+
tags.uniq
|
95
|
+
end
|
96
|
+
|
86
97
|
private
|
87
98
|
|
88
99
|
def build_order_sql(sort_by, order)
|
@@ -100,16 +111,16 @@ module AdditionalTags
|
|
100
111
|
Arel.sql sql
|
101
112
|
end
|
102
113
|
|
103
|
-
def tag_for_joins(klass,
|
114
|
+
def tag_for_joins(klass, project_join: nil, project: nil, without_projects: false)
|
104
115
|
table_name = klass.table_name
|
105
116
|
|
106
117
|
joins = ["JOIN #{TAGGING_TABLE_NAME} ON #{TAGGING_TABLE_NAME}.tag_id = #{TAG_TABLE_NAME}.id"]
|
107
118
|
joins << "JOIN #{table_name} " \
|
108
119
|
"ON #{table_name}.id = #{TAGGING_TABLE_NAME}.taggable_id AND #{TAGGING_TABLE_NAME}.taggable_type = '#{klass}'"
|
109
120
|
|
110
|
-
if
|
111
|
-
joins <<
|
112
|
-
elsif
|
121
|
+
if project_join
|
122
|
+
joins << project_join
|
123
|
+
elsif project || !without_projects
|
113
124
|
joins << "JOIN #{Project.table_name} ON #{table_name}.project_id = #{Project.table_name}.id"
|
114
125
|
end
|
115
126
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: additional_tags
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- AlphaNodes
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-
|
11
|
+
date: 2021-08-22 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: acts-as-taggable-on
|
@@ -80,6 +80,7 @@ files:
|
|
80
80
|
- app/jobs/additional_tags_remove_unused_tag_job.rb
|
81
81
|
- app/models/migrate_tag.rb
|
82
82
|
- app/models/migrate_tagging.rb
|
83
|
+
- app/models/query_tags_column.rb
|
83
84
|
- app/views/additional_tags/_html_head.html.slim
|
84
85
|
- app/views/additional_tags/_tag_list.html.slim
|
85
86
|
- app/views/additional_tags/context_menu.html.slim
|
@@ -142,6 +143,7 @@ files:
|
|
142
143
|
- lib/additional_tags/patches/journal_patch.rb
|
143
144
|
- lib/additional_tags/patches/my_controller_patch.rb
|
144
145
|
- lib/additional_tags/patches/queries_helper_patch.rb
|
146
|
+
- lib/additional_tags/patches/query_patch.rb
|
145
147
|
- lib/additional_tags/patches/reports_controller_patch.rb
|
146
148
|
- lib/additional_tags/patches/settings_controller_patch.rb
|
147
149
|
- lib/additional_tags/patches/time_entry_patch.rb
|