additional_tags 1.0.1 → 1.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|